mirror of
https://github.com/rdmsr/zag.git
synced 2026-10-27 13:58:20 +00:00
121 lines
3.1 KiB
Zig
121 lines
3.1 KiB
Zig
const std = @import("std");
|
|
const config = @import("config");
|
|
const r = @import("root");
|
|
const ksyms = @import("ksyms");
|
|
const ke = r.ke;
|
|
const ki = ke.private;
|
|
|
|
extern var text_start_addr: u8;
|
|
extern var text_end_addr: u8;
|
|
|
|
const StackFrame = struct {
|
|
prev: ?*StackFrame,
|
|
return_addr: usize,
|
|
};
|
|
|
|
const Symbol = struct {
|
|
name: []const u8,
|
|
offset: usize,
|
|
};
|
|
|
|
fn get_symbol_name(addr: usize) ?Symbol {
|
|
const symbols = ksyms.get_symbols();
|
|
|
|
// Do a binary search on the ksyms array.
|
|
// The address may not be exact, so we look for the closest
|
|
// symbol that is less than or equal to the address.
|
|
var left: usize = 0;
|
|
var right: usize = symbols.len;
|
|
while (left < right) {
|
|
const mid = left + (right - left) / 2;
|
|
const sym = symbols[mid];
|
|
if (sym.addr == addr) {
|
|
return .{ .name = sym.name_ptr[0..sym.name_len], .offset = 0 };
|
|
} else if (sym.addr < addr) {
|
|
left = mid + 1;
|
|
} else {
|
|
right = mid;
|
|
}
|
|
}
|
|
|
|
if (left > 0) {
|
|
const sym = symbols[left - 1];
|
|
|
|
if (sym.addr <= addr) {
|
|
return .{ .name = sym.name_ptr[0..sym.name_len], .offset = addr - sym.addr };
|
|
}
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
fn is_kernel_text(addr: usize) bool {
|
|
const s = @intFromPtr(&text_start_addr);
|
|
const e = @intFromPtr(&text_end_addr);
|
|
return addr >= s and addr < e;
|
|
}
|
|
|
|
fn walk_stack_frame(base: usize) void {
|
|
var frame: ?*StackFrame = @ptrFromInt(base);
|
|
var depth: usize = 0;
|
|
while (frame) |f| : (depth += 1) {
|
|
if (depth > 64) break;
|
|
const ret_addr = f.return_addr;
|
|
if (!is_kernel_text(ret_addr)) {
|
|
break;
|
|
}
|
|
const sym = get_symbol_name(ret_addr) orelse Symbol{ .name = "???", .offset = 0 };
|
|
std.log.err(" #{d} {s}+0x{x} - 0x{x}", .{ depth, sym.name, sym.offset, ret_addr });
|
|
frame = f.prev;
|
|
}
|
|
}
|
|
|
|
pub var panic_lock: ke.SpinLock = .init();
|
|
var crash_count: std.atomic.Value(u8) = .init(0);
|
|
|
|
pub fn panic_with_frame(
|
|
msg: []const u8,
|
|
frame: usize,
|
|
) noreturn {
|
|
_ = ki.impl.disable_interrupts();
|
|
|
|
std.log.info("Crash count is {} on cpu {}", .{ crash_count.load(.monotonic), ke.cpu.current() });
|
|
|
|
if (crash_count.fetchAdd(1, .monotonic) != 0) {
|
|
std.log.err("Recursive panic from CPU {}", .{ke.cpu.current()});
|
|
// Another CPU has already crashed, just freeze manually right now.
|
|
|
|
while (true) {
|
|
ki.impl.halt();
|
|
}
|
|
}
|
|
|
|
// We're the first one who actually crashed, that means we get to handle
|
|
// things like dumping the system info and freezing other CPUs. Start by
|
|
// doing the freeze.
|
|
ki.ipi.freeze_cpus();
|
|
|
|
_ = ke.ipl.raise(.High);
|
|
|
|
std.log.err("KERNEL PANIC: {s} on CPU {}, curthread is {*}", .{
|
|
msg,
|
|
ke.cpu.current(),
|
|
ki.sched.percpu.local().current_thread.?,
|
|
});
|
|
|
|
std.log.err("Stack trace:", .{});
|
|
|
|
walk_stack_frame(frame);
|
|
|
|
while (true) {
|
|
ki.impl.halt();
|
|
}
|
|
}
|
|
|
|
pub fn panic(
|
|
msg: []const u8,
|
|
_: ?usize,
|
|
) noreturn {
|
|
panic_with_frame(msg, @frameAddress());
|
|
}
|