Several minor changes related to debug output. - Colorize the debugcon logger like the userspace one. - Display the process and thread for each cpu in the panic display - Skip the panic() frame in panic back traces - Don't try to follow obviously bad (non-canonical) stack frame pointers
58 lines
1.4 KiB
C++
58 lines
1.4 KiB
C++
#include "assert.h"
|
|
#include "idt.h"
|
|
|
|
namespace panic {
|
|
|
|
uint32_t *apic_icr = reinterpret_cast<uint32_t*>(0xffffc000fee00300);
|
|
void const *symbol_table = nullptr;
|
|
|
|
void
|
|
install(uintptr_t entrypoint, util::const_buffer symbol_data)
|
|
{
|
|
IDT::set_nmi_handler(entrypoint);
|
|
symbol_table = symbol_data.pointer;
|
|
}
|
|
|
|
[[ noreturn ]]
|
|
void panic(
|
|
const char *message,
|
|
const cpu_state *user,
|
|
const char *function,
|
|
const char *file,
|
|
uint64_t line)
|
|
{
|
|
cpu_data &cpu = current_cpu();
|
|
|
|
// Grab the global panic block for ourselves
|
|
cpu.panic = __atomic_exchange_n(&g_panic_data_p, nullptr, __ATOMIC_ACQ_REL);
|
|
|
|
// If we aren't the first CPU to panic, cpu.panic will be null
|
|
if (cpu.panic) {
|
|
cpu.panic->symbol_data = symbol_table;
|
|
cpu.panic->user_state = user;
|
|
|
|
cpu.panic->message = message;
|
|
cpu.panic->function = function;
|
|
cpu.panic->file = file;
|
|
cpu.panic->line = line;
|
|
|
|
cpu.panic->cpus = g_num_cpus;
|
|
|
|
static constexpr uint32_t send_nmi_command =
|
|
(4 << 8) | // Delivery mode NMI
|
|
(1 << 14) | // assert level high
|
|
(2 << 18); // destination all
|
|
|
|
*apic_icr = send_nmi_command;
|
|
}
|
|
|
|
while (1) asm ("hlt");
|
|
}
|
|
|
|
} // namespace panic
|
|
|
|
extern "C"
|
|
void __assert_fail(const char *message, const char *file, unsigned line, const char *function) {
|
|
panic::panic(message, nullptr, function, file, line);
|
|
}
|