diff options
Diffstat (limited to 'sys/kern/kern_panic.c')
-rw-r--r-- | sys/kern/kern_panic.c | 102 |
1 files changed, 95 insertions, 7 deletions
diff --git a/sys/kern/kern_panic.c b/sys/kern/kern_panic.c index 8aa7594..13b4964 100644 --- a/sys/kern/kern_panic.c +++ b/sys/kern/kern_panic.c @@ -31,6 +31,74 @@ #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 + * things ::) + * + * @do_trace: If true, a backtrace will be printed + * @reboot_type: REBOOT_* defines + */ +static void +bas(bool do_trace, int reboot_type) +{ + static struct spinlock lock = {0}; + + spinlock_acquire(&lock); /* Never released */ + + if (do_trace) { + 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 @@ -45,17 +113,37 @@ void panic(const char *fmt, ...) { va_list ap; - static struct spinlock lock = {0}; - spinlock_acquire(&lock); /* Never released */ + /* Shut everything else up */ + md_intoff(); + cpu_halt_others(); + + if (PANIC_SCR) { + panic_screen(); + } va_start(ap, fmt); + do_panic(fmt, &ap); + __builtin_unreachable(); +} - kprintf(OMIT_TIMESTAMP "panic: "); - vkprintf(fmt, &ap); +/* + * Halt and catch fire - immediately ceases all system activity + * with an optional message. + * + * @fmt: printf() format string, NULL to not + * specify any message (not recommended) + */ +void +hcf(const char *fmt, ...) +{ + va_list ap; - kprintf(OMIT_TIMESTAMP "** backtrace\n"); - md_backtrace(); + if (fmt != NULL) { + va_start(ap, fmt); + kprintf(OMIT_TIMESTAMP); + vkprintf(fmt, &ap); + } - cpu_reboot(REBOOT_HALT); + bas(true, REBOOT_HALT); __builtin_unreachable(); } |