From 9afa80b45d36471c02df455ba87dd4df277c768f Mon Sep 17 00:00:00 2001 From: fwsGonzo Date: Mon, 11 Sep 2017 03:18:46 -0700 Subject: [PATCH] kernel: Add custom double fault handler to avoid triple fault --- src/arch/x86_64/arch_start.asm | 2 +- src/arch/x86_64/ist.cpp | 4 ++-- src/kernel/syscalls.cpp | 39 +++++++++++++++++++++++++--------- src/platform/x86_pc/idt.cpp | 15 +++++++++++-- 4 files changed, 45 insertions(+), 15 deletions(-) diff --git a/src/arch/x86_64/arch_start.asm b/src/arch/x86_64/arch_start.asm index 055b96087e..cec61dfd91 100644 --- a/src/arch/x86_64/arch_start.asm +++ b/src/arch/x86_64/arch_start.asm @@ -24,7 +24,7 @@ extern __multiboot_addr %define P4_TAB 0x1000 %define P3_TAB 0x2000 ;; - 0x5fff %define P2_TAB 0x100000 -%define STACK_LOCATION 0x9fff00 +%define STACK_LOCATION 0x9ffff0 [BITS 32] __arch_start: diff --git a/src/arch/x86_64/ist.cpp b/src/arch/x86_64/ist.cpp index 4d03924bff..a5d5e7f690 100644 --- a/src/arch/x86_64/ist.cpp +++ b/src/arch/x86_64/ist.cpp @@ -11,7 +11,7 @@ extern gdtr64 __gdt64_base_pointer; #define INTR_SIZE 4096 #define NMI_SIZE 20480 -#define DFI_SIZE 20480 +#define DFI_SIZE 4096 namespace x86 { @@ -19,7 +19,7 @@ namespace x86 { char* intr; // 4kb char* nmi; // 20kb - char* dfi; // 20kb + char* dfi; // 4kb AMD64_TSS tss; }; diff --git a/src/kernel/syscalls.cpp b/src/kernel/syscalls.cpp index 4fb8f57aab..a37e987f99 100644 --- a/src/kernel/syscalls.cpp +++ b/src/kernel/syscalls.cpp @@ -151,6 +151,9 @@ void OS::on_panic(on_panic_func func) panic_handler = std::move(func); } +extern "C" __attribute__((noreturn)) void panic_epilogue(const char*); + + /** * panic: * Display reason for kernel panic @@ -193,21 +196,37 @@ asm("panic_begin:"); fflush(stderr); SMP::global_unlock(); - // call custom on panic handler (if present) - if (panic_handler) panic_handler(why); + panic_epilogue(why); +} -#if defined(ARCH_x86) +extern "C" +void double_fault(const char* why) +{ SMP::global_lock(); - // Signal End-Of-Transmission - kprint("\x04"); + fprintf(stderr, "\n%s\nCPU: %d, Reason: %s\n", + panic_signature, SMP::cpu_id(), why); SMP::global_unlock(); - // .. if we return from the panic handler, go to permanent sleep - while (1) asm("cli; hlt"); + panic_epilogue(why); +} + +void panic_epilogue(const char* why) +{ + // call custom on panic handler (if present) + if (panic_handler) panic_handler(why); + + #if defined(ARCH_x86) + SMP::global_lock(); + // Signal End-Of-Transmission + kprint("\x04"); + SMP::global_unlock(); + + // .. if we return from the panic handler, go to permanent sleep + while (1) asm("cli; hlt"); + #else + #warning "panic() handler not implemented for selected arch" + #endif __builtin_unreachable(); -#else - #warning "panic() handler not implemented for selected arch" -#endif } // Shutdown the machine when one of the exit functions are called diff --git a/src/platform/x86_pc/idt.cpp b/src/platform/x86_pc/idt.cpp index 61f617d69c..c7468105b2 100644 --- a/src/platform/x86_pc/idt.cpp +++ b/src/platform/x86_pc/idt.cpp @@ -259,6 +259,8 @@ static void cpu_dump_regs(uintptr_t* regs) fprintf(stderr, "\n"); } +extern "C" void double_fault(const char*); + extern "C" __attribute__((noreturn, optnone)) void __cpu_exception(uintptr_t* regs, int error, uint32_t code) @@ -270,8 +272,17 @@ void __cpu_exception(uintptr_t* regs, int error, uint32_t code) exception_names[error], error, (void*) regs[RIP_REG], code); cpu_dump_regs(regs); SMP::global_unlock(); - // call panic, which will decide what to do next + // error message: char buffer[64]; snprintf(buffer, sizeof(buffer), "%s (%d)", exception_names[error], error); - panic(buffer); + // normal CPU exception + if (error != 0x8) { + // call panic, which will decide what to do next + panic(buffer); + } + else { + // handle double faults differently + double_fault(buffer); + } + __builtin_unreachable(); }