Kernel: We can create basic userspace processes

These are still allocated on the kernel memory
This commit is contained in:
Bananymous
2023-04-12 17:51:36 +03:00
parent 34358b8471
commit 8ee63f8264
10 changed files with 121 additions and 82 deletions

View File

@@ -2,6 +2,7 @@
#include <kernel/CriticalScope.h>
#include <kernel/FS/VirtualFileSystem.h>
#include <kernel/LockGuard.h>
#include <kernel/MMU.h>
#include <kernel/Process.h>
#include <kernel/Scheduler.h>
@@ -20,6 +21,25 @@ namespace Kernel
return process;
}
BAN::ErrorOr<BAN::RefPtr<Process>> Process::create_userspace(void(*entry)())
{
auto process = TRY(BAN::RefPtr<Process>::create(s_next_pid++));
TRY(process->m_working_directory.push_back('/'));
TRY(process->init_stdio());
TRY(process->add_thread(
[](void* entry_func)
{
Thread& current = Thread::current();
MMU::get().allocate_range(current.stack_base(), current.stack_size(), MMU::Flags::UserSupervisor | MMU::Flags::ReadWrite | MMU::Flags::Present);
current.jump_userspace((uintptr_t)entry_func);
ASSERT_NOT_REACHED();
}, (void*)entry
));
return process;
}
Process::Process(pid_t pid)
: m_pid(pid)
, m_tty(TTY::current())

View File

@@ -1,19 +1,28 @@
#include <kernel/Debug.h>
#include <kernel/kprint.h>
#include <kernel/Process.h>
#include <kernel/Syscall.h>
namespace Kernel
{
int sys_test()
void sys_exit()
{
dprintln("hello");
Process::current()->exit();
}
int sys_read(int fd, void* buffer, size_t size)
{
auto res = Process::current()->read(fd, buffer, size);
if (res.is_error())
return res.error().get_error_code();
return 0;
}
int sys_putc(void* ch)
int sys_write(int fd, const void* buffer, size_t size)
{
kprint("{}", (char)(uintptr_t)ch);
auto res = Process::current()->write(fd, buffer, size);
if (res.is_error())
return res.error().get_error_code();
return 0;
}
@@ -23,14 +32,17 @@ namespace Kernel
(void)arg2;
(void)arg3;
int ret;
int ret = 0;
switch (syscall)
{
case SYS_TEST:
ret = sys_test();
case SYS_EXIT:
sys_exit();
break;
case SYS_PUTC:
ret = sys_putc(arg1);
case SYS_READ:
ret = sys_read((int)(uintptr_t)arg1, arg2, (size_t)(uintptr_t)arg3);
break;
case SYS_WRITE:
ret = sys_write((int)(uintptr_t)arg1, arg2, (size_t)(uintptr_t)arg3);
break;
default:
ret = -1;

View File

@@ -10,6 +10,7 @@
namespace Kernel
{
extern "C" void thread_jump_userspace(uintptr_t rsp, uintptr_t rip);
template<size_t size, typename T>
static void write_to_stack(uintptr_t& rsp, const T& value)
@@ -63,6 +64,11 @@ namespace Kernel
kfree(m_stack_base);
}
void Thread::jump_userspace(uintptr_t rip)
{
thread_jump_userspace(rsp(), rip);
}
void Thread::on_exit()
{
if (m_process)

View File

@@ -103,6 +103,7 @@ extern "C" uintptr_t g_userspace_start;
extern "C" uintptr_t g_userspace_end;
extern void userspace_entry();
static void jump_userspace();
static void init2(void*);
@@ -154,54 +155,10 @@ extern "C" void kernel_main()
MUST(Scheduler::initialize());
Scheduler& scheduler = Scheduler::get();
#if 0
MUST(scheduler.add_thread(MUST(Thread::create(
[] (void*)
{
MMU::get().allocate_range((uintptr_t)&g_userspace_start, (uintptr_t)&g_userspace_end - (uintptr_t)&g_userspace_start, MMU::Flags::UserSupervisor | MMU::Flags::Present);
MMU::get().allocate_range((uintptr_t)&g_rodata_start, (uintptr_t)&g_rodata_end - (uintptr_t)&g_rodata_start, MMU::Flags::UserSupervisor | MMU::Flags::Present);
void* userspace_stack = kmalloc(4096, 4096);
ASSERT(userspace_stack);
MMU::get().allocate_page((uintptr_t)userspace_stack, MMU::Flags::UserSupervisor | MMU::Flags::ReadWrite | MMU::Flags::Present);
BOCHS_BREAK();
#if ARCH(x86_64)
asm volatile(
"pushq %0;"
"pushq %1;"
"pushfq;"
"pushq %2;"
"pushq %3;"
"iretq;"
:: "r"((uintptr_t)0x20 | 3), "r"((uintptr_t)userspace_stack + 4096), "r"((uintptr_t)0x18 | 3), "r"(userspace_entry)
);
#else
asm volatile(
"movl %0, %%eax;"
"movw %%ax, %%ds;"
"movw %%ax, %%es;"
"movw %%ax, %%fs;"
"movw %%ax, %%gs;"
"movl %1, %%esp;"
"pushl %0;"
"pushl %1;"
"pushfl;"
"pushl %2;"
"pushl %3;"
"iret;"
:: "r"((uintptr_t)0x20 | 3), "r"((uintptr_t)userspace_stack + 4096), "r"((uintptr_t)0x18 | 3), "r"(userspace_entry)
);
#endif
}
))));
#else
MUST(scheduler.add_thread(MUST(Thread::create(init2, terminal_driver))));
#endif
scheduler.start();
ASSERT(false);
ASSERT_NOT_REACHED();
}
static void init2(void* terminal_driver)
@@ -220,6 +177,8 @@ static void init2(void* terminal_driver)
ASSERT(tty1);
DeviceManager::get().add_device(tty1);
return jump_userspace();
MUST(Process::create_kernel(
[](void*)
{
@@ -229,4 +188,14 @@ static void init2(void* terminal_driver)
shell->run();
}, nullptr
));
}
}
static void jump_userspace()
{
using namespace Kernel;
MMU::get().allocate_range((uintptr_t)&g_userspace_start, (uintptr_t)&g_userspace_end - (uintptr_t)&g_userspace_start, MMU::Flags::UserSupervisor | MMU::Flags::Present);
MMU::get().allocate_range((uintptr_t)&g_rodata_start, (uintptr_t)&g_rodata_end - (uintptr_t)&g_rodata_start, MMU::Flags::UserSupervisor | MMU::Flags::Present);
MUST(Process::create_userspace(userspace_entry));
}