summaryrefslogtreecommitdiff
path: root/sys/kern/kern_panic.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/kern/kern_panic.c')
-rw-r--r--sys/kern/kern_panic.c83
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();
}