akaros/kern/arch/x86/kdebug.c
<<
>>
Prefs
   1#include <string.h>
   2#include <assert.h>
   3#include <kdebug.h>
   4#include <pmap.h>
   5#include <process.h>
   6#include <kmalloc.h>
   7#include <arch/uaccess.h>
   8
   9void gen_backtrace(void (*pfunc)(void *, const char *), void *opaque)
  10{
  11        uintptr_t pcs[MAX_BT_DEPTH];
  12        size_t nr_pcs;
  13
  14        nr_pcs = backtrace_list(get_caller_pc(), get_caller_fp(), pcs,
  15                                MAX_BT_DEPTH);
  16        print_backtrace_list(pcs, nr_pcs, pfunc, opaque);
  17}
  18
  19static bool pc_is_asm_trampoline(uintptr_t pc)
  20{
  21        extern char __asm_entry_points_start[], __asm_entry_points_end[];
  22        extern char __asm_pop_hwtf_start[], __asm_pop_hwtf_end[];
  23        extern char __asm_pop_swtf_start[], __asm_pop_swtf_end[];
  24        extern char __asm_pop_vmtf_start[], __asm_pop_vmtf_end[];
  25
  26        if (((uintptr_t)__asm_entry_points_start <= pc) &&
  27            (pc < (uintptr_t)__asm_entry_points_end))
  28                return TRUE;
  29        if (((uintptr_t)__asm_pop_hwtf_start <= pc) &&
  30            (pc < (uintptr_t)__asm_pop_hwtf_end))
  31                return TRUE;
  32        if (((uintptr_t)__asm_pop_swtf_start <= pc) &&
  33            (pc < (uintptr_t)__asm_pop_swtf_end))
  34                return TRUE;
  35        if (((uintptr_t)__asm_pop_vmtf_start <= pc) &&
  36            (pc < (uintptr_t)__asm_pop_vmtf_end))
  37                return TRUE;
  38        return FALSE;
  39}
  40
  41size_t backtrace_list(uintptr_t pc, uintptr_t fp, uintptr_t *pcs,
  42                      size_t nr_slots)
  43{
  44        size_t nr_pcs = 0;
  45
  46        while (nr_pcs < nr_slots) {
  47                pcs[nr_pcs++] = pc;
  48                printd("PC %p FP %p\n", pc, fp);
  49                if (pc_is_asm_trampoline(pc))
  50                        break;
  51                if (!fp)
  52                        break;
  53                assert(KERNBASE <= fp);
  54                /* We need to check the next FP before reading PC from beyond
  55                 * it.  FP could be 0 and be at the top of the stack, and
  56                 * reading PC in that case will be a wild read. */
  57                if (!*(uintptr_t*)fp)
  58                        break;
  59                /* We used to set PC = retaddr - 1, where the -1 would put our
  60                 * PC back inside the function that called us.  This was for
  61                 * obscure cases where a no-return function calls another
  62                 * function and has no other code after the function call.  Or
  63                 * something. */
  64                pc = *(uintptr_t*)(fp + sizeof(uintptr_t));
  65                fp = *(uintptr_t*)fp;
  66        }
  67        return nr_pcs;
  68}
  69
  70size_t backtrace_user_list(uintptr_t pc, uintptr_t fp, uintptr_t *pcs,
  71                                                   size_t nr_slots)
  72{
  73        int error;
  74        size_t nr_pcs = 0;
  75        uintptr_t frame[2];
  76
  77        while (nr_pcs < nr_slots) {
  78                pcs[nr_pcs++] = pc;
  79                if (!fp)
  80                        break;
  81                error = copy_from_user(frame, (const void *) fp, 2 *
  82                                       sizeof(uintptr_t));
  83                if (unlikely(error))
  84                        break;
  85                pc = frame[1];
  86                fp = frame[0];
  87        }
  88        return nr_pcs;
  89}
  90
  91/* Assumes 32-bit header */
  92void print_fpu_state(struct ancillary_state *fpu)
  93{
  94        print_lock();
  95        printk("fcw:        0x%04x\n", fpu->fp_head_n64.fcw);
  96        printk("fsw:        0x%04x\n", fpu->fp_head_n64.fsw);
  97        printk("ftw:          0x%02x\n", fpu->fp_head_n64.ftw);
  98        printk("fop:        0x%04x\n", fpu->fp_head_n64.fop);
  99        printk("fpu_ip: 0x%08x\n", fpu->fp_head_n64.fpu_ip);
 100        printk("cs:         0x%04x\n", fpu->fp_head_n64.cs);
 101        printk("fpu_dp: 0x%08x\n", fpu->fp_head_n64.fpu_dp);
 102        printk("ds:         0x%04x\n", fpu->fp_head_n64.ds);
 103        printk("mxcsr:  0x%08x\n", fpu->fp_head_n64.mxcsr);
 104        printk("mxcsrm: 0x%08x\n", fpu->fp_head_n64.mxcsr_mask);
 105
 106        for (int i = 0; i < sizeof(struct ancillary_state); i++) {
 107                if (i % 20 == 0)
 108                        printk("\n");
 109                printk("%02x ", *((uint8_t*)fpu + i));
 110        }
 111        printk("\n");
 112        print_unlock();
 113}
 114