ARM: Fix table walk going on while ASID changes error
This commit is contained in:
parent
5962fecc1d
commit
55920a5ca7
4 changed files with 38 additions and 4 deletions
|
@ -74,6 +74,9 @@ template<> ArmFault::FaultVals ArmFaultVals<FastInterrupt>::vals =
|
||||||
template<> ArmFault::FaultVals ArmFaultVals<FlushPipe>::vals =
|
template<> ArmFault::FaultVals ArmFaultVals<FlushPipe>::vals =
|
||||||
{"Pipe Flush", 0x00, MODE_SVC, 0, 0, true, true}; // some dummy values
|
{"Pipe Flush", 0x00, MODE_SVC, 0, 0, true, true}; // some dummy values
|
||||||
|
|
||||||
|
template<> ArmFault::FaultVals ArmFaultVals<ReExec>::vals =
|
||||||
|
{"ReExec Flush", 0x00, MODE_SVC, 0, 0, true, true}; // some dummy values
|
||||||
|
|
||||||
Addr
|
Addr
|
||||||
ArmFault::getVector(ThreadContext *tc)
|
ArmFault::getVector(ThreadContext *tc)
|
||||||
{
|
{
|
||||||
|
@ -225,6 +228,17 @@ FlushPipe::invoke(ThreadContext *tc, StaticInstPtr inst) {
|
||||||
tc->pcState(pc);
|
tc->pcState(pc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ReExec::invoke(ThreadContext *tc, StaticInstPtr inst) {
|
||||||
|
DPRINTF(Faults, "Invoking ReExec Fault\n");
|
||||||
|
|
||||||
|
// Set the PC to then the faulting instruction.
|
||||||
|
// Net effect is simply squashing all instructions including this
|
||||||
|
// instruction and refetching/rexecuting current instruction
|
||||||
|
PCState pc = tc->pcState();
|
||||||
|
tc->pcState(pc);
|
||||||
|
}
|
||||||
|
|
||||||
template void AbortFault<PrefetchAbort>::invoke(ThreadContext *tc,
|
template void AbortFault<PrefetchAbort>::invoke(ThreadContext *tc,
|
||||||
StaticInstPtr inst);
|
StaticInstPtr inst);
|
||||||
template void AbortFault<DataAbort>::invoke(ThreadContext *tc,
|
template void AbortFault<DataAbort>::invoke(ThreadContext *tc,
|
||||||
|
|
|
@ -242,6 +242,16 @@ class FlushPipe : public ArmFaultVals<FlushPipe>
|
||||||
StaticInstPtr inst = StaticInst::nullStaticInstPtr);
|
StaticInstPtr inst = StaticInst::nullStaticInstPtr);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// A fault that flushes the pipe, including the faulting instructions
|
||||||
|
class ReExec : public ArmFaultVals<ReExec>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ReExec() {}
|
||||||
|
void invoke(ThreadContext *tc,
|
||||||
|
StaticInstPtr inst = StaticInst::nullStaticInstPtr);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
static inline Fault genMachineCheckFault()
|
static inline Fault genMachineCheckFault()
|
||||||
{
|
{
|
||||||
return new Reset();
|
return new Reset();
|
||||||
|
|
|
@ -114,8 +114,16 @@ TableWalker::walk(RequestPtr _req, ThreadContext *_tc, uint8_t _cid, TLB::Mode _
|
||||||
|
|
||||||
currState = new WalkerState();
|
currState = new WalkerState();
|
||||||
currState->tableWalker = this;
|
currState->tableWalker = this;
|
||||||
}
|
} else if (_timing) {
|
||||||
else if (_timing) {
|
// This is a translation that was completed and then faulted again
|
||||||
|
// because some underlying parameters that affect the translation
|
||||||
|
// changed out from under us (e.g. asid). It will either be a
|
||||||
|
// misprediction, in which case nothing will happen or we'll use
|
||||||
|
// this fault to re-execute the faulting instruction which should clean
|
||||||
|
// up everything.
|
||||||
|
if (currState->vaddr == _req->getVaddr()) {
|
||||||
|
return new ReExec;
|
||||||
|
}
|
||||||
panic("currState should always be empty in timing mode!\n");
|
panic("currState should always be empty in timing mode!\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -446,8 +446,10 @@ Fault
|
||||||
TLB::translateFs(RequestPtr req, ThreadContext *tc, Mode mode,
|
TLB::translateFs(RequestPtr req, ThreadContext *tc, Mode mode,
|
||||||
Translation *translation, bool &delay, bool timing)
|
Translation *translation, bool &delay, bool timing)
|
||||||
{
|
{
|
||||||
if (!miscRegValid)
|
if (!miscRegValid) {
|
||||||
updateMiscReg(tc);
|
updateMiscReg(tc);
|
||||||
|
DPRINTF(TLBVerbose, "TLB variables changed!\n");
|
||||||
|
}
|
||||||
|
|
||||||
Addr vaddr = req->getVaddr();
|
Addr vaddr = req->getVaddr();
|
||||||
uint32_t flags = req->getFlags();
|
uint32_t flags = req->getFlags();
|
||||||
|
@ -456,7 +458,7 @@ TLB::translateFs(RequestPtr req, ThreadContext *tc, Mode mode,
|
||||||
bool is_write = (mode == Write);
|
bool is_write = (mode == Write);
|
||||||
bool is_priv = isPriv && !(flags & UserMode);
|
bool is_priv = isPriv && !(flags & UserMode);
|
||||||
|
|
||||||
DPRINTF(TLBVerbose, "CPSR is user:%d UserMode:%d\n",
|
DPRINTF(TLBVerbose, "CPSR is priv:%d UserMode:%d\n",
|
||||||
isPriv, flags & UserMode);
|
isPriv, flags & UserMode);
|
||||||
// If this is a clrex instruction, provide a PA of 0 with no fault
|
// If this is a clrex instruction, provide a PA of 0 with no fault
|
||||||
// This will force the monitor to set the tracked address to 0
|
// This will force the monitor to set the tracked address to 0
|
||||||
|
|
Loading…
Reference in a new issue