[INTERRUPTS] Exception handling
This commit is contained in:
67
kernel/interrupts/interrupts.c
Normal file
67
kernel/interrupts/interrupts.c
Normal file
@@ -0,0 +1,67 @@
|
||||
#include <int.h>
|
||||
#include <debug.h>
|
||||
#include <registers.h>
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
|
||||
struct int_gate_descriptor idt[NUM_INTERRUPTS];
|
||||
struct idtr idtr;
|
||||
int_handler_t int_handlers[NUM_INTERRUPTS];
|
||||
|
||||
void idt_set(uint32_t num, void *vector, uint16_t cs, uint8_t ist, uint8_t flags)
|
||||
{
|
||||
uintptr_t v = (uintptr_t)vector;
|
||||
idt[num].base_l = v & 0xFFFF;
|
||||
idt[num].base_m = (v >> 16) & 0xFFFF;
|
||||
idt[num].base_h = (v >> 32) & 0xFFFFFFFF;
|
||||
idt[num].cs = cs;
|
||||
idt[num].ist = ist;
|
||||
idt[num].flags = flags;
|
||||
}
|
||||
|
||||
void interrupt_init()
|
||||
{
|
||||
// Clear IDT and interrupt handler list
|
||||
memset(idt, 0, sizeof(idt));
|
||||
memset(int_handlers, 0, sizeof(int_handlers));
|
||||
|
||||
// Register all vectors in the IDT
|
||||
extern void *isr_table[];
|
||||
for(int i=0; i < NUM_INTERRUPTS; i++)
|
||||
{
|
||||
idt_set(i, isr_table[i], 0x8, 0,
|
||||
(IDT_PRESENT | IDT_DPL0 | IDT_INTERRUPT));
|
||||
}
|
||||
|
||||
// Setup pointer and load IDT
|
||||
idtr.addr = (uint64_t)idt;
|
||||
idtr.len = sizeof(idt)-1;
|
||||
load_idt(&idtr);
|
||||
}
|
||||
|
||||
int_handler_t register_int_handler(uint32_t num, int_handler_t h)
|
||||
{
|
||||
// Replace the handler for an interrupt
|
||||
// Return the old handler
|
||||
int_handler_t old = int_handlers[num];
|
||||
int_handlers[num] = h;
|
||||
return old;
|
||||
}
|
||||
|
||||
|
||||
registers_t *int_handler(registers_t *r)
|
||||
{
|
||||
// If a handler is registered, pass everything onto it
|
||||
if(int_handlers[r->int_no])
|
||||
return int_handlers[r->int_no](r);
|
||||
|
||||
debug("\n===============================================================================\n");
|
||||
debug_error("Unhandled interrupt!\n");
|
||||
print_registers(r);
|
||||
|
||||
#ifndef NDEBUG
|
||||
asm("int_handler_breakpoint:");
|
||||
#endif
|
||||
|
||||
for(;;);
|
||||
}
|
||||
28
kernel/interrupts/isr.S.py
Normal file
28
kernel/interrupts/isr.S.py
Normal file
@@ -0,0 +1,28 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
print('''
|
||||
.intel_syntax noprefix
|
||||
.extern isr_common
|
||||
''')
|
||||
|
||||
print('// Interrupt Service Routines')
|
||||
for i in range(255):
|
||||
print('''isr{0}:
|
||||
cli
|
||||
{1}
|
||||
push {0}
|
||||
jmp isr_common
|
||||
'''.format(i,
|
||||
'push 0' if i not in [8, 10, 11, 12, 13, 14, 17] else 'nop'))
|
||||
|
||||
print('''
|
||||
|
||||
// Vector table
|
||||
|
||||
.section .data
|
||||
.global isr_table
|
||||
isr_table:
|
||||
''')
|
||||
for i in range(255):
|
||||
print(' .quad isr{}'.format(i))
|
||||
49
kernel/interrupts/isr_common.S
Normal file
49
kernel/interrupts/isr_common.S
Normal file
@@ -0,0 +1,49 @@
|
||||
.intel_syntax noprefix
|
||||
|
||||
.extern int_handler
|
||||
.global isr_common
|
||||
.global isr_return
|
||||
|
||||
isr_common:
|
||||
// Push all registers
|
||||
push r15
|
||||
push r14
|
||||
push r13
|
||||
push r12
|
||||
push r11
|
||||
push r10
|
||||
push r9
|
||||
push r8
|
||||
push rbp
|
||||
push rdi
|
||||
push rsi
|
||||
push rdx
|
||||
push rcx
|
||||
push rbx
|
||||
push rax
|
||||
mov rdi, rsp
|
||||
call int_handler
|
||||
mov rdi, rax
|
||||
|
||||
isr_return:
|
||||
// Return and restore stack
|
||||
mov rsp, rdi
|
||||
pop rax
|
||||
pop rbx
|
||||
pop rcx
|
||||
pop rdx
|
||||
pop rsi
|
||||
pop rdi
|
||||
pop rbp
|
||||
pop r8
|
||||
pop r9
|
||||
pop r10
|
||||
pop r11
|
||||
pop r12
|
||||
pop r13
|
||||
pop r14
|
||||
pop r15
|
||||
// Pop error code and fault number
|
||||
add rsp, 16
|
||||
iretq
|
||||
|
||||
Reference in New Issue
Block a user