diff --git a/zion/CMakeLists.txt b/zion/CMakeLists.txt index d1c5446..575e5c5 100644 --- a/zion/CMakeLists.txt +++ b/zion/CMakeLists.txt @@ -6,6 +6,7 @@ add_executable(zion common/gdt.cpp common/load_gdt.s common/msr.cpp + common/stack_unwind.cpp debug/debug.cpp interrupt/apic.cpp interrupt/apic_timer.cpp diff --git a/zion/common/stack_unwind.cpp b/zion/common/stack_unwind.cpp new file mode 100644 index 0000000..4bdbc10 --- /dev/null +++ b/zion/common/stack_unwind.cpp @@ -0,0 +1,20 @@ +#include "common/stack_unwind.h" + +#include "debug/debug.h" + +namespace { + +bool IsValid(uint64_t* rbp) { return rbp && *rbp != kStackBaseSentinel; } + +} // namespace + +void StackUnwind(uint64_t rbp) { + dbgln("-- Begin Stack --"); + uint64_t* rbp_ptr = reinterpret_cast(rbp); + while (IsValid(rbp_ptr)) { + uint64_t rip = *(rbp_ptr + 1); + dbgln("RIP: {x}", rip); + rbp_ptr = reinterpret_cast(*rbp_ptr); + } + dbgln("-- End Stack --"); +} diff --git a/zion/common/stack_unwind.h b/zion/common/stack_unwind.h new file mode 100644 index 0000000..cb3d33c --- /dev/null +++ b/zion/common/stack_unwind.h @@ -0,0 +1,7 @@ +#pragma once + +#include + +const uint64_t kStackBaseSentinel = 0xABBACDCD'12345678; + +void StackUnwind(uint64_t rbp); diff --git a/zion/interrupt/interrupt.cpp b/zion/interrupt/interrupt.cpp index 2f0ade4..adaa37b 100644 --- a/zion/interrupt/interrupt.cpp +++ b/zion/interrupt/interrupt.cpp @@ -3,6 +3,7 @@ #include #include "common/port.h" +#include "common/stack_unwind.h" #include "debug/debug.h" #include "interrupt/apic.h" #include "interrupt/apic_timer.h" @@ -69,15 +70,29 @@ struct InterruptFrame { uint64_t ss; }; +bool IsUserSpace(uint64_t addr) { return (addr & (1l << 63)) == 0; } + extern "C" void isr_divide_by_zero(); extern "C" void interrupt_divide_by_zero(InterruptFrame* frame) { dbgln("RIP: {x}", frame->rip); + StackUnwind(frame->rbp); + + if (IsUserSpace(frame->rip)) { + gScheduler->CurrentProcess().Exit(); + UNREACHABLE + } panic("DIV0"); } extern "C" void isr_invalid_opcode(); extern "C" void interrupt_invalid_opcode(InterruptFrame* frame) { dbgln("RIP: {x}", frame->rip); + StackUnwind(frame->rbp); + + if (IsUserSpace(frame->rip)) { + gScheduler->CurrentProcess().Exit(); + UNREACHABLE + } panic("INVALID OPCODE"); } @@ -96,7 +111,12 @@ extern "C" void interrupt_protection_fault(InterruptFrame* frame) { dbgln("Index: {}", err >> 3); dbgln("RIP: {x}", frame->rip); dbgln("RSP: {x}", frame->rsp); + StackUnwind(frame->rbp); + if (IsUserSpace(frame->rip)) { + gScheduler->CurrentProcess().Exit(); + UNREACHABLE + } panic("GP"); } @@ -133,11 +153,23 @@ extern "C" void interrupt_page_fault(InterruptFrame* frame) { dbgln("rip: {x}", frame->rip); dbgln("addr: {x}", frame->cr2); + StackUnwind(frame->rbp); + + if (IsUserSpace(frame->rip)) { + gScheduler->CurrentProcess().Exit(); + UNREACHABLE + } + panic("PF"); } extern "C" void isr_fpe_fault(); extern "C" void interrupt_fpe_fault(InterruptFrame* frame) { + dbgln("Floating point exception."); + if (IsUserSpace(frame->rip)) { + gScheduler->CurrentProcess().Exit(); + UNREACHABLE + } panic("Floating point exception"); } diff --git a/zion/object/thread.cpp b/zion/object/thread.cpp index f524d55..e3440e6 100644 --- a/zion/object/thread.cpp +++ b/zion/object/thread.cpp @@ -1,6 +1,7 @@ #include "object/thread.h" #include "common/gdt.h" +#include "common/stack_unwind.h" #include "debug/debug.h" #include "memory/kernel_vmm.h" #include "memory/paging_util.h" @@ -71,6 +72,7 @@ void Thread::Init() { // will emit movaps calls to non-16-bit-aligned stack // addresses. rsp -= 0x8; + *reinterpret_cast(rsp) = kStackBaseSentinel; SetRsp0(rsp0_start_); jump_user_space(rip_, rsp, arg1_, arg2_); } diff --git a/zion/scheduler/jump_user_space.s b/zion/scheduler/jump_user_space.s index b2b22a7..7fe2cba 100644 --- a/zion/scheduler/jump_user_space.s +++ b/zion/scheduler/jump_user_space.s @@ -8,6 +8,7 @@ jump_user_space: mov %ax, %fs mov %ax, %gs + mov %rsi, %rbp pushq $0x23 # ss pushq %rsi pushq $0x202 # Bit 9 enables interrupts.