SCP pagefaults can block
[akaros.git] / kern / arch / x86 / trap64.c
index 43334f2..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,7 +50,7 @@ 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("HW TRAP frame at %p on core %d\n", hw_tf, core_id());
        printk("  rax  0x%016lx\n",           hw_tf->tf_rax);
@@ -86,7 +83,7 @@ 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) - 
@@ -99,7 +96,7 @@ 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_depth_disabled++;
+       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);
@@ -115,7 +112,7 @@ void print_swtrapframe(struct sw_trapframe *sw_tf)
        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_depth_disabled--;
+       pcpui->__lock_checking_enabled++;
 }
 
 void page_fault_handler(struct hw_trapframe *hw_tf)
@@ -127,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. */
@@ -136,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);