diff options
Diffstat (limited to 'sys/kern/kern_panic.c')
-rw-r--r-- | sys/kern/kern_panic.c | 83 |
1 files changed, 76 insertions, 7 deletions
diff --git a/sys/kern/kern_panic.c b/sys/kern/kern_panic.c index 8aa7594..099f620 100644 --- a/sys/kern/kern_panic.c +++ b/sys/kern/kern_panic.c @@ -31,6 +31,57 @@ #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> + +/* + * 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) { + kprintf(OMIT_TIMESTAMP "** backtrace\n"); + md_backtrace(); + } + + kprintf(OMIT_TIMESTAMP "\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); + kprintf(OMIT_TIMESTAMP "panic: "); + vkprintf(fmt, ap); + bas(true, REBOOT_HALT); + + __builtin_unreachable(); +} /* * Tells the user something terribly wrong happened then @@ -45,17 +96,35 @@ 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(); + + 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(); } |