summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTuan Ta <qtt2@cornell.edu>2018-04-02 15:18:57 -0400
committerTuan Ta <qtt2@cornell.edu>2018-06-14 22:42:16 +0000
commit642a563cf08171f1a89ae67229e93187cae28bd8 (patch)
tree980800270fd015745c9ba8914a88e4ef2d96ad70
parent7341f14f147337810325b19bac20db095b162911 (diff)
downloadgem5-642a563cf08171f1a89ae67229e93187cae28bd8.tar.xz
cpu: Prevent suspended TimingSimple CPUs from fetching next instructions
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>
-rw-r--r--src/cpu/simple/timing.cc23
1 files changed, 15 insertions, 8 deletions
diff --git a/src/cpu/simple/timing.cc b/src/cpu/simple/timing.cc
index 14e760af9..b5450cf5f 100644
--- a/src/cpu/simple/timing.cc
+++ b/src/cpu/simple/timing.cc
@@ -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