103 lines
2.8 KiB
Rust
103 lines
2.8 KiB
Rust
//! Kernel panic handler code
|
|
use core::sync::atomic::{AtomicBool, AtomicU32, Ordering};
|
|
|
|
// use device_api::interrupt::{IpiDeliveryTarget, IpiMessage};
|
|
use kernel_arch::{Architecture, ArchitectureImpl};
|
|
use libk::{
|
|
arch::{Cpu, LocalCpu},
|
|
debug::{self, PanicLoggerSink},
|
|
device::display::console::flush_consoles,
|
|
};
|
|
use libk_util::sync::SpinFence;
|
|
|
|
use crate::arch::{Platform, PLATFORM};
|
|
|
|
static PANIC_HANDLED_FENCE: SpinFence = SpinFence::new();
|
|
|
|
// Just a simple sequencer to ensure secondary panics don't trash the screen
|
|
static PANIC_FINISHED_FENCE: SpinFence = SpinFence::new();
|
|
static PANIC_SEQUENCE: AtomicU32 = AtomicU32::new(0);
|
|
|
|
/// Panic handler for CPUs other than the one that initiated it
|
|
pub fn panic_secondary() -> ! {
|
|
// Will also mask IRQs in this section
|
|
let cpu = Cpu::local();
|
|
|
|
PANIC_HANDLED_FENCE.signal();
|
|
PANIC_FINISHED_FENCE.wait_one();
|
|
|
|
while PANIC_SEQUENCE.load(Ordering::Acquire) != cpu.id() {
|
|
core::hint::spin_loop();
|
|
}
|
|
|
|
log::error!(target: "raw", "X");
|
|
flush_consoles();
|
|
|
|
PANIC_SEQUENCE.fetch_add(1, Ordering::Release);
|
|
|
|
loop {
|
|
ArchitectureImpl::wait_for_interrupt();
|
|
}
|
|
}
|
|
|
|
fn dump_panic_info(cpu: &LocalCpu, pi: &core::panic::PanicInfo) {
|
|
let sink = PanicLoggerSink::lock();
|
|
|
|
debug::panic_log!(sink, "--- BEGIN PANIC ---\n");
|
|
debug::panic_log!(sink, "In CPU {}\n", cpu.id());
|
|
debug::panic_log!(sink, "Kernel panic");
|
|
|
|
if let Some(location) = pi.location() {
|
|
debug::panic_log!(sink, " at {}:{}:\n", location.file(), location.line());
|
|
} else {
|
|
debug::panic_log!(sink, ":\n");
|
|
}
|
|
debug::panic_log!(sink, "\n{}\n", pi.message());
|
|
debug::panic_log!(sink, "--- END PANIC ---\n");
|
|
}
|
|
|
|
pub(crate) fn panic_handler(pi: &core::panic::PanicInfo) -> ! {
|
|
let cpu = Cpu::local();
|
|
|
|
static PANIC_HAPPENED: AtomicBool = AtomicBool::new(false);
|
|
|
|
if PANIC_HAPPENED
|
|
.compare_exchange(false, true, Ordering::Release, Ordering::Acquire)
|
|
.is_ok()
|
|
{
|
|
// TODO IPI leads to triple fault sometimes in x86-64
|
|
// // Let other CPUs know we're screwed
|
|
// if unsafe {
|
|
// PLATFORM
|
|
// .send_ipi(IpiDeliveryTarget::OtherCpus, IpiMessage::Panic)
|
|
// .unwrap_or(false)
|
|
// } {
|
|
// let ap_count = ArchitectureImpl::cpu_count() - 1;
|
|
// PANIC_HANDLED_FENCE.wait_all(ap_count);
|
|
// }
|
|
|
|
// unsafe { hack_locks() };
|
|
|
|
dump_panic_info(&cpu, pi);
|
|
|
|
PANIC_FINISHED_FENCE.signal();
|
|
while PANIC_SEQUENCE.load(Ordering::Acquire) != cpu.id() {
|
|
core::hint::spin_loop();
|
|
}
|
|
|
|
log::error!(target: "raw", "X");
|
|
|
|
flush_consoles();
|
|
|
|
PANIC_SEQUENCE.fetch_add(1, Ordering::Release);
|
|
|
|
unsafe {
|
|
PLATFORM.reset();
|
|
}
|
|
}
|
|
|
|
loop {
|
|
ArchitectureImpl::wait_for_interrupt();
|
|
}
|
|
}
|