Fix lock debugging issue with page faults and IRQs
authorBarret Rhoden <brho@cs.berkeley.edu>
Fri, 4 Dec 2015 20:48:02 +0000 (15:48 -0500)
committerBarret Rhoden <brho@cs.berkeley.edu>
Thu, 10 Dec 2015 15:40:20 +0000 (10:40 -0500)
There was a brief window between enabling IRQs and disabling lock checking.
If you receive an IRQ in here and that IRQ grabs a lock (e.g. timer IRQ),
you'll panic.

If you build with spinlock debugging and execute something like:

/ $ ash looper.sh prov -p1 -tc -m > /dev/null

and wait a minute or two, you'll catch a bug.  What's going on is that
looper and prov eventually get the kernel to trigger a soft page fault.
Then we get an IRQ during the window after enable_irq.  The lock debugger
flips out since we grab a lock with a kernel trap depth, which is
dangerous.  The old code was trying to work around this by disabling the
debugger, but it should have done so before enabling interrupts.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
kern/arch/x86/trap.c

index 0ff448b..fe1774f 100644 (file)
@@ -240,9 +240,6 @@ static bool __handle_page_fault(struct hw_trapframe *hw_tf, unsigned long *aux)
        struct per_cpu_info *pcpui = &per_cpu_info[core_id()];
        int err;
 
-       /* safe to reenable after rcr2 */
-       enable_irq();
-
        if (!pcpui->cur_proc) {
                if (try_handle_exception_fixup(hw_tf))
                        return TRUE;
@@ -262,6 +259,8 @@ static bool __handle_page_fault(struct hw_trapframe *hw_tf, unsigned long *aux)
         * Also consider turning on IRQs globally while we call HPF. */
        if (in_kernel(hw_tf))
                pcpui->__lock_checking_enabled--;
+       /* safe to reenable after rcr2 and after disabling lock checking */
+       enable_irq();
        err = handle_page_fault(pcpui->cur_proc, fault_va, prot);
        if (in_kernel(hw_tf))
                pcpui->__lock_checking_enabled++;