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 asm volatile ("movl %1,%%esp; " /* move to future stack */
30 "pushl %2; " /* push cs */
31 "movl %0,%%esp; " /* move to TF */
32 "addl $0x20,%%esp; " /* move to tf_gs slot */
33 "movl %1,(%%esp); " /* write future esp */
34 "subl $0x20,%%esp; " /* move back to tf start */
35 "popal; " /* restore regs */
36 "popl %%esp; " /* set stack ptr */
37 "subl $0x4,%%esp; " /* jump down past CS */
38 "ret " /* return to the EIP */
40 : "g"(&ctx->hw_tf), "r"(ctx->hw_tf.tf_esp),
41 "r"(ctx->hw_tf.tf_eip)
43 panic("ret failed"); /* mostly to placate your mom */
46 static void print_regs(push_regs_t *regs)
48 printk(" edi 0x%08x\n", regs->reg_edi);
49 printk(" esi 0x%08x\n", regs->reg_esi);
50 printk(" ebp 0x%08x\n", regs->reg_ebp);
51 printk(" oesp 0x%08x\n", regs->reg_oesp);
52 printk(" ebx 0x%08x\n", regs->reg_ebx);
53 printk(" edx 0x%08x\n", regs->reg_edx);
54 printk(" ecx 0x%08x\n", regs->reg_ecx);
55 printk(" eax 0x%08x\n", regs->reg_eax);
58 void print_trapframe(struct hw_trapframe *hw_tf)
60 static spinlock_t ptf_lock = SPINLOCK_INITIALIZER_IRQSAVE;
62 struct per_cpu_info *pcpui = &per_cpu_info[core_id()];
63 /* This is only called in debug scenarios, and often when the kernel trapped
64 * and needs to tell us about it. Disable the lock checker so it doesn't go
65 * nuts when we print/panic */
66 pcpui->__lock_checking_enabled--;
67 spin_lock_irqsave(&ptf_lock);
68 printk("TRAP frame at %p on core %d\n", hw_tf, core_id());
69 print_regs(&hw_tf->tf_regs);
70 printk(" gs 0x----%04x\n", hw_tf->tf_gs);
71 printk(" fs 0x----%04x\n", hw_tf->tf_fs);
72 printk(" es 0x----%04x\n", hw_tf->tf_es);
73 printk(" ds 0x----%04x\n", hw_tf->tf_ds);
74 printk(" trap 0x%08x %s\n", hw_tf->tf_trapno,
75 x86_trapname(hw_tf->tf_trapno));
76 printk(" err 0x%08x\n", hw_tf->tf_err);
77 printk(" eip 0x%08x\n", hw_tf->tf_eip);
78 printk(" cs 0x----%04x\n", hw_tf->tf_cs);
79 printk(" flag 0x%08x\n", hw_tf->tf_eflags);
80 /* Prevents us from thinking these mean something for nested interrupts. */
81 if (hw_tf->tf_cs != GD_KT) {
82 printk(" esp 0x%08x\n", hw_tf->tf_esp);
83 printk(" ss 0x----%04x\n", hw_tf->tf_ss);
85 spin_unlock_irqsave(&ptf_lock);
86 pcpui->__lock_checking_enabled++;
89 void page_fault_handler(struct hw_trapframe *hw_tf)
91 uint32_t fault_va = rcr2();
92 int prot = hw_tf->tf_err & PF_ERROR_WRITE ? PROT_WRITE : PROT_READ;
95 /* TODO - handle kernel page faults */
96 if ((hw_tf->tf_cs & 3) == 0) {
97 print_trapframe(hw_tf);
98 backtrace_kframe(hw_tf);
99 panic("Page Fault in the Kernel at 0x%08x!", fault_va);
100 /* if we want to do something like kill a process or other code, be
101 * aware we are in a sort of irq-like context, meaning the main kernel
102 * code we 'interrupted' could be holding locks - even irqsave locks. */
104 /* safe to reenable after rcr2 */
106 if ((err = handle_page_fault(current, fault_va, prot))) {
107 /* Destroy the faulting process */
108 printk("[%08x] user %s fault va %08x ip %08x on core %d with err %d\n",
109 current->pid, prot & PROT_READ ? "READ" : "WRITE", fault_va,
110 hw_tf->tf_eip, core_id(), err);
111 print_trapframe(hw_tf);
112 /* Turn this on to help debug bad function pointers */
113 printd("esp %p\n\t 0(esp): %p\n\t 4(esp): %p\n\t 8(esp): %p\n"
114 "\t12(esp): %p\n", hw_tf->tf_esp,
115 *(uintptr_t*)(hw_tf->tf_esp + 0),
116 *(uintptr_t*)(hw_tf->tf_esp + 4),
117 *(uintptr_t*)(hw_tf->tf_esp + 8),
118 *(uintptr_t*)(hw_tf->tf_esp + 12));
119 proc_destroy(current);