diff options
Diffstat (limited to 'src/kernel/arch/amd64/interrupts/isr.c')
-rw-r--r-- | src/kernel/arch/amd64/interrupts/isr.c | 61 |
1 files changed, 38 insertions, 23 deletions
diff --git a/src/kernel/arch/amd64/interrupts/isr.c b/src/kernel/arch/amd64/interrupts/isr.c index dd97fd4..bf84c5c 100644 --- a/src/kernel/arch/amd64/interrupts/isr.c +++ b/src/kernel/arch/amd64/interrupts/isr.c @@ -8,29 +8,48 @@ #include <stdint.h> enum { - NMI = 0x02, - GP_FAULT = 0x0d, - PAGE_FAULT = 0x0e, + Nmi = 0x02, + GpFault = 0x0d, + PageFault = 0x0e, }; +typedef struct { + uint64_t ip, cs, flags; + /* only valid if switching from/into user mode */ + uint64_t sp, ss; +} IretFrame; + void (*irq_fn[16])(void) = {0}; -static void log_interrupt(int interrupt, uint64_t *stackframe) { +static uint64_t +getcr2(void) +{ + uint64_t cr2; + asm("mov %%cr2, %0" : "=r"(cr2)); + return cr2; +} + +static void +log_interrupt(uint8_t inr, void *stackframe) +{ + IretFrame *iret = stackframe; + uint64_t *errcode = ((uint64_t*)stackframe) - 1; kprintf("interrupt %d, rip = k/%08x, cs 0x%x, code 0x%x\n", - interrupt, stackframe[0], stackframe[1], stackframe[-1]); - if ((stackframe[1] & 0x3) == 0) { - uint64_t *stack = (void*)stackframe[3]; - kprintf("kernel rip = %p, *rip = %p\n", stack, *stack); + inr, iret->ip, iret->cs, *errcode); + if ((iret->cs & 0x3) == 0) { /* ring 0? */ + uint64_t *stack = (void*)iret->sp; + kprintf("kernel rsp = %p, *rsp = %p\n", stack, *stack); } - if (interrupt == PAGE_FAULT) { - uint64_t addr = 0x69; - asm("mov %%cr2, %0" : "=r"(addr)); - kprintf("addr 0x%x\n", addr); + if (inr == PageFault) { + kprintf("addr 0x%x\n", getcr2()); } } -void isr_stage3(uint8_t interrupt, uint64_t *stackframe) { - uint8_t irqn = interrupt - IRQ_IBASE; +void +isr_stage3(uint8_t inr, void *stackframe) +{ + IretFrame *iret = stackframe; + uint8_t irqn = inr - IRQ_IBASE; if (irqn < 16) { if (irq_fn[irqn]) { irq_fn[irqn](); @@ -39,21 +58,17 @@ void isr_stage3(uint8_t interrupt, uint64_t *stackframe) { } } - if (interrupt == NMI) { /* print some debugging information */ - log_interrupt(interrupt, stackframe); + if (inr == Nmi) { /* print some debugging information */ + log_interrupt(inr, stackframe); mem_debugprint(); return; } - if (interrupt == PAGE_FAULT || interrupt == GP_FAULT) { - stackframe++; - } - - if ((stackframe[1] & 0x3) == 0) { /* in kernel */ - log_interrupt(interrupt, stackframe); + if ((iret->cs & 0x3) == 0) { /* ring 0? */ + log_interrupt(inr, stackframe); cpu_halt(); } else { /* in user */ - proc_kill(proc_cur, interrupt); + proc_kill(proc_cur, inr); proc_switch_any(); } } |