Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support saving kernel crash logs using boot2dump #139

Merged
merged 2 commits into from
Dec 19, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions kernel/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ log = "0.4"
spin = "0.9.2"
goblin = { version = "0.4", default-features = false, features = ["elf64"] }
smoltcp = { version = "0.7.5", default-features = false, features = ["alloc", "proto-ipv4", "socket", "socket-raw", "socket-udp", "socket-tcp", "proto-dhcpv4", "ethernet"] }
boot2dump = { version = "0" }

# Data structues.
bitflags = "1.3.2"
Expand Down
46 changes: 45 additions & 1 deletion kernel/lang_items.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,27 @@
use core::sync::atomic::AtomicBool;

pub static PANICKED: AtomicBool = AtomicBool::new(false);
static mut KERNEL_DUMP_BUF: KernelDump = KernelDump::empty();

#[repr(C, packed)]
struct KernelDump {
/// `0xdeadbeee`
magic: u32,
/// The length of the kernel log.
len: u32,
/// The kernel log (including the panic message).
log: [u8; 4096],
}

impl KernelDump {
const fn empty() -> KernelDump {
KernelDump {
magic: 0,
len: 0,
log: [0; 4096],
}
}
}

#[alloc_error_handler]
fn alloc_error_handler(layout: core::alloc::Layout) -> ! {
Expand All @@ -11,6 +32,7 @@ fn alloc_error_handler(layout: core::alloc::Layout) -> ! {
#[panic_handler]
#[cfg(not(test))]
fn panic(info: &core::panic::PanicInfo) -> ! {
use crate::logger::KERNEL_LOG_BUF;
use core::sync::atomic::Ordering;

if PANICKED.load(Ordering::SeqCst) {
Expand All @@ -21,5 +43,27 @@ fn panic(info: &core::panic::PanicInfo) -> ! {
PANICKED.store(true, Ordering::SeqCst);
error!("{}", info);
kerla_runtime::backtrace::backtrace();
kerla_runtime::arch::halt();

unsafe {
warn!("preparing a crash dump...");
KERNEL_LOG_BUF.force_unlock();
let mut off = 0;
let mut log_buffer = KERNEL_LOG_BUF.lock();
while let Some(slice) = log_buffer.pop_slice(KERNEL_DUMP_BUF.log.len().saturating_sub(off))
{
KERNEL_DUMP_BUF.log[off..(off + slice.len())].copy_from_slice(slice);
off += slice.len();
}

KERNEL_DUMP_BUF.magic = 0xdeadbeee;
KERNEL_DUMP_BUF.len = off as u32;

warn!("prepared crash dump: log_len={}", off);
warn!("booting boot2dump...");
let dump_as_bytes = core::slice::from_raw_parts(
&KERNEL_DUMP_BUF as *const _ as *const u8,
core::mem::size_of::<KernelDump>(),
);
boot2dump::save_to_file_and_reboot("kerla.dump", dump_as_bytes);
}
}
15 changes: 11 additions & 4 deletions kernel/logger.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,18 @@ impl Printer for LoggedPrinter {
fn print_bytes(&self, s: &[u8]) {
self.inner.print_bytes(s);

// Don't write into the kernel log buffer as it may call a printk function
// due to an assertion.
if !PANICKED.load(Ordering::SeqCst) {
KERNEL_LOG_BUF.lock().push_slice(s);
if PANICKED.load(Ordering::SeqCst) {
// If kernel panics, it's uncertain whether KERNEL_LOG_BUF is in
// a dead lock.
//
// Since only single CPU can continue handling a panic, we can
// ensure it's safe to unlock it.
unsafe {
KERNEL_LOG_BUF.force_unlock();
}
}

KERNEL_LOG_BUF.lock().push_slice(s);
}
}

Expand Down