ARM: Adding a bogus fault that does nothing.
This fault can used to flush the pipe, not including the faulting instruction. The particular case I needed this was for a self-modifying code. It needed to drain the store queue and force the following instruction to refetch from icache. DCCMVAC cp15 mcr instruction is modified to raise this fault.
This commit is contained in:
parent
8376f7bca3
commit
c23e8c31eb
4 changed files with 55 additions and 4 deletions
|
@ -71,6 +71,9 @@ template<> ArmFault::FaultVals ArmFaultVals<Interrupt>::vals =
|
|||
template<> ArmFault::FaultVals ArmFaultVals<FastInterrupt>::vals =
|
||||
{"FIQ", 0x1C, MODE_FIQ, 4, 4, true, true};
|
||||
|
||||
template<> ArmFault::FaultVals ArmFaultVals<FlushPipe>::vals =
|
||||
{"Pipe Flush", 0x00, MODE_SVC, 0, 0, true, true}; // some dummy values
|
||||
|
||||
Addr
|
||||
ArmFault::getVector(ThreadContext *tc)
|
||||
{
|
||||
|
@ -213,12 +216,22 @@ AbortFault<T>::invoke(ThreadContext *tc)
|
|||
tc->setMiscReg(T::FarIndex, faultAddr);
|
||||
}
|
||||
|
||||
void
|
||||
FlushPipe::invoke(ThreadContext *tc) {
|
||||
DPRINTF(Faults, "Invoking FlushPipe Fault\n");
|
||||
|
||||
// Set the PC to the next instruction of the faulting instruction.
|
||||
// Net effect is simply squashing all instructions behind and
|
||||
// start refetching from the next instruction.
|
||||
tc->setPC(tc->readNextPC());
|
||||
tc->setNextPC(tc->readNextNPC());
|
||||
tc->setMicroPC(0);
|
||||
tc->setNextMicroPC(1);
|
||||
}
|
||||
|
||||
template void AbortFault<PrefetchAbort>::invoke(ThreadContext *tc);
|
||||
template void AbortFault<DataAbort>::invoke(ThreadContext *tc);
|
||||
|
||||
// return via SUBS pc, lr, xxx; rfe, movs, ldm
|
||||
|
||||
|
||||
|
||||
} // namespace ArmISA
|
||||
|
||||
|
|
|
@ -227,6 +227,14 @@ class DataAbort : public AbortFault<DataAbort>
|
|||
class Interrupt : public ArmFaultVals<Interrupt> {};
|
||||
class FastInterrupt : public ArmFaultVals<FastInterrupt> {};
|
||||
|
||||
// A fault that flushes the pipe, excluding the faulting instructions
|
||||
class FlushPipe : public ArmFaultVals<FlushPipe>
|
||||
{
|
||||
public:
|
||||
FlushPipe() {}
|
||||
void invoke(ThreadContext *tc);
|
||||
};
|
||||
|
||||
static inline Fault genMachineCheckFault()
|
||||
{
|
||||
return new Reset();
|
||||
|
|
|
@ -111,7 +111,7 @@ let {{
|
|||
return new WarnUnimplemented(
|
||||
isRead ? "mrc dcimvac" : "mcr dcimvac", machInst);
|
||||
case MISCREG_DCCMVAC:
|
||||
return new WarnUnimplemented(
|
||||
return new FlushPipeInst(
|
||||
isRead ? "mrc dccmvac" : "mcr dccmvac", machInst);
|
||||
case MISCREG_DCCMVAU:
|
||||
return new WarnUnimplemented(
|
||||
|
|
|
@ -101,6 +101,22 @@ output header {{
|
|||
std::string
|
||||
generateDisassembly(Addr pc, const SymbolTable *symtab) const;
|
||||
};
|
||||
|
||||
class FlushPipeInst : public ArmStaticInst
|
||||
{
|
||||
public:
|
||||
FlushPipeInst(const char *_mnemonic, ExtMachInst _machInst)
|
||||
: ArmStaticInst(_mnemonic, _machInst, No_OpClass)
|
||||
{
|
||||
flags[IsNonSpeculative] = true;
|
||||
}
|
||||
|
||||
%(BasicExecDeclare)s
|
||||
|
||||
std::string
|
||||
generateDisassembly(Addr pc, const SymbolTable *symtab) const;
|
||||
|
||||
};
|
||||
}};
|
||||
|
||||
output decoder {{
|
||||
|
@ -117,6 +133,13 @@ output decoder {{
|
|||
{
|
||||
return csprintf("%-10s (unimplemented)", mnemonic);
|
||||
}
|
||||
|
||||
std::string
|
||||
FlushPipeInst::generateDisassembly(Addr pc,
|
||||
const SymbolTable *symtab) const
|
||||
{
|
||||
return csprintf("%-10s (pipe flush)", mnemonic);
|
||||
}
|
||||
}};
|
||||
|
||||
output exec {{
|
||||
|
@ -142,6 +165,13 @@ output exec {{
|
|||
|
||||
return NoFault;
|
||||
}
|
||||
|
||||
Fault
|
||||
FlushPipeInst::execute(%(CPU_exec_context)s *xc,
|
||||
Trace::InstRecord *traceData) const
|
||||
{
|
||||
return new FlushPipe();
|
||||
}
|
||||
}};
|
||||
|
||||
|
||||
|
|
Loading…
Reference in a new issue