mirror of
https://github.com/asterinas/asterinas.git
synced 2025-06-22 00:43:24 +00:00
Provide the way to override the panic handler.
This commit is contained in:
committed by
Tate, Hongliang Tian
parent
3c857d746e
commit
131a25c15c
29
Cargo.lock
generated
29
Cargo.lock
generated
@ -282,7 +282,7 @@ version = "0.1.0"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.77",
|
"syn 2.0.79",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -344,7 +344,7 @@ checksum = "0cc8b54b395f2fcfbb3d90c47b01c7f444d94d05bdeb775811dec868ac3bbc26"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.77",
|
"syn 2.0.79",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -514,7 +514,7 @@ dependencies = [
|
|||||||
"proc-macro-error",
|
"proc-macro-error",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.77",
|
"syn 2.0.79",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -549,7 +549,7 @@ checksum = "cb7330aeadfbe296029522e6c40f315320aba36fc43a5b3632f3795348f3bd22"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.77",
|
"syn 2.0.79",
|
||||||
"unicode-xid",
|
"unicode-xid",
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -655,7 +655,7 @@ checksum = "ba330b70a5341d3bc730b8e205aaee97ddab5d9c448c4f51a7c2d924266fa8f9"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.77",
|
"syn 2.0.79",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -755,7 +755,7 @@ version = "0.1.0"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.77",
|
"syn 2.0.79",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -1034,7 +1034,7 @@ checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.77",
|
"syn 2.0.79",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -1088,7 +1088,6 @@ version = "0.9.3"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"ostd",
|
"ostd",
|
||||||
"owo-colors 4.0.0",
|
"owo-colors 4.0.0",
|
||||||
"unwinding",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -1141,7 +1140,7 @@ dependencies = [
|
|||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"rand",
|
"rand",
|
||||||
"syn 2.0.77",
|
"syn 2.0.79",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -1369,7 +1368,7 @@ checksum = "33c85360c95e7d137454dc81d9a4ed2b8efd8fbe19cee57357b32b9771fccb67"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.77",
|
"syn 2.0.79",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -1456,9 +1455,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "syn"
|
name = "syn"
|
||||||
version = "2.0.77"
|
version = "2.0.79"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "9f35bcdf61fd8e7be6caf75f429fdca8beb3ed76584befb503b1569faee373ed"
|
checksum = "89132cd0bf050864e1d38dc3bbc07a0eb8e7530af26344d3d2bbbef83499f590"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
@ -1507,7 +1506,7 @@ checksum = "090198534930841fab3a5d1bb637cde49e339654e606195f8d9c76eeb081dc96"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.77",
|
"syn 2.0.79",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -1621,7 +1620,7 @@ checksum = "c19ee3a01d435eda42cb9931269b349d28a1762f91ddf01c68d276f74b957cc3"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.77",
|
"syn 2.0.79",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -1809,5 +1808,5 @@ checksum = "9ce1b18ccd8e73a9321186f97e46f9f04b778851177567b1975109d26a08d2a6"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.77",
|
"syn 2.0.79",
|
||||||
]
|
]
|
||||||
|
@ -6,7 +6,7 @@ extern crate #TARGET_NAME#;
|
|||||||
#[panic_handler]
|
#[panic_handler]
|
||||||
fn panic(info: &core::panic::PanicInfo) -> ! {
|
fn panic(info: &core::panic::PanicInfo) -> ! {
|
||||||
extern "Rust" {
|
extern "Rust" {
|
||||||
pub fn __aster_panic_handler(info: &core::panic::PanicInfo) -> !;
|
pub fn __ostd_panic_handler(info: &core::panic::PanicInfo) -> !;
|
||||||
}
|
}
|
||||||
unsafe { __aster_panic_handler(info); }
|
unsafe { __ostd_panic_handler(info); }
|
||||||
}
|
}
|
||||||
|
@ -11,4 +11,3 @@ repository ="https://github.com/asterinas/asterinas"
|
|||||||
[dependencies]
|
[dependencies]
|
||||||
ostd = { version = "0.9.3", path = "../../ostd" }
|
ostd = { version = "0.9.3", path = "../../ostd" }
|
||||||
owo-colors = "4.0.0"
|
owo-colors = "4.0.0"
|
||||||
unwinding = { version = "0.2.3", default-features = false, features = ["fde-gnu-eh-frame-hdr", "hide-trace", "panic", "personality", "unwinder"] }
|
|
||||||
|
@ -16,7 +16,7 @@ use alloc::{boxed::Box, collections::BTreeSet, string::String, vec::Vec};
|
|||||||
use core::{any::Any, format_args};
|
use core::{any::Any, format_args};
|
||||||
|
|
||||||
use ostd::{
|
use ostd::{
|
||||||
early_print,
|
early_print, early_println,
|
||||||
ktest::{
|
ktest::{
|
||||||
get_ktest_crate_whitelist, get_ktest_test_whitelist, KtestError, KtestItem, KtestIter,
|
get_ktest_crate_whitelist, get_ktest_test_whitelist, KtestError, KtestItem, KtestIter,
|
||||||
},
|
},
|
||||||
@ -54,11 +54,32 @@ fn main() {
|
|||||||
unreachable!("The spawn method will NOT return in the boot context")
|
unreachable!("The spawn method will NOT return in the boot context")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[ostd::ktest::panic_handler]
|
||||||
|
fn panic_handler(info: &core::panic::PanicInfo) -> ! {
|
||||||
|
let _irq_guard = ostd::trap::disable_local();
|
||||||
|
|
||||||
|
use alloc::{boxed::Box, string::ToString};
|
||||||
|
|
||||||
|
use ostd::panic::begin_panic;
|
||||||
|
|
||||||
|
let throw_info = ostd::ktest::PanicInfo {
|
||||||
|
message: info.message().to_string(),
|
||||||
|
file: info.location().unwrap().file().to_string(),
|
||||||
|
line: info.location().unwrap().line() as usize,
|
||||||
|
col: info.location().unwrap().column() as usize,
|
||||||
|
};
|
||||||
|
|
||||||
|
// Throw an exception and expecting it to be caught.
|
||||||
|
begin_panic(Box::new(throw_info.clone()));
|
||||||
|
|
||||||
|
// If not caught, abort the kernel.
|
||||||
|
early_println!("An uncaught panic occurred: {:#?}", throw_info);
|
||||||
|
|
||||||
|
ostd::prelude::abort();
|
||||||
|
}
|
||||||
|
|
||||||
/// Run all the tests registered by `#[ktest]` in the `.ktest_array` section.
|
/// Run all the tests registered by `#[ktest]` in the `.ktest_array` section.
|
||||||
///
|
///
|
||||||
/// Need to provide a print function `print` to print the test result, and a `catch_unwind`
|
|
||||||
/// implementation to catch the panic.
|
|
||||||
///
|
|
||||||
/// The `whitelist` argument is optional. If it is `None`, all tests compiled will be run.
|
/// The `whitelist` argument is optional. If it is `None`, all tests compiled will be run.
|
||||||
/// If it is `Some`, only the tests whose test path being the suffix of any paths in the whitelist
|
/// If it is `Some`, only the tests whose test path being the suffix of any paths in the whitelist
|
||||||
/// will be run.
|
/// will be run.
|
||||||
@ -129,7 +150,7 @@ fn run_crate_ktests(crate_: &KtestCrate, whitelist: &Option<SuffixTrie>) -> Ktes
|
|||||||
);
|
);
|
||||||
debug_assert_eq!(test.info().package, crate_name);
|
debug_assert_eq!(test.info().package, crate_name);
|
||||||
match test.run(
|
match test.run(
|
||||||
&(unwinding::panic::catch_unwind::<(), fn()>
|
&(ostd::panic::catch_unwind::<(), fn()>
|
||||||
as fn(fn()) -> Result<(), Box<(dyn Any + Send + 'static)>>),
|
as fn(fn()) -> Result<(), Box<(dyn Any + Send + 'static)>>),
|
||||||
) {
|
) {
|
||||||
Ok(()) => {
|
Ok(()) => {
|
||||||
|
@ -31,8 +31,6 @@ pub fn main(_attr: TokenStream, item: TokenStream) -> TokenStream {
|
|||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
#[linkage = "weak"]
|
#[linkage = "weak"]
|
||||||
extern "Rust" fn __ostd_main() -> ! {
|
extern "Rust" fn __ostd_main() -> ! {
|
||||||
// SAFETY: The function is called only once on the BSP.
|
|
||||||
unsafe { ostd::init() };
|
|
||||||
#main_fn_name();
|
#main_fn_name();
|
||||||
ostd::prelude::abort();
|
ostd::prelude::abort();
|
||||||
}
|
}
|
||||||
@ -58,8 +56,6 @@ pub fn test_main(_attr: TokenStream, item: TokenStream) -> TokenStream {
|
|||||||
quote!(
|
quote!(
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
extern "Rust" fn __ostd_main() -> ! {
|
extern "Rust" fn __ostd_main() -> ! {
|
||||||
// SAFETY: The function is called only once on the BSP.
|
|
||||||
unsafe { ostd::init() };
|
|
||||||
#main_fn_name();
|
#main_fn_name();
|
||||||
ostd::prelude::abort();
|
ostd::prelude::abort();
|
||||||
}
|
}
|
||||||
@ -69,6 +65,49 @@ pub fn test_main(_attr: TokenStream, item: TokenStream) -> TokenStream {
|
|||||||
.into()
|
.into()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A macro attribute for the panic handler.
|
||||||
|
///
|
||||||
|
/// The attributed function will be used to override OSTD's default
|
||||||
|
/// implementation of Rust's `#[panic_handler]`. The function takes a single
|
||||||
|
/// parameter of type `&core::panic::PanicInfo` and does not return.
|
||||||
|
#[proc_macro_attribute]
|
||||||
|
pub fn panic_handler(_attr: TokenStream, item: TokenStream) -> TokenStream {
|
||||||
|
let handler_fn = parse_macro_input!(item as ItemFn);
|
||||||
|
let handler_fn_name = &handler_fn.sig.ident;
|
||||||
|
|
||||||
|
quote!(
|
||||||
|
#[cfg(not(ktest))]
|
||||||
|
#[no_mangle]
|
||||||
|
extern "Rust" fn __ostd_panic_handler(info: &core::panic::PanicInfo) -> ! {
|
||||||
|
#handler_fn_name(info);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(not(ktest))]
|
||||||
|
#handler_fn
|
||||||
|
)
|
||||||
|
.into()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A macro attribute for the panic handler.
|
||||||
|
///
|
||||||
|
/// This macro is used for internal OSDK implementation. Do not use it
|
||||||
|
/// directly.
|
||||||
|
#[proc_macro_attribute]
|
||||||
|
pub fn test_panic_handler(_attr: TokenStream, item: TokenStream) -> TokenStream {
|
||||||
|
let handler_fn = parse_macro_input!(item as ItemFn);
|
||||||
|
let handler_fn_name = &handler_fn.sig.ident;
|
||||||
|
|
||||||
|
quote!(
|
||||||
|
#[no_mangle]
|
||||||
|
extern "Rust" fn __ostd_panic_handler(info: &core::panic::PanicInfo) -> ! {
|
||||||
|
#handler_fn_name(info);
|
||||||
|
}
|
||||||
|
|
||||||
|
#handler_fn
|
||||||
|
)
|
||||||
|
.into()
|
||||||
|
}
|
||||||
|
|
||||||
/// The test attribute macro to mark a test function.
|
/// The test attribute macro to mark a test function.
|
||||||
///
|
///
|
||||||
/// # Example
|
/// # Example
|
||||||
|
@ -75,7 +75,6 @@ pub struct PanicInfo {
|
|||||||
pub file: String,
|
pub file: String,
|
||||||
pub line: usize,
|
pub line: usize,
|
||||||
pub col: usize,
|
pub col: usize,
|
||||||
pub resolve_panic: fn(),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl core::fmt::Display for PanicInfo {
|
impl core::fmt::Display for PanicInfo {
|
||||||
@ -163,7 +162,6 @@ impl KtestItem {
|
|||||||
Ok(()) => Err(KtestError::ShouldPanicButNoPanic),
|
Ok(()) => Err(KtestError::ShouldPanicButNoPanic),
|
||||||
Err(e) => match e.downcast::<PanicInfo>() {
|
Err(e) => match e.downcast::<PanicInfo>() {
|
||||||
Ok(s) => {
|
Ok(s) => {
|
||||||
(s.resolve_panic)();
|
|
||||||
if let Some(expected) = self.should_panic.1 {
|
if let Some(expected) = self.should_panic.1 {
|
||||||
if s.message == expected {
|
if s.message == expected {
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -68,7 +68,7 @@ pub struct CallbackElement {
|
|||||||
|
|
||||||
impl CallbackElement {
|
impl CallbackElement {
|
||||||
pub fn call(&self, element: &TrapFrame) {
|
pub fn call(&self, element: &TrapFrame) {
|
||||||
self.function.call((element,));
|
(self.function)(element);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -118,12 +118,18 @@ pub fn init() {
|
|||||||
///
|
///
|
||||||
/// This function should be only called from the bootloader-specific module.
|
/// This function should be only called from the bootloader-specific module.
|
||||||
pub(crate) fn call_ostd_main() -> ! {
|
pub(crate) fn call_ostd_main() -> ! {
|
||||||
unsafe {
|
|
||||||
// The entry point of kernel code, which should be defined by the package that
|
// The entry point of kernel code, which should be defined by the package that
|
||||||
// uses OSTD.
|
// uses OSTD.
|
||||||
extern "Rust" {
|
extern "Rust" {
|
||||||
fn __ostd_main() -> !;
|
fn __ostd_main() -> !;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SAFETY: The function is called only once on the BSP.
|
||||||
|
unsafe { crate::init() };
|
||||||
|
|
||||||
|
// SAFETY: This external function is defined by the package that uses OSTD,
|
||||||
|
// which should be generated by the `ostd::main` macro. So it is safe.
|
||||||
|
unsafe {
|
||||||
__ostd_main();
|
__ostd_main();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -11,6 +11,7 @@
|
|||||||
#![feature(generic_const_exprs)]
|
#![feature(generic_const_exprs)]
|
||||||
#![feature(iter_from_coroutine)]
|
#![feature(iter_from_coroutine)]
|
||||||
#![feature(let_chains)]
|
#![feature(let_chains)]
|
||||||
|
#![feature(linkage)]
|
||||||
#![feature(min_specialization)]
|
#![feature(min_specialization)]
|
||||||
#![feature(negative_impls)]
|
#![feature(negative_impls)]
|
||||||
#![feature(ptr_sub_ptr)]
|
#![feature(ptr_sub_ptr)]
|
||||||
@ -36,7 +37,7 @@ mod error;
|
|||||||
pub mod io_mem;
|
pub mod io_mem;
|
||||||
pub mod logger;
|
pub mod logger;
|
||||||
pub mod mm;
|
pub mod mm;
|
||||||
pub mod panicking;
|
pub mod panic;
|
||||||
pub mod prelude;
|
pub mod prelude;
|
||||||
pub mod smp;
|
pub mod smp;
|
||||||
pub mod sync;
|
pub mod sync;
|
||||||
@ -47,7 +48,7 @@ pub mod user;
|
|||||||
|
|
||||||
use core::sync::atomic::AtomicBool;
|
use core::sync::atomic::AtomicBool;
|
||||||
|
|
||||||
pub use ostd_macros::main;
|
pub use ostd_macros::{main, panic_handler};
|
||||||
pub use ostd_pod::Pod;
|
pub use ostd_pod::Pod;
|
||||||
|
|
||||||
pub use self::{error::Error, prelude::Result};
|
pub use self::{error::Error, prelude::Result};
|
||||||
@ -65,7 +66,7 @@ pub use self::{error::Error, prelude::Result};
|
|||||||
// make inter-initialization-dependencies more clear and reduce usages of
|
// make inter-initialization-dependencies more clear and reduce usages of
|
||||||
// boot stage only global variables.
|
// boot stage only global variables.
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
pub unsafe fn init() {
|
unsafe fn init() {
|
||||||
arch::enable_cpu_features();
|
arch::enable_cpu_features();
|
||||||
arch::serial::init();
|
arch::serial::init();
|
||||||
|
|
||||||
@ -153,6 +154,6 @@ pub mod ktest {
|
|||||||
//! It is rather discouraged to use the definitions here directly. The
|
//! It is rather discouraged to use the definitions here directly. The
|
||||||
//! `ktest` attribute is sufficient for all normal use cases.
|
//! `ktest` attribute is sufficient for all normal use cases.
|
||||||
|
|
||||||
pub use ostd_macros::test_main as main;
|
pub use ostd_macros::{test_main as main, test_panic_handler as panic_handler};
|
||||||
pub use ostd_test::*;
|
pub use ostd_test::*;
|
||||||
}
|
}
|
||||||
|
@ -4,60 +4,45 @@
|
|||||||
|
|
||||||
use core::ffi::c_void;
|
use core::ffi::c_void;
|
||||||
|
|
||||||
|
pub use unwinding::panic::{begin_panic, catch_unwind};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
arch::qemu::{exit_qemu, QemuExitCode},
|
arch::qemu::{exit_qemu, QemuExitCode},
|
||||||
cpu_local_cell, early_print, early_println,
|
early_print, early_println,
|
||||||
sync::SpinLock,
|
sync::SpinLock,
|
||||||
};
|
};
|
||||||
|
|
||||||
extern crate cfg_if;
|
extern crate cfg_if;
|
||||||
extern crate gimli;
|
extern crate gimli;
|
||||||
|
|
||||||
use gimli::Register;
|
use gimli::Register;
|
||||||
use unwinding::abi::{
|
use unwinding::abi::{
|
||||||
UnwindContext, UnwindReasonCode, _Unwind_Backtrace, _Unwind_FindEnclosingFunction,
|
UnwindContext, UnwindReasonCode, _Unwind_Backtrace, _Unwind_FindEnclosingFunction,
|
||||||
_Unwind_GetGR, _Unwind_GetIP,
|
_Unwind_GetGR, _Unwind_GetIP,
|
||||||
};
|
};
|
||||||
|
|
||||||
cpu_local_cell! {
|
/// The default panic handler for OSTD based kernels.
|
||||||
|
///
|
||||||
|
/// The user can override it by defining their own panic handler with the macro
|
||||||
|
/// `#[ostd::panic_handler]`.
|
||||||
|
#[cfg(not(ktest))]
|
||||||
|
#[no_mangle]
|
||||||
|
pub fn __ostd_panic_handler(info: &core::panic::PanicInfo) -> ! {
|
||||||
|
let _irq_guard = crate::trap::disable_local();
|
||||||
|
|
||||||
|
crate::cpu_local_cell! {
|
||||||
static IN_PANIC: bool = false;
|
static IN_PANIC: bool = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The asterinas panic handler.
|
|
||||||
///
|
|
||||||
/// The panic handler must be defined in the binary crate or in the crate that the binary
|
|
||||||
/// crate explicitly declares by `extern crate`. We cannot let the base crate depend on OSTD
|
|
||||||
/// due to prismatic dependencies. That's why we export this symbol and state the
|
|
||||||
/// panic handler in the binary crate.
|
|
||||||
#[export_name = "__aster_panic_handler"]
|
|
||||||
pub fn panic_handler(info: &core::panic::PanicInfo) -> ! {
|
|
||||||
let _irq_guard = crate::trap::disable_local();
|
|
||||||
|
|
||||||
if IN_PANIC.load() {
|
if IN_PANIC.load() {
|
||||||
early_println!("{}", info);
|
early_println!("The panic handler panicked {:#?}", info);
|
||||||
early_println!("The panic handler panicked when processing the above panic. Aborting.");
|
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
|
|
||||||
// If in ktest, we would like to catch the panics and resume the test.
|
IN_PANIC.store(true);
|
||||||
#[cfg(ktest)]
|
|
||||||
{
|
|
||||||
use alloc::{boxed::Box, string::ToString};
|
|
||||||
|
|
||||||
use unwinding::panic::begin_panic;
|
early_println!("Non-resettable panic! {:#?}", info);
|
||||||
|
|
||||||
let throw_info = ostd_test::PanicInfo {
|
|
||||||
message: info.message().to_string(),
|
|
||||||
file: info.location().unwrap().file().to_string(),
|
|
||||||
line: info.location().unwrap().line() as usize,
|
|
||||||
col: info.location().unwrap().column() as usize,
|
|
||||||
resolve_panic: || {
|
|
||||||
IN_PANIC.store(false);
|
|
||||||
},
|
|
||||||
};
|
|
||||||
// Throw an exception and expecting it to be caught.
|
|
||||||
begin_panic(Box::new(throw_info.clone()));
|
|
||||||
}
|
|
||||||
early_println!("{}", info);
|
|
||||||
print_stack_trace();
|
print_stack_trace();
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
@ -67,7 +52,10 @@ pub fn abort() -> ! {
|
|||||||
exit_qemu(QemuExitCode::Failed);
|
exit_qemu(QemuExitCode::Failed);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn print_stack_trace() {
|
/// Prints the stack trace of the current thread to the console.
|
||||||
|
///
|
||||||
|
/// The printing procedure is protected by a spin lock to prevent interleaving.
|
||||||
|
pub fn print_stack_trace() {
|
||||||
/// We acquire a global lock to prevent the frames in the stack trace from
|
/// We acquire a global lock to prevent the frames in the stack trace from
|
||||||
/// interleaving. The spin lock is used merely for its simplicity.
|
/// interleaving. The spin lock is used merely for its simplicity.
|
||||||
static BACKTRACE_PRINT_LOCK: SpinLock<()> = SpinLock::new(());
|
static BACKTRACE_PRINT_LOCK: SpinLock<()> = SpinLock::new(());
|
||||||
@ -98,6 +86,10 @@ fn print_stack_trace() {
|
|||||||
cfg_if::cfg_if! {
|
cfg_if::cfg_if! {
|
||||||
if #[cfg(target_arch = "x86_64")] {
|
if #[cfg(target_arch = "x86_64")] {
|
||||||
let reg_name = gimli::X86_64::register_name(Register(i)).unwrap_or("unknown");
|
let reg_name = gimli::X86_64::register_name(Register(i)).unwrap_or("unknown");
|
||||||
|
} else if #[cfg(target_arch = "riscv64")] {
|
||||||
|
let reg_name = gimli::RiscV::register_name(Register(i)).unwrap_or("unknown");
|
||||||
|
} else if #[cfg(target_arch = "aarch64")] {
|
||||||
|
let reg_name = gimli::AArch64::register_name(Register(i)).unwrap_or("unknown");
|
||||||
} else {
|
} else {
|
||||||
let reg_name = "unknown";
|
let reg_name = "unknown";
|
||||||
}
|
}
|
@ -15,5 +15,5 @@ pub use ostd_macros::ktest;
|
|||||||
pub use crate::{
|
pub use crate::{
|
||||||
early_print as print, early_println as println,
|
early_print as print, early_println as println,
|
||||||
mm::{Paddr, Vaddr},
|
mm::{Paddr, Vaddr},
|
||||||
panicking::abort,
|
panic::abort,
|
||||||
};
|
};
|
||||||
|
@ -170,7 +170,7 @@ impl TaskOptions {
|
|||||||
extern "C" fn kernel_task_entry() {
|
extern "C" fn kernel_task_entry() {
|
||||||
let current_task = current_task()
|
let current_task = current_task()
|
||||||
.expect("no current task, it should have current task in kernel task entry");
|
.expect("no current task, it should have current task in kernel task entry");
|
||||||
current_task.func.call(());
|
(current_task.func)();
|
||||||
current_task.exit();
|
current_task.exit();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user