all kernel headers have been moved from include/mango to include/kernel and include definitions that are only relevant to kernel-space. any definitions that are relevant to both kernel- and user-space (i.e. type definitions, syscall IDs) have been moved to include/mango within libmango.
202 lines
3.7 KiB
C
202 lines
3.7 KiB
C
#include <arch/irq.h>
|
|
#include <kernel/libc/stdio.h>
|
|
#include <kernel/machine/cpu.h>
|
|
#include <kernel/machine/panic.h>
|
|
#include <kernel/printk.h>
|
|
#include <kernel/vm.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
|
|
|
|
struct stack_frame {
|
|
uintptr_t rbp;
|
|
uintptr_t rip;
|
|
} __attribute__((packed));
|
|
|
|
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 ml_cpu_context *ctx)
|
|
{
|
|
printk("cpu state:");
|
|
if (ctx) {
|
|
printk(" rax %016llx rbx %016llx rcx %016llx",
|
|
ctx->rax,
|
|
ctx->rbx,
|
|
ctx->rcx);
|
|
printk(" rdx %016llx rsi %016llx rdi %016llx",
|
|
ctx->rdx,
|
|
ctx->rsi,
|
|
ctx->rdi);
|
|
printk(" rsp %016llx rbp %016llx r8 %016llx",
|
|
ctx->rsp,
|
|
ctx->rbp,
|
|
ctx->r8);
|
|
printk(" r9 %016llx r10 %016llx r11 %016llx",
|
|
ctx->r9,
|
|
ctx->r10,
|
|
ctx->r11);
|
|
printk(" r12 %016llx r13 %016llx r14 %016llx",
|
|
ctx->r12,
|
|
ctx->r13,
|
|
ctx->r14);
|
|
printk(" r15 %016llx rip %016llx cs %04x ss %04x",
|
|
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);
|
|
}
|
|
|
|
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)
|
|
{
|
|
uintptr_t *bp;
|
|
asm volatile("mov %%rbp, %0" : "=r"(bp));
|
|
print_stack_trace(ip, bp);
|
|
}
|
|
|
|
void ml_print_stack_trace_irq(struct ml_cpu_context *ctx)
|
|
{
|
|
print_stack_trace(ctx->rip, (uintptr_t *)ctx->rbp);
|
|
}
|