2019-05-31 07:41:28 +01:00
|
|
|
// Zig version: 0.4.0
|
|
|
|
|
|
|
|
const panic = @import("../../panic.zig");
|
|
|
|
const idt = @import("idt.zig");
|
|
|
|
const arch = @import("arch.zig");
|
2019-07-31 22:41:22 +01:00
|
|
|
const syscalls = @import("syscalls.zig");
|
2019-05-31 07:41:28 +01:00
|
|
|
|
|
|
|
const NUMBER_OF_ENTRIES: u16 = 32;
|
|
|
|
|
2019-06-02 17:14:02 +01:00
|
|
|
// The external assembly that is fist called to set up the exception handler.
|
2019-05-31 07:41:28 +01:00
|
|
|
extern fn isr0() void;
|
|
|
|
extern fn isr1() void;
|
|
|
|
extern fn isr2() void;
|
|
|
|
extern fn isr3() void;
|
|
|
|
extern fn isr4() void;
|
|
|
|
extern fn isr5() void;
|
|
|
|
extern fn isr6() void;
|
|
|
|
extern fn isr7() void;
|
|
|
|
extern fn isr8() void;
|
|
|
|
extern fn isr9() void;
|
|
|
|
extern fn isr10() void;
|
|
|
|
extern fn isr11() void;
|
|
|
|
extern fn isr12() void;
|
|
|
|
extern fn isr13() void;
|
|
|
|
extern fn isr14() void;
|
|
|
|
extern fn isr15() void;
|
|
|
|
extern fn isr16() void;
|
|
|
|
extern fn isr17() void;
|
|
|
|
extern fn isr18() void;
|
|
|
|
extern fn isr19() void;
|
|
|
|
extern fn isr20() void;
|
|
|
|
extern fn isr21() void;
|
|
|
|
extern fn isr22() void;
|
|
|
|
extern fn isr23() void;
|
|
|
|
extern fn isr24() void;
|
|
|
|
extern fn isr25() void;
|
|
|
|
extern fn isr26() void;
|
|
|
|
extern fn isr27() void;
|
|
|
|
extern fn isr28() void;
|
|
|
|
extern fn isr29() void;
|
|
|
|
extern fn isr30() void;
|
|
|
|
extern fn isr31() void;
|
2019-07-31 22:41:22 +01:00
|
|
|
extern fn isr128() void;
|
2019-05-31 07:41:28 +01:00
|
|
|
|
2019-06-02 17:14:02 +01:00
|
|
|
/// The exception messaged that is printed when a exception happens
|
2019-05-31 07:41:28 +01:00
|
|
|
const exception_msg: [NUMBER_OF_ENTRIES][]const u8 = [NUMBER_OF_ENTRIES][]const u8 {
|
|
|
|
"Divide By Zero",
|
|
|
|
"Single Step (Debugger)",
|
|
|
|
"Non Maskable Interrupt",
|
|
|
|
"Breakpoint (Debugger)",
|
|
|
|
"Overflow",
|
|
|
|
"Bound Range Exceeded",
|
|
|
|
"Invalid Opcode",
|
|
|
|
"No Coprocessor, Device Not Available",
|
|
|
|
"Double Fault",
|
|
|
|
"Coprocessor Segment Overrun",
|
|
|
|
"Invalid Task State Segment (TSS)",
|
|
|
|
"Segment Not Present",
|
|
|
|
"Stack Segment Overrun",
|
|
|
|
"General Protection Fault",
|
|
|
|
"Page Fault",
|
|
|
|
"Unknown Interrupt",
|
|
|
|
"x87 FPU Floating Point Error",
|
|
|
|
"Alignment Check",
|
|
|
|
"Machine Check",
|
|
|
|
"SIMD Floating Point",
|
|
|
|
"Virtualization",
|
|
|
|
"Reserved",
|
|
|
|
"Reserved",
|
|
|
|
"Reserved",
|
|
|
|
"Reserved",
|
|
|
|
"Reserved",
|
|
|
|
"Reserved",
|
|
|
|
"Reserved",
|
|
|
|
"Reserved",
|
|
|
|
"Reserved",
|
|
|
|
"Security",
|
|
|
|
"Reserved"
|
|
|
|
};
|
|
|
|
|
2019-07-31 22:41:22 +01:00
|
|
|
/// Errors that an isr function can return
|
|
|
|
pub const IsrError = error {
|
|
|
|
UnrecognisedIsr
|
|
|
|
};
|
|
|
|
|
|
|
|
/// An isr handler. Takes an interrupt context and returns void.
|
|
|
|
/// Should finish quickly to avoid delaying further interrupts and the previously running code
|
|
|
|
pub const IsrHandler = fn(*arch.InterruptContext)void;
|
|
|
|
|
2019-06-02 17:14:02 +01:00
|
|
|
// The of exception handlers initialised to unhandled.
|
2019-07-31 22:41:22 +01:00
|
|
|
var isr_handlers: [NUMBER_OF_ENTRIES]IsrHandler = []IsrHandler{unhandled} ** NUMBER_OF_ENTRIES;
|
|
|
|
var syscall_handler: IsrHandler = unhandled;
|
2019-05-31 07:41:28 +01:00
|
|
|
|
2019-06-02 17:14:02 +01:00
|
|
|
///
|
|
|
|
/// A dummy handler that will make a call to panic as it is a unhandled exception.
|
|
|
|
///
|
|
|
|
/// Arguments:
|
|
|
|
/// IN context: *arch.InterruptContext - Pointer to the exception context containing the
|
|
|
|
/// contents of the register at the time of the exception.
|
|
|
|
///
|
2019-05-31 07:41:28 +01:00
|
|
|
fn unhandled(context: *arch.InterruptContext) void {
|
|
|
|
const interrupt_num = context.int_num;
|
|
|
|
panic.panicFmt(null, "Unhandled exception: {}, number {}", exception_msg[interrupt_num], interrupt_num);
|
|
|
|
}
|
|
|
|
|
2019-07-31 22:41:22 +01:00
|
|
|
///
|
|
|
|
/// Checks if the isr is valid and returns true if it is, else false.
|
|
|
|
/// To be valid it must be greater than or equal to 0 and less than NUMBER_OF_ENTRIES.
|
|
|
|
///
|
|
|
|
/// Arguments:
|
|
|
|
/// IN isr_num: u16 - The isr number to check
|
|
|
|
///
|
|
|
|
pub fn isValidIsr(isr_num: u32) bool {
|
|
|
|
return isr_num >= 0 and isr_num < NUMBER_OF_ENTRIES;
|
|
|
|
}
|
|
|
|
|
2019-06-02 17:14:02 +01:00
|
|
|
///
|
|
|
|
/// The exception handler that each of the exceptions will call when a exception happens.
|
|
|
|
///
|
|
|
|
/// Arguments:
|
|
|
|
/// IN context: *arch.InterruptContext - Pointer to the exception context containing the
|
|
|
|
/// contents of the register at the time of the exception.
|
|
|
|
///
|
2019-05-31 07:41:28 +01:00
|
|
|
export fn isrHandler(context: *arch.InterruptContext) void {
|
|
|
|
const isr_num = context.int_num;
|
2019-07-31 22:41:22 +01:00
|
|
|
if (isr_num == syscalls.INTERRUPT) {
|
|
|
|
syscall_handler(context);
|
|
|
|
} else if (isValidIsr(isr_num)) {
|
|
|
|
isr_handlers[isr_num](context);
|
|
|
|
} else {
|
|
|
|
panic.panicFmt(null, "Unrecognised isr: {}\n", isr_num);
|
|
|
|
}
|
2019-05-31 07:41:28 +01:00
|
|
|
}
|
|
|
|
|
2019-06-02 17:14:02 +01:00
|
|
|
///
|
|
|
|
/// Register an exception by setting its exception handler to the given function.
|
|
|
|
///
|
|
|
|
/// Arguments:
|
|
|
|
/// IN irq_num: u16 - The exception number to register.
|
|
|
|
///
|
2019-07-31 22:41:22 +01:00
|
|
|
/// Errors:
|
|
|
|
/// IsrError.UnrecognisedIsr - If `isr_num` is invalid (see isValidIsr)
|
|
|
|
///
|
|
|
|
pub fn registerIsr(isr_num: u16, handler: fn(*arch.InterruptContext)void) !void {
|
|
|
|
if (isr_num == syscalls.INTERRUPT) {
|
|
|
|
syscall_handler = handler;
|
|
|
|
} else if (isValidIsr(isr_num)) {
|
|
|
|
isr_handlers[isr_num] = handler;
|
|
|
|
} else {
|
|
|
|
return IsrError.UnrecognisedIsr;
|
|
|
|
}
|
2019-05-31 07:41:28 +01:00
|
|
|
}
|
|
|
|
|
2019-06-02 17:14:02 +01:00
|
|
|
///
|
|
|
|
/// Unregister an exception by setting its exception handler to the unhandled function call to
|
|
|
|
/// panic.
|
|
|
|
///
|
|
|
|
/// Arguments:
|
|
|
|
/// IN irq_num: u16 - The exception number to unregister.
|
|
|
|
///
|
2019-05-31 07:41:28 +01:00
|
|
|
pub fn unregisterIsr(isr_num: u16) void {
|
|
|
|
isr_handlers[isr_num] = unhandled;
|
|
|
|
}
|
|
|
|
|
2019-06-02 17:14:02 +01:00
|
|
|
///
|
|
|
|
/// Initialise the exception and opening up all the IDT interrupt gates for each exception.
|
|
|
|
///
|
2019-05-31 07:41:28 +01:00
|
|
|
pub fn init() void {
|
|
|
|
idt.openInterruptGate(0, isr0);
|
|
|
|
idt.openInterruptGate(1, isr1);
|
|
|
|
idt.openInterruptGate(2, isr2);
|
|
|
|
idt.openInterruptGate(3, isr3);
|
|
|
|
idt.openInterruptGate(4, isr4);
|
|
|
|
idt.openInterruptGate(5, isr5);
|
|
|
|
idt.openInterruptGate(6, isr6);
|
|
|
|
idt.openInterruptGate(7, isr7);
|
|
|
|
idt.openInterruptGate(8, isr8);
|
|
|
|
idt.openInterruptGate(9, isr9);
|
|
|
|
idt.openInterruptGate(10, isr10);
|
|
|
|
idt.openInterruptGate(11, isr11);
|
|
|
|
idt.openInterruptGate(12, isr12);
|
|
|
|
idt.openInterruptGate(13, isr13);
|
|
|
|
idt.openInterruptGate(14, isr14);
|
|
|
|
idt.openInterruptGate(15, isr15);
|
|
|
|
idt.openInterruptGate(16, isr16);
|
|
|
|
idt.openInterruptGate(17, isr17);
|
|
|
|
idt.openInterruptGate(18, isr18);
|
|
|
|
idt.openInterruptGate(19, isr19);
|
|
|
|
idt.openInterruptGate(20, isr20);
|
|
|
|
idt.openInterruptGate(21, isr21);
|
|
|
|
idt.openInterruptGate(22, isr22);
|
|
|
|
idt.openInterruptGate(23, isr23);
|
|
|
|
idt.openInterruptGate(24, isr24);
|
|
|
|
idt.openInterruptGate(25, isr25);
|
|
|
|
idt.openInterruptGate(26, isr26);
|
|
|
|
idt.openInterruptGate(27, isr27);
|
|
|
|
idt.openInterruptGate(28, isr28);
|
|
|
|
idt.openInterruptGate(29, isr29);
|
|
|
|
idt.openInterruptGate(30, isr30);
|
|
|
|
idt.openInterruptGate(31, isr31);
|
2019-07-31 22:41:22 +01:00
|
|
|
idt.openInterruptGate(syscalls.INTERRUPT, isr128);
|
|
|
|
}
|