strat9_kernel/boot/
panic.rs1use core::{
2 panic::PanicInfo,
3 sync::atomic::{AtomicBool, Ordering},
4};
5use spin::Mutex;
6use x86_64::VirtAddr;
7
8type PanicHook = fn(&PanicInfo);
9const MAX_PANIC_HOOKS: usize = 8;
10
11static PANIC_HOOKS: Mutex<[Option<PanicHook>; MAX_PANIC_HOOKS]> =
12 Mutex::new([None; MAX_PANIC_HOOKS]);
13static PANIC_IN_PROGRESS: AtomicBool = AtomicBool::new(false);
14
15pub fn register_panic_hook(hook: PanicHook) -> bool {
17 let mut hooks = PANIC_HOOKS.lock();
18 for slot in hooks.iter_mut() {
19 if slot.is_none() {
20 *slot = Some(hook);
21 return true;
22 }
23 }
24 false
25}
26
27fn run_panic_hooks(info: &PanicInfo) {
29 if let Some(hooks) = PANIC_HOOKS.try_lock() {
33 for hook in hooks.iter().flatten() {
34 hook(info);
35 }
36 }
37}
38
39fn panic_hook_dump_context(_info: &PanicInfo) {
41 let ticks = crate::process::scheduler::ticks();
42 let cr3 = crate::memory::paging::active_page_table().as_u64();
43 crate::serial_println!("panic-hook: ticks={} cr3=0x{:x}", ticks, cr3);
44 if let Some(task) = crate::process::scheduler::current_task_clone_try() {
47 crate::serial_println!(
48 "panic-hook: current_task id={} name={}",
49 task.id.as_u64(),
50 task.name
51 );
52 } else {
53 crate::serial_println!("panic-hook: current_task none (scheduler locked or idle)");
54 }
55 let fb = crate::arch::x86_64::vga::framebuffer_info();
56 crate::serial_println!(
57 "panic-hook: fb={}x{} {}bpp pitch={} text={}x{}",
58 fb.width,
59 fb.height,
60 fb.bpp,
61 fb.pitch,
62 fb.text_cols,
63 fb.text_rows
64 );
65}
66
67#[inline(always)]
69fn read_rbp() -> u64 {
70 let rbp: u64;
71 unsafe {
72 core::arch::asm!("mov {}, rbp", out(reg) rbp, options(nomem, nostack, preserves_flags));
73 }
74 rbp
75}
76
77#[inline(always)]
79fn read_rsp() -> u64 {
80 let rsp: u64;
81 unsafe {
82 core::arch::asm!("mov {}, rsp", out(reg) rsp, options(nomem, nostack, preserves_flags));
83 }
84 rsp
85}
86
87fn addr_readable(addr: u64) -> bool {
89 crate::memory::paging::translate(VirtAddr::new(addr)).is_some()
90}
91
92fn panic_hook_backtrace(_info: &PanicInfo) {
94 let mut rbp = read_rbp();
95 let rsp = read_rsp();
96 crate::serial_println!("panic-hook: stack rsp=0x{:x} rbp=0x{:x}", rsp, rbp);
97 crate::serial_println!("panic-hook: backtrace (frame-pointer)");
98
99 for i in 0..16 {
101 if rbp == 0 || (rbp & 0x7) != 0 {
102 crate::serial_println!(" #{:02}: stop (invalid rbp=0x{:x})", i, rbp);
103 break;
104 }
105 if !addr_readable(rbp) || !addr_readable(rbp.saturating_add(8)) {
106 crate::serial_println!(" #{:02}: stop (unmapped rbp=0x{:x})", i, rbp);
107 break;
108 }
109
110 let prev = unsafe { *(rbp as *const u64) };
111 let ret = unsafe { *((rbp + 8) as *const u64) };
112 crate::serial_println!(" #{:02}: rip=0x{:x} rbp=0x{:x}", i, ret, rbp);
113
114 if prev <= rbp || prev.saturating_sub(rbp) > 1024 * 1024 {
116 break;
117 }
118 rbp = prev;
119 }
120}
121
122pub fn install_default_panic_hooks() {
124 let _ = register_panic_hook(panic_hook_dump_context);
125 let _ = register_panic_hook(panic_hook_backtrace);
126}
127
128pub fn panic_handler(info: &PanicInfo) -> ! {
130 crate::arch::x86_64::serial::enter_emergency_mode();
133
134 crate::arch::x86_64::smp::broadcast_panic_halt();
136
137 if PANIC_IN_PROGRESS.swap(true, Ordering::SeqCst) {
139 loop {
140 crate::arch::x86_64::hlt();
141 }
142 }
143
144 crate::arch::x86_64::cli();
146
147 crate::serial_println!("\n\x1b[31;1m!!! KERNEL PANIC !!!\x1b[0m");
149
150 run_panic_hooks(info);
152
153 if crate::arch::x86_64::vga::is_available() {
155 if let Some(mut writer) = crate::arch::x86_64::vga::VGA_WRITER.try_lock() {
156 use core::fmt::Write;
157 writer.set_rgb_color(
158 crate::arch::x86_64::vga::RgbColor::new(0xFF, 0xE7, 0xA0),
159 crate::arch::x86_64::vga::RgbColor::new(0x3A, 0x1F, 0x00),
160 );
161 writer.clear();
162 let _ = writeln!(writer, "=== GURU MEDIATiON :: KERNEL PANiK ===");
163 if let Some(location) = info.location() {
164 let _ = writeln!(
165 writer,
166 "not kalm :: panik at {}:{}:{}",
167 location.file(),
168 location.line(),
169 location.column()
170 );
171 }
172 let _ = writeln!(writer, "Message: {}", info.message());
173 }
174 }
175
176 crate::serial_println!("=== GURU MEDIATiON :: KERNEL PANiK ===");
178 if let Some(location) = info.location() {
179 crate::serial_println!(
180 "not kalm :: panik at {}:{}:{}",
181 location.file(),
182 location.line(),
183 location.column()
184 );
185 }
186 crate::serial_println!("Message: {}", info.message());
187 crate::serial_println!("====================");
188
189 loop {
191 crate::arch::x86_64::hlt();
192 }
193}