1 /* Copyright (c) 2009-13 The Regents of the University of California
2 * Barret Rhoden <brho@cs.berkeley.edu>
3 * See LICENSE for details.
5 * x86 trap.c bit-specific functions. */
10 #include <arch/console.h>
11 #include <arch/apic.h>
12 #include <ros/common.h>
26 /* Starts running the current TF, just using ret. */
27 void pop_kernel_ctx(struct kernel_ctx *ctx)
29 struct sw_trapframe *tf = &ctx->sw_tf;
30 /* We're starting at rbx's spot in the sw_tf */
31 asm volatile ("movq %0, %%rsp; "
38 "popq %%rax; " /* pop rip */
40 "jmp *%%rax; " /* stored rip */
41 : : "g"(&ctx->sw_tf.tf_rbx) : "memory");
45 void print_trapframe(struct hw_trapframe *hw_tf)
47 static spinlock_t ptf_lock = SPINLOCK_INITIALIZER_IRQSAVE;
49 struct per_cpu_info *pcpui = &per_cpu_info[core_id()];
50 /* This is only called in debug scenarios, and often when the kernel trapped
51 * and needs to tell us about it. Disable the lock checker so it doesn't go
52 * nuts when we print/panic */
53 pcpui->__lock_depth_disabled++;
54 spin_lock_irqsave(&ptf_lock);
55 printk("HW TRAP frame at %p on core %d\n", hw_tf, core_id());
56 printk(" rax 0x%016lx\n", hw_tf->tf_rax);
57 printk(" rbx 0x%016lx\n", hw_tf->tf_rbx);
58 printk(" rcx 0x%016lx\n", hw_tf->tf_rcx);
59 printk(" rdx 0x%016lx\n", hw_tf->tf_rdx);
60 printk(" rbp 0x%016lx\n", hw_tf->tf_rbp);
61 printk(" rsi 0x%016lx\n", hw_tf->tf_rsi);
62 printk(" rdi 0x%016lx\n", hw_tf->tf_rdi);
63 printk(" r8 0x%016lx\n", hw_tf->tf_r8);
64 printk(" r9 0x%016lx\n", hw_tf->tf_r9);
65 printk(" r10 0x%016lx\n", hw_tf->tf_r10);
66 printk(" r11 0x%016lx\n", hw_tf->tf_r11);
67 printk(" r12 0x%016lx\n", hw_tf->tf_r12);
68 printk(" r13 0x%016lx\n", hw_tf->tf_r13);
69 printk(" r14 0x%016lx\n", hw_tf->tf_r14);
70 printk(" r15 0x%016lx\n", hw_tf->tf_r15);
71 printk(" trap 0x%08x %s\n", hw_tf->tf_trapno,
72 x86_trapname(hw_tf->tf_trapno));
73 /* FYI: these aren't physically adjacent to trap and err */
74 if (hw_tf->tf_cs == GD_KT)
75 printk(" gsbs 0x%016lx\n", read_msr(MSR_GS_BASE));
77 printk(" gsbs 0x%016lx\n", hw_tf->tf_gsbase);
78 printk(" fsbs 0x%016lx\n", hw_tf->tf_fsbase);
79 printk(" err 0x--------%08x\n", hw_tf->tf_err);
80 printk(" rip 0x%016lx\n", hw_tf->tf_rip);
81 printk(" cs 0x------------%04x\n", hw_tf->tf_cs);
82 printk(" flag 0x%016lx\n", hw_tf->tf_rflags);
83 printk(" rsp 0x%016lx\n", hw_tf->tf_rsp);
84 printk(" ss 0x------------%04x\n", hw_tf->tf_ss);
85 spin_unlock_irqsave(&ptf_lock);
86 pcpui->__lock_depth_disabled--;
88 /* Used in trapentry64.S */
89 static_assert(offsetof(struct hw_trapframe, tf_cs) -
90 offsetof(struct hw_trapframe, tf_rax) == 0x90);
91 /* Used in trap64.h */
92 static_assert(offsetof(struct per_cpu_info, stacktop) == 0);
95 void print_swtrapframe(struct sw_trapframe *sw_tf)
97 static spinlock_t ptf_lock = SPINLOCK_INITIALIZER_IRQSAVE;
98 struct per_cpu_info *pcpui = &per_cpu_info[core_id()];
99 pcpui->__lock_depth_disabled++;
100 spin_lock_irqsave(&ptf_lock);
101 printk("SW TRAP frame at %p on core %d\n", sw_tf, core_id());
102 printk(" rbx 0x%016lx\n", sw_tf->tf_rbx);
103 printk(" rbp 0x%016lx\n", sw_tf->tf_rbp);
104 printk(" r12 0x%016lx\n", sw_tf->tf_r12);
105 printk(" r13 0x%016lx\n", sw_tf->tf_r13);
106 printk(" r14 0x%016lx\n", sw_tf->tf_r14);
107 printk(" r15 0x%016lx\n", sw_tf->tf_r15);
108 printk(" gsbs 0x%016lx\n", sw_tf->tf_gsbase);
109 printk(" fsbs 0x%016lx\n", sw_tf->tf_fsbase);
110 printk(" rip 0x%016lx\n", sw_tf->tf_rip);
111 printk(" rsp 0x%016lx\n", sw_tf->tf_rsp);
112 printk(" mxcsr 0x%08x\n", sw_tf->tf_mxcsr);
113 printk(" fpucw 0x%04x\n", sw_tf->tf_fpucw);
114 spin_unlock_irqsave(&ptf_lock);
115 pcpui->__lock_depth_disabled--;
118 void page_fault_handler(struct hw_trapframe *hw_tf)
120 uintptr_t fault_va = rcr2();
121 int prot = hw_tf->tf_err & PF_ERROR_WRITE ? PROT_WRITE : PROT_READ;
124 /* TODO - handle kernel page faults */
125 if ((hw_tf->tf_cs & 3) == 0) {
126 print_trapframe(hw_tf);
127 panic("Page Fault in the Kernel at 0x%08x!", fault_va);
128 /* if we want to do something like kill a process or other code, be
129 * aware we are in a sort of irq-like context, meaning the main kernel
130 * code we 'interrupted' could be holding locks - even irqsave locks. */
132 /* safe to reenable after rcr2 */
134 if ((err = handle_page_fault(current, fault_va, prot))) {
135 /* Destroy the faulting process */
136 printk("[%08x] user %s fault va %p ip %p on core %d with err %d\n",
137 current->pid, prot & PROT_READ ? "READ" : "WRITE", fault_va,
138 hw_tf->tf_rip, core_id(), err);
139 print_trapframe(hw_tf);
140 /* Turn this on to help debug bad function pointers */
141 printd("rsp %p\n\t 0(rsp): %p\n\t 8(rsp): %p\n\t 16(rsp): %p\n"
142 "\t24(rsp): %p\n", hw_tf->tf_rsp,
143 *(uintptr_t*)(hw_tf->tf_rsp + 0),
144 *(uintptr_t*)(hw_tf->tf_rsp + 8),
145 *(uintptr_t*)(hw_tf->tf_rsp + 16),
146 *(uintptr_t*)(hw_tf->tf_rsp + 24));
147 proc_destroy(current);