SCP pagefaults can block
[akaros.git] / kern / arch / x86 / trap64.c
index 9f08438..30a397d 100644 (file)
 /* Starts running the current TF, just using ret. */
 void pop_kernel_ctx(struct kernel_ctx *ctx)
 {
-       #if 0
-       asm volatile ("movl %1,%%esp;           " /* move to future stack */
-                     "pushl %2;                " /* push cs */
-                     "movl %0,%%esp;           " /* move to TF */
-                     "addl $0x20,%%esp;        " /* move to tf_gs slot */
-                     "movl %1,(%%esp);         " /* write future esp */
-                     "subl $0x20,%%esp;        " /* move back to tf start */
-                     "popal;                   " /* restore regs */
-                     "popl %%esp;              " /* set stack ptr */
-                     "subl $0x4,%%esp;         " /* jump down past CS */
-                     "ret                      " /* return to the EIP */
-                     :
-                     : "g"(&ctx->hw_tf), "r"(ctx->hw_tf.tf_esp),
-                       "r"(ctx->hw_tf.tf_eip)
-                     : "memory");
-       #endif
+       struct sw_trapframe *tf = &ctx->sw_tf;
+       /* We're starting at rbx's spot in the sw_tf */
+       asm volatile ("movq %0, %%rsp;          "
+                                 "popq %%rbx;              "
+                                 "popq %%rbp;              "
+                                 "popq %%r12;              "
+                                 "popq %%r13;              "
+                                 "popq %%r14;              "
+                                 "popq %%r15;              "
+                                 "popq %%rax;              " /* pop rip */
+                                 "popq %%rsp;              "
+                                 "jmp *%%rax;              " /* stored rip */
+                                 : : "g"(&ctx->sw_tf.tf_rbx) : "memory");
        panic("ret failed");
 }
 
@@ -53,9 +50,9 @@ void print_trapframe(struct hw_trapframe *hw_tf)
        /* This is only called in debug scenarios, and often when the kernel trapped
         * and needs to tell us about it.  Disable the lock checker so it doesn't go
         * nuts when we print/panic */
-       pcpui->__lock_depth_disabled++;
+       pcpui->__lock_checking_enabled--;
        spin_lock_irqsave(&ptf_lock);
-       printk("TRAP frame at %p on core %d\n", hw_tf, core_id());
+       printk("HW TRAP frame at %p on core %d\n", hw_tf, core_id());
        printk("  rax  0x%016lx\n",           hw_tf->tf_rax);
        printk("  rbx  0x%016lx\n",           hw_tf->tf_rbx);
        printk("  rcx  0x%016lx\n",           hw_tf->tf_rcx);
@@ -73,8 +70,12 @@ void print_trapframe(struct hw_trapframe *hw_tf)
        printk("  r15  0x%016lx\n",           hw_tf->tf_r15);
        printk("  trap 0x%08x %s\n",          hw_tf->tf_trapno,
                                              x86_trapname(hw_tf->tf_trapno));
-       printk("  gs   0x%04x\n",             hw_tf->tf_gs);
-       printk("  fs   0x%04x\n",             hw_tf->tf_fs);
+       /* FYI: these aren't physically adjacent to trap and err */
+       if (hw_tf->tf_cs == GD_KT)
+               printk("  gsbs 0x%016lx\n",       read_msr(MSR_GS_BASE));
+       else
+               printk("  gsbs 0x%016lx\n",       hw_tf->tf_gsbase);
+       printk("  fsbs 0x%016lx\n",           hw_tf->tf_fsbase);
        printk("  err  0x--------%08x\n",     hw_tf->tf_err);
        printk("  rip  0x%016lx\n",           hw_tf->tf_rip);
        printk("  cs   0x------------%04x\n", hw_tf->tf_cs);
@@ -82,7 +83,36 @@ void print_trapframe(struct hw_trapframe *hw_tf)
        printk("  rsp  0x%016lx\n",           hw_tf->tf_rsp);
        printk("  ss   0x------------%04x\n", hw_tf->tf_ss);
        spin_unlock_irqsave(&ptf_lock);
