mirror of
https://github.com/justinian/jsix.git
synced 2025-12-09 16:04:32 -08:00
[kernel] Stop creating user stacks in the kernel
Stop creating stacks in user space for user threads, that should be done by the thread's creator. This change adds process and stack_top arguments to the thread_create syscall, so that threads can be created in other processes, and given a stack address. Also included is a fix in add_thunk_user due to the r11/flags change. THIS COMMIT BREAKS USERSPACE. See subsequent commits for the user side changes related to this change.
This commit is contained in:
@@ -2,6 +2,8 @@ object thread : kobject {
|
||||
uid 11f23e593d5761bd
|
||||
|
||||
method create [constructor] {
|
||||
param process object process
|
||||
param stack_top address
|
||||
param entrypoint address
|
||||
}
|
||||
|
||||
|
||||
@@ -86,7 +86,7 @@ process::update()
|
||||
}
|
||||
|
||||
thread *
|
||||
process::create_thread(uint8_t priority, bool user)
|
||||
process::create_thread(uintptr_t rsp3, uint8_t priority)
|
||||
{
|
||||
if (priority == default_priority)
|
||||
priority = scheduler::default_priority;
|
||||
@@ -94,17 +94,8 @@ process::create_thread(uint8_t priority, bool user)
|
||||
thread *th = new thread(*this, priority);
|
||||
kassert(th, "Failed to create thread!");
|
||||
|
||||
if (user) {
|
||||
uintptr_t stack_top = stacks_top - (m_threads.count() * stack_size);
|
||||
|
||||
vm_flags flags = vm_flags::zero|vm_flags::write;
|
||||
vm_area *vma = new vm_area_open(stack_size, flags);
|
||||
m_space.add(stack_top - stack_size, vma);
|
||||
|
||||
// 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);
|
||||
}
|
||||
if (rsp3)
|
||||
th->tcb()->rsp3 = rsp3;
|
||||
|
||||
m_threads.append(th);
|
||||
scheduler::get().add_thread(th->tcb());
|
||||
|
||||
@@ -43,10 +43,10 @@ public:
|
||||
vm_space & space() { return m_space; }
|
||||
|
||||
/// Create a new thread in this process
|
||||
/// \args rsp3 If non-zero, sets the ring3 stack pointer to this value
|
||||
/// \args priority The new thread's scheduling priority
|
||||
/// \args user If true, create a userspace stack for this thread
|
||||
/// \returns The newly created thread object
|
||||
thread * create_thread(uint8_t priorty = default_priority, bool user = true);
|
||||
thread * create_thread(uintptr_t rsp3 = 0, uint8_t priorty = default_priority);
|
||||
|
||||
/// Start tracking an object with a handle.
|
||||
/// \args obj The object this handle refers to
|
||||
|
||||
@@ -172,14 +172,15 @@ thread::add_thunk_user(uintptr_t rip3, uintptr_t rip0, uint64_t flags)
|
||||
// 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;
|
||||
m_tcb.rflags3 = flags;
|
||||
|
||||
stack[7] = rip3; // return rip in rcx
|
||||
stack[6] = m_tcb.rsp3; // rbp
|
||||
stack[5] = 0xbbbbbbbb; // rbx
|
||||
stack[4] = flags; // r11 sets RFLAGS
|
||||
m_tcb.rsp -= sizeof(uintptr_t) * 7;
|
||||
uintptr_t *stack = reinterpret_cast<uintptr_t*>(m_tcb.rsp);
|
||||
|
||||
stack[6] = rip3; // return rip in rcx
|
||||
stack[5] = m_tcb.rsp3; // rbp
|
||||
stack[4] = 0xbbbbbbbb; // rbx
|
||||
stack[3] = 0x12121212; // r12
|
||||
stack[2] = 0x13131313; // r13
|
||||
stack[1] = 0x14141414; // r14
|
||||
|
||||
@@ -70,7 +70,7 @@ inline T * push(uintptr_t &rsp, size_t size = sizeof(T)) {
|
||||
void
|
||||
scheduler::create_kernel_task(void (*task)(), uint8_t priority, bool constant)
|
||||
{
|
||||
thread *th = process::kernel_process().create_thread(priority, false);
|
||||
thread *th = process::kernel_process().create_thread(0, priority);
|
||||
auto *tcb = th->tcb();
|
||||
|
||||
th->add_thunk_kernel(reinterpret_cast<uintptr_t>(task));
|
||||
|
||||
@@ -9,19 +9,22 @@
|
||||
namespace syscalls {
|
||||
|
||||
j6_status_t
|
||||
thread_create(j6_handle_t *handle, uintptr_t entrypoint)
|
||||
thread_create(j6_handle_t *handle, j6_handle_t proc, uintptr_t stack_top, uintptr_t entrypoint)
|
||||
{
|
||||
thread &parent = thread::current();
|
||||
process &p = parent.parent();
|
||||
thread &parent_th = thread::current();
|
||||
process &parent_pr = parent_th.parent();
|
||||
|
||||
thread *child = p.create_thread();
|
||||
process *owner = get_handle<process>(proc);
|
||||
if (!owner) return j6_err_invalid_arg;
|
||||
|
||||
thread *child = owner->create_thread(stack_top);
|
||||
child->add_thunk_user(entrypoint);
|
||||
*handle = child->self_handle();
|
||||
child->clear_state(thread::state::loading);
|
||||
child->set_state(thread::state::ready);
|
||||
|
||||
log::debug(logs::task, "Thread %llx spawned new thread %llx, handle %d",
|
||||
parent.koid(), child->koid(), *handle);
|
||||
log::debug(logs::task, "Thread %llx:%llx spawned new thread %llx:%llx",
|
||||
parent_pr.koid(), parent_th.koid(), owner->koid(), child->koid());
|
||||
|
||||
return j6_status_ok;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user