diff options
Diffstat (limited to 'src/kernel/arch')
-rw-r--r-- | src/kernel/arch/amd64/interrupts/isr.c | 26 |
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(); } |