summaryrefslogtreecommitdiff
path: root/src/cpu/simple
diff options
context:
space:
mode:
authorAli Saidi <Ali.Saidi@ARM.com>2011-02-11 18:29:35 -0600
committerAli Saidi <Ali.Saidi@ARM.com>2011-02-11 18:29:35 -0600
commit1411cb0b0f01577c74d0f181404138cb43ce8ac8 (patch)
tree45e8e042f6063dbcc0267d01d506438f47f1fda3 /src/cpu/simple
parente2507407b17188dca802082434cfe0230d9bfa61 (diff)
downloadgem5-1411cb0b0f01577c74d0f181404138cb43ce8ac8.tar.xz
SimpleCPU: Fix a case where a DTLB fault redirects fetch and an I-side walk occurs.
This change fixes an issue where a DTLB fault occurs and redirects fetch to handle the fault and the ITLB requires a walk which delays translation. In this case the status of the cpu isn't updated appropriately, and an additional instruction fetch occurs. Eventually this hits an assert as multiple instruction fetches are occuring in the system and when the second one returns the processor is in the wrong state. Some asserts below are removed because it was always true (typo) and the state after the initiateAcc() the processor could be in any valid state when a d-side fault occurs.
Diffstat (limited to 'src/cpu/simple')
-rw-r--r--src/cpu/simple/timing.cc12
-rw-r--r--src/cpu/simple/timing.hh5
2 files changed, 10 insertions, 7 deletions
diff --git a/src/cpu/simple/timing.cc b/src/cpu/simple/timing.cc
index 453699f84..ab1ff91e8 100644
--- a/src/cpu/simple/timing.cc
+++ b/src/cpu/simple/timing.cc
@@ -752,6 +752,7 @@ TimingSimpleCPU::sendFetch(Fault fault, RequestPtr req, ThreadContext *tc)
} else {
delete req;
// fetch fault: advance directly to next instruction (fault handler)
+ _status = Running;
advanceInst(fault);
}
@@ -805,12 +806,11 @@ TimingSimpleCPU::completeIfetch(PacketPtr pkt)
if (curStaticInst && curStaticInst->isMemRef()) {
// load or store: just send to dcache
Fault fault = curStaticInst->initiateAcc(this, traceData);
- if (_status != Running) {
- // instruction will complete in dcache response callback
- assert(_status == DcacheWaitResponse ||
- _status == DcacheRetry || DTBWaitResponse);
- assert(fault == NoFault);
- } else {
+
+ // If we're not running now the instruction will complete in a dcache
+ // response callback or the instruction faulted and has started an
+ // ifetch
+ if (_status == Running) {
if (fault != NoFault && traceData) {
// If there was a fault, we shouldn't trace this instruction.
delete traceData;
diff --git a/src/cpu/simple/timing.hh b/src/cpu/simple/timing.hh
index 098db5f5a..a7a3eb7c3 100644
--- a/src/cpu/simple/timing.hh
+++ b/src/cpu/simple/timing.hh
@@ -109,7 +109,10 @@ class TimingSimpleCPU : public BaseSimpleCPU
void
markDelayed()
- {}
+ {
+ assert(cpu->_status == Running);
+ cpu->_status = ITBWaitResponse;
+ }
void
finish(Fault fault, RequestPtr req, ThreadContext *tc,