-       pcpui->__lock_depth_disabled--;
+       pcpui->__lock_checking_enabled++;
+
+       /* Used in trapentry64.S */
+       static_assert(offsetof(struct hw_trapframe, tf_cs) - 
+                     offsetof(struct hw_trapframe, tf_rax) == 0x90);
+       /* Used in trap64.h */
+       static_assert(offsetof(struct per_cpu_info, stacktop) == 0);
+}
+
+void print_swtrapframe(struct sw_trapframe *sw_tf)
+{
+       static spinlock_t ptf_lock = SPINLOCK_INITIALIZER_IRQSAVE;
+       struct per_cpu_info *pcpui = &per_cpu_info[core_id()];
+       pcpui->__lock_checking_enabled--;
+       spin_lock_irqsave(&ptf_lock);
+       printk("SW TRAP frame at %p on core %d\n", sw_tf, core_id());
+       printk("  rbx  0x%016lx\n",           sw_tf->tf_rbx);
+       printk("  rbp  0x%016lx\n",           sw_tf->tf_rbp);
+       printk("  r12  0x%016lx\n",           sw_tf->tf_r12);
+       printk("  r13  0x%016lx\n",           sw_tf->tf_r13);
+       printk("  r14  0x%016lx\n",           sw_tf->tf_r14);
+       printk("  r15  0x%016lx\n",           sw_tf->tf_r15);
+       printk("  gsbs 0x%016lx\n",           sw_tf->tf_gsbase);
+       printk("  fsbs 0x%016lx\n",           sw_tf->tf_fsbase);
+       printk("  rip  0x%016lx\n",           sw_tf->tf_rip);
+       printk("  rsp  0x%016lx\n",           sw_tf->tf_rsp);
+       printk(" mxcsr 0x%08x\n",             sw_tf->tf_mxcsr);
+       printk(" fpucw 0x%04x\n",             sw_tf->tf_fpucw);
+       spin_unlock_irqsave(&ptf_lock);
+       pcpui->__lock_checking_enabled++;
 }
 
 void page_fault_handler(struct hw_trapframe *hw_tf)
@@ -94,7 +124,8 @@ void page_fault_handler(struct hw_trapframe *hw_tf)
        /* TODO - handle kernel page faults */
        if ((hw_tf->tf_cs & 3) == 0) {
                print_trapframe(hw_tf);
-               panic("Page Fault in the Kernel at 0x%08x!", fault_va);
+               backtrace_kframe(hw_tf);
+               panic("Page Fault in the Kernel at %p!", fault_va);
                /* if we want to do something like kill a process or other code, be
                 * aware we are in a sort of irq-like context, meaning the main kernel
                 * code we 'interrupted' could be holding locks - even irqsave locks. */
@@ -103,7 +134,7 @@ void page_fault_handler(struct hw_trapframe *hw_tf)
        enable_irq();
        if ((err = handle_page_fault(current, fault_va, prot))) {
                /* Destroy the faulting process */
-               printk("[%08x] user %s fault va %08x ip %08x on core %d with err %d\n",
+               printk("[%08x] user %s fault va %p ip %p on core %d with err %d\n",
                       current->pid, prot & PROT_READ ? "READ" : "WRITE", fault_va,
                       hw_tf->tf_rip, core_id(), err);
                print_trapframe(hw_tf);
@@ -117,10 +148,3 @@ void page_fault_handler(struct hw_trapframe *hw_tf)
                proc_destroy(current);
        }
 }
-
-void sysenter_init(void)
-{
-       //write_msr(MSR_IA32_SYSENTER_CS, GD_KT);
-       //write_msr(MSR_IA32_SYSENTER_ESP, ts.ts_esp0);
-       //write_msr(MSR_IA32_SYSENTER_EIP, (uint32_t) &sysenter_handler);
-}