[kernel] Split loading from scheduler
In preparation for moving things to the init process, move process loading out of the scheduler. memory_bootstrap now has a load_simple_process function for mapping an args::program into memory, and the stack setup has been simplified (though all the initv values are still being added by the kernel - this needs rework) and normalized to use the thread::add_thunk_user code path.
This commit is contained in:
@@ -106,7 +106,9 @@ process::create_thread(uint8_t priority, bool user)
|
||||
vm_flags::zero|vm_flags::write);
|
||||
m_space.add(stack_top - stack_size, vma);
|
||||
|
||||
th->tcb()->rsp3 = stack_top;
|
||||
// Space for null frame - because the page gets zeroed on
|
||||
// allocation, just pointing rsp here does the trick
|
||||
th->tcb()->rsp3 = stack_top - 2 * sizeof(uint64_t);
|
||||
}
|
||||
|
||||
m_threads.append(th);
|
||||
|
||||
@@ -16,7 +16,7 @@ public:
|
||||
constexpr static uintptr_t stacks_top = 0x0000800000000000;
|
||||
|
||||
/// Size of userspace thread stacks
|
||||
constexpr static size_t stack_size = 0x4000;
|
||||
constexpr static size_t stack_size = 0x4000000; // 64MiB
|
||||
|
||||
/// Value that represents default priority
|
||||
constexpr static uint8_t default_priority = 0xff;
|
||||
|
||||
@@ -149,6 +149,10 @@ thread::exit(int32_t code)
|
||||
void
|
||||
thread::add_thunk_kernel(uintptr_t rip)
|
||||
{
|
||||
// This adds just enough values to the top of the
|
||||
// kernel stack to come out of task_switch correctly
|
||||
// and start executing at rip (still in kernel mode)
|
||||
|
||||
m_tcb.rsp -= sizeof(uintptr_t) * 7;
|
||||
uintptr_t *stack = reinterpret_cast<uintptr_t*>(m_tcb.rsp);
|
||||
|
||||
@@ -162,15 +166,24 @@ thread::add_thunk_kernel(uintptr_t rip)
|
||||
}
|
||||
|
||||
void
|
||||
thread::add_thunk_user(uintptr_t rip)
|
||||
thread::add_thunk_user(uintptr_t rip3, uintptr_t rip0, uint64_t flags)
|
||||
{
|
||||
// This sets up the stack to:
|
||||
// a) come out of task_switch and return to rip0 (default is the
|
||||
// kernel/user trampoline) (via add_thunk_kernel) - if this is
|
||||
// changed, it needs to end up at the trampoline with the stack
|
||||
// as it was
|
||||
// b) come out of the kernel/user trampoline and start executing
|
||||
// in user mode at rip
|
||||
|
||||
m_tcb.rsp -= sizeof(uintptr_t) * 8;
|
||||
uintptr_t *stack = reinterpret_cast<uintptr_t*>(m_tcb.rsp);
|
||||
flags |= 0x200;
|
||||
|
||||
stack[7] = rip; // return rip in rcx
|
||||
stack[7] = rip3; // return rip in rcx
|
||||
stack[6] = m_tcb.rsp3; // rbp
|
||||
stack[5] = 0xbbbbbbbb; // rbx
|
||||
stack[4] = 0x00000200; // r11 sets RFLAGS
|
||||
stack[4] = flags; // r11 sets RFLAGS
|
||||
stack[3] = 0x12121212; // r12
|
||||
stack[2] = 0x13131313; // r13
|
||||
stack[1] = 0x14141414; // r14
|
||||
@@ -178,7 +191,7 @@ thread::add_thunk_user(uintptr_t rip)
|
||||
|
||||
static const uintptr_t trampoline =
|
||||
reinterpret_cast<uintptr_t>(kernel_to_user_trampoline);
|
||||
add_thunk_kernel(trampoline);
|
||||
add_thunk_kernel(rip0 ? rip0 : trampoline);
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
@@ -137,9 +137,12 @@ public:
|
||||
/// \arg rip The address to return to, must be kernel space
|
||||
void add_thunk_kernel(uintptr_t rip);
|
||||
|
||||
/// Add a stack header that returns to the given address in user space.
|
||||
/// \arg rip The address to return to, must be user space
|
||||
void add_thunk_user(uintptr_t rip);
|
||||
/// Add a stack header that returns to the given address in user space
|
||||
/// via a function in kernel space.
|
||||
/// \arg rip3 The user space address to return to
|
||||
/// \arg rip0 The kernel function to pass through, optional
|
||||
/// \arg flags Extra RFLAGS values to set, optional
|
||||
void add_thunk_user(uintptr_t rip3, uintptr_t rip0 = 0, uint64_t flags = 0);
|
||||
|
||||
/// Get the handle representing this thread to its process
|
||||
j6_handle_t self_handle() const { return m_self_handle; }
|
||||
|
||||
Reference in New Issue
Block a user