summaryrefslogtreecommitdiffstats
path: root/rsnix/src/sched.rs
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--rsnix/src/sched.rs59
1 files changed, 52 insertions, 7 deletions
diff --git a/rsnix/src/sched.rs b/rsnix/src/sched.rs
index dbe3647..cfce58f 100644
--- a/rsnix/src/sched.rs
+++ b/rsnix/src/sched.rs
@@ -28,7 +28,9 @@ use core::fmt;
28use core::sync::atomic::{AtomicBool, AtomicU64, Ordering}; 28use core::sync::atomic::{AtomicBool, AtomicU64, Ordering};
29 29
30extern crate alloc; 30extern crate alloc;
31use alloc::format;
31use alloc::string::String; 32use alloc::string::String;
33use alloc::string::ToString;
32use alloc::vec::Vec; 34use alloc::vec::Vec;
33 35
34use crate::interrupts::IntFrame; 36use crate::interrupts::IntFrame;
@@ -280,11 +282,7 @@ pub fn spawn(entry: fn(), name: &str) -> Option<usize> {
280 }; 282 };
281 let ok = spawn_at(id, entry, name); 283 let ok = spawn_at(id, entry, name);
282 unlock(); 284 unlock();
283 if ok { 285 if ok { Some(id) } else { None }
284 Some(id)
285 } else {
286 None
287 }
288} 286}
289 287
290unsafe fn reap(id: usize) { 288unsafe fn reap(id: usize) {
@@ -548,10 +546,57 @@ pub fn abort_current(msg: &str) -> ! {
548/// Vector 14 (page fault) handler — runs on the dedicated IST stack. 546/// Vector 14 (page fault) handler — runs on the dedicated IST stack.
549/// A fault in a real task (id >= 2) kills the task gracefully; anything 547/// A fault in a real task (id >= 2) kills the task gracefully; anything
550/// else (shell, idle, pre-scheduler) is a kernel bug: halt. 548/// else (shell, idle, pre-scheduler) is a kernel bug: halt.
549/// Dump a fatal exception to serial *and* the screen (raw, bypassing the
550/// vt), then halt the shell or abort the faulting background task.
551///
552/// Real hardware has no serial console, so the screen dump is what lets
553/// a user report a crash precisely — vector, fault address, RIP and task.
554/// Runs with interrupts disabled (we're inside the ISR).
555#[allow(clippy::needless_return)]
556pub(crate) fn fault_dump(kind: &str, cr2: u64, frame: &crate::interrupts::IntFrame) -> ! {
557 let vector = frame.vector;
558 let error = frame.error;
559 let rip = frame.rip;
560 let rflags = frame.rflags;
561 let rsp = frame.rsp;
562 let id = unsafe { CURRENT };
563 let name = name_str(id);
564 let name_buf = name.to_string();
565 let in_kernel = unsafe { CURRENT } <= IDLE_TID;
566
567 // Serial: a full, parseable line.
568 crate::serial_println!(
569 "!!! {} vec={} err={:#x} rip={:#x} cr2={:#x} rsp={:#x} rflags={:#x} task={} \"{}\"",
570 kind,
571 vector,
572 error,
573 rip,
574 cr2,
575 rsp,
576 rflags,
577 id,
578 name_buf
579 );
580 crate::serial_println!("!!! halting (shell task fault — machine stops)");
581
582 // Screen: white-on-red band via the clamped raw dump path.
583 let l1 = alloc::format!("!!! {} vec={} err={:#x}", kind, vector, error);
584 let l2 = alloc::format!("rip={:#x} cr2={:#x}", rip, cr2);
585 let l3 = alloc::format!("rsp={:#x} task={} {}", rsp, id, name_buf);
586 let lines = [l1.as_str(), l2.as_str(), l3.as_str()];
587 crate::gop::dump_lines(&lines);
588
589 if in_kernel {
590 crate::interrupts::halt()
591 } else {
592 abort_current(&format!("{} vec={}", kind, vector))
593 }
594}
595
551pub fn page_fault(cr2: u64, frame_ptr: usize) -> usize { 596pub fn page_fault(cr2: u64, frame_ptr: usize) -> usize {
552 if !is_ready() || unsafe { CURRENT } <= IDLE_TID { 597 if !is_ready() || unsafe { CURRENT } <= IDLE_TID {
553 crate::serial_println!("pgfault: kernel page fault at {:#x} — halting", cr2); 598 let frame = unsafe { &*(frame_ptr as *const crate::interrupts::IntFrame) };
554 crate::interrupts::halt(); 599 fault_dump("page fault", cr2, frame)
555 } 600 }
556 let g = unsafe { TASKS[CURRENT].guard }; 601 let g = unsafe { TASKS[CURRENT].guard };
557 let in_guard = g != 0 && cr2 >= g as u64 && cr2 < (g + memory::PAGE_SIZE) as u64; 602 let in_guard = g != 0 && cr2 >= g as u64 && cr2 < (g + memory::PAGE_SIZE) as u64;