diff options
Diffstat (limited to '')
| -rw-r--r-- | rsnix/src/sched.rs | 59 |
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; | |||
| 28 | use core::sync::atomic::{AtomicBool, AtomicU64, Ordering}; | 28 | use core::sync::atomic::{AtomicBool, AtomicU64, Ordering}; |
| 29 | 29 | ||
| 30 | extern crate alloc; | 30 | extern crate alloc; |
| 31 | use alloc::format; | ||
| 31 | use alloc::string::String; | 32 | use alloc::string::String; |
| 33 | use alloc::string::ToString; | ||
| 32 | use alloc::vec::Vec; | 34 | use alloc::vec::Vec; |
| 33 | 35 | ||
| 34 | use crate::interrupts::IntFrame; | 36 | use 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 | ||
| 290 | unsafe fn reap(id: usize) { | 288 | unsafe 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)] | ||
| 556 | pub(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 | |||
| 551 | pub fn page_fault(cr2: u64, frame_ptr: usize) -> usize { | 596 | pub 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; |
