Moved the exception handling functions to arch_int.cpp, shared between x86 and x86_64.
This commit is contained in:
@@ -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);
|
void* x86_get_double_fault_stack(int32 cpu, size_t* _size);
|
||||||
int32 x86_double_fault_get_cpu(void);
|
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__
|
#ifndef __x86_64__
|
||||||
|
|
||||||
@@ -415,8 +419,8 @@ void x86_fnsave(void* fpuState);
|
|||||||
void x86_frstor(const void* fpuState);
|
void x86_frstor(const void* fpuState);
|
||||||
void x86_fnsave_swap(void* oldFpuState, const void* newFpuState);
|
void x86_fnsave_swap(void* oldFpuState, const void* newFpuState);
|
||||||
void x86_set_task_gate(int32 cpu, int32 n, int32 segment);
|
void x86_set_task_gate(int32 cpu, int32 n, int32 segment);
|
||||||
void x86_double_fault_exception(struct iframe* frame);
|
void x86_double_fault_exception(iframe* frame);
|
||||||
void x86_page_fault_exception_double_fault(struct iframe* frame);
|
void x86_page_fault_exception_double_fault(iframe* frame);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
@@ -5,6 +5,9 @@
|
|||||||
#ifndef _VM86_H
|
#ifndef _VM86_H
|
||||||
#define _VM86_H
|
#define _VM86_H
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef __x86_64__
|
||||||
|
|
||||||
#include <OS.h>
|
#include <OS.h>
|
||||||
#include <arch/x86/arch_cpu.h>
|
#include <arch/x86/arch_cpu.h>
|
||||||
|
|
||||||
@@ -34,5 +37,6 @@ status_t vm86_do_int(struct vm86_state *state, uint8 vec);
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -9,14 +9,12 @@
|
|||||||
* Distributed under the terms of the NewOS License.
|
* Distributed under the terms of the NewOS License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <int.h>
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
#include <cpu.h>
|
#include <cpu.h>
|
||||||
#include <int.h>
|
|
||||||
#include <kscheduler.h>
|
|
||||||
#include <ksyscalls.h>
|
|
||||||
#include <smp.h>
|
#include <smp.h>
|
||||||
#include <team.h>
|
|
||||||
#include <thread.h>
|
|
||||||
#include <vm/vm.h>
|
#include <vm/vm.h>
|
||||||
#include <vm/vm_priv.h>
|
#include <vm/vm_priv.h>
|
||||||
|
|
||||||
@@ -33,34 +31,6 @@
|
|||||||
|
|
||||||
#include "interrupts.h"
|
#include "interrupts.h"
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
|
|
||||||
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];
|
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_function* gInterruptHandlerTable[
|
||||||
INTERRUPT_HANDLER_TABLE_SIZE];
|
INTERRUPT_HANDLER_TABLE_SIZE];
|
||||||
|
|
||||||
extern void hardware_interrupt(struct iframe* frame);
|
|
||||||
|
|
||||||
|
|
||||||
/*! Initializes a descriptor in an IDT.
|
/*! Initializes a descriptor in an IDT.
|
||||||
*/
|
*/
|
||||||
@@ -140,145 +108,6 @@ x86_get_idt(int32 cpu)
|
|||||||
// #pragma mark -
|
// #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
|
void
|
||||||
x86_double_fault_exception(struct iframe* frame)
|
x86_double_fault_exception(struct iframe* frame)
|
||||||
{
|
{
|
||||||
@@ -618,29 +447,29 @@ arch_int_init(struct kernel_args *args)
|
|||||||
|
|
||||||
// defaults
|
// defaults
|
||||||
for (i = 0; i < ARCH_INTERRUPT_BASE; i++)
|
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++)
|
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[0] = x86_unexpected_exception; // Divide Error Exception (#DE)
|
||||||
table[1] = x86_handle_debug_exception; // Debug Exception (#DB)
|
table[1] = x86_handle_debug_exception; // Debug Exception (#DB)
|
||||||
table[2] = fatal_exception; // NMI Interrupt
|
table[2] = x86_fatal_exception; // NMI Interrupt
|
||||||
table[3] = x86_handle_breakpoint_exception; // Breakpoint Exception (#BP)
|
table[3] = x86_handle_breakpoint_exception; // Breakpoint Exception (#BP)
|
||||||
table[4] = unexpected_exception; // Overflow Exception (#OF)
|
table[4] = x86_unexpected_exception; // Overflow Exception (#OF)
|
||||||
table[5] = unexpected_exception; // BOUND Range Exceeded Exception (#BR)
|
table[5] = x86_unexpected_exception; // BOUND Range Exceeded Exception (#BR)
|
||||||
table[6] = unexpected_exception; // Invalid Opcode Exception (#UD)
|
table[6] = x86_unexpected_exception; // Invalid Opcode Exception (#UD)
|
||||||
table[7] = fatal_exception; // Device Not Available Exception (#NM)
|
table[7] = x86_fatal_exception; // Device Not Available Exception (#NM)
|
||||||
table[8] = x86_double_fault_exception; // Double Fault Exception (#DF)
|
table[8] = x86_double_fault_exception; // Double Fault Exception (#DF)
|
||||||
table[9] = fatal_exception; // Coprocessor Segment Overrun
|
table[9] = x86_fatal_exception; // Coprocessor Segment Overrun
|
||||||
table[10] = fatal_exception; // Invalid TSS Exception (#TS)
|
table[10] = x86_fatal_exception; // Invalid TSS Exception (#TS)
|
||||||
table[11] = fatal_exception; // Segment Not Present (#NP)
|
table[11] = x86_fatal_exception; // Segment Not Present (#NP)
|
||||||
table[12] = fatal_exception; // Stack Fault Exception (#SS)
|
table[12] = x86_fatal_exception; // Stack Fault Exception (#SS)
|
||||||
table[13] = unexpected_exception; // General Protection Exception (#GP)
|
table[13] = x86_unexpected_exception; // General Protection Exception (#GP)
|
||||||
table[14] = x86_page_fault_exception; // Page-Fault Exception (#PF)
|
table[14] = x86_page_fault_exception; // Page-Fault Exception (#PF)
|
||||||
table[16] = unexpected_exception; // x87 FPU Floating-Point Error (#MF)
|
table[16] = x86_unexpected_exception; // x87 FPU Floating-Point Error (#MF)
|
||||||
table[17] = unexpected_exception; // Alignment Check Exception (#AC)
|
table[17] = x86_unexpected_exception; // Alignment Check Exception (#AC)
|
||||||
table[18] = fatal_exception; // Machine-Check Exception (#MC)
|
table[18] = x86_fatal_exception; // Machine-Check Exception (#MC)
|
||||||
table[19] = unexpected_exception; // SIMD Floating-Point Exception (#XF)
|
table[19] = x86_unexpected_exception; // SIMD Floating-Point Exception (#XF)
|
||||||
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,7 +6,6 @@
|
|||||||
|
|
||||||
#include <int.h>
|
#include <int.h>
|
||||||
|
|
||||||
#include <string.h>
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
#include <boot/kernel_args.h>
|
#include <boot/kernel_args.h>
|
||||||
@@ -22,78 +21,12 @@
|
|||||||
typedef void interrupt_handler_function(iframe* frame);
|
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 const uint32 kInterruptHandlerTableSize = 256;
|
||||||
|
|
||||||
static interrupt_descriptor* sIDT;
|
static interrupt_descriptor* sIDT;
|
||||||
interrupt_handler_function* gInterruptHandlerTable[kInterruptHandlerTableSize];
|
interrupt_handler_function* gInterruptHandlerTable[kInterruptHandlerTableSize];
|
||||||
|
|
||||||
extern uint8 isr_array[kInterruptHandlerTableSize][16];
|
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. */
|
/*! Returns the virtual IDT address for CPU \a cpu. */
|
||||||
@@ -134,31 +67,31 @@ arch_int_init(kernel_args* args)
|
|||||||
|
|
||||||
// Initialize the interrupt handler table.
|
// Initialize the interrupt handler table.
|
||||||
for (uint32 i = 0; i < ARCH_INTERRUPT_BASE; i++)
|
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++)
|
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] = x86_handle_debug_exception; // Debug Exception (#DB)
|
||||||
table[1] = unexpected_exception;
|
table[1] = x86_unexpected_exception;
|
||||||
table[2] = fatal_exception; // NMI Interrupt
|
table[2] = x86_fatal_exception; // NMI Interrupt
|
||||||
//table[3] = x86_handle_breakpoint_exception; // Breakpoint Exception (#BP)
|
//table[3] = x86_handle_breakpoint_exception; // Breakpoint Exception (#BP)
|
||||||
table[3] = unexpected_exception;
|
table[3] = x86_unexpected_exception;
|
||||||
table[4] = unexpected_exception; // Overflow Exception (#OF)
|
table[4] = x86_unexpected_exception; // Overflow Exception (#OF)
|
||||||
table[5] = unexpected_exception; // BOUND Range Exceeded Exception (#BR)
|
table[5] = x86_unexpected_exception; // BOUND Range Exceeded Exception (#BR)
|
||||||
table[6] = unexpected_exception; // Invalid Opcode Exception (#UD)
|
table[6] = x86_unexpected_exception; // Invalid Opcode Exception (#UD)
|
||||||
table[7] = fatal_exception; // Device Not Available Exception (#NM)
|
table[7] = x86_fatal_exception; // Device Not Available Exception (#NM)
|
||||||
table[8] = fatal_exception; // Double Fault Exception (#DF)
|
table[8] = x86_fatal_exception; // Double Fault Exception (#DF)
|
||||||
table[9] = fatal_exception; // Coprocessor Segment Overrun
|
table[9] = x86_fatal_exception; // Coprocessor Segment Overrun
|
||||||
table[10] = fatal_exception; // Invalid TSS Exception (#TS)
|
table[10] = x86_fatal_exception; // Invalid TSS Exception (#TS)
|
||||||
table[11] = fatal_exception; // Segment Not Present (#NP)
|
table[11] = x86_fatal_exception; // Segment Not Present (#NP)
|
||||||
table[12] = fatal_exception; // Stack Fault Exception (#SS)
|
table[12] = x86_fatal_exception; // Stack Fault Exception (#SS)
|
||||||
table[13] = unexpected_exception; // General Protection Exception (#GP)
|
table[13] = x86_unexpected_exception; // General Protection Exception (#GP)
|
||||||
table[14] = x86_page_fault_exception; // Page-Fault Exception (#PF)
|
table[14] = x86_page_fault_exception; // Page-Fault Exception (#PF)
|
||||||
table[16] = unexpected_exception; // x87 FPU Floating-Point Error (#MF)
|
table[16] = x86_unexpected_exception; // x87 FPU Floating-Point Error (#MF)
|
||||||
table[17] = unexpected_exception; // Alignment Check Exception (#AC)
|
table[17] = x86_unexpected_exception; // Alignment Check Exception (#AC)
|
||||||
table[18] = fatal_exception; // Machine-Check Exception (#MC)
|
table[18] = x86_fatal_exception; // Machine-Check Exception (#MC)
|
||||||
table[19] = unexpected_exception; // SIMD Floating-Point Exception (#XF)
|
table[19] = x86_unexpected_exception; // SIMD Floating-Point Exception (#XF)
|
||||||
|
|
||||||
// Load the IDT.
|
// Load the IDT.
|
||||||
gdt_idt_descr idtr = {
|
gdt_idt_descr idtr = {
|
||||||
|
|||||||
@@ -25,6 +25,7 @@
|
|||||||
#include <arch/x86/apic.h>
|
#include <arch/x86/apic.h>
|
||||||
#include <arch/x86/descriptors.h>
|
#include <arch/x86/descriptors.h>
|
||||||
#include <arch/x86/msi.h>
|
#include <arch/x86/msi.h>
|
||||||
|
#include <arch/x86/vm86.h>
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
@@ -41,11 +42,176 @@
|
|||||||
#endif
|
#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 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
|
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;
|
int32 vector = frame->vector - ARCH_INTERRUPT_BASE;
|
||||||
bool levelTriggered = false;
|
bool levelTriggered = false;
|
||||||
|
|||||||
Reference in New Issue
Block a user