56 #include "debug/Faults.hh" 103 static_assert(
sizeof(ArmFault::shortDescFaultSources) ==
105 "Invalid size of ArmFault::shortDescFaultSources[]");
148 static_assert(
sizeof(ArmFault::longDescFaultSources) ==
150 "Invalid size of ArmFault::longDescFaultSources[]");
194 static_assert(
sizeof(ArmFault::aarch64FaultSources) ==
196 "Invalid size of ArmFault::aarch64FaultSources[]");
204 "Reset", 0x000, 0x000, 0x000, 0x000, 0x000,
MODE_SVC,
208 "Undefined Instruction", 0x004, 0x000, 0x200, 0x400, 0x600,
MODE_UNDEFINED,
212 "Supervisor Call", 0x008, 0x000, 0x200, 0x400, 0x600,
MODE_SVC,
216 "Secure Monitor Call", 0x008, 0x000, 0x200, 0x400, 0x600,
MODE_MON,
220 "Hypervisor Call", 0x008, 0x000, 0x200, 0x400, 0x600,
MODE_HYP,
221 4, 4, 4, 4,
true,
false,
false,
EC_HVC 224 "Prefetch Abort", 0x00C, 0x000, 0x200, 0x400, 0x600,
MODE_ABORT,
228 "Data Abort", 0x010, 0x000, 0x200, 0x400, 0x600,
MODE_ABORT,
232 "Virtual Data Abort", 0x010, 0x000, 0x200, 0x400, 0x600,
MODE_ABORT,
237 "Hypervisor Trap", 0x014, 0x000, 0x200, 0x400, 0x600,
MODE_HYP,
241 "Secure Monitor Trap", 0x004, 0x000, 0x200, 0x400, 0x600,
MODE_MON,
245 "IRQ", 0x018, 0x080, 0x280, 0x480, 0x680,
MODE_IRQ,
249 "Virtual IRQ", 0x018, 0x080, 0x280, 0x480, 0x680,
MODE_IRQ,
253 "FIQ", 0x01C, 0x100, 0x300, 0x500, 0x700,
MODE_FIQ,
257 "Virtual FIQ", 0x01C, 0x100, 0x300, 0x500, 0x700,
MODE_FIQ,
261 "Illegal Inst Set State Fault", 0x004, 0x000, 0x200, 0x400, 0x600,
MODE_UNDEFINED,
266 "Supervisor Trap", 0x014, 0x000, 0x200, 0x400, 0x600,
MODE_SVC,
271 "PC Alignment Fault", 0x000, 0x000, 0x200, 0x400, 0x600,
MODE_SVC,
276 "SP Alignment Fault", 0x000, 0x000, 0x200, 0x400, 0x600,
MODE_SVC,
281 "SError", 0x000, 0x180, 0x380, 0x580, 0x780,
MODE_SVC,
286 "Software Breakpoint", 0x000, 0x000, 0x200, 0x400, 0x600,
MODE_SVC,
291 "ArmSev Flush", 0x000, 0x000, 0x000, 0x000, 0x000,
MODE_SVC,
344 panic(
"Invalid target exception level");
361 panic(
"Invalid exception level");
377 panic(
"Invalid exception level");
386 uint32_t exc_class = (uint32_t)
ec(tc);
387 uint32_t issVal =
iss();
391 value = exc_class << 26;
399 }
else if ((
bits(exc_class, 5, 3) != 4) ||
400 (
bits(exc_class, 2) &&
bits(issVal, 24))) {
405 if (!
from64 && ((
bits(exc_class, 5, 4) == 0) &&
406 (
bits(exc_class, 3, 0) != 0))) {
416 value |=
bits(issVal, 19, 0);
460 if (
toEL ==
EL2 && hcr.e2h && hcr.tge) {
507 ITSTATE it = tc->
pcState().itstate();
508 saved_cpsr.it2 = it.top6;
509 saved_cpsr.it1 = it.bottom2;
517 if (have_security && saved_cpsr.mode ==
MODE_MON) {
533 if (!scr.ea) {cpsr.a = 1;}
534 if (!scr.fiq) {cpsr.f = 1;}
535 if (!scr.irq) {cpsr.i = 1;}
552 cpsr.it1 = cpsr.it2 = 0;
554 cpsr.pan =
span ? 1 : saved_cpsr.pan;
582 assert(have_security);
599 panic(
"unknown Mode\n");
603 DPRINTF(Faults,
"Invoking Fault:%s cpsr:%#x PC:%#x lr:%#x newVec: %#x " 605 newPc, arm_inst ?
csprintf(
"inst: %#x", arm_inst->encoding()) :
609 pc.nextThumb(pc.thumb());
611 pc.nextJazelle(pc.jazelle());
612 pc.aarch64(!cpsr.width);
613 pc.nextAArch64(!cpsr.width);
614 pc.illegalExec(
false);
639 panic(
"Invalid target exception level");
659 ITSTATE it = tc->
pcState().itstate();
661 spsr.it1 = it.bottom2;
669 Addr ret_addr = curr_pc;
679 OperatingMode64
mode = 0;
687 cpsr.pan =
span ? 1 : spsr.pan;
697 DPRINTF(Faults,
"Invoking Fault (AArch64 target EL):%s cpsr:%#x PC:%#x " 698 "elr:%#x newVec: %#x %s\n",
name(), cpsr, curr_pc, ret_addr,
699 new_pc, arm_inst ?
csprintf(
"inst: %#x", arm_inst->encoding()) :
702 pc.aarch64(!cpsr.width);
703 pc.nextAArch64(!cpsr.width);
704 pc.illegalExec(
false);
765 pc.nextAArch64(
true);
779 assert(unknown || mnemonic != NULL);
782 panic(
"Attempted to execute disabled instruction " 783 "'%s' (inst 0x%08x)", mnemonic, arm_inst->encoding());
784 }
else if (unknown) {
785 panic(
"Attempted to execute unknown instruction (inst 0x%08x)",
786 arm_inst->encoding());
788 panic(
"Attempted to execute unimplemented instruction " 789 "'%s' (inst 0x%08x)", mnemonic, arm_inst->encoding());
821 uint32_t new_iss = 0;
822 uint32_t op0, op1, op2, CRn, CRm, Rt, dir;
832 new_iss = op0 << 20 | op2 << 17 | op1 << 14 | CRn << 10 |
833 Rt << 5 | CRm << 1 | dir;
868 toHyp = scr.ns && (cpsr.mode ==
MODE_HYP);
877 return (overrideEc !=
EC_INVALID) ? overrideEc :
905 return (overrideEc !=
EC_INVALID) ? overrideEc : vals.ec;
929 bool isHypTrap =
false;
954 bool lower_32 =
false;
961 lower_32 =
ELIs32(tc, static_cast<ExceptionLevel>(
toEL - 1));
1036 return (overrideEc !=
EC_INVALID) ? overrideEc :
1050 bool override_LPAE =
false;
1054 override_LPAE =
true;
1058 DPRINTF(Faults,
"Warning: Incomplete translation method " 1059 "override detected.\n");
1080 }
else if (stage2) {
1087 DPRINTF(Faults,
"Abort Fault source=%#x fsr=%#x faultAddr=%#x "\
1088 "tranMethod=%#x\n", source, fsr, faultAddr, tranMethod);
1098 DPRINTF(Faults,
"Abort Fault (Stage 2) VA: 0x%x IPA: 0x%x\n",
1110 srcEncoded = getFaultStatusCode(tc);
1112 panic(
"Invalid fault source\n");
1123 "Trying to use un-updated ArmFault internal variables\n");
1131 fsc = ArmFault::longDescFaultSources[source];
1133 fsc = ArmFault::shortDescFaultSources[source];
1137 fsc = ArmFault::aarch64FaultSources[source];
1149 auto fsc = getFaultStatusCode(tc);
1157 fsr.fsLow =
bits(fsc, 3, 0);
1158 fsr.fsHigh =
bits(fsc, 4);
1159 fsr.domain =
static_cast<uint8_t
>(
domain);
1162 fsr.wnr = (write ? 1 : 0);
1174 return (!scr.ns || scr.aw);
1204 val = srcEncoded & 0x3F;
1231 va = (stage2 ? OVAddr : faultAddr);
1269 return scr.ea && !isMMUFault();
1297 panic(
"Asynchronous External Abort should be handled with " 1298 "SystemErrors (SErrors)!");
1329 return scr.ea && !isMMUFault();
1459 return (!scr.ns || scr.aw);
1498 return (!scr.ns || scr.aw);
1510 return (!scr.ns || scr.fw);
1599 (hcr.tge || mdcr.tde);
1610 DPRINTF(Faults,
"Invoking ArmSev Fault\n");
1653 auto arm_fault =
dynamic_cast<ArmFault *
>(fault.get());
bool routeToHyp(ThreadContext *tc) const override
#define panic(...)
This implements a cprintf based panic() function.
void invoke(ThreadContext *tc, const StaticInstPtr &inst=StaticInst::nullStaticInstPtr) override
static uint8_t aarch64FaultSources[NumFaultSources]
Encodings of the fault sources in AArch64 state.
virtual uint8_t armPcElrOffset()=0
uint32_t iss() const override
virtual void setMiscReg(RegIndex misc_reg, RegVal val)=0
bool routeToHyp(ThreadContext *tc) const override
virtual System * getSystemPtr()=0
static ExceptionLevel currEL(ThreadContext *tc)
virtual void syscall(Fault *fault)=0
ExceptionClass ec(ThreadContext *tc) const override
MiscRegIndex getFaultAddrReg64() const
bool haveSecurity() const
Returns true if this system implements the Security Extensions.
const uint16_t currELTOffset
System error (AArch64 only)
virtual TheISA::PCState pcState() const =0
virtual FaultOffset offset(ThreadContext *tc)=0
virtual RegVal readIntReg(RegIndex reg_idx) const =0
void setSyndrome(ThreadContext *tc, MiscRegIndex syndrome_reg) override
virtual void setMiscRegNoEffect(RegIndex misc_reg, RegVal val)=0
void annotate(AnnotationIDs id, uint64_t val) override
static bool opModeIsT(OperatingMode mode)
ExceptionClass ec(ThreadContext *tc) const override
void clearInterrupt(ThreadID tid, int int_num, int index)
void invoke(ThreadContext *tc, const StaticInstPtr &inst=StaticInst::nullStaticInstPtr) override
bool highestELIs64() const
Returns true if the register width of the highest implemented exception level is 64 bits (ARMv8) ...
bool FullSystem
The FullSystem variable can be used to determine the current mode of simulation.
virtual void annotateFault(ArmFault *fault)
ExceptionClass ec(ThreadContext *tc) const override
virtual BaseCPU * getCpuPtr()=0
void clearInterrupts(ThreadID tid)
virtual FSR getFsr(ThreadContext *tc) const
ExceptionClass ec(ThreadContext *tc) const override
const uint16_t currELHOffset
virtual RegVal readCCReg(RegIndex reg_idx) const =0
bool fiqDisable(ThreadContext *tc) override
Addr purifyTaggedAddr(Addr addr, ThreadContext *tc, ExceptionLevel el, TCR tcr, bool isInstr)
Removes the tag from tagged addresses if that mode is enabled.
ThreadContext is the external interface to all thread state for anything outside of the CPU...
virtual bool fiqDisable(ThreadContext *tc)=0
RegVal getMPIDR(ArmSystem *arm_sys, ThreadContext *tc)
This helper function is returing the value of MPIDR_EL1.
virtual FaultName name() const =0
virtual bool routeToHyp(ThreadContext *tc) const
static bool haveEL(ThreadContext *tc, ExceptionLevel el)
Return true if the system implements a specific exception level.
ExceptionClass ec(ThreadContext *tc) const override
virtual FaultOffset offset64(ThreadContext *tc)=0
Bitfield< 31, 28 > condCode
void invoke(ThreadContext *tc, const StaticInstPtr &inst=StaticInst::nullStaticInstPtr) override
static uint8_t shortDescFaultSources[NumFaultSources]
Encodings of the fault sources when the short-desc.
virtual bool getFaultVAddr(Addr &va) const
bool routeToHyp(ThreadContext *tc) const override
bool ELIs64(ThreadContext *tc, ExceptionLevel el)
uint32_t iss() const override
static uint8_t longDescFaultSources[NumFaultSources]
Encodings of the fault sources when the long-desc.
void invoke(ThreadContext *tc, const StaticInstPtr &inst=StaticInst::nullStaticInstPtr) override
std::string csprintf(const char *format, const Args &...args)
void invoke(ThreadContext *tc, const StaticInstPtr &inst=StaticInst::nullStaticInstPtr) override
uint32_t iss() const override
bool routeToHyp(ThreadContext *tc) const override
const uint16_t lowerEL32Offset
ArmStaticInst * instrAnnotate(const StaticInstPtr &inst)
bool abortDisable(ThreadContext *tc) override
virtual bool routeToMonitor(ThreadContext *tc) const override
virtual bool abortDisable(ThreadContext *tc)=0
static ExceptionLevel opModeToEL(OperatingMode mode)
const uint16_t lowerEL64Offset
bool ELIs32(ThreadContext *tc, ExceptionLevel el)
bool routeToHyp(ThreadContext *tc) const override
HypervisorCall(ExtMachInst _machInst, uint32_t _imm)
void invoke(ThreadContext *tc, const StaticInstPtr &inst) override
virtual FaultStat & countStat()=0
virtual bool routeToMonitor(ThreadContext *tc) const =0
SoftwareBreakpoint(ExtMachInst _mach_inst, uint32_t _iss)
virtual uint8_t thumbPcOffset(bool isHyp)=0
Addr getVector64(ThreadContext *tc)
virtual void setIntReg(RegIndex reg_idx, RegVal val)=0
Addr getFaultVAddr() const
bool haveVirtualization() const
Returns true if this system implements the virtualization Extensions.
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
bool routeToHyp(ThreadContext *tc) const override
ExceptionClass ec(ThreadContext *tc) const override
MiscRegIndex getSyndromeReg64() const
void invoke64(ThreadContext *tc, const StaticInstPtr &inst=StaticInst::nullStaticInstPtr)
bool routeToMonitor(ThreadContext *tc) const override
uint32_t iss() const override
void invoke(ThreadContext *tc, const StaticInstPtr &inst=StaticInst::nullStaticInstPtr) override
ExceptionClass ec(ThreadContext *tc) const override
bool getFaultVAddr(Addr &va) const override
virtual OperatingMode nextMode()=0
void invoke(ThreadContext *tc, const StaticInstPtr &inst=StaticInst::nullStaticInstPtr) override
virtual uint8_t thumbPcElrOffset()=0
bool abortDisable(ThreadContext *tc) override
virtual uint32_t iss() const =0
virtual RegVal readMiscRegNoEffect(RegIndex misc_reg) const =0
virtual Addr getVector(ThreadContext *tc)
bool longDescFormatInUse(ThreadContext *tc)
bool routeToHyp(ThreadContext *tc) const override
Addr getVector(ThreadContext *tc) override
virtual void advancePC(TheISA::PCState &pcState) const =0
GenericISA::SimplePCState< MachInst > PCState
void invoke(ThreadContext *tc, const StaticInstPtr &inst=StaticInst::nullStaticInstPtr) override
bool routeToMonitor(ThreadContext *tc) const override
void invoke(ThreadContext *tc, const StaticInstPtr &inst=StaticInst::nullStaticInstPtr) override
virtual int threadId() const =0
bool routeToHyp(ThreadContext *tc) const override
bool routeToHyp(ThreadContext *tc) const override
FSR getFsr(ThreadContext *tc) const override
bool routeToHyp(ThreadContext *tc) const override
uint32_t iss() const override
bool abortDisable(ThreadContext *tc) override
virtual void clearArchRegs()=0
virtual uint8_t armPcOffset(bool isHyp)=0
IllegalInstSetStateFault()
void update(ThreadContext *tc)
void annotate(ArmFault::AnnotationIDs id, uint64_t val) override
bool routeToMonitor(ThreadContext *tc) const override
virtual void setSyndrome(ThreadContext *tc, MiscRegIndex syndrome_reg)
bool routeToHyp(ThreadContext *tc) const override
bool inSecureState(ThreadContext *tc)
virtual ExceptionClass ec(ThreadContext *tc) const =0
ExceptionClass ec(ThreadContext *tc) const override
FaultOffset offset64(ThreadContext *tc) override
static const int NumArgumentRegs M5_VAR_USED
T bits(T val, int first, int last)
Extract the bitfield from position 'first' to 'last' (inclusive) from 'val' and right justify it...
bool EL2Enabled(ThreadContext *tc)
ExceptionClass ec(ThreadContext *tc) const override
#define panic_if(cond,...)
Conditional panic macro that checks the supplied condition and only panics if the condition is true a...
Addr resetAddr() const
Returns the reset address if the highest implemented exception level is 64 bits (ARMv8) ...
T * get() const
Directly access the pointer itself without taking a reference.
virtual RegVal readMiscReg(RegIndex misc_reg)=0
ExceptionClass ec(ThreadContext *tc) const override
std::shared_ptr< FaultBase > Fault
FaultOffset offset(ThreadContext *tc) override
bool routeToMonitor(ThreadContext *tc) const override
bool routeToMonitor(ThreadContext *tc) const override
virtual void invoke(ThreadContext *tc, const StaticInstPtr &inst=StaticInst::nullStaticInstPtr)
Addr getFaultVAddr() const
ExceptionClass ec(ThreadContext *tc) const override
uint32_t iss() const override
uint8_t getFaultStatusCode(ThreadContext *tc) const