Files
mango/arch/x86_64/panic.c

180 lines
3.5 KiB
C
Raw Normal View History

2023-05-06 22:18:34 +01:00
#include "socks/machine/panic.h"
#include "socks/vm.h"
2023-04-09 16:35:15 +01:00
#include <socks/printk.h>
#include <socks/libc/stdio.h>
#include <arch/irq.h>
#define R_CF 0
#define R_PF 2
#define R_AF 4
#define R_ZF 6
#define R_SF 7
#define R_TF 8
#define R_IF 9
#define R_DF 10
#define R_OF 11
#define R_NT 14
#define R_VM 17
#define R_AC 18
#define R_VIF 19
#define R_VIP 20
#define R_ID 21
#define R_MAX 21
2023-05-06 22:18:34 +01:00
struct stack_frame {
uintptr_t rbp;
uintptr_t rip;
} __attribute__((packed));
2023-04-09 16:35:15 +01:00
const char *pf_rfl_name(int bit)
{
switch (bit) {
case R_CF:
return "CF";
case R_PF:
return "PF";
case R_AF:
return "AF";
case R_ZF:
return "ZF";
case R_SF:
return "SF";
case R_TF:
return "TF";
case R_IF:
return "IF";
case R_DF:
return "DF";
case R_OF:
return "OF";
case R_NT:
return "NT";
case R_VM:
return "VM";
case R_AC:
return "AC";
case R_VIF:
return "VIF";
case R_VIP:
return "VIP";
case R_ID:
return "ID";
default:
return NULL;
}
}
int pf_rfl_iopl(uint64_t flags)
{
int mask = 0x3000;
int val = flags & mask;
return val >> 12;
}
static void print_rflags(uintptr_t rflags)
{
char buf[128];
size_t buf_i = 0;
buf_i += snprintf(buf, sizeof(buf), " rfl %08lx [", rflags);
for (int i = 0; i < R_MAX; i++) {
if (rflags & (1 << i)) {
const char *name = pf_rfl_name(i);
if (name) {
buf_i += snprintf(buf + buf_i, sizeof(buf) - buf_i, " %s", name);
}
}
}
snprintf(buf + buf_i, sizeof(buf) - buf_i, " ]");
printk(buf);
}
void ml_print_cpu_state(struct cpu_context *ctx)
{
printk("cpu state:");
if (ctx) {
printk(" rax %016llx rbx %016llx rcx %016llx",
2023-04-09 16:35:15 +01:00
ctx->rax, ctx->rbx, ctx->rcx);
printk(" rdx %016llx rsi %016llx rdi %016llx",
2023-04-09 16:35:15 +01:00
ctx->rdx, ctx->rsi, ctx->rdi);
printk(" rsp %016llx rbp %016llx r8 %016llx",
2023-04-09 16:35:15 +01:00
ctx->rsp, ctx->rbp, ctx->r8);
printk(" r9 %016llx r10 %016llx r11 %016llx",
2023-04-09 16:35:15 +01:00
ctx->r9, ctx->r10, ctx->r11);
printk(" r12 %016llx r13 %016llx r14 %016llx",
2023-04-09 16:35:15 +01:00
ctx->r12, ctx->r13, ctx->r14);
printk(" r15 %016llx rip %016llx cs %04x ss %04x",
2023-04-09 16:35:15 +01:00
ctx->r15, ctx->rip, ctx->cs, ctx->ss);
print_rflags(ctx->rflags);
}
uintptr_t cr0 = 0, cr2 = 0, cr3 = 0, cr4 = 0;
asm volatile("mov %%cr0, %%rax" : "=a" (cr0));
asm volatile("mov %%cr2, %%rax" : "=a" (cr2));
asm volatile("mov %%cr3, %%rax" : "=a" (cr3));
asm volatile("mov %%cr4, %%rax" : "=a" (cr4));
printk(" cr0 %016llx cr2 %016llx", cr0, cr2);
printk(" cr3 %016llx cr4 %016llx", cr3, cr4);
2023-04-09 16:35:15 +01:00
}
2023-05-06 22:18:34 +01:00
static void print_stack_item(uintptr_t addr)
{
if (!addr) {
return;
}
char buf[64];
size_t i = 0;
i += snprintf(buf, sizeof(buf), " [<%p>] ", addr);
size_t offset = 0;
char name[128];
int found = -1;
if (found == 0 && name[0] != '\0') {
i += snprintf(buf + i, sizeof(buf) - i, "%s+0x%lx", name, offset);
} else {
i += snprintf(buf + i, sizeof(buf) - i, "?");
}
printk("%s", buf);
}
static void print_stack_trace(uintptr_t ip, uintptr_t *bp)
{
struct stack_frame *stk = (struct stack_frame *)bp;
printk("call trace:");
print_stack_item(ip);
int max_frames = 10, current_frame = 0;
while (1) {
if (!vm_virt_to_phys(stk) ||
bp == NULL ||
current_frame > max_frames) {
break;
}
uintptr_t addr = stk->rip;
print_stack_item(addr);
stk = (struct stack_frame *)stk->rbp;
current_frame++;
}
}
void ml_print_stack_trace(uintptr_t ip)
2023-04-09 16:35:15 +01:00
{
2023-05-06 22:18:34 +01:00
uintptr_t *bp;
asm volatile("mov %%rbp, %0" : "=r" (bp));
print_stack_trace(ip, bp);
}
2023-04-09 16:35:15 +01:00
2023-05-06 22:18:34 +01:00
void ml_print_stack_trace_irq(struct cpu_context *ctx)
{
print_stack_trace(ctx->rip, (uintptr_t *)ctx->rbp);
2023-04-09 16:35:15 +01:00
}