From d08379a80b88b66365ff7779be6b8fa44c3b7874 Mon Sep 17 00:00:00 2001 From: Ingo Weinhold Date: Thu, 21 Jul 2005 23:47:08 +0000 Subject: [PATCH] * Now we deal with all x86 exceptions, i.e. we no longer panic() when a user application performs a division by zero or causes a general protection fault. For some exceptions (e.g. machine check) I wasn't quite sure whether they can be caused by user apps at all, so we panic() in those cases. Wouldn't harm, if someone more knowledgable would check this, though. * Removed the unused fault handling stuff, respectively moved the little that was used into x86/arch_int.c. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@13795 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- headers/private/kernel/arch/faults.h | 13 --- headers/private/kernel/arch/x86/faults.h | 14 --- src/system/kernel/Jamfile | 1 - src/system/kernel/arch/ppc/Jamfile | 1 - src/system/kernel/arch/ppc/arch_faults.c | 15 --- src/system/kernel/arch/x86/Jamfile | 1 - src/system/kernel/arch/x86/arch_faults.c | 39 ------- src/system/kernel/arch/x86/arch_int.c | 133 ++++++++++++++++++++--- src/system/kernel/faults.c | 74 ------------- src/system/kernel/main.c | 3 - 10 files changed, 117 insertions(+), 177 deletions(-) delete mode 100644 headers/private/kernel/arch/faults.h delete mode 100644 headers/private/kernel/arch/x86/faults.h delete mode 100644 src/system/kernel/arch/ppc/arch_faults.c delete mode 100644 src/system/kernel/arch/x86/arch_faults.c delete mode 100644 src/system/kernel/faults.c diff --git a/headers/private/kernel/arch/faults.h b/headers/private/kernel/arch/faults.h deleted file mode 100644 index 505b5abec5..0000000000 --- a/headers/private/kernel/arch/faults.h +++ /dev/null @@ -1,13 +0,0 @@ -/* -** Copyright 2001-2002, Travis Geiselbrecht. All rights reserved. -** Distributed under the terms of the NewOS License. -*/ -#ifndef KERNEL_ARCH_FAULTS_H -#define KERNEL_ARCH_FAULTS_H - -struct kernel_args; - -int faults_init(kernel_args *ka); -int arch_faults_init(kernel_args *ka); - -#endif /* KERNEL_ARCH_FAULTS_H */ diff --git a/headers/private/kernel/arch/x86/faults.h b/headers/private/kernel/arch/x86/faults.h deleted file mode 100644 index b0141c6817..0000000000 --- a/headers/private/kernel/arch/x86/faults.h +++ /dev/null @@ -1,14 +0,0 @@ -/* -** Copyright 2001-2002, Travis Geiselbrecht. All rights reserved. -** Distributed under the terms of the NewOS License. -*/ -#ifndef _NEWOS_KERNEL_ARCH_I386_FAULTS -#define _NEWOS_KERNEL_ARCH_I386_FAULTS - -struct iframe; - -int i386_general_protection_fault(int errorcode); -int i386_double_fault(struct iframe *frame); - -#endif - diff --git a/src/system/kernel/Jamfile b/src/system/kernel/Jamfile index 0d39c4c684..9ceb60cb3f 100644 --- a/src/system/kernel/Jamfile +++ b/src/system/kernel/Jamfile @@ -20,7 +20,6 @@ KernelMergeObject kernel_core.o : boot_item.cpp cpu.c elf.c - faults.c heap.c image.c int.c diff --git a/src/system/kernel/arch/ppc/Jamfile b/src/system/kernel/arch/ppc/Jamfile index 935c6349f0..65385c8bdb 100644 --- a/src/system/kernel/arch/ppc/Jamfile +++ b/src/system/kernel/arch/ppc/Jamfile @@ -8,7 +8,6 @@ KernelStaticLibrary libppc : arch_debug.c arch_elf.c arch_exceptions.S - arch_faults.c arch_int.c arch_mmu.cpp arch_real_time_clock.c diff --git a/src/system/kernel/arch/ppc/arch_faults.c b/src/system/kernel/arch/ppc/arch_faults.c deleted file mode 100644 index bea483a18f..0000000000 --- a/src/system/kernel/arch/ppc/arch_faults.c +++ /dev/null @@ -1,15 +0,0 @@ -/* -** Copyright 2001, Travis Geiselbrecht. All rights reserved. -** Distributed under the terms of the NewOS License. -*/ - - -#include - - -int -arch_faults_init(kernel_args *ka) -{ - return 0; -} - diff --git a/src/system/kernel/arch/x86/Jamfile b/src/system/kernel/arch/x86/Jamfile index a0b9816738..5ce4b0802a 100644 --- a/src/system/kernel/arch/x86/Jamfile +++ b/src/system/kernel/arch/x86/Jamfile @@ -8,7 +8,6 @@ KernelStaticLibrary libx86 : arch_debug.c arch_debug_console.c arch_elf.c - arch_faults.c arch_int.c # arch_selector.c arch_real_time_clock.c diff --git a/src/system/kernel/arch/x86/arch_faults.c b/src/system/kernel/arch/x86/arch_faults.c deleted file mode 100644 index 60e49f8cfa..0000000000 --- a/src/system/kernel/arch/x86/arch_faults.c +++ /dev/null @@ -1,39 +0,0 @@ -/* -** Copyright 2001, Travis Geiselbrecht. All rights reserved. -** Distributed under the terms of the NewOS License. -*/ - -#include -#include -#include -#include - -#include -#include - -// XXX this module is largely outdated. Will probably be removed later. - -int arch_faults_init(kernel_args *ka) -{ - return 0; -} - -int i386_general_protection_fault(int errorcode) -{ - return general_protection_fault(errorcode); -} - -int i386_double_fault(struct iframe *frame) -{ - struct tss *tss = x86_get_main_tss(); - - frame->cs = tss->cs; - frame->eip = tss->eip; - frame->esp = tss->esp; - frame->flags = tss->eflags; - - panic("double fault! errorcode = 0x%x\n", frame->error_code); - - return B_HANDLED_INTERRUPT; -} - diff --git a/src/system/kernel/arch/x86/arch_int.c b/src/system/kernel/arch/x86/arch_int.c index 8e03767c99..7d55505fcc 100644 --- a/src/system/kernel/arch/x86/arch_int.c +++ b/src/system/kernel/arch/x86/arch_int.c @@ -8,24 +8,24 @@ #include #include -#include -#include -#include #include +#include +#include +#include +#include #include #include -#include -#include #include #include +#include -#include #include #include "interrupts.h" #include +#include //#define TRACE_ARCH_INT @@ -67,7 +67,7 @@ #define PIC_SLAVE_INT_BASE 0x28 #define PIC_NUM_INTS 0x0f -const char *kInterruptNames[] = { +static const char *kInterruptNames[] = { /* 0 */ "Divide Error Exception", /* 1 */ "Debug Exception", /* 2 */ "NMI Interrupt", @@ -89,6 +89,7 @@ const char *kInterruptNames[] = { /* 18 */ "Machine-Check Exception", /* 19 */ "SIMD Floating-Point Exception", }; +static const int kInterruptNameCount = 20; #define MAX_ARGS 16 @@ -284,6 +285,45 @@ arch_int_are_interrupts_enabled(void) } +static const char * +exception_name(int number, char *buffer, int32 bufferSize) +{ + if (number >= 0 && number < kInterruptNameCount) + return kInterruptNames[number]; + + snprintf(buffer, bufferSize, "exception %d", number); + return buffer; +} + + +static void +fatal_exception(struct iframe *frame) +{ + char name[32]; + panic("Fatal exception \"%s\" occurred! Error code: 0x%x\n", + exception_name(frame->vector, name, sizeof(name)), frame->error_code); +} + + +static void +unexpected_exception(struct iframe *frame, debug_exception_type type, + int signal) +{ + if (frame->cs == USER_CODE_SEG) { + enable_interrupts(); + + if (user_debug_exception_occurred(type, signal)) + send_signal(team_get_current_team_id(), signal); + } else { + char name[32]; + panic("Unexpected exception \"%s\" occurred in kernel mode! " + "Error code: 0x%x\n", + exception_name(frame->vector, name, sizeof(name)), + frame->error_code); + } +} + + /* keep the compiler happy, this function must be called only from assembly */ void i386_handle_trap(struct iframe frame); @@ -307,19 +347,65 @@ i386_handle_trap(struct iframe frame) // dprintf("i386_handle_trap: vector 0x%x, ip 0x%x, cpu %d\n", frame.vector, frame.eip, smp_get_current_cpu()); switch (frame.vector) { - case 1: + + // fatal exceptions + + case 2: // NMI Interrupt + case 7: // Device Not Available Exception (#NM) + case 9: // Coprocessor Segment Overrun + case 10: // Invalid TSS Exception (#TS) + case 11: // Segment Not Present (#NP) + case 12: // Stack Fault Exception (#SS) + case 18: // Machine-Check Exception (#MC) + fatal_exception(&frame); + break; + + case 8: // Double Fault Exception (#DF) + { + struct tss *tss = x86_get_main_tss(); + + frame.cs = tss->cs; + frame.eip = tss->eip; + frame.esp = tss->esp; + frame.flags = tss->eflags; + + panic("double fault! errorcode = 0x%x\n", frame.error_code); + + break; + } + + // exceptions we can handle + // (most of them only when occurring in userland) + + case 0: // Divide Error Exception (#DE) + unexpected_exception(&frame, B_DIVIDE_ERROR, SIGFPE); + break; + + case 1: // Debug Exception (#DB) ret = i386_handle_debug_exception(&frame); break; - case 3: + + case 3: // Breakpoint Exception (#BP) ret = i386_handle_breakpoint_exception(&frame); break; - case 8: // double fault - ret = i386_double_fault(&frame); + + case 4: // Overflow Exception (#OF) + unexpected_exception(&frame, B_OVERFLOW_EXCEPTION, SIGTRAP); break; - case 13: // general protection fault - ret = i386_general_protection_fault(frame.error_code); + + case 5: // BOUND Range Exceeded Exception (#BR) + unexpected_exception(&frame, B_BOUNDS_CHECK_EXCEPTION, SIGTRAP); break; - case 14: // page fault + + case 6: // Invalid Opcode Exception (#UD) + unexpected_exception(&frame, B_INVALID_OPCODE_EXCEPTION, SIGILL); + break; + + case 13: // General Protection Exception (#GP) + unexpected_exception(&frame, B_GENERAL_PROTECTION_FAULT, SIGKILL); + break; + + case 14: // Page-Fault Exception (#PF) { unsigned int cr2; addr_t newip; @@ -347,6 +433,18 @@ i386_handle_trap(struct iframe frame) break; } + case 16: // x87 FPU Floating-Point Error (#MF) + unexpected_exception(&frame, B_FLOATING_POINT_EXCEPTION, SIGFPE); + break; + + case 17: // Alignment Check Exception (#AC) + unexpected_exception(&frame, B_ALIGNMENT_EXCEPTION, SIGTRAP); + break; + + case 19: // SIMD Floating-Point Exception (#XF) + unexpected_exception(&frame, B_FLOATING_POINT_EXCEPTION, SIGFPE); + break; + case 99: // syscall { uint64 retcode; @@ -393,8 +491,11 @@ i386_handle_trap(struct iframe frame) ret = int_io_interrupt_handler(frame.vector - ARCH_INTERRUPT_BASE); } else { - panic("i386_handle_trap: unhandled trap 0x%x (%s) at ip 0x%x, thread 0x%x!\n", - frame.vector, kInterruptNames[frame.vector], frame.eip, thread ? thread->id : -1); + char name[32]; + panic("i386_handle_trap: unhandled trap 0x%x (%s) at ip 0x%x, " + "thread 0x%x!\n", frame.vector, + exception_name(frame.vector, name, sizeof(name)), frame.eip, + thread ? thread->id : -1); ret = B_HANDLED_INTERRUPT; } break; diff --git a/src/system/kernel/faults.c b/src/system/kernel/faults.c deleted file mode 100644 index 77669112fd..0000000000 --- a/src/system/kernel/faults.c +++ /dev/null @@ -1,74 +0,0 @@ -/* Contains the basic code for fault handling. */ - -/* -** Copyright 2001, Travis Geiselbrecht. All rights reserved. -** Distributed under the terms of the NewOS License. -*/ - - -#include -#include -#include -#include -#include -#include -#include -#include -#include - - -int -faults_init(kernel_args *ka) -{ - dprintf("init_fault_handlers: entry\n"); - return arch_faults_init(ka); -} - - -int -general_protection_fault(int errorcode) -{ - panic("GENERAL PROTECTION FAULT: errcode 0x%x. Killing system.\n", errorcode); - - return B_HANDLED_INTERRUPT; -} - - -static const char * -fpu_fault_to_str(enum fpu_faults fpu_fault) -{ - switch (fpu_fault) { - default: - case FPU_FAULT_CODE_UNKNOWN: - return "unknown"; - case FPU_FAULT_CODE_DIVBYZERO: - return "divbyzero"; - case FPU_FAULT_CODE_INVALID_OP: - return "invalid op"; - case FPU_FAULT_CODE_OVERFLOW: - return "overflow"; - case FPU_FAULT_CODE_UNDERFLOW: - return "underflow"; - case FPU_FAULT_CODE_INEXACT: - return "inexact"; - } -} - - -int -fpu_fault(int fpu_fault) -{ - panic("FPU FAULT: errcode 0x%x (%s), Killing system.\n", fpu_fault, fpu_fault_to_str(fpu_fault)); - - return B_HANDLED_INTERRUPT; -} - - -int -fpu_disable_fault(void) -{ - panic("FPU DISABLE FAULT: Killing system.\n"); - - return B_HANDLED_INTERRUPT; -} - diff --git a/src/system/kernel/main.c b/src/system/kernel/main.c index df7256b876..ca73adb57a 100644 --- a/src/system/kernel/main.c +++ b/src/system/kernel/main.c @@ -13,7 +13,6 @@ #include #include -#include #include #include #include @@ -109,8 +108,6 @@ _start(kernel_args *oldka, int cpu_num) TRACE(("init system info\n")); system_info_init(&ka); - TRACE(("init faults\n")); - faults_init(&ka); TRACE(("init SMP\n")); smp_init(&ka); TRACE(("init timer\n"));