cpu: Prevent suspended TimingSimple CPUs from fetching next instructions
authorTuan Ta <qtt2@cornell.edu>
Mon, 2 Apr 2018 19:18:57 +0000 (15:18 -0400)
committerTuan Ta <qtt2@cornell.edu>
Thu, 14 Jun 2018 22:42:16 +0000 (22:42 +0000)
In TimingSimpleCPU model, when a CPU is suspended by a syscall (e.g.,
futex(FUTEX_WAIT)), the CPU waits for another CPU to wake it up
(e.g., FUTEX_WAKE operation). While staying Idle, the suspended CPU
should not try to fetch next instructions after the syscall.

This patch added a status check before a CPU schedule a fetch event
after a fault is handled.

Change-Id: I0cc953135686c9b35afe94942aa1d0b245ec60a2
Reviewed-on: https://gem5-review.googlesource.com/8181
Reviewed-by: Andreas Sandberg <andreas.sandberg@arm.com>
Maintainer: Brandon Potter <Brandon.Potter@amd.com>

src/cpu/simple/timing.cc

index 14e760af9acf83024a2ce77adec775ecc201d445..b5450cf5fe76c98e5c0f79ba6555c77d778f1cdf 100644 (file)
@@ -680,25 +680,32 @@ TimingSimpleCPU::advanceInst(const Fault &fault)
         return;
 
     if (fault != NoFault) {
-        DPRINTF(SimpleCPU, "Fault occured, scheduling fetch event\n");
+        DPRINTF(SimpleCPU, "Fault occured. Handling the fault\n");
 
         advancePC(fault);
 
-        Tick stall = dynamic_pointer_cast<SyscallRetryFault>(fault) ?
-                     clockEdge(syscallRetryLatency) : clockEdge();
-
-        reschedule(fetchEvent, stall, true);
+        // A syscall fault could suspend this CPU (e.g., futex_wait)
+        // If the _status is not Idle, schedule an event to fetch the next
+        // instruction after 'stall' ticks.
+        // If the cpu has been suspended (i.e., _status == Idle), another
+        // cpu will wake this cpu up later.
+        if (_status != Idle) {
+            DPRINTF(SimpleCPU, "Scheduling fetch event after the Fault\n");
+
+            Tick stall = dynamic_pointer_cast<SyscallRetryFault>(fault) ?
+                         clockEdge(syscallRetryLatency) : clockEdge();
+            reschedule(fetchEvent, stall, true);
+            _status = Faulting;
+        }
 
-        _status = Faulting;
         return;
     }
 
-
     if (!t_info.stayAtPC)
         advancePC(fault);
 
     if (tryCompleteDrain())
-            return;
+        return;
 
     if (_status == BaseSimpleCPU::Running) {
         // kick off fetch of next instruction... callback from icache