x86: Kernel tries to handle user page faults
authorBarret Rhoden <brho@cs.berkeley.edu>
Wed, 9 Apr 2014 00:02:37 +0000 (17:02 -0700)
committerBarret Rhoden <brho@cs.berkeley.edu>
Wed, 9 Apr 2014 00:02:37 +0000 (17:02 -0700)
We could deadlock doing this - need to review and be careful any time we access
a user pointer.

Segvs will still cause a panic, but anon memory should work.

kern/arch/x86/trap.c

index 6f968e1..28c9f16 100644 (file)
@@ -241,18 +241,29 @@ static bool __handle_page_fault(struct hw_trapframe *hw_tf, unsigned long *aux)
        int prot = hw_tf->tf_err & PF_ERROR_WRITE ? PROT_WRITE : PROT_READ;
        int err;
 
-       /* TODO - handle kernel page faults */
-       if ((hw_tf->tf_cs & 3) == 0) {
+       /* safe to reenable after rcr2 */
+       enable_irq();
+
+       if (!current) {
+               /* still catch KPFs */
+               assert((hw_tf->tf_cs & 3) == 0);
                print_trapframe(hw_tf);
                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. */
+               panic("Proc-less Page Fault in the Kernel at %p!", fault_va);
        }
-       /* safe to reenable after rcr2 */
-       enable_irq();
+       /* TODO - handle kernel page faults.  This is dangerous, since we might be
+        * holding locks in the kernel and could deadlock when we HPF. */
        if ((err = handle_page_fault(current, fault_va, prot))) {
+               if ((hw_tf->tf_cs & 3) == 0) {
+                       print_trapframe(hw_tf);
+                       backtrace_kframe(hw_tf);
+                       panic("Proc-ful 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. */
+               }
+
                if (err == -EAGAIN)
                        hw_tf->tf_err |= PF_VMR_BACKED;
                *aux = fault_va;