Make cpu_halt() return with IRQs disabled
authorBarret Rhoden <brho@cs.berkeley.edu>
Mon, 20 Nov 2017 19:12:47 +0000 (14:12 -0500)
committerBarret Rhoden <brho@cs.berkeley.edu>
Wed, 22 Nov 2017 16:49:34 +0000 (11:49 -0500)
And don't assume we woke from an IRQ that changed the kernel pcpui state.
Although that is always the case, it won't be if we woke due to an mwait.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
kern/arch/riscv/entry.S
kern/arch/x86/idle.c
kern/src/smp.c
kern/src/syscall.c

index 87dee12..725a59d 100644 (file)
@@ -194,3 +194,4 @@ cpu_halt:
 1:b     1b   # handle_ipi can advance the PC to break out of this loop.
   ret
 after_cpu_halt:
+  clearpcr ASM_CR(PCR_SR), SR_ET
index 402b047..e5029b8 100644 (file)
@@ -6,7 +6,7 @@
 
 static unsigned int x86_cstate;
 
-/* This atomically enables interrupts and halts.
+/* This atomically enables interrupts and halts.  It returns with IRQs off.
  *
  * Note that sti does not take effect until after the *next* instruction */
 void cpu_halt(void)
@@ -19,6 +19,7 @@ void cpu_halt(void)
        } else {
                asm volatile("sti; hlt" : : : "memory");
        }
+       disable_irq();
 }
 
 void set_pstate(unsigned int pstate)
index ef06842..d08bf1d 100644 (file)
@@ -66,18 +66,18 @@ static void __attribute__((noreturn)) __smp_idle(void *arg)
        clear_rkmsg(pcpui);
        pcpui->cur_kthread->flags = KTH_DEFAULT_FLAGS;
        enable_irq();   /* one-shot change to get any IRQs before we halt later */
+       disable_irq();
        while (1) {
-               disable_irq();
                process_routine_kmsg();
                try_run_proc();
                cpu_bored();            /* call out to the ksched */
                /* cpu_halt() atomically turns on interrupts and halts the core.
                 * Important to do this, since we could have a RKM come in via an
                 * interrupt right while PRKM is returning, and we wouldn't catch
-                * it. */
+                * it.  When it returns, IRQs are back off. */
                __set_cpu_state(pcpui, CPU_STATE_IDLE);
                cpu_halt();
-               /* interrupts are back on now (given our current semantics) */
+               __set_cpu_state(pcpui, CPU_STATE_KERNEL);
        }
        assert(0);
 }
index 39bd0eb..9de2669 100644 (file)
@@ -1456,8 +1456,9 @@ static int sys_halt_core(struct proc *p, unsigned long usec)
                enable_irq();
                return 0;
        }
-       /* CPU_STATE is reset to KERNEL by the IRQ handler that wakes us */
        cpu_halt();
+       __set_cpu_state(pcpui, CPU_STATE_KERNEL);
+       enable_irq();
        return 0;
 }