diff options
Diffstat (limited to 'sys/kern/kern_panic.c')
-rw-r--r-- | sys/kern/kern_panic.c | 60 |
1 files changed, 54 insertions, 6 deletions
diff --git a/sys/kern/kern_panic.c b/sys/kern/kern_panic.c index 950ea8f..13b4964 100644 --- a/sys/kern/kern_panic.c +++ b/sys/kern/kern_panic.c @@ -31,6 +31,25 @@ #include <sys/spinlock.h> #include <sys/syslog.h> #include <sys/reboot.h> +#include <dev/cons/cons.h> +#include <machine/cdefs.h> +#include <machine/cpu.h> +#include <string.h> + +#if defined(__PANIC_SCR) +#define PANIC_SCR __PANIC_SCR +#else +#define PANIC_SCR 0 +#endif + +static void +panic_puts(const char *str) +{ + size_t len; + + len = strlen(str); + cons_putstr(&g_root_scr, str, len); +} /* * Burn and sizzle - the core logic that really ends @@ -47,14 +66,40 @@ bas(bool do_trace, int reboot_type) spinlock_acquire(&lock); /* Never released */ if (do_trace) { - kprintf(OMIT_TIMESTAMP "** backtrace\n"); + panic_puts(" ** backtrace\n"); md_backtrace(); } + panic_puts("\n-- ALL CORES HAVE BEEN HALTED --\n"); cpu_reboot(reboot_type); __builtin_unreachable(); } +static void +panic_screen(void) +{ + struct cons_screen *scr = &g_root_scr; + + if (scr->fb_mem != NULL) { + scr->bg = 0x8B0000; + scr->fg = 0xAABBAA; + cons_reset_cursor(scr); + cons_clear_scr(scr, 0x393B39); + } +} + +static void +do_panic(const char *fmt, va_list *ap) +{ + syslog_silence(false); + spinlock_release(&g_root_scr.lock); + panic_puts("panic: "); + vkprintf(fmt, ap); + bas(true, REBOOT_HALT); + + __builtin_unreachable(); +} + /* * Tells the user something terribly wrong happened then * halting the system as soon as possible. @@ -69,11 +114,15 @@ panic(const char *fmt, ...) { va_list ap; - va_start(ap, fmt); - kprintf(OMIT_TIMESTAMP "panic: "); - vkprintf(fmt, &ap); - bas(true, REBOOT_HALT); + /* Shut everything else up */ + md_intoff(); + cpu_halt_others(); + if (PANIC_SCR) { + panic_screen(); + } + va_start(ap, fmt); + do_panic(fmt, &ap); __builtin_unreachable(); } @@ -89,7 +138,6 @@ hcf(const char *fmt, ...) { va_list ap; - if (fmt != NULL) { va_start(ap, fmt); kprintf(OMIT_TIMESTAMP); |