x86_64: Syscall/Sysenter/int 0x80 (XCC)
[akaros.git] / kern / arch / x86 / trap64.c
1 /* Copyright (c) 2009-13 The Regents of the University of California
2  * Barret Rhoden <brho@cs.berkeley.edu>
3  * See LICENSE for details.
4  *
5  * x86 trap.c bit-specific functions. */
6
7 #include <arch/mmu.h>
8 #include <arch/x86.h>
9 #include <arch/arch.h>
10 #include <arch/console.h>
11 #include <arch/apic.h>
12 #include <ros/common.h>
13 #include <smp.h>
14 #include <assert.h>
15 #include <pmap.h>
16 #include <trap.h>
17 #include <monitor.h>
18 #include <process.h>
19 #include <mm.h>
20 #include <stdio.h>
21 #include <slab.h>
22 #include <syscall.h>
23 #include <kdebug.h>
24 #include <kmalloc.h>
25
26 /* Starts running the current TF, just using ret. */
27 void pop_kernel_ctx(struct kernel_ctx *ctx)
28 {
29         #if 0
30         asm volatile ("movl %1,%%esp;           " /* move to future stack */
31                       "pushl %2;                " /* push cs */
32                       "movl %0,%%esp;           " /* move to TF */
33                       "addl $0x20,%%esp;        " /* move to tf_gs slot */
34                       "movl %1,(%%esp);         " /* write future esp */
35                       "subl $0x20,%%esp;        " /* move back to tf start */
36                       "popal;                   " /* restore regs */
37                       "popl %%esp;              " /* set stack ptr */
38                       "subl $0x4,%%esp;         " /* jump down past CS */
39                       "ret                      " /* return to the EIP */
40                       :
41                       : "g"(&ctx->hw_tf), "r"(ctx->hw_tf.tf_esp),
42                         "r"(ctx->hw_tf.tf_eip)
43                       : "memory");
44         #endif
45         panic("ret failed");
46 }
47
48 void print_trapframe(struct hw_trapframe *hw_tf)
49 {
50         static spinlock_t ptf_lock = SPINLOCK_INITIALIZER_IRQSAVE;
51
52         struct per_cpu_info *pcpui = &per_cpu_info[core_id()];
53         /* This is only called in debug scenarios, and often when the kernel trapped
54          * and needs to tell us about it.  Disable the lock checker so it doesn't go
55          * nuts when we print/panic */
56         pcpui->__lock_depth_disabled++;
57         spin_lock_irqsave(&ptf_lock);
58         printk("HW TRAP frame at %p on core %d\n", hw_tf, core_id());
59         printk("  rax  0x%016lx\n",           hw_tf->tf_rax);
60         printk("  rbx  0x%016lx\n",           hw_tf->tf_rbx);
61         printk("  rcx  0x%016lx\n",           hw_tf->tf_rcx);
62         printk("  rdx  0x%016lx\n",           hw_tf->tf_rdx);
63         printk("  rbp  0x%016lx\n",           hw_tf->tf_rbp);
64         printk("  rsi  0x%016lx\n",           hw_tf->tf_rsi);
65         printk("  rdi  0x%016lx\n",           hw_tf->tf_rdi);
66         printk("  r8   0x%016lx\n",           hw_tf->tf_r8);
67         printk("  r9   0x%016lx\n",           hw_tf->tf_r9);
68         printk("  r10  0x%016lx\n",           hw_tf->tf_r10);
69         printk("  r11  0x%016lx\n",           hw_tf->tf_r11);
70         printk("  r12  0x%016lx\n",           hw_tf->tf_r12);
71         printk("  r13  0x%016lx\n",           hw_tf->tf_r13);
72         printk("  r14  0x%016lx\n",           hw_tf->tf_r14);
73         printk("  r15  0x%016lx\n",           hw_tf->tf_r15);
74         printk("  trap 0x%08x %s\n",          hw_tf->tf_trapno,
75                                               x86_trapname(hw_tf->tf_trapno));
76         /* FYI: these aren't physically adjacent to trap and err */
77         if (hw_tf->tf_cs == GD_KT)
78                 printk("  gsbs 0x%016lx\n",       read_msr(MSR_GS_BASE));
79         else
80                 printk("  gsbs 0x%016lx\n",       hw_tf->tf_gsbase);
81         printk("  fsbs 0x%016lx\n",           hw_tf->tf_fsbase);
82         printk("  err  0x--------%08x\n",     hw_tf->tf_err);
83         printk("  rip  0x%016lx\n",           hw_tf->tf_rip);
84         printk("  cs   0x------------%04x\n", hw_tf->tf_cs);
85         printk("  flag 0x%016lx\n",           hw_tf->tf_rflags);
86         printk("  rsp  0x%016lx\n",           hw_tf->tf_rsp);
87         printk("  ss   0x------------%04x\n", hw_tf->tf_ss);
88         spin_unlock_irqsave(&ptf_lock);
89         pcpui->__lock_depth_disabled--;
90
91         /* Used in trapentry64.S */
92         static_assert(offsetof(struct hw_trapframe, tf_cs) - 
93                       offsetof(struct hw_trapframe, tf_rax) == 0x90);
94         /* Used in trap64.h */
95         static_assert(offsetof(struct per_cpu_info, stacktop) == 0);
96 }
97
98 void print_swtrapframe(struct sw_trapframe *sw_tf)
99 {
100         static spinlock_t ptf_lock = SPINLOCK_INITIALIZER_IRQSAVE;
101         struct per_cpu_info *pcpui = &per_cpu_info[core_id()];
102         pcpui->__lock_depth_disabled++;
103         spin_lock_irqsave(&ptf_lock);
104         printk("SW TRAP frame at %p on core %d\n", sw_tf, core_id());
105         printk("  rbx  0x%016lx\n",           sw_tf->tf_rbx);
106         printk("  rbp  0x%016lx\n",           sw_tf->tf_rbp);
107         printk("  r12  0x%016lx\n",           sw_tf->tf_r12);
108         printk("  r13  0x%016lx\n",           sw_tf->tf_r13);
109         printk("  r14  0x%016lx\n",           sw_tf->tf_r14);
110         printk("  r15  0x%016lx\n",           sw_tf->tf_r15);
111         printk("  gsbs 0x%016lx\n",           sw_tf->tf_gsbase);
112         printk("  fsbs 0x%016lx\n",           sw_tf->tf_fsbase);
113         printk("  rip  0x%016lx\n",           sw_tf->tf_rip);
114         printk("  rsp  0x%016lx\n",           sw_tf->tf_rsp);
115         printk(" mxcsr 0x%08x\n",             sw_tf->tf_mxcsr);
116         printk(" fpucw 0x%04x\n",             sw_tf->tf_fpucw);
117         spin_unlock_irqsave(&ptf_lock);
118         pcpui->__lock_depth_disabled--;
119 }
120
121 void page_fault_handler(struct hw_trapframe *hw_tf)
122 {
123         uintptr_t fault_va = rcr2();
124         int prot = hw_tf->tf_err & PF_ERROR_WRITE ? PROT_WRITE : PROT_READ;
125         int err;
126
127         /* TODO - handle kernel page faults */
128         if ((hw_tf->tf_cs & 3) == 0) {
129                 print_trapframe(hw_tf);
130                 panic("Page Fault in the Kernel at 0x%08x!", fault_va);
131                 /* if we want to do something like kill a process or other code, be
132                  * aware we are in a sort of irq-like context, meaning the main kernel
133                  * code we 'interrupted' could be holding locks - even irqsave locks. */
134         }
135         /* safe to reenable after rcr2 */
136         enable_irq();
137         if ((err = handle_page_fault(current, fault_va, prot))) {
138                 /* Destroy the faulting process */
139                 printk("[%08x] user %s fault va %08x ip %08x on core %d with err %d\n",
140                        current->pid, prot & PROT_READ ? "READ" : "WRITE", fault_va,
141                        hw_tf->tf_rip, core_id(), err);
142                 print_trapframe(hw_tf);
143                 /* Turn this on to help debug bad function pointers */
144                 printd("rsp %p\n\t 0(rsp): %p\n\t 8(rsp): %p\n\t 16(rsp): %p\n"
145                        "\t24(rsp): %p\n", hw_tf->tf_rsp,
146                        *(uintptr_t*)(hw_tf->tf_rsp +  0),
147                        *(uintptr_t*)(hw_tf->tf_rsp +  8),
148                        *(uintptr_t*)(hw_tf->tf_rsp + 16),
149                        *(uintptr_t*)(hw_tf->tf_rsp + 24));
150                 proc_destroy(current);
151         }
152 }