Moved the exception handling functions to arch_int.cpp, shared between x86 and x86_64.

This commit is contained in:
Alex Smith 2012-07-21 09:11:09 +01:00
parent 4451c47c64
commit 6497f6b1ec
5 changed files with 220 additions and 284 deletions

View File

@ -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

View File

@ -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

View File

@ -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;
}

View File

@ -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 = {

View File

@ -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;