Splits x86 into 32 and 64 bit (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 static void print_regs(push_regs_t *regs)
49 {
50         printk("  edi  0x%08x\n", regs->reg_edi);
51         printk("  esi  0x%08x\n", regs->reg_esi);
52         printk("  ebp  0x%08x\n", regs->reg_ebp);
53         printk("  oesp 0x%08x\n", regs->reg_oesp);
54         printk("  ebx  0x%08x\n", regs->reg_ebx);
55         printk("  edx  0x%08x\n", regs->reg_edx);
56         printk("  ecx  0x%08x\n", regs->reg_ecx);
57         printk("  eax  0x%08x\n", regs->reg_eax);
58 }
59
60 void print_trapframe(struct hw_trapframe *hw_tf)
61 {
62         static spinlock_t ptf_lock = SPINLOCK_INITIALIZER_IRQSAVE;
63
64         struct per_cpu_info *pcpui = &per_cpu_info[core_id()];
65         /* This is only called in debug scenarios, and often when the kernel trapped
66          * and needs to tell us about it.  Disable the lock checker so it doesn't go
67          * nuts when we print/panic */
68         pcpui->__lock_depth_disabled++;
69         spin_lock_irqsave(&ptf_lock);
70         printk("TRAP frame at %p on core %d\n", hw_tf, core_id());
71         print_regs(&hw_tf->tf_regs);
72         printk("  gs   0x----%04x\n", hw_tf->tf_gs);
73         printk("  fs   0x----%04x\n", hw_tf->tf_fs);
74         printk("  es   0x----%04x\n", hw_tf->tf_es);
75         printk("  ds   0x----%04x\n", hw_tf->tf_ds);
76         printk("  trap 0x%08x %s\n",  hw_tf->tf_trapno,
77                                       x86_trapname(hw_tf->tf_trapno));
78         printk("  err  0x%08x\n",     hw_tf->tf_err);
79         printk("  eip  0x%08x\n",     hw_tf->tf_eip);
80         printk("  cs   0x----%04x\n", hw_tf->tf_cs);
81         printk("  flag 0x%08x\n",     hw_tf->tf_eflags);
82         /* Prevents us from thinking these mean something for nested interrupts. */
83         if (hw_tf->tf_cs != GD_KT) {
84                 printk("  esp  0x%08x\n",     hw_tf->tf_esp);
85                 printk("  ss   0x----%04x\n", hw_tf->tf_ss);
86         }
87         spin_unlock_irqsave(&ptf_lock);
88         pcpui->__lock_depth_disabled--;
89 }
90
91 void page_fault_handler(struct hw_trapframe *hw_tf)
92 {
93         uintptr_t fault_va = rcr2();
94         int prot = hw_tf->tf_err & PF_ERROR_WRITE ? PROT_WRITE : PROT_READ;
95         int err;
96
97         /* TODO - handle kernel page faults */
98         if ((hw_tf->tf_cs & 3) == 0) {
99                 print_trapframe(hw_tf);
100                 panic("Page Fault in the Kernel at 0x%08x!", fault_va);
101                 /* if we want to do something like kill a process or other code, be
102                  * aware we are in a sort of irq-like context, meaning the main kernel
103                  * code we 'interrupted' could be holding locks - even irqsave locks. */
104         }
105         /* safe to reenable after rcr2 */
106         enable_irq();
107         if ((err = handle_page_fault(current, fault_va, prot))) {
108                 /* Destroy the faulting process */
109                 printk("[%08x] user %s fault va %08x ip %08x on core %d with err %d\n",
110                        current->pid, prot & PROT_READ ? "READ" : "WRITE", fault_va,
111                        hw_tf->tf_eip, core_id(), err);
112                 print_trapframe(hw_tf);
113                 /* Turn this on to help debug bad function pointers */
114                 printd("esp %p\n\t 0(esp): %p\n\t 4(esp): %p\n\t 8(esp): %p\n"
115                        "\t12(esp): %p\n", hw_tf->tf_esp,
116                        *(uintptr_t*)(hw_tf->tf_esp +  0),
117                        *(uintptr_t*)(hw_tf->tf_esp +  4),
118                        *(uintptr_t*)(hw_tf->tf_esp +  8),
119                        *(uintptr_t*)(hw_tf->tf_esp + 12));
120                 proc_destroy(current);
121         }
122 }
123
124 void sysenter_init(void)
125 {
126         //write_msr(MSR_IA32_SYSENTER_CS, GD_KT);
127         //write_msr(MSR_IA32_SYSENTER_ESP, ts.ts_esp0);
128         //write_msr(MSR_IA32_SYSENTER_EIP, (uint32_t) &sysenter_handler);
129 }