cpu: Check for instruction-count events before fetch
Instruction fetch should not commence if there already is an instruction-count event in the queue. The most conspicuous scenario where this leads to obvious breakage, is guest debugging. Imagine the first bytes in the program pointed to by _start are invalid instruction encoding, and we pass the --wait-gdb flag. Then in GDB we set $pc to point to valid instructions, and we "continue". gem5 will abort with "invalid instruction". This is not how real targets behave: neither software- (e.g. ptrace) based debuggers, nor low-level (e.g. OpenOCD or XMD connected over JTAG to debug early initialization code eg when the MMU has not been switched on yet, etc.) Fetching should start from where $pc was set to. This patch tries to model this behavior. Change-Id: Ibce6fdbbb082edf1073ae96745bc7867878f99ca Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/27587 Reviewed-by: Jason Lowe-Power <power.jg@gmail.com> Maintainer: Jason Lowe-Power <power.jg@gmail.com> Tested-by: kokoro <noreply+kokoro@google.com>
This commit is contained in:
@@ -646,6 +646,8 @@ AtomicSimpleCPU::tick()
|
||||
return;
|
||||
}
|
||||
|
||||
serviceInstCountEvents();
|
||||
|
||||
Fault fault = NoFault;
|
||||
|
||||
TheISA::PCState pcState = thread->pcState();
|
||||
|
||||
@@ -302,6 +302,12 @@ BaseSimpleCPU::setupFetchRequest(const RequestPtr &req)
|
||||
instRequestorId(), instAddr);
|
||||
}
|
||||
|
||||
void
|
||||
BaseSimpleCPU::serviceInstCountEvents()
|
||||
{
|
||||
SimpleExecContext &t_info = *threadInfo[curThread];
|
||||
t_info.thread->comInstEventQueue.serviceEvents(t_info.numInst);
|
||||
}
|
||||
|
||||
void
|
||||
BaseSimpleCPU::preExecute()
|
||||
@@ -316,9 +322,6 @@ BaseSimpleCPU::preExecute()
|
||||
t_info.setPredicate(true);
|
||||
t_info.setMemAccPredicate(true);
|
||||
|
||||
// check for instruction-count-based events
|
||||
thread->comInstEventQueue.serviceEvents(t_info.numInst);
|
||||
|
||||
// decode the instruction
|
||||
TheISA::PCState pcState = thread->pcState();
|
||||
|
||||
|
||||
@@ -130,6 +130,7 @@ class BaseSimpleCPU : public BaseCPU
|
||||
public:
|
||||
void checkForInterrupts();
|
||||
void setupFetchRequest(const RequestPtr &req);
|
||||
void serviceInstCountEvents();
|
||||
void preExecute();
|
||||
void postExecute();
|
||||
void advancePC(const Fault &fault);
|
||||
|
||||
@@ -805,6 +805,8 @@ TimingSimpleCPU::advanceInst(const Fault &fault)
|
||||
if (tryCompleteDrain())
|
||||
return;
|
||||
|
||||
serviceInstCountEvents();
|
||||
|
||||
if (_status == BaseSimpleCPU::Running) {
|
||||
// kick off fetch of next instruction... callback from icache
|
||||
// response will cause that instruction to be executed,
|
||||
|
||||
Reference in New Issue
Block a user