Moved the exception handling functions to arch_int.cpp, shared between x86 and x86_64.
This commit is contained in:
parent
4451c47c64
commit
6497f6b1ec
@ -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
|
||||
|
||||
|
@ -5,6 +5,9 @@
|
||||
#ifndef _VM86_H
|
||||
#define _VM86_H
|
||||
|
||||
|
||||
#ifndef __x86_64__
|
||||
|
||||
#include <OS.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
|
||||
|
||||
|
||||
|
@ -9,14 +9,12 @@
|
||||
* Distributed under the terms of the NewOS License.
|
||||
*/
|
||||
|
||||
#include <int.h>
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <cpu.h>
|
||||
#include <int.h>
|
||||
#include <kscheduler.h>
|
||||
#include <ksyscalls.h>
|
||||
#include <smp.h>
|
||||
#include <team.h>
|
||||
#include <thread.h>
|
||||
#include <vm/vm.h>
|
||||
#include <vm/vm_priv.h>
|
||||
|
||||
@ -33,34 +31,6 @@
|
||||
|
||||
#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];
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
@ -6,7 +6,6 @@
|
||||
|
||||
#include <int.h>
|
||||
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <boot/kernel_args.h>
|
||||
@ -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 = {
|
||||
|
@ -25,6 +25,7 @@
|
||||
#include <arch/x86/apic.h>
|
||||
#include <arch/x86/descriptors.h>
|
||||
#include <arch/x86/msi.h>
|
||||
#include <arch/x86/vm86.h>
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user