From 82585d70771bbac69f95127b003446486623c07a Mon Sep 17 00:00:00 2001 From: Peter Mikkelsen Date: Sun, 27 Jul 2025 16:53:54 +0200 Subject: Tweaks to the interrupt handler mechanism --- Makefile | 1 + src/aplos.h | 4 ++ src/interrupt.c | 115 ++++++++++++++++++++++++++++++++++++++++---------------- src/main.c | 4 -- src/nasty.S | 33 +++++++++++----- src/paging.c | 12 ++++++ 6 files changed, 123 insertions(+), 46 deletions(-) create mode 100644 src/paging.c diff --git a/Makefile b/Makefile index c90629e..f450e04 100644 --- a/Makefile +++ b/Makefile @@ -27,6 +27,7 @@ OFILES = \ src/interrupt.o \ src/main.o \ src/nasty.o \ + src/paging.o \ src/panic.o \ src/screen.o \ src/utf8.o \ diff --git a/src/aplos.h b/src/aplos.h index e364eea..d9d6cdb 100644 --- a/src/aplos.h +++ b/src/aplos.h @@ -49,8 +49,12 @@ void disable_interrupts(void); void enable_interrupts(void); void set_gdt(struct table_reg *, uint64_t, uint64_t, uint64_t); void set_idt(struct table_reg *); +uint64_t get_cr2(void); extern void (*isr_stubs[32])(void); +/* paging.c */ +bool page_fault_handler(uint32_t); + /* panic.c */ void panic(void); diff --git a/src/interrupt.c b/src/interrupt.c index 97bc921..54f9947 100644 --- a/src/interrupt.c +++ b/src/interrupt.c @@ -1,41 +1,92 @@ #include "aplos.h" -static char8_t *descriptions[256] = { - [0] = u8"divide-by-zero-error", - [1] = u8"debug", - [2] = u8"non-maskable-interrupt", - [3] = u8"breakpoint", - [4] = u8"overflow", - [5] = u8"bound-range", - [6] = u8"invalid-opcode", - [7] = u8"device-not-available", - [8] = u8"double-fault", - [9] = u8"coprocessor-segment-overrun", - [10] = u8"invalid-tss", - [11] = u8"segment-not-present", - [12] = u8"stack", - [13] = u8"general-protection", - [14] = u8"page-fault", - [16] = u8"x87 floating-point exception-pending", - [17] = u8"alignment-check", - [18] = u8"machine-check", - [19] = u8"simd floating-point", - [21] = u8"control protection", - [28] = u8"hypervisor injection exception", - [29] = u8"vmm communication exception", - [30] = u8"security exception", +struct handler { + char8_t *description; + bool (*fn)(uint32_t code); +} handlers[256] = { + [0] = { + .description = u8"divide-by-zero-error" + }, + [1] = { + .description = u8"debug" + }, + [2] = { + .description = u8"non-maskable-interrupt" + }, + [3] = { + .description = u8"breakpoint" + }, + [4] = { + .description = u8"overflow" + }, + [5] = { + .description = u8"bound-range" + }, + [6] = { + .description = u8"invalid-opcode" + }, + [7] = { + .description = u8"device-not-available" + }, + [8] = { + .description = u8"double-fault" + }, + [9] = { + .description = u8"coprocessor-segment-overrun" + }, + [10] = { + .description = u8"invalid-tss" + }, + [11] = { + .description = u8"segment-not-present" + }, + [12] = { + .description = u8"stack" + }, + [13] = { + .description = u8"general-protection" + }, + [14] = { + .description = u8"page-fault", + .fn = page_fault_handler + }, + [16] = { + .description = u8"x87 floating-point exception-pending" + }, + [17] = { + .description = u8"alignment-check" + }, + [18] = { + .description = u8"machine-check" + }, + [19] = { + .description = u8"simd floating-point" + }, + [21] = { + .description = u8"control protection" + }, + [28] = { + .description = u8"hypervisor injection exception" + }, + [29] = { + .description = u8"vmm communication exception" + }, + [30] = { + .description = u8"security exception" + } }; void -interrupt_handler(uint8_t n) +interrupt_handler(uint8_t n, uint32_t code) { - char8_t *desc = descriptions[n]; - - print(u8"Got interrupt: %u8", n); - if(desc) - print(u8" (%s)", desc); - print(u8"\n"); - panic(); + struct handler *h = handlers+n; + bool handled; + if(h->fn) + handled = h->fn(code); + if(!handled){ + print(u8"Unhandled interrupt: %u8 (%s) with error code %x32\n", n, h->description ? h->description : u8"???", code); + panic(); + } } diff --git a/src/main.c b/src/main.c index a0c0ebc..cfec00f 100644 --- a/src/main.c +++ b/src/main.c @@ -12,10 +12,6 @@ main(struct boot_info *info) welcome(); print(u8"CPU count: %u64\n", cpu_count()); print_memmap(info); - - /* Uncomment lines below to trigger a page fault (to see if the interrupts are setup correctly) */ -// uint64_t *silly = (uint64_t *)0x1234; -// print(u8"Fun: %u64\n", *silly); } static void diff --git a/src/nasty.S b/src/nasty.S index 3f1c569..ac9fc91 100644 --- a/src/nasty.S +++ b/src/nasty.S @@ -37,6 +37,11 @@ enable_interrupts: sti ret +.global get_cr2 +get_cr2: + mov rax, cr2 + ret + #define DEFINE_ISRS \ ISR(0) \ ISR(1) \ @@ -46,20 +51,20 @@ enable_interrupts: ISR(5) \ ISR(6) \ ISR(7) \ - ISR(8) \ + ISR_E(8) \ ISR(9) \ - ISR(10) \ - ISR(11) \ - ISR(12) \ - ISR(13) \ - ISR(14) \ + ISR_E(10) \ + ISR_E(11) \ + ISR_E(12) \ + ISR_E(13) \ + ISR_E(14) \ ISR(15) \ ISR(16) \ - ISR(17) \ + ISR_E(17) \ ISR(18) \ ISR(19) \ ISR(20) \ - ISR(21) \ + ISR_E(21) \ ISR(22) \ ISR(23) \ ISR(24) \ @@ -75,13 +80,21 @@ enable_interrupts: #define ISR(n) \ isr_stub_##n: \ mov rdi, n; \ + mov rsi, 0; \ call interrupt_handler; \ iretq; +#define ISR_E(n) \ +isr_stub_##n: \ + pop rsi; \ + mov rdi, n; \ + call interrupt_handler; + iretq; DEFINE_ISRS #undef ISR +#undef ISR_E -#define ISR(n) \ - .quad isr_stub_##n; +#define ISR(n) .quad isr_stub_##n; +#define ISR_E(n) .quad isr_stub_##n; .section .data .global isr_stubs diff --git a/src/paging.c b/src/paging.c new file mode 100644 index 0000000..539b26a --- /dev/null +++ b/src/paging.c @@ -0,0 +1,12 @@ +#include "aplos.h" + +bool +page_fault_handler(uint32_t code) +{ + int write = code&0x2; + + uint64_t addr = get_cr2(); + print(u8"Page fault trying to %s %p\n", write ? u8"write to" : u8"read from", addr); + + return false; /* We didn't actually handle it */ +} -- cgit v1.2.3