summaryrefslogtreecommitdiff
path: root/src/kernel/arch/amd64/interrupts/isr.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/kernel/arch/amd64/interrupts/isr.c')
-rw-r--r--src/kernel/arch/amd64/interrupts/isr.c26
1 files changed, 26 insertions, 0 deletions
diff --git a/src/kernel/arch/amd64/interrupts/isr.c b/src/kernel/arch/amd64/interrupts/isr.c
index 15993b2..75e9dc6 100644
--- a/src/kernel/arch/amd64/interrupts/isr.c
+++ b/src/kernel/arch/amd64/interrupts/isr.c
@@ -74,6 +74,32 @@ isr_stage3(uint8_t inr, IsrFrame *sf)
log_interrupt(inr, sf);
cpu_halt();
} else { /* in user */
+ if (inr == PageFault) {
+ char buf[64];
+ int len = snprintf(
+ buf, sizeof(buf),
+ "sys: fault %s ip=%p cr2=%p", /* format inspired by plan9 */
+ (sf->errcode & 2) ? "write" : "read",
+ sf->iret.ip,
+ getcr2()
+ );
+
+ /* save registers (ignoring SSE) */
+ proc_cur->regs = sf->regs;
+ proc_cur->regs.rsp = sf->iret.sp;
+ proc_cur->regs.rip = sf->iret.ip;
+ proc_cur->regs.flags = sf->iret.flags;
+
+ proc_intr(proc_cur, buf, len);
+ proc_intr_deliver(proc_cur);
+
+ /* restore */
+ sf->regs = proc_cur->regs;
+ sf->iret.sp = proc_cur->regs.rsp;
+ sf->iret.ip = proc_cur->regs.rip;
+ sf->iret.flags = proc_cur->regs.flags;
+ return;
+ }
proc_kill(proc_cur, inr);
proc_switch_any();
}