From 7efc3a6ea1fb6ff1d1c1c25f2262dd5c1d910916 Mon Sep 17 00:00:00 2001 From: apio Date: Mon, 19 Jun 2023 10:45:08 +0200 Subject: [PATCH] kernel: Show stack traces on page faults + crash the process instead of the whole system on GPFs --- kernel/src/arch/x86_64/CPU.cpp | 39 ++++++++++++++++++++++++++++------ 1 file changed, 32 insertions(+), 7 deletions(-) diff --git a/kernel/src/arch/x86_64/CPU.cpp b/kernel/src/arch/x86_64/CPU.cpp index 1da8ee53..c7083ecd 100644 --- a/kernel/src/arch/x86_64/CPU.cpp +++ b/kernel/src/arch/x86_64/CPU.cpp @@ -80,6 +80,8 @@ void decode_page_fault_error_code(u64 code) decode_page_fault_error_code(regs->error); + CPU::print_stack_trace_at(regs); + if (!is_in_kernel(regs)) { // FIXME: Kill this process with SIGSEGV once we have signals and all that. @@ -105,8 +107,6 @@ void decode_page_fault_error_code(u64 code) unreachable(); } - CPU::print_stack_trace_at(regs); - CPU::efficient_halt(); } @@ -118,6 +118,31 @@ void decode_page_fault_error_code(u64 code) CPU::print_stack_trace_at(regs); + if (!is_in_kernel(regs)) + { + // FIXME: Kill this process with SIGSEGV once we have signals and all that. + kerrorln("Current task %zu was terminated because of a general protection fault", Scheduler::current()->id); + if (Scheduler::current()->is_kernel) Scheduler::current()->state = ThreadState::Dying; + else + { + auto* current = Scheduler::current(); + auto* parent = current->parent; + if (parent && parent->state == ThreadState::Waiting) + { + auto child = *parent->child_being_waited_for; + if (child == -1 || child == (pid_t)current->id) + { + parent->child_being_waited_for = (pid_t)current->id; + parent->wake_up(); + } + } + current->state = ThreadState::Exited; + } + Scheduler::current()->status = 127; + kernel_yield(); + unreachable(); + } + CPU::efficient_halt(); } @@ -302,14 +327,14 @@ namespace CPU asm volatile("hlt"); } - [[noreturn]] void efficient_halt() // Halt the CPU, using the lowest power possible. On x86-64 we do this using the - // "hlt" instruction, which puts the CPU into a low-power idle state until the - // next interrupt arrives... and we disable interrupts beforehand. + [[noreturn]] void efficient_halt() // Halt the CPU, using the lowest power possible. On x86-64 we do this using + // the "hlt" instruction, which puts the CPU into a low-power idle state + // until the next interrupt arrives... and we disable interrupts beforehand. { asm volatile("cli"); // Disable interrupts loop: - asm volatile("hlt"); // Let the cpu rest and pause until the next interrupt arrives... which in this case should - // be never (unless an NMI arrives) :) + asm volatile("hlt"); // Let the cpu rest and pause until the next interrupt arrives... which in this case + // should be never (unless an NMI arrives) :) goto loop; // Safeguard: if we ever wake up, start our low-power rest again }