diff --git a/core/src/arch/x86_64/thread.zig b/core/src/arch/x86_64/thread.zig index 3bfe88f..be63c7f 100644 --- a/core/src/arch/x86_64/thread.zig +++ b/core/src/arch/x86_64/thread.zig @@ -1,7 +1,7 @@ const std = @import("std"); const interrupts = @import("interrupts.zig"); -pub inline fn enterTask(regs: *interrupts.InterruptStackFrame, comptime base: u64, directory: u64) noreturn { +pub inline fn enterTask(regs: *interrupts.InterruptStackFrame, base: u64, directory: u64) noreturn { asm volatile ( \\ addq %[base], %rsp \\ push %[ss] @@ -47,6 +47,13 @@ pub fn idleLoop() callconv(.Naked) noreturn { ); } +pub inline fn readStackPointer() usize { + return asm volatile ( + \\ mov %rsp, %[result] + : [result] "=r" (-> usize), + ); +} + pub fn setAddress(regs: *interrupts.InterruptStackFrame, address: u64) void { regs.rip = address; } diff --git a/core/src/thread.zig b/core/src/thread.zig index 6939363..29de783 100644 --- a/core/src/thread.zig +++ b/core/src/thread.zig @@ -44,7 +44,13 @@ pub fn enterTask(task: *ThreadControlBlock) noreturn { task.state = .Running; - arch.enterTask(&task.regs, vmm.PHYSICAL_MAPPING_BASE, table.address); + // If the stack is in user memory, then we need a pointer to its higher-half version. If it's already in kernel memory, no need to do anything. + var base: usize = 0; + if (arch.readStackPointer() < vmm.PHYSICAL_MAPPING_BASE) { + base += vmm.PHYSICAL_MAPPING_BASE; + } + + arch.enterTask(&task.regs, base, table.address); } fn switchTask(regs: *interrupts.InterruptStackFrame, new_task: *ThreadControlBlock) void {