Overhaul lock_test.R
[akaros.git] / kern / arch / x86 / kdebug.c
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
9 void 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
19 static 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
41 size_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
70 size_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 */
92 void 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 }