diff options
Diffstat (limited to 'src/kernel/arch/amd64')
-rw-r--r-- | src/kernel/arch/amd64/interrupts.h | 3 | ||||
-rw-r--r-- | src/kernel/arch/amd64/interrupts/isr.c | 22 | ||||
-rw-r--r-- | src/kernel/arch/amd64/interrupts/isr_stub.s | 36 |
3 files changed, 43 insertions, 18 deletions
diff --git a/src/kernel/arch/amd64/interrupts.h b/src/kernel/arch/amd64/interrupts.h index 288bd78..f968906 100644 --- a/src/kernel/arch/amd64/interrupts.h +++ b/src/kernel/arch/amd64/interrupts.h @@ -11,7 +11,8 @@ extern void (*irq_fn[16])(void); extern const char _isr_stubs; +struct IsrFrame; void irq_init(void); void irq_eoi(uint8_t line); -void isr_stage3(uint8_t interrupt, void *stackframe); +void isr_stage3(uint8_t interrupt, struct IsrFrame *stackframe); diff --git a/src/kernel/arch/amd64/interrupts/isr.c b/src/kernel/arch/amd64/interrupts/isr.c index bf84c5c..15993b2 100644 --- a/src/kernel/arch/amd64/interrupts/isr.c +++ b/src/kernel/arch/amd64/interrupts/isr.c @@ -19,6 +19,13 @@ typedef struct { uint64_t sp, ss; } IretFrame; +typedef struct IsrFrame { + UserRegs regs; /* doesn't include ip, flags, sp */ + uint64_t _retaddr; + uint64_t errcode; + IretFrame iret; +} __attribute__((packed)) IsrFrame; + void (*irq_fn[16])(void) = {0}; static uint64_t @@ -30,12 +37,11 @@ getcr2(void) } static void -log_interrupt(uint8_t inr, void *stackframe) +log_interrupt(uint8_t inr, IsrFrame *sf) { - IretFrame *iret = stackframe; - uint64_t *errcode = ((uint64_t*)stackframe) - 1; + IretFrame *iret = &sf->iret; kprintf("interrupt %d, rip = k/%08x, cs 0x%x, code 0x%x\n", - inr, iret->ip, iret->cs, *errcode); + inr, iret->ip, iret->cs, sf->errcode); if ((iret->cs & 0x3) == 0) { /* ring 0? */ uint64_t *stack = (void*)iret->sp; kprintf("kernel rsp = %p, *rsp = %p\n", stack, *stack); @@ -46,9 +52,9 @@ log_interrupt(uint8_t inr, void *stackframe) } void -isr_stage3(uint8_t inr, void *stackframe) +isr_stage3(uint8_t inr, IsrFrame *sf) { - IretFrame *iret = stackframe; + IretFrame *iret = &sf->iret; uint8_t irqn = inr - IRQ_IBASE; if (irqn < 16) { if (irq_fn[irqn]) { @@ -59,13 +65,13 @@ isr_stage3(uint8_t inr, void *stackframe) } if (inr == Nmi) { /* print some debugging information */ - log_interrupt(inr, stackframe); + log_interrupt(inr, sf); mem_debugprint(); return; } if ((iret->cs & 0x3) == 0) { /* ring 0? */ - log_interrupt(inr, stackframe); + log_interrupt(inr, sf); cpu_halt(); } else { /* in user */ proc_kill(proc_cur, inr); diff --git a/src/kernel/arch/amd64/interrupts/isr_stub.s b/src/kernel/arch/amd64/interrupts/isr_stub.s index 3134808..5604f19 100644 --- a/src/kernel/arch/amd64/interrupts/isr_stub.s +++ b/src/kernel/arch/amd64/interrupts/isr_stub.s @@ -22,18 +22,27 @@ _isr_stubs: .endr _isr_stage2: - /* pushal order, without %esp. 15 in total */ + /* UserRegs */ + /* I'm skipping fields that are in the IRET stack frame + * on the assumption it's easier to deal with them from C. */ + push $0 /* flags */ + push $0 /* ip */ + push %rax push %rcx push %rdx push %rbx + + push $0 /* rsp */ push %rbp push %rsi push %rdi + push %r8 push %r9 push %r10 push %r11 + push %r12 push %r13 push %r14 @@ -45,15 +54,15 @@ _isr_stage2: // basically if you're context switching, FXSAVE /* first argument: vector nr. computed from the return address at offset - * 15*8 = 120 */ - mov 120(%rsp), %rdi + * 18*8 = 144 */ + mov 144(%rsp), %rdi sub $_isr_stubs, %rdi shr $3, %rdi - /* second argument: IRET stack frame */ - lea 136(%rsp), %rsi + /* second argument: stack frame */ + mov %rsp, %rsi - // load kernel paging + /* load kernel paging */ mov %cr3, %rbx push %rbx mov $pml4_identity, %rbx @@ -64,27 +73,36 @@ _isr_stage2: call isr_stage3 mov %rbp, %rsp - pop %rax // restore old cr3 + pop %rax /* restore old cr3 */ mov %rax, %cr3 - // restore registers + /* restore registers */ pop %r15 pop %r14 pop %r13 pop %r12 + pop %r11 pop %r10 pop %r9 pop %r8 + pop %rdi pop %rsi pop %rbp + pop %rbx /* skip rsp */ + pop %rbx pop %rdx pop %rcx pop %rax - add $16, %rsp /* skip return address from call and the error code */ + /* skips: + * UserRegs.ip + * UserRegs.flags + * return address from the CALL in the stub + * error code */ + add $32, %rsp iretq .align 8 |