diff --git a/headers/private/kernel/arch/x86/arch_cpu.h b/headers/private/kernel/arch/x86/arch_cpu.h index a9100c77c5..836b27f7b1 100644 --- a/headers/private/kernel/arch/x86/arch_cpu.h +++ b/headers/private/kernel/arch/x86/arch_cpu.h @@ -407,7 +407,11 @@ bool x86_check_feature(uint32 feature, enum x86_feature_type type); void* x86_get_double_fault_stack(int32 cpu, size_t* _size); int32 x86_double_fault_get_cpu(void); -void x86_page_fault_exception(struct iframe* iframe); +void x86_invalid_exception(iframe* frame); +void x86_fatal_exception(iframe* frame); +void x86_unexpected_exception(iframe* frame); +void x86_hardware_interrupt(iframe* frame); +void x86_page_fault_exception(iframe* iframe); #ifndef __x86_64__ @@ -415,8 +419,8 @@ void x86_fnsave(void* fpuState); void x86_frstor(const void* fpuState); void x86_fnsave_swap(void* oldFpuState, const void* newFpuState); void x86_set_task_gate(int32 cpu, int32 n, int32 segment); -void x86_double_fault_exception(struct iframe* frame); -void x86_page_fault_exception_double_fault(struct iframe* frame); +void x86_double_fault_exception(iframe* frame); +void x86_page_fault_exception_double_fault(iframe* frame); #endif diff --git a/headers/private/kernel/arch/x86/vm86.h b/headers/private/kernel/arch/x86/vm86.h index a7d939b422..7e4692da48 100644 --- a/headers/private/kernel/arch/x86/vm86.h +++ b/headers/private/kernel/arch/x86/vm86.h @@ -5,6 +5,9 @@ #ifndef _VM86_H #define _VM86_H + +#ifndef __x86_64__ + #include #include @@ -34,5 +37,6 @@ status_t vm86_do_int(struct vm86_state *state, uint8 vec); #endif #endif +#endif diff --git a/src/system/kernel/arch/x86/32/int.cpp b/src/system/kernel/arch/x86/32/int.cpp index b290c0df46..d718623538 100644 --- a/src/system/kernel/arch/x86/32/int.cpp +++ b/src/system/kernel/arch/x86/32/int.cpp @@ -9,14 +9,12 @@ * Distributed under the terms of the NewOS License. */ +#include + +#include #include -#include -#include -#include #include -#include -#include #include #include @@ -33,34 +31,6 @@ #include "interrupts.h" -#include - - -static const char *kInterruptNames[] = { - /* 0 */ "Divide Error Exception", - /* 1 */ "Debug Exception", - /* 2 */ "NMI Interrupt", - /* 3 */ "Breakpoint Exception", - /* 4 */ "Overflow Exception", - /* 5 */ "BOUND Range Exceeded Exception", - /* 6 */ "Invalid Opcode Exception", - /* 7 */ "Device Not Available Exception", - /* 8 */ "Double Fault Exception", - /* 9 */ "Coprocessor Segment Overrun", - /* 10 */ "Invalid TSS Exception", - /* 11 */ "Segment Not Present", - /* 12 */ "Stack Fault Exception", - /* 13 */ "General Protection Exception", - /* 14 */ "Page-Fault Exception", - /* 15 */ "-", - /* 16 */ "x87 FPU Floating-Point Error", - /* 17 */ "Alignment Check Exception", - /* 18 */ "Machine-Check Exception", - /* 19 */ "SIMD Floating-Point Exception", -}; -static const int kInterruptNameCount = 20; - -#define MAX_ARGS 16 static interrupt_descriptor* sIDTs[B_MAX_CPU_COUNT]; @@ -71,8 +41,6 @@ typedef void interrupt_handler_function(struct iframe* frame); interrupt_handler_function* gInterruptHandlerTable[ INTERRUPT_HANDLER_TABLE_SIZE]; -extern void hardware_interrupt(struct iframe* frame); - /*! Initializes a descriptor in an IDT. */ @@ -140,145 +108,6 @@ x86_get_idt(int32 cpu) // #pragma mark - -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 -invalid_exception(struct iframe* frame) -{ - Thread* thread = thread_get_current_thread(); - char name[32]; - panic("unhandled trap 0x%lx (%s) at ip 0x%lx, thread %ld!\n", - frame->vector, exception_name(frame->vector, name, sizeof(name)), - frame->ip, thread ? thread->id : -1); -} - - -static void -fatal_exception(struct iframe *frame) -{ - char name[32]; - panic("Fatal exception \"%s\" occurred! Error code: 0x%lx\n", - exception_name(frame->vector, name, sizeof(name)), frame->error_code); -} - - -static void -unexpected_exception(struct iframe* frame) -{ - debug_exception_type type; - uint32 signalNumber; - int32 signalCode; - addr_t signalAddress = 0; - int32 signalError = B_ERROR; - - if (IFRAME_IS_VM86(frame)) { - x86_vm86_return((struct vm86_iframe *)frame, (frame->vector == 13) ? - B_OK : B_ERROR); - // won't get here - } - - switch (frame->vector) { - case 0: // Divide Error Exception (#DE) - type = B_DIVIDE_ERROR; - signalNumber = SIGFPE; - signalCode = FPE_INTDIV; - signalAddress = frame->ip; - break; - - case 4: // Overflow Exception (#OF) - type = B_OVERFLOW_EXCEPTION; - signalNumber = SIGFPE; - signalCode = FPE_INTOVF; - signalAddress = frame->ip; - break; - - case 5: // BOUND Range Exceeded Exception (#BR) - type = B_BOUNDS_CHECK_EXCEPTION; - signalNumber = SIGTRAP; - signalCode = SI_USER; - break; - - case 6: // Invalid Opcode Exception (#UD) - type = B_INVALID_OPCODE_EXCEPTION; - signalNumber = SIGILL; - signalCode = ILL_ILLOPC; - signalAddress = frame->ip; - break; - - case 13: // General Protection Exception (#GP) - type = B_GENERAL_PROTECTION_FAULT; - signalNumber = SIGILL; - signalCode = ILL_PRVOPC; // or ILL_PRVREG - signalAddress = frame->ip; - break; - - case 16: // x87 FPU Floating-Point Error (#MF) - type = B_FLOATING_POINT_EXCEPTION; - signalNumber = SIGFPE; - signalCode = FPE_FLTDIV; - // TODO: Determine the correct cause via the FPU status - // register! - signalAddress = frame->ip; - break; - - case 17: // Alignment Check Exception (#AC) - type = B_ALIGNMENT_EXCEPTION; - signalNumber = SIGBUS; - signalCode = BUS_ADRALN; - // TODO: Also get the address (from where?). Since we don't enable - // alignment checking this exception should never happen, though. - signalError = EFAULT; - break; - - case 19: // SIMD Floating-Point Exception (#XF) - type = B_FLOATING_POINT_EXCEPTION; - signalNumber = SIGFPE; - signalCode = FPE_FLTDIV; - // TODO: Determine the correct cause via the MXCSR register! - signalAddress = frame->ip; - break; - - default: - invalid_exception(frame); - return; - } - - if (IFRAME_IS_USER(frame)) { - struct sigaction action; - Thread* thread = thread_get_current_thread(); - - enable_interrupts(); - - // If the thread has a signal handler for the signal, we simply send it - // the signal. Otherwise we notify the user debugger first. - if ((sigaction(signalNumber, NULL, &action) == 0 - && action.sa_handler != SIG_DFL - && action.sa_handler != SIG_IGN) - || user_debug_exception_occurred(type, signalNumber)) { - Signal signal(signalNumber, signalCode, signalError, - thread->team->id); - signal.SetAddress((void*)signalAddress); - send_signal_to_thread(thread, signal, 0); - } - } else { - char name[32]; - panic("Unexpected exception \"%s\" occurred in kernel mode! " - "Error code: 0x%lx\n", - exception_name(frame->vector, name, sizeof(name)), - frame->error_code); - } -} - - void x86_double_fault_exception(struct iframe* frame) { @@ -618,29 +447,29 @@ arch_int_init(struct kernel_args *args) // defaults for (i = 0; i < ARCH_INTERRUPT_BASE; i++) - table[i] = invalid_exception; + table[i] = x86_invalid_exception; for (i = ARCH_INTERRUPT_BASE; i < INTERRUPT_HANDLER_TABLE_SIZE; i++) - table[i] = hardware_interrupt; + table[i] = x86_hardware_interrupt; - table[0] = unexpected_exception; // Divide Error Exception (#DE) - table[1] = x86_handle_debug_exception; // Debug Exception (#DB) - table[2] = fatal_exception; // NMI Interrupt + table[0] = x86_unexpected_exception; // Divide Error Exception (#DE) + table[1] = x86_handle_debug_exception; // Debug Exception (#DB) + table[2] = x86_fatal_exception; // NMI Interrupt table[3] = x86_handle_breakpoint_exception; // Breakpoint Exception (#BP) - table[4] = unexpected_exception; // Overflow Exception (#OF) - table[5] = unexpected_exception; // BOUND Range Exceeded Exception (#BR) - table[6] = unexpected_exception; // Invalid Opcode Exception (#UD) - table[7] = fatal_exception; // Device Not Available Exception (#NM) - table[8] = x86_double_fault_exception; // Double Fault Exception (#DF) - table[9] = fatal_exception; // Coprocessor Segment Overrun - table[10] = fatal_exception; // Invalid TSS Exception (#TS) - table[11] = fatal_exception; // Segment Not Present (#NP) - table[12] = fatal_exception; // Stack Fault Exception (#SS) - table[13] = unexpected_exception; // General Protection Exception (#GP) + table[4] = x86_unexpected_exception; // Overflow Exception (#OF) + table[5] = x86_unexpected_exception; // BOUND Range Exceeded Exception (#BR) + table[6] = x86_unexpected_exception; // Invalid Opcode Exception (#UD) + table[7] = x86_fatal_exception; // Device Not Available Exception (#NM) + table[8] = x86_double_fault_exception; // Double Fault Exception (#DF) + table[9] = x86_fatal_exception; // Coprocessor Segment Overrun + table[10] = x86_fatal_exception; // Invalid TSS Exception (#TS) + table[11] = x86_fatal_exception; // Segment Not Present (#NP) + table[12] = x86_fatal_exception; // Stack Fault Exception (#SS) + table[13] = x86_unexpected_exception; // General Protection Exception (#GP) table[14] = x86_page_fault_exception; // Page-Fault Exception (#PF) - table[16] = unexpected_exception; // x87 FPU Floating-Point Error (#MF) - table[17] = unexpected_exception; // Alignment Check Exception (#AC) - table[18] = fatal_exception; // Machine-Check Exception (#MC) - table[19] = unexpected_exception; // SIMD Floating-Point Exception (#XF) + table[16] = x86_unexpected_exception; // x87 FPU Floating-Point Error (#MF) + table[17] = x86_unexpected_exception; // Alignment Check Exception (#AC) + table[18] = x86_fatal_exception; // Machine-Check Exception (#MC) + table[19] = x86_unexpected_exception; // SIMD Floating-Point Exception (#XF) return B_OK; } diff --git a/src/system/kernel/arch/x86/64/int.cpp b/src/system/kernel/arch/x86/64/int.cpp index f0cfb800e6..1f43415abf 100644 --- a/src/system/kernel/arch/x86/64/int.cpp +++ b/src/system/kernel/arch/x86/64/int.cpp @@ -6,7 +6,6 @@ #include -#include #include #include @@ -22,78 +21,12 @@ typedef void interrupt_handler_function(iframe* frame); -static const char* kInterruptNames[] = { - /* 0 */ "Divide Error Exception", - /* 1 */ "Debug Exception", - /* 2 */ "NMI Interrupt", - /* 3 */ "Breakpoint Exception", - /* 4 */ "Overflow Exception", - /* 5 */ "BOUND Range Exceeded Exception", - /* 6 */ "Invalid Opcode Exception", - /* 7 */ "Device Not Available Exception", - /* 8 */ "Double Fault Exception", - /* 9 */ "Coprocessor Segment Overrun", - /* 10 */ "Invalid TSS Exception", - /* 11 */ "Segment Not Present", - /* 12 */ "Stack Fault Exception", - /* 13 */ "General Protection Exception", - /* 14 */ "Page-Fault Exception", - /* 15 */ "-", - /* 16 */ "x87 FPU Floating-Point Error", - /* 17 */ "Alignment Check Exception", - /* 18 */ "Machine-Check Exception", - /* 19 */ "SIMD Floating-Point Exception", -}; - static const uint32 kInterruptHandlerTableSize = 256; static interrupt_descriptor* sIDT; interrupt_handler_function* gInterruptHandlerTable[kInterruptHandlerTableSize]; extern uint8 isr_array[kInterruptHandlerTableSize][16]; -extern void hardware_interrupt(struct iframe* frame); - - -static const char* -exception_name(uint64 number, char* buffer, size_t bufferSize) -{ - if (number >= 0 - && number < (sizeof(kInterruptNames) / sizeof(kInterruptNames[0]))) - return kInterruptNames[number]; - - snprintf(buffer, bufferSize, "exception %lu", number); - return buffer; -} - - -static void -invalid_exception(iframe* frame) -{ - char name[32]; - panic("unhandled trap %#lx (%s) at ip %#lx\n", - frame->vector, exception_name(frame->vector, name, sizeof(name)), - frame->ip); -} - - -static void -fatal_exception(iframe* frame) -{ - char name[32]; - panic("fatal exception %#lx (%s) at ip %#lx, error code %#lx\n", - frame->vector, exception_name(frame->vector, name, sizeof(name)), - frame->ip, frame->error_code); -} - - -static void -unexpected_exception(iframe* frame) -{ - char name[32]; - panic("fatal exception %#lx (%s) at ip %#lx, error code %#lx\n", - frame->vector, exception_name(frame->vector, name, sizeof(name)), - frame->ip, frame->error_code); -} /*! Returns the virtual IDT address for CPU \a cpu. */ @@ -134,31 +67,31 @@ arch_int_init(kernel_args* args) // Initialize the interrupt handler table. for (uint32 i = 0; i < ARCH_INTERRUPT_BASE; i++) - table[i] = invalid_exception; + table[i] = x86_invalid_exception; for (uint32 i = ARCH_INTERRUPT_BASE; i < kInterruptHandlerTableSize; i++) - table[i] = hardware_interrupt; + table[i] = x86_hardware_interrupt; - table[0] = unexpected_exception; // Divide Error Exception (#DE) + table[0] = x86_unexpected_exception; // Divide Error Exception (#DE) //table[1] = x86_handle_debug_exception; // Debug Exception (#DB) - table[1] = unexpected_exception; - table[2] = fatal_exception; // NMI Interrupt + table[1] = x86_unexpected_exception; + table[2] = x86_fatal_exception; // NMI Interrupt //table[3] = x86_handle_breakpoint_exception; // Breakpoint Exception (#BP) - table[3] = unexpected_exception; - table[4] = unexpected_exception; // Overflow Exception (#OF) - table[5] = unexpected_exception; // BOUND Range Exceeded Exception (#BR) - table[6] = unexpected_exception; // Invalid Opcode Exception (#UD) - table[7] = fatal_exception; // Device Not Available Exception (#NM) - table[8] = fatal_exception; // Double Fault Exception (#DF) - table[9] = fatal_exception; // Coprocessor Segment Overrun - table[10] = fatal_exception; // Invalid TSS Exception (#TS) - table[11] = fatal_exception; // Segment Not Present (#NP) - table[12] = fatal_exception; // Stack Fault Exception (#SS) - table[13] = unexpected_exception; // General Protection Exception (#GP) + table[3] = x86_unexpected_exception; + table[4] = x86_unexpected_exception; // Overflow Exception (#OF) + table[5] = x86_unexpected_exception; // BOUND Range Exceeded Exception (#BR) + table[6] = x86_unexpected_exception; // Invalid Opcode Exception (#UD) + table[7] = x86_fatal_exception; // Device Not Available Exception (#NM) + table[8] = x86_fatal_exception; // Double Fault Exception (#DF) + table[9] = x86_fatal_exception; // Coprocessor Segment Overrun + table[10] = x86_fatal_exception; // Invalid TSS Exception (#TS) + table[11] = x86_fatal_exception; // Segment Not Present (#NP) + table[12] = x86_fatal_exception; // Stack Fault Exception (#SS) + table[13] = x86_unexpected_exception; // General Protection Exception (#GP) table[14] = x86_page_fault_exception; // Page-Fault Exception (#PF) - table[16] = unexpected_exception; // x87 FPU Floating-Point Error (#MF) - table[17] = unexpected_exception; // Alignment Check Exception (#AC) - table[18] = fatal_exception; // Machine-Check Exception (#MC) - table[19] = unexpected_exception; // SIMD Floating-Point Exception (#XF) + table[16] = x86_unexpected_exception; // x87 FPU Floating-Point Error (#MF) + table[17] = x86_unexpected_exception; // Alignment Check Exception (#AC) + table[18] = x86_fatal_exception; // Machine-Check Exception (#MC) + table[19] = x86_unexpected_exception; // SIMD Floating-Point Exception (#XF) // Load the IDT. gdt_idt_descr idtr = { diff --git a/src/system/kernel/arch/x86/arch_int.cpp b/src/system/kernel/arch/x86/arch_int.cpp index 9d35513e0f..f604defdb1 100644 --- a/src/system/kernel/arch/x86/arch_int.cpp +++ b/src/system/kernel/arch/x86/arch_int.cpp @@ -25,6 +25,7 @@ #include #include #include +#include #include @@ -41,11 +42,176 @@ #endif +static const char *kInterruptNames[] = { + /* 0 */ "Divide Error Exception", + /* 1 */ "Debug Exception", + /* 2 */ "NMI Interrupt", + /* 3 */ "Breakpoint Exception", + /* 4 */ "Overflow Exception", + /* 5 */ "BOUND Range Exceeded Exception", + /* 6 */ "Invalid Opcode Exception", + /* 7 */ "Device Not Available Exception", + /* 8 */ "Double Fault Exception", + /* 9 */ "Coprocessor Segment Overrun", + /* 10 */ "Invalid TSS Exception", + /* 11 */ "Segment Not Present", + /* 12 */ "Stack Fault Exception", + /* 13 */ "General Protection Exception", + /* 14 */ "Page-Fault Exception", + /* 15 */ "-", + /* 16 */ "x87 FPU Floating-Point Error", + /* 17 */ "Alignment Check Exception", + /* 18 */ "Machine-Check Exception", + /* 19 */ "SIMD Floating-Point Exception", +}; +static const int kInterruptNameCount = 20; + static const interrupt_controller* sCurrentPIC = NULL; +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; +} + + void -hardware_interrupt(struct iframe* frame) +x86_invalid_exception(iframe* frame) +{ + Thread* thread = thread_get_current_thread(); + char name[32]; + panic("unhandled trap 0x%lx (%s) at ip 0x%lx, thread %" B_PRId32 "!\n", + frame->vector, exception_name(frame->vector, name, sizeof(name)), + frame->ip, thread ? thread->id : -1); +} + + +void +x86_fatal_exception(iframe* frame) +{ + char name[32]; + panic("Fatal exception \"%s\" occurred! Error code: 0x%lx\n", + exception_name(frame->vector, name, sizeof(name)), frame->error_code); +} + + +void +x86_unexpected_exception(iframe* frame) +{ + debug_exception_type type; + uint32 signalNumber; + int32 signalCode; + addr_t signalAddress = 0; + int32 signalError = B_ERROR; + +#ifndef __x86_64__ + if (IFRAME_IS_VM86(frame)) { + x86_vm86_return((vm86_iframe*)frame, (frame->vector == 13) ? + B_OK : B_ERROR); + // won't get here + } +#endif + + switch (frame->vector) { + case 0: // Divide Error Exception (#DE) + type = B_DIVIDE_ERROR; + signalNumber = SIGFPE; + signalCode = FPE_INTDIV; + signalAddress = frame->ip; + break; + + case 4: // Overflow Exception (#OF) + type = B_OVERFLOW_EXCEPTION; + signalNumber = SIGFPE; + signalCode = FPE_INTOVF; + signalAddress = frame->ip; + break; + + case 5: // BOUND Range Exceeded Exception (#BR) + type = B_BOUNDS_CHECK_EXCEPTION; + signalNumber = SIGTRAP; + signalCode = SI_USER; + break; + + case 6: // Invalid Opcode Exception (#UD) + type = B_INVALID_OPCODE_EXCEPTION; + signalNumber = SIGILL; + signalCode = ILL_ILLOPC; + signalAddress = frame->ip; + break; + + case 13: // General Protection Exception (#GP) + type = B_GENERAL_PROTECTION_FAULT; + signalNumber = SIGILL; + signalCode = ILL_PRVOPC; // or ILL_PRVREG + signalAddress = frame->ip; + break; + + case 16: // x87 FPU Floating-Point Error (#MF) + type = B_FLOATING_POINT_EXCEPTION; + signalNumber = SIGFPE; + signalCode = FPE_FLTDIV; + // TODO: Determine the correct cause via the FPU status + // register! + signalAddress = frame->ip; + break; + + case 17: // Alignment Check Exception (#AC) + type = B_ALIGNMENT_EXCEPTION; + signalNumber = SIGBUS; + signalCode = BUS_ADRALN; + // TODO: Also get the address (from where?). Since we don't enable + // alignment checking this exception should never happen, though. + signalError = EFAULT; + break; + + case 19: // SIMD Floating-Point Exception (#XF) + type = B_FLOATING_POINT_EXCEPTION; + signalNumber = SIGFPE; + signalCode = FPE_FLTDIV; + // TODO: Determine the correct cause via the MXCSR register! + signalAddress = frame->ip; + break; + + default: + x86_invalid_exception(frame); + return; + } + + if (IFRAME_IS_USER(frame)) { + struct sigaction action; + Thread* thread = thread_get_current_thread(); + + enable_interrupts(); + + // If the thread has a signal handler for the signal, we simply send it + // the signal. Otherwise we notify the user debugger first. + if ((sigaction(signalNumber, NULL, &action) == 0 + && action.sa_handler != SIG_DFL + && action.sa_handler != SIG_IGN) + || user_debug_exception_occurred(type, signalNumber)) { + Signal signal(signalNumber, signalCode, signalError, + thread->team->id); + signal.SetAddress((void*)signalAddress); + send_signal_to_thread(thread, signal, 0); + } + } else { + char name[32]; + panic("Unexpected exception \"%s\" occurred in kernel mode! " + "Error code: 0x%lx\n", + exception_name(frame->vector, name, sizeof(name)), + frame->error_code); + } +} + + +void +x86_hardware_interrupt(struct iframe* frame) { int32 vector = frame->vector - ARCH_INTERRUPT_BASE; bool levelTriggered = false;