summaryrefslogtreecommitdiff
path: root/src/kernel/arch/amd64
diff options
context:
space:
mode:
authordzwdz2024-08-03 02:04:58 +0200
committerdzwdz2024-08-03 02:04:58 +0200
commit27b8676963d5d69353f44fde7faaa9a4dfe1567b (patch)
tree7c5decd1bc4b4a43a1ee331e671681830eb1d1da /src/kernel/arch/amd64
parent974c2581c9524aa7546f5863ecc26065e328cd54 (diff)
kernel: send user interrupt on page fault
I really should just rename interrupts to something else. This is inspired by Plan9 and meant to make debugging easier, as the dying process can take a stacktrace etc. It kinda sucks that the default handler now depends on fprintf, which is quite a bit of code, but whatever.
Diffstat (limited to 'src/kernel/arch/amd64')
-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();
}