summaryrefslogtreecommitdiffstats
path: root/rsnix/src/interrupts.rs
diff options
context:
space:
mode:
authorsalmonik <salmonik@tuta.io>2026-08-02 15:21:34 +0200
committersalmonik <salmonik@tuta.io>2026-08-02 15:21:34 +0200
commitc7d92071e1dd11c45999457b16554b4abaa73b28 (patch)
treeaff7c7f19adcffe1dd91e1c2514af02c77fd524e /rsnix/src/interrupts.rs
parentv0.5.5: fix real-hardware boot crash — shadow back in heap as first allocation (diff)
downloadrs-dos-c7d92071e1dd11c45999457b16554b4abaa73b28.tar.gz
rs-dos-c7d92071e1dd11c45999457b16554b4abaa73b28.zip
v0.5.5: crash reports go to a dedicated CRASHLOG USB stick
The fault handler now writes crash.log to the volume labeled CRASHLOG (label-selected via fat::crash_vol), falling back to slot 0. On real hardware the boot USB may be unwritable, so a second stick labeled CRASHLOG survives the write; the shell auto-prints the previous crash report from it at next boot (read_crash_log resolves /disk/<uid>/crash.log through the FAT path, since Disk nodes hold no cached children). - fat.rs: volume_label() + crash_vol() (no allocation) - fs.rs: write_crash_log targets crash_vol(); read_crash_log prefers the CRASHLOG disk node; drop now-unused first_disk() - mkdisk.sh: --label option - test-fault.sh: boots with a dedicated CRASHLOG stick (mkfs -F 32 -n CRASHLOG), verifies crash.log lands there and NOT on the ESP
Diffstat (limited to '')
-rw-r--r--rsnix/src/interrupts.rs41
1 files changed, 41 insertions, 0 deletions
diff --git a/rsnix/src/interrupts.rs b/rsnix/src/interrupts.rs
index be252df..927e4f1 100644
--- a/rsnix/src/interrupts.rs
+++ b/rsnix/src/interrupts.rs
@@ -393,6 +393,38 @@ pub(crate) struct IntFrame {
393 pub(crate) ss: u64, 393 pub(crate) ss: u64,
394} 394}
395 395
396// ---------------------------------------------------------------------------
397// Fault-dump re-entry guard
398// ---------------------------------------------------------------------------
399
400/// Set when `sched::fault_dump` is running. Any CPU exception that
401/// fires *while the dump is already in progress* (typically because the
402/// heap is corrupted and the dump path tripped over it) must never
403/// recurse into the dump — that chain (#PF → #DF → #PF) is a triple
404/// fault, which silently resets the machine with no report (black
405/// screen, firmware splash — exactly what real hardware showed). The
406/// guard short-circuits to a raw heap-free band and a hard halt.
407static mut IN_DUMP: bool = false;
408
409pub fn enter_dump() {
410 unsafe {
411 IN_DUMP = true;
412 }
413}
414
415fn in_dump() -> bool {
416 unsafe { IN_DUMP }
417}
418
419/// Raw, heap-free fallback: a fault fired inside the fault dump.
420fn dump_guard_halt() -> ! {
421 crate::gop::dump_lines(&[
422 "!!! fault inside fault dump",
423 "!!! halting (no triple fault)",
424 ]);
425 halt();
426}
427
396/// Called from the asm common handler — dispatches to the right Rust 428/// Called from the asm common handler — dispatches to the right Rust
397/// handler and returns the frame pointer the asm should switch to (the 429/// handler and returns the frame pointer the asm should switch to (the
398/// next task's, or the same one when no switch happens). 430/// next task's, or the same one when no switch happens).
@@ -433,9 +465,15 @@ unsafe extern "C" fn isr_dispatch(frame: &IntFrame) -> usize {
433 8 => { 465 8 => {
434 // Double fault — dump the frame (we're on the IST stack 466 // Double fault — dump the frame (we're on the IST stack
435 // so this is safe) and halt. 467 // so this is safe) and halt.
468 if in_dump() {
469 dump_guard_halt();
470 }
436 crate::sched::fault_dump("double fault", 0, frame) 471 crate::sched::fault_dump("double fault", 0, frame)
437 } 472 }
438 14 => { 473 14 => {
474 if in_dump() {
475 dump_guard_halt();
476 }
439 let cr2: u64; 477 let cr2: u64;
440 core::arch::asm!("mov {}, cr2", out(reg) cr2, 478 core::arch::asm!("mov {}, cr2", out(reg) cr2,
441 options(nostack, preserves_flags)); 479 options(nostack, preserves_flags));
@@ -445,6 +483,9 @@ unsafe extern "C" fn isr_dispatch(frame: &IntFrame) -> usize {
445 v if v < 32 => { 483 v if v < 32 => {
446 // Any other CPU exception: full dump (screen + serial), 484 // Any other CPU exception: full dump (screen + serial),
447 // then halt the shell or abort the faulting background task. 485 // then halt the shell or abort the faulting background task.
486 if in_dump() {
487 dump_guard_halt();
488 }
448 crate::sched::fault_dump("exception", 0, frame) 489 crate::sched::fault_dump("exception", 0, frame)
449 } 490 }
450 _ => fp, 491 _ => fp,