diff --git a/kernel/x64/thread.cpp b/kernel/x64/thread.cpp index abad6676..7e1037c8 100644 --- a/kernel/x64/thread.cpp +++ b/kernel/x64/thread.cpp @@ -22,134 +22,138 @@ *******************************************************************************/ +#include +#include + #include #include -namespace Sortix +namespace Sortix { + +void Thread::SaveRegisters(const CPU::InterruptRegisters* src) { - void Thread::SaveRegisters(const CPU::InterruptRegisters* src) - { - registers.rip = src->rip; - registers.userrsp = src->userrsp; - registers.rax = src->rax; - registers.rbx = src->rbx; - registers.rcx = src->rcx; - registers.rdx = src->rdx; - registers.rdi = src->rdi; - registers.rsi = src->rsi; - registers.rbp = src->rbp; - registers.r8 = src->r8; - registers.r9 = src->r9; - registers.r10 = src->r10; - registers.r11 = src->r11; - registers.r12 = src->r12; - registers.r13 = src->r13; - registers.r14 = src->r14; - registers.r15 = src->r15; - registers.cs = src->cs; - registers.ds = src->ds; - registers.ss = src->ss; - registers.rflags = src->rflags; - registers.kerrno = src->kerrno; - registers.signal_pending = src->signal_pending; - } - - void Thread::LoadRegisters(CPU::InterruptRegisters* dest) - { - dest->rip = registers.rip; - dest->userrsp = registers.userrsp; - dest->rax = registers.rax; - dest->rbx = registers.rbx; - dest->rcx = registers.rcx; - dest->rdx = registers.rdx; - dest->rdi = registers.rdi; - dest->rsi = registers.rsi; - dest->rbp = registers.rbp; - dest->r8 = registers.r8; - dest->r9 = registers.r9; - dest->r10 = registers.r10; - dest->r11 = registers.r11; - dest->r12 = registers.r12; - dest->r13 = registers.r13; - dest->r14 = registers.r14; - dest->r15 = registers.r15; - dest->cs = registers.cs; - dest->ds = registers.ds; - dest->ss = registers.ss; - dest->rflags = registers.rflags; - dest->kerrno = registers.kerrno; - dest->signal_pending = registers.signal_pending; - } - - void SetupKernelThreadRegs(CPU::InterruptRegisters* regs, ThreadEntry entry, - void* user, addr_t stack, size_t stacksize) - { - // Instead of directly calling the desired entry point, we call a small - // stub that calls it for us and then destroys the kernel thread if - // the entry function returns. Note that since we use a register based - // calling convention, we call BootstrapKernelThread directly. - regs->rip = (addr_t) BootstrapKernelThread; - regs->userrsp = stack + stacksize - sizeof(size_t); - *((size_t*) regs->userrsp) = 0; /* back tracing stops at NULL rip */ - regs->rax = 0; - regs->rbx = 0; - regs->rcx = 0; - regs->rdx = 0; - regs->rdi = (addr_t) user; - regs->rsi = (addr_t) entry; - regs->rbp = 0; - regs->r8 = 0; - regs->r9 = 0; - regs->r10 = 0; - regs->r11 = 0; - regs->r12 = 0; - regs->r13 = 0; - regs->r14 = 0; - regs->r15 = 0; - regs->cs = KCS | KRPL; - regs->ds = KDS | KRPL; - regs->ss = KDS | KRPL; - regs->rflags = FLAGS_RESERVED1 | FLAGS_INTERRUPT | FLAGS_ID; - regs->kerrno = 0; - regs->signal_pending = 0; - } - - void Thread::HandleSignalFixupRegsCPU(CPU::InterruptRegisters* regs) - { - if ( regs->InUserspace() ) - return; - regs->rip = regs->rdi; - regs->rflags = regs->rsi; - regs->userrsp = regs->r8; - regs->cs = UCS | URPL; - regs->ds = UDS | URPL; - regs->ss = UDS | URPL; - } - - void Thread::HandleSignalCPU(CPU::InterruptRegisters* regs) - { - const size_t STACK_ALIGNMENT = 16UL; - const size_t RED_ZONE_SIZE = 128UL; - regs->userrsp -= RED_ZONE_SIZE; - regs->userrsp &= ~(STACK_ALIGNMENT-1UL); - regs->rbp = regs->userrsp; - regs->rdi = currentsignal; - regs->rip = (size_t) sighandler; - regs->rflags = FLAGS_RESERVED1 | FLAGS_INTERRUPT | FLAGS_ID; - regs->kerrno = 0; - regs->signal_pending = 0; - } - - void Thread::GotoOnSigKill(CPU::InterruptRegisters* regs) - { - regs->rip = (unsigned long) Thread__OnSigKill; - regs->rdi = (unsigned long) this; - regs->userrsp = regs->rbp = kernelstackpos + kernelstacksize; - regs->rflags = FLAGS_RESERVED1 | FLAGS_INTERRUPT | FLAGS_ID; - regs->cs = KCS | KRPL; - regs->ds = KDS | KRPL; - regs->ss = KDS | KRPL; - regs->kerrno = 0; - regs->signal_pending = 0; - } + registers.rip = src->rip; + registers.userrsp = src->userrsp; + registers.rax = src->rax; + registers.rbx = src->rbx; + registers.rcx = src->rcx; + registers.rdx = src->rdx; + registers.rdi = src->rdi; + registers.rsi = src->rsi; + registers.rbp = src->rbp; + registers.r8 = src->r8; + registers.r9 = src->r9; + registers.r10 = src->r10; + registers.r11 = src->r11; + registers.r12 = src->r12; + registers.r13 = src->r13; + registers.r14 = src->r14; + registers.r15 = src->r15; + registers.cs = src->cs; + registers.ds = src->ds; + registers.ss = src->ss; + registers.rflags = src->rflags; + registers.kerrno = src->kerrno; + registers.signal_pending = src->signal_pending; } + +void Thread::LoadRegisters(CPU::InterruptRegisters* dest) +{ + dest->rip = registers.rip; + dest->userrsp = registers.userrsp; + dest->rax = registers.rax; + dest->rbx = registers.rbx; + dest->rcx = registers.rcx; + dest->rdx = registers.rdx; + dest->rdi = registers.rdi; + dest->rsi = registers.rsi; + dest->rbp = registers.rbp; + dest->r8 = registers.r8; + dest->r9 = registers.r9; + dest->r10 = registers.r10; + dest->r11 = registers.r11; + dest->r12 = registers.r12; + dest->r13 = registers.r13; + dest->r14 = registers.r14; + dest->r15 = registers.r15; + dest->cs = registers.cs; + dest->ds = registers.ds; + dest->ss = registers.ss; + dest->rflags = registers.rflags; + dest->kerrno = registers.kerrno; + dest->signal_pending = registers.signal_pending; +} + +void SetupKernelThreadRegs(CPU::InterruptRegisters* regs, ThreadEntry entry, + void* user, addr_t stack, size_t stacksize) +{ + // Instead of directly calling the desired entry point, we call a small + // stub that calls it for us and then destroys the kernel thread if + // the entry function returns. Note that since we use a register based + // calling convention, we call BootstrapKernelThread directly. + regs->rip = (addr_t) BootstrapKernelThread; + regs->userrsp = stack + stacksize - sizeof(size_t); + *((size_t*) regs->userrsp) = 0; /* back tracing stops at NULL rip */ + regs->rax = 0; + regs->rbx = 0; + regs->rcx = 0; + regs->rdx = 0; + regs->rdi = (addr_t) user; + regs->rsi = (addr_t) entry; + regs->rbp = 0; + regs->r8 = 0; + regs->r9 = 0; + regs->r10 = 0; + regs->r11 = 0; + regs->r12 = 0; + regs->r13 = 0; + regs->r14 = 0; + regs->r15 = 0; + regs->cs = KCS | KRPL; + regs->ds = KDS | KRPL; + regs->ss = KDS | KRPL; + regs->rflags = FLAGS_RESERVED1 | FLAGS_INTERRUPT | FLAGS_ID; + regs->kerrno = 0; + regs->signal_pending = 0; +} + +void Thread::HandleSignalFixupRegsCPU(CPU::InterruptRegisters* regs) +{ + if ( regs->InUserspace() ) + return; + regs->rip = regs->rdi; + regs->rflags = regs->rsi; + regs->userrsp = regs->r8; + regs->cs = UCS | URPL; + regs->ds = UDS | URPL; + regs->ss = UDS | URPL; +} + +void Thread::HandleSignalCPU(CPU::InterruptRegisters* regs) +{ + const size_t STACK_ALIGNMENT = 16UL; + const size_t RED_ZONE_SIZE = 128UL; + regs->userrsp -= RED_ZONE_SIZE; + regs->userrsp &= ~(STACK_ALIGNMENT-1UL); + regs->rbp = regs->userrsp; + regs->rdi = currentsignal; + regs->rip = (size_t) sighandler; + regs->rflags = FLAGS_RESERVED1 | FLAGS_INTERRUPT | FLAGS_ID; + regs->kerrno = 0; + regs->signal_pending = 0; +} + +void Thread::GotoOnSigKill(CPU::InterruptRegisters* regs) +{ + regs->rip = (unsigned long) Thread__OnSigKill; + regs->rdi = (unsigned long) this; + regs->userrsp = regs->rbp = kernelstackpos + kernelstacksize; + regs->rflags = FLAGS_RESERVED1 | FLAGS_INTERRUPT | FLAGS_ID; + regs->cs = KCS | KRPL; + regs->ds = KDS | KRPL; + regs->ss = KDS | KRPL; + regs->kerrno = 0; + regs->signal_pending = 0; +} + +} // namespace Sortix diff --git a/kernel/x86/thread.cpp b/kernel/x86/thread.cpp index 55a25fe8..4f79f142 100644 --- a/kernel/x86/thread.cpp +++ b/kernel/x86/thread.cpp @@ -22,120 +22,124 @@ *******************************************************************************/ +#include +#include + #include #include -namespace Sortix +namespace Sortix { + +void Thread::SaveRegisters(const CPU::InterruptRegisters* src) { - void Thread::SaveRegisters(const CPU::InterruptRegisters* src) - { - registers.eip = src->eip; - registers.useresp = src->useresp; - registers.eax = src->eax; - registers.ebx = src->ebx; - registers.ecx = src->ecx; - registers.edx = src->edx; - registers.edi = src->edi; - registers.esi = src->esi; - registers.ebp = src->ebp; - registers.cs = src->cs; - registers.ds = src->ds; - registers.ss = src->ss; - registers.eflags = src->eflags; - registers.kerrno = src->kerrno; - registers.signal_pending = src->signal_pending; - } - - void Thread::LoadRegisters(CPU::InterruptRegisters* dest) - { - dest->eip = registers.eip; - dest->useresp = registers.useresp; - dest->eax = registers.eax; - dest->ebx = registers.ebx; - dest->ecx = registers.ecx; - dest->edx = registers.edx; - dest->edi = registers.edi; - dest->esi = registers.esi; - dest->ebp = registers.ebp; - dest->cs = registers.cs; - dest->ds = registers.ds; - dest->ss = registers.ss; - dest->eflags = registers.eflags; - dest->kerrno = registers.kerrno; - dest->signal_pending = registers.signal_pending; - } - - extern "C" void asm_call_BootstrapKernelThread(void); - - void SetupKernelThreadRegs(CPU::InterruptRegisters* regs, ThreadEntry entry, - void* user, addr_t stack, size_t stacksize) - { - // Instead of directly calling the desired entry point, we call a small - // stub that calls it for us and then destroys the kernel thread if - // the entry function returns. Note that since we use a stack based - // calling convention, we go through a proxy that uses %edi and %esi - // as parameters and pushes them to the stack and then does the call. - regs->eip = (addr_t) asm_call_BootstrapKernelThread; - regs->useresp = stack + stacksize - sizeof(size_t); - *((size_t*) regs->useresp) = 0; /* back tracing stops at NULL rip */ - regs->eax = 0; - regs->ebx = 0; - regs->ecx = 0; - regs->edx = 0; - regs->edi = (addr_t) user; - regs->esi = (addr_t) entry; - regs->ebp = 0; - regs->cs = KCS | KRPL; - regs->ds = KDS | KRPL; - regs->ss = KDS | KRPL; - regs->eflags = FLAGS_RESERVED1 | FLAGS_INTERRUPT | FLAGS_ID; - regs->kerrno = 0; - regs->signal_pending = 0; - } - - void Thread::HandleSignalFixupRegsCPU(CPU::InterruptRegisters* regs) - { - if ( regs->InUserspace() ) - return; - uint32_t* params = (uint32_t*) regs->ebx; - regs->eip = params[0]; - regs->eflags = params[2]; - regs->useresp = params[3]; - regs->cs = UCS | URPL; - regs->ds = UDS | URPL; - regs->ss = UDS | URPL; - } - - void Thread::HandleSignalCPU(CPU::InterruptRegisters* regs) - { - const size_t STACK_ALIGNMENT = 16UL; - const size_t RED_ZONE_SIZE = 128UL; - regs->useresp -= RED_ZONE_SIZE; - regs->useresp &= ~(STACK_ALIGNMENT-1UL); - regs->ebp = regs->useresp; - regs->edi = currentsignal; - regs->eip = (size_t) sighandler; - regs->eflags = FLAGS_RESERVED1 | FLAGS_INTERRUPT | FLAGS_ID; - regs->kerrno = 0; - regs->signal_pending = 0; - } - - extern "C" void asm_call_Thread__OnSigKill(void); - - void Thread::GotoOnSigKill(CPU::InterruptRegisters* regs) - { - regs->eip = (unsigned long) asm_call_Thread__OnSigKill; - regs->edi = (unsigned long) this; - // TODO: HACK: The -256 is because if we are jumping to the safe stack - // we currently are on, this may not be fully supported by interrupt.s - // that is quite aware of this (but isn't perfect). If our destination - // is further down the stack, then we are probably safe. - regs->useresp = regs->ebp = kernelstackpos + kernelstacksize - 256; - regs->eflags = FLAGS_RESERVED1 | FLAGS_INTERRUPT | FLAGS_ID; - regs->cs = KCS | KRPL; - regs->ds = KDS | KRPL; - regs->ss = KDS | KRPL; - regs->kerrno = 0; - regs->signal_pending = 0; - } + registers.eip = src->eip; + registers.useresp = src->useresp; + registers.eax = src->eax; + registers.ebx = src->ebx; + registers.ecx = src->ecx; + registers.edx = src->edx; + registers.edi = src->edi; + registers.esi = src->esi; + registers.ebp = src->ebp; + registers.cs = src->cs; + registers.ds = src->ds; + registers.ss = src->ss; + registers.eflags = src->eflags; + registers.kerrno = src->kerrno; + registers.signal_pending = src->signal_pending; } + +void Thread::LoadRegisters(CPU::InterruptRegisters* dest) +{ + dest->eip = registers.eip; + dest->useresp = registers.useresp; + dest->eax = registers.eax; + dest->ebx = registers.ebx; + dest->ecx = registers.ecx; + dest->edx = registers.edx; + dest->edi = registers.edi; + dest->esi = registers.esi; + dest->ebp = registers.ebp; + dest->cs = registers.cs; + dest->ds = registers.ds; + dest->ss = registers.ss; + dest->eflags = registers.eflags; + dest->kerrno = registers.kerrno; + dest->signal_pending = registers.signal_pending; +} + +extern "C" void asm_call_BootstrapKernelThread(void); + +void SetupKernelThreadRegs(CPU::InterruptRegisters* regs, ThreadEntry entry, + void* user, addr_t stack, size_t stacksize) +{ + // Instead of directly calling the desired entry point, we call a small + // stub that calls it for us and then destroys the kernel thread if + // the entry function returns. Note that since we use a stack based + // calling convention, we go through a proxy that uses %edi and %esi + // as parameters and pushes them to the stack and then does the call. + regs->eip = (addr_t) asm_call_BootstrapKernelThread; + regs->useresp = stack + stacksize - sizeof(size_t); + *((size_t*) regs->useresp) = 0; /* back tracing stops at NULL rip */ + regs->eax = 0; + regs->ebx = 0; + regs->ecx = 0; + regs->edx = 0; + regs->edi = (addr_t) user; + regs->esi = (addr_t) entry; + regs->ebp = 0; + regs->cs = KCS | KRPL; + regs->ds = KDS | KRPL; + regs->ss = KDS | KRPL; + regs->eflags = FLAGS_RESERVED1 | FLAGS_INTERRUPT | FLAGS_ID; + regs->kerrno = 0; + regs->signal_pending = 0; +} + +void Thread::HandleSignalFixupRegsCPU(CPU::InterruptRegisters* regs) +{ + if ( regs->InUserspace() ) + return; + uint32_t* params = (uint32_t*) regs->ebx; + regs->eip = params[0]; + regs->eflags = params[2]; + regs->useresp = params[3]; + regs->cs = UCS | URPL; + regs->ds = UDS | URPL; + regs->ss = UDS | URPL; +} + +void Thread::HandleSignalCPU(CPU::InterruptRegisters* regs) +{ + const size_t STACK_ALIGNMENT = 16UL; + const size_t RED_ZONE_SIZE = 128UL; + regs->useresp -= RED_ZONE_SIZE; + regs->useresp &= ~(STACK_ALIGNMENT-1UL); + regs->ebp = regs->useresp; + regs->edi = currentsignal; + regs->eip = (size_t) sighandler; + regs->eflags = FLAGS_RESERVED1 | FLAGS_INTERRUPT | FLAGS_ID; + regs->kerrno = 0; + regs->signal_pending = 0; +} + +extern "C" void asm_call_Thread__OnSigKill(void); + +void Thread::GotoOnSigKill(CPU::InterruptRegisters* regs) +{ + regs->eip = (unsigned long) asm_call_Thread__OnSigKill; + regs->edi = (unsigned long) this; + // TODO: HACK: The -256 is because if we are jumping to the safe stack + // we currently are on, this may not be fully supported by interrupt.s + // that is quite aware of this (but isn't perfect). If our destination + // is further down the stack, then we are probably safe. + regs->useresp = regs->ebp = kernelstackpos + kernelstacksize - 256; + regs->eflags = FLAGS_RESERVED1 | FLAGS_INTERRUPT | FLAGS_ID; + regs->cs = KCS | KRPL; + regs->ds = KDS | KRPL; + regs->ss = KDS | KRPL; + regs->kerrno = 0; + regs->signal_pending = 0; +} + +} // namespace Sortix