forked from Bananymous/banan-os
Kernel: We can create basic userspace processes
These are still allocated on the kernel memory
This commit is contained in:
@@ -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())
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user