aboutsummaryrefslogtreecommitdiff
path: root/sys/arch/amd64/amd64
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 /sys/arch/amd64/amd64
parent54ce6d3224e68674de3036ed571a85ff09207068 (diff)
kernel/amd64: Add panic backtrace
Signed-off-by: Ian Moffett <ian@osmora.org>
Diffstat (limited to 'sys/arch/amd64/amd64')
-rw-r--r--sys/arch/amd64/amd64/machdep.c46
1 files changed, 46 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)
{