diff options
author | Tuan Ta <qtt2@cornell.edu> | 2018-04-02 15:18:57 -0400 |
---|---|---|
committer | Tuan Ta <qtt2@cornell.edu> | 2018-06-14 22:42:16 +0000 |
commit | 642a563cf08171f1a89ae67229e93187cae28bd8 (patch) | |
tree | 980800270fd015745c9ba8914a88e4ef2d96ad70 | |
parent | 7341f14f147337810325b19bac20db095b162911 (diff) | |
download | gem5-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.cc | 23 |
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 |