From ec7ed8cd25b213c6d018ef1e97890ed06592b701 Mon Sep 17 00:00:00 2001
From: Glauber Costa <glommer@cloudius-systems.com>
Date: Fri, 13 Dec 2013 14:50:09 +0400
Subject: [PATCH] enable interrupts during page fault handling

Context: going to wait with irqs_disabled is a call for disaster.  While it is
true that not every time we call wait we actually end up waiting, that should
be an invalid call, due to the times we may wait. Because of that, it would
be good to express that nonsense in an assertion.

There is however, places we sleep with irqs disabled currently. Although they
are technically safe, because we implicitly enable interrupts, they end up
reaching wait() in a non-safe state. That happens in the page fault handler.
Explicitly enabling interrupts will allow us to test for valid / invalid wait
status.

With this test applied, all tests in our whitelist still passes.

Signed-off-by: Glauber Costa <glommer@cloudius-systems.com>
Signed-off-by: Avi Kivity <avi@cloudius-systems.com>
---
 arch/x64/mmu.cc  | 4 ++++
 include/sched.hh | 4 ++++
 2 files changed, 8 insertions(+)

diff --git a/arch/x64/mmu.cc b/arch/x64/mmu.cc
index 1ccaa591f..a8698da7a 100644
--- a/arch/x64/mmu.cc
+++ b/arch/x64/mmu.cc
@@ -5,6 +5,7 @@
  * BSD license as described in the LICENSE file in the top-level directory.
  */
 
+#include "arch.hh"
 #include "arch-cpu.hh"
 #include "debug.hh"
 #include "sched.hh"
@@ -26,6 +27,9 @@ void page_fault(exception_frame *ef)
     assert(sched::preemptable());
     assert(ef->rflags & processor::rflags_if);
 
+    // And since we may sleep, make sure interrupts are enabled.
+    arch::irq_enable();
+
     sched::inplace_arch_fpu fpu;
     fpu.save();
     mmu::vm_fault(addr, ef);
diff --git a/include/sched.hh b/include/sched.hh
index 739e774f0..0409dc8df 100644
--- a/include/sched.hh
+++ b/include/sched.hh
@@ -8,6 +8,7 @@
 #ifndef SCHED_HH_
 #define SCHED_HH_
 
+#include "arch.hh"
 #include "arch-thread-state.hh"
 #include "arch-cpu.hh"
 #include <functional>
@@ -587,6 +588,9 @@ template <class Mutex, class Pred>
 inline
 void thread::do_wait_until(Mutex& mtx, Pred pred)
 {
+    assert(arch::irq_enabled());
+    assert(preemptable());
+
     thread* me = current();
     while (true) {
         {
-- 
GitLab