summaryrefslogtreecommitdiff
path: root/src/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'src/kernel')
-rw-r--r--src/kernel/arch/amd64/interrupts.h3
-rw-r--r--src/kernel/arch/amd64/interrupts/isr.c22
-rw-r--r--src/kernel/arch/amd64/interrupts/isr_stub.s36
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