aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIan Moffett <ian@osmora.org>2024-12-20 00:28:10 -0500
committerIan Moffett <ian@osmora.org>2024-12-20 00:29:20 -0500
commita455da84568992df1e84ba3ff45ff229ecd7c5be (patch)
tree6402a431a83501150c55ba3fa8d82345a59de752
parent54ce6d3224e68674de3036ed571a85ff09207068 (diff)
kernel/amd64: Add panic backtrace
Signed-off-by: Ian Moffett <ian@osmora.org>
-rw-r--r--sys/arch/amd64/amd64/machdep.c46
-rw-r--r--sys/include/sys/ksyms.h44
-rw-r--r--sys/include/sys/panic.h1
-rw-r--r--sys/kern/kern_panic.c3
4 files changed, 94 insertions, 0 deletions
diff --git a/sys/arch/amd64/amd64/machdep.c b/sys/arch/amd64/amd64/machdep.c
index c09ca0e..f74feb1 100644
--- a/sys/arch/amd64/amd64/machdep.c
+++ b/sys/arch/amd64/amd64/machdep.c
@@ -29,6 +29,8 @@
#include <sys/types.h>
#include <sys/syslog.h>
+#include <sys/ksyms.h>
+#include <sys/panic.h>
#include <machine/cpu.h>
#include <machine/gdt.h>
#include <machine/tss.h>
@@ -108,6 +110,50 @@ try_mitigate_spectre(void)
ibrs_enable();
}
+static const char *
+backtrace_addr_to_name(uintptr_t addr, off_t *off)
+{
+ uintptr_t prev_addr = 0;
+ const char *name = NULL;
+
+ for (size_t i = 0;;) {
+ if (g_ksym_table[i].addr > addr) {
+ *off = addr - prev_addr;
+ return name;
+ }
+
+ prev_addr = g_ksym_table[i].addr;
+ name = g_ksym_table[i].name;
+ if (g_ksym_table[i++].addr == (uint64_t)-1)
+ break;
+ }
+
+ return NULL;
+}
+
+void
+backtrace(void)
+{
+ uintptr_t *rbp;
+ uintptr_t rip;
+ off_t off;
+ const char *name;
+
+ __ASMV("mov %%rbp, %0" : "=r" (rbp) :: "memory");
+ while (1) {
+ rip = rbp[1];
+ rbp = (uintptr_t *)rbp[0];
+ name = backtrace_addr_to_name(rip, &off);
+
+ if (rbp == NULL)
+ break;
+ if (name == NULL)
+ name = "???";
+
+ kprintf(OMIT_TIMESTAMP "%p @ <%s+0x%x>\n", rip, name, off);
+ }
+}
+
void
cpu_halt_all(void)
{
diff --git a/sys/include/sys/ksyms.h b/sys/include/sys/ksyms.h
new file mode 100644
index 0000000..2862cbc
--- /dev/null
+++ b/sys/include/sys/ksyms.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2023-2024 Ian Marco Moffett and the Osmora Team.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Hyra nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _SYS_KSYMS_H_
+#define _SYS_KSYMS_H_
+
+#include <sys/cdefs.h>
+
+#if defined(_KERNEL)
+struct kernel_symbol {
+ uint64_t addr;
+ char* name;
+};
+
+__weak extern struct kernel_symbol g_ksym_table[];
+
+#endif /* defined(_KERNEL) */
+#endif
diff --git a/sys/include/sys/panic.h b/sys/include/sys/panic.h
index d3e6211..9db6a1e 100644
--- a/sys/include/sys/panic.h
+++ b/sys/include/sys/panic.h
@@ -33,6 +33,7 @@
#if defined(_KERNEL)
void panic(const char *fmt, ...);
+void backtrace(void);
#endif /* _KERNEL */
#endif /* !_SYS_PANIC_H_ */
diff --git a/sys/kern/kern_panic.c b/sys/kern/kern_panic.c
index 0a17456..af154a8 100644
--- a/sys/kern/kern_panic.c
+++ b/sys/kern/kern_panic.c
@@ -53,6 +53,9 @@ panic(const char *fmt, ...)
kprintf(OMIT_TIMESTAMP "panic: ");
vkprintf(fmt, &ap);
+ kprintf(OMIT_TIMESTAMP "** backtrace\n");
+ backtrace();
+
cpu_reboot(REBOOT_HALT);
__builtin_unreachable();
}