1use crate::early_println;
6
7extern crate cfg_if;
8extern crate gimli;
9
10#[linkage = "weak"]
15#[unsafe(no_mangle)]
17pub fn __ostd_panic_handler(info: &core::panic::PanicInfo) -> ! {
18 let _irq_guard = crate::irq::disable_local();
19
20 crate::cpu_local_cell! {
21 static IN_PANIC: bool = false;
22 }
23
24 if IN_PANIC.load() {
25 early_println!("The panic handler panicked {:#?}", info);
26 abort();
27 }
28
29 IN_PANIC.store(true);
30
31 early_println!("Non-resettable panic! {:#?}", info);
32
33 print_stack_trace();
34 abort();
35}
36
37pub fn abort() -> ! {
41 crate::power::poweroff(crate::power::ExitCode::Failure);
45}
46
47#[derive(Debug)]
52pub(crate) struct PanicGuard {
53 _private: (),
54}
55
56impl Drop for PanicGuard {
57 fn drop(&mut self) {
58 early_println!("Panicked in `PanicGuard`, aborting the system");
59 abort();
60 }
61}
62
63impl PanicGuard {
64 pub(crate) fn new() -> Self {
66 PanicGuard { _private: () }
67 }
68
69 pub(crate) fn forget(self) {
74 core::mem::forget(self);
75 }
76}
77
78#[cfg(not(target_arch = "loongarch64"))]
79pub use unwinding::panic::{begin_panic, catch_unwind};
80
81#[cfg(not(target_arch = "loongarch64"))]
85pub fn print_stack_trace() {
86 use core::ffi::c_void;
87
88 use gimli::Register;
89 use unwinding::abi::{
90 _Unwind_Backtrace, _Unwind_FindEnclosingFunction, _Unwind_GetGR, _Unwind_GetIP,
91 UnwindContext, UnwindReasonCode,
92 };
93
94 use crate::{early_print, sync::SpinLock};
95
96 static BACKTRACE_PRINT_LOCK: SpinLock<()> = SpinLock::new(());
99 let _lock = BACKTRACE_PRINT_LOCK.lock();
100
101 early_println!("Printing stack trace:");
102
103 struct CallbackData {
104 counter: usize,
105 }
106 extern "C" fn callback(unwind_ctx: &UnwindContext<'_>, arg: *mut c_void) -> UnwindReasonCode {
107 let data = unsafe { &mut *(arg as *mut CallbackData) };
108 data.counter += 1;
109 let pc = _Unwind_GetIP(unwind_ctx);
110 if pc > 0 {
111 let fde_initial_address = _Unwind_FindEnclosingFunction(pc as *mut c_void) as usize;
112 early_println!(
113 "{:4}: fn {:#18x} - pc {:#18x} / registers:",
114 data.counter,
115 fde_initial_address,
116 pc,
117 );
118 }
119 for i in 0..8u16 {
122 let reg_i = _Unwind_GetGR(unwind_ctx, i as i32);
123 cfg_if::cfg_if! {
124 if #[cfg(target_arch = "x86_64")] {
125 let reg_name = gimli::X86_64::register_name(Register(i)).unwrap_or("unknown");
126 } else if #[cfg(target_arch = "riscv64")] {
127 let reg_name = gimli::RiscV::register_name(Register(i)).unwrap_or("unknown");
128 } else if #[cfg(target_arch = "aarch64")] {
129 let reg_name = gimli::AArch64::register_name(Register(i)).unwrap_or("unknown");
130 } else {
131 let reg_name = "unknown";
132 }
133 }
134 if i.is_multiple_of(4) {
135 early_print!("\n ");
136 }
137 early_print!(" {} {:#18x};", reg_name, reg_i);
138 }
139 early_print!("\n\n");
140 UnwindReasonCode::NO_REASON
141 }
142
143 let mut data = CallbackData { counter: 0 };
144 _Unwind_Backtrace(callback, &mut data as *mut _ as _);
145}
146
147#[cfg(target_arch = "loongarch64")]
149pub fn catch_unwind<R, F: FnOnce() -> R>(
150 f: F,
151) -> Result<R, alloc::boxed::Box<dyn core::any::Any + Send>> {
152 Ok(f())
154}
155
156#[cfg(target_arch = "loongarch64")]
158pub fn begin_panic<R>(_: alloc::boxed::Box<R>) {
159 }
161
162#[cfg(target_arch = "loongarch64")]
164pub fn print_stack_trace() {
165 early_println!("Printing stack trace:");
167}