id_aa64afr1_el1 = Param.UInt64(0x0000000000000000,
"AArch64 Auxiliary Feature Register 1")
- # 1 CTX CMPs | 2 WRPs | 16 BRPs | !PMU | !Trace | Debug v8-A
- id_aa64dfr0_el1 = Param.UInt64(0x000000000010F006,
+ # 1 CTX CMPs | 16 WRPs | 16 BRPs | !PMU | !Trace | Debug v8-A
+ id_aa64dfr0_el1 = Param.UInt64(0x0000000000F0F006,
"AArch64 Debug Feature Register 0")
# Reserved for future expansion
id_aa64dfr1_el1 = Param.UInt64(0x0000000000000000,
"Hardware Breakpoint", 0x000, 0x000, 0x200, 0x400, 0x600, MODE_SVC,
0, 0, 0, 0, true, false, false, EC_HW_BREAKPOINT
);
+template<> ArmFault::FaultVals ArmFaultVals<Watchpoint>::vals(
+ "Watchpoint", 0x000, 0x000, 0x200, 0x400, 0x600, MODE_SVC,
+ 0, 0, 0, 0, true, false, false, EC_WATCHPOINT
+);
template<> ArmFault::FaultVals ArmFaultVals<ArmSev>::vals(
// Some dummy values
"ArmSev Flush", 0x000, 0x000, 0x000, 0x000, 0x000, MODE_SVC,
tc->setMiscReg(T::FarIndex, faultAddr);
if (debug == ArmFault::BRKPOINT){
Rext.moe = 0x1;
+ } else if (debug > ArmFault::BRKPOINT) {
+ Rext.moe = 0xa;
+ fsr.cm = (debug == ArmFault::WPOINT_CM)? 1 : 0;
}
tc->setMiscReg(T::FsrIndex, fsr);
toHyp |= (stage2 ||
((currEL(tc) != EL2) &&
(((source == AsynchronousExternalAbort) && hcr.amo) ||
- ((source == DebugEvent) && hdcr.tde))) ||
- ((currEL(tc) == EL0) && hcr.tge &&
- ((source == AlignmentFault) ||
- (source == SynchronousExternalAbort)))) && !inSecureState(tc);
+ ((source == DebugEvent) && (hdcr.tde || hcr.tge)))) ||
+ ((currEL(tc) == EL0) && hcr.tge &&
+ ((source == AlignmentFault) ||
+ (source == SynchronousExternalAbort)))) && !inSecureState(tc);
return toHyp;
}
}
+Watchpoint::Watchpoint(ExtMachInst _mach_inst, Addr _vaddr,
+ bool _write, bool _cm)
+ : ArmFaultVals<Watchpoint>(_mach_inst), vAddr(_vaddr),
+ write(_write), cm(_cm)
+{}
+
+uint32_t
+Watchpoint::iss() const
+{
+ uint32_t iss = 0x0022;
+// NV
+// if (toEL == EL2)
+// iss |= 0x02000;
+ if (cm)
+ iss |= 0x00100;
+ if (write)
+ iss |= 0x00040;
+ return iss;
+}
+
+void
+Watchpoint::invoke(ThreadContext *tc, const StaticInstPtr &inst)
+{
+ ArmFaultVals<Watchpoint>::invoke(tc, inst);
+ // Set the FAR
+ tc->setMiscReg(getFaultAddrReg64(), vAddr);
+
+}
+
+bool
+Watchpoint::routeToHyp(ThreadContext *tc) const
+{
+ const HCR hcr = tc->readMiscRegNoEffect(MISCREG_HCR_EL2);
+ const HDCR mdcr = tc->readMiscRegNoEffect(MISCREG_MDCR_EL2);
+
+ return fromEL == EL2 || (EL2Enabled(tc) && fromEL <= EL1 &&
+ (hcr.tge || mdcr.tde));
+}
+
+void
+Watchpoint::annotate(AnnotationIDs id, uint64_t val)
+{
+ ArmFaultVals<Watchpoint>::annotate(id, val);
+ switch (id)
+ {
+ case OFA:
+ vAddr = val;
+ break;
+ // Just ignore unknown ID's
+ default:
+ break;
+ }
+}
+
+ExceptionClass
+Watchpoint::ec(ThreadContext *tc) const
+{
+ // AArch64
+ if (toEL == fromEL)
+ return EC_WATCHPOINT_CURR_EL;
+ else
+ return EC_WATCHPOINT_LOWER_EL;
+}
+
void
ArmSev::invoke(ThreadContext *tc, const StaticInstPtr &inst) {
DPRINTF(Faults, "Invoking ArmSev Fault\n");
template class ArmFaultVals<SPAlignmentFault>;
template class ArmFaultVals<SystemError>;
template class ArmFaultVals<SoftwareBreakpoint>;
+template class ArmFaultVals<HardwareBreakpoint>;
+template class ArmFaultVals<Watchpoint>;
template class ArmFaultVals<ArmSev>;
template class AbortFault<PrefetchAbort>;
template class AbortFault<DataAbort>;
{
NODEBUG = 0,
BRKPOINT,
+ WPOINT_CM,
+ WPOINT_NOCM
};
struct FaultVals
bool ar;
DataAbort(Addr _addr, TlbEntry::DomainType _domain, bool _write, uint8_t _source,
- bool _stage2 = false, ArmFault::TranMethod _tranMethod = ArmFault::UnknownTran) :
+ bool _stage2=false,
+ ArmFault::TranMethod _tranMethod=ArmFault::UnknownTran,
+ ArmFault::DebugType _debug_type=ArmFault::NODEBUG) :
AbortFault<DataAbort>(_addr, _write, _domain, _source, _stage2,
- _tranMethod),
+ _tranMethod, _debug_type),
isv(false), sas (0), sse(0), srt(0), cm(0), sf(false), ar(false)
{}
ExceptionClass ec(ThreadContext *tc) const override;
};
+class Watchpoint : public ArmFaultVals<Watchpoint>
+{
+ private:
+ Addr vAddr;
+ bool write;
+ bool cm;
+
+ public:
+ Watchpoint(ExtMachInst _mach_inst, Addr _vaddr, bool _write, bool _cm);
+ void invoke(ThreadContext *tc, const StaticInstPtr &inst =
+ StaticInst::nullStaticInstPtr) override;
+ bool routeToHyp(ThreadContext *tc) const override;
+ uint32_t iss() const override;
+ ExceptionClass ec(ThreadContext *tc) const override;
+ void annotate(AnnotationIDs id, uint64_t val);
+};
+
// A fault that flushes the pipe, excluding the faulting instructions
class ArmSev : public ArmFaultVals<ArmSev>
{
template<> ArmFault::FaultVals ArmFaultVals<SystemError>::vals;
template<> ArmFault::FaultVals ArmFaultVals<SoftwareBreakpoint>::vals;
template<> ArmFault::FaultVals ArmFaultVals<HardwareBreakpoint>::vals;
+template<> ArmFault::FaultVals ArmFaultVals<Watchpoint>::vals;
template<> ArmFault::FaultVals ArmFaultVals<ArmSev>::vals;
/**
case MISCREG_DBGBCR15:
selfDebug->updateDBGBCR(15, val);
break;
+ case MISCREG_DBGWCR0:
+ selfDebug->updateDBGWCR(0, val);
+ break;
+ case MISCREG_DBGWCR1:
+ selfDebug->updateDBGWCR(1, val);
+ break;
+ case MISCREG_DBGWCR2:
+ selfDebug->updateDBGWCR(2, val);
+ break;
+ case MISCREG_DBGWCR3:
+ selfDebug->updateDBGWCR(3, val);
+ break;
+ case MISCREG_DBGWCR4:
+ selfDebug->updateDBGWCR(4, val);
+ break;
+ case MISCREG_DBGWCR5:
+ selfDebug->updateDBGWCR(5, val);
+ break;
+ case MISCREG_DBGWCR6:
+ selfDebug->updateDBGWCR(6, val);
+ break;
+ case MISCREG_DBGWCR7:
+ selfDebug->updateDBGWCR(7, val);
+ break;
+ case MISCREG_DBGWCR8:
+ selfDebug->updateDBGWCR(8, val);
+ break;
+ case MISCREG_DBGWCR9:
+ selfDebug->updateDBGWCR(9, val);
+ break;
+ case MISCREG_DBGWCR10:
+ selfDebug->updateDBGWCR(10, val);
+ break;
+ case MISCREG_DBGWCR11:
+ selfDebug->updateDBGWCR(11, val);
+ break;
+ case MISCREG_DBGWCR12:
+ selfDebug->updateDBGWCR(12, val);
+ break;
+ case MISCREG_DBGWCR13:
+ selfDebug->updateDBGWCR(13, val);
+ break;
+ case MISCREG_DBGWCR14:
+ selfDebug->updateDBGWCR(14, val);
+ break;
+ case MISCREG_DBGWCR15:
+ selfDebug->updateDBGWCR(15, val);
+ break;
case MISCREG_MDCR_EL2:
{
case MISCREG_DBGBCR15_EL1:
selfDebug->updateDBGBCR(15, val);
break;
+ case MISCREG_DBGWCR0_EL1:
+ selfDebug->updateDBGWCR(0, val);
+ break;
+ case MISCREG_DBGWCR1_EL1:
+ selfDebug->updateDBGWCR(1, val);
+ break;
+ case MISCREG_DBGWCR2_EL1:
+ selfDebug->updateDBGWCR(2, val);
+ break;
+ case MISCREG_DBGWCR3_EL1:
+ selfDebug->updateDBGWCR(3, val);
+ break;
+ case MISCREG_DBGWCR4_EL1:
+ selfDebug->updateDBGWCR(4, val);
+ break;
+ case MISCREG_DBGWCR5_EL1:
+ selfDebug->updateDBGWCR(5, val);
+ break;
+ case MISCREG_DBGWCR6_EL1:
+ selfDebug->updateDBGWCR(6, val);
+ break;
+ case MISCREG_DBGWCR7_EL1:
+ selfDebug->updateDBGWCR(7, val);
+ break;
+ case MISCREG_DBGWCR8_EL1:
+ selfDebug->updateDBGWCR(8, val);
+ break;
+ case MISCREG_DBGWCR9_EL1:
+ selfDebug->updateDBGWCR(9, val);
+ break;
+ case MISCREG_DBGWCR10_EL1:
+ selfDebug->updateDBGWCR(10, val);
+ break;
+ case MISCREG_DBGWCR11_EL1:
+ selfDebug->updateDBGWCR(11, val);
+ break;
+ case MISCREG_DBGWCR12_EL1:
+ selfDebug->updateDBGWCR(12, val);
+ break;
+ case MISCREG_DBGWCR13_EL1:
+ selfDebug->updateDBGWCR(13, val);
+ break;
+ case MISCREG_DBGWCR14_EL1:
+ selfDebug->updateDBGWCR(14, val);
+ break;
+ case MISCREG_DBGWCR15_EL1:
+ selfDebug->updateDBGWCR(15, val);
+ break;
case MISCREG_IFSR:
{
// ARM ARM (ARM DDI 0406C.b) B4.1.96
return MISCREG_DBGBCR15;
}
break;
+ case 6:
+ switch (crm) {
+ case 0:
+ return MISCREG_DBGWVR0;
+ case 1:
+ return MISCREG_DBGWVR1;
+ case 2:
+ return MISCREG_DBGWVR2;
+ case 3:
+ return MISCREG_DBGWVR3;
+ case 4:
+ return MISCREG_DBGWVR4;
+ case 5:
+ return MISCREG_DBGWVR5;
+ case 6:
+ return MISCREG_DBGWVR6;
+ case 7:
+ return MISCREG_DBGWVR7;
+ case 8:
+ return MISCREG_DBGWVR8;
+ case 9:
+ return MISCREG_DBGWVR9;
+ case 10:
+ return MISCREG_DBGWVR10;
+ case 11:
+ return MISCREG_DBGWVR11;
+ case 12:
+ return MISCREG_DBGWVR12;
+ case 13:
+ return MISCREG_DBGWVR13;
+ case 14:
+ return MISCREG_DBGWVR14;
+ case 15:
+ return MISCREG_DBGWVR15;
+ break;
+ }
+ break;
+ case 7:
+ switch (crm) {
+ case 0:
+ return MISCREG_DBGWCR0;
+ case 1:
+ return MISCREG_DBGWCR1;
+ case 2:
+ return MISCREG_DBGWCR2;
+ case 3:
+ return MISCREG_DBGWCR3;
+ case 4:
+ return MISCREG_DBGWCR4;
+ case 5:
+ return MISCREG_DBGWCR5;
+ case 6:
+ return MISCREG_DBGWCR6;
+ case 7:
+ return MISCREG_DBGWCR7;
+ case 8:
+ return MISCREG_DBGWCR8;
+ case 9:
+ return MISCREG_DBGWCR9;
+ case 10:
+ return MISCREG_DBGWCR10;
+ case 11:
+ return MISCREG_DBGWCR11;
+ case 12:
+ return MISCREG_DBGWCR12;
+ case 13:
+ return MISCREG_DBGWCR13;
+ case 14:
+ return MISCREG_DBGWCR14;
+ case 15:
+ return MISCREG_DBGWCR15;
+ }
+ break;
}
break;
case 7:
return MISCREG_DBGBVR4_EL1;
case 5:
return MISCREG_DBGBCR4_EL1;
+ case 6:
+ return MISCREG_DBGWVR4_EL1;
+ case 7:
+ return MISCREG_DBGWCR4_EL1;
}
break;
case 5:
return MISCREG_DBGBVR5_EL1;
case 5:
return MISCREG_DBGBCR5_EL1;
+ case 6:
+ return MISCREG_DBGWVR5_EL1;
+ case 7:
+ return MISCREG_DBGWCR5_EL1;
}
break;
case 6:
return MISCREG_DBGBVR6_EL1;
case 5:
return MISCREG_DBGBCR6_EL1;
+ case 6:
+ return MISCREG_DBGWVR6_EL1;
+ case 7:
+ return MISCREG_DBGWCR6_EL1;
}
break;
case 7:
return MISCREG_DBGBVR7_EL1;
case 5:
return MISCREG_DBGBCR7_EL1;
+ case 6:
+ return MISCREG_DBGWVR7_EL1;
+ case 7:
+ return MISCREG_DBGWCR7_EL1;
}
break;
case 8:
return MISCREG_DBGBVR8_EL1;
case 5:
return MISCREG_DBGBCR8_EL1;
+ case 6:
+ return MISCREG_DBGWVR8_EL1;
+ case 7:
+ return MISCREG_DBGWCR8_EL1;
}
break;
case 9:
return MISCREG_DBGBVR9_EL1;
case 5:
return MISCREG_DBGBCR9_EL1;
+ case 6:
+ return MISCREG_DBGWVR9_EL1;
+ case 7:
+ return MISCREG_DBGWCR9_EL1;
}
break;
case 10:
return MISCREG_DBGBVR10_EL1;
case 5:
return MISCREG_DBGBCR10_EL1;
+ case 6:
+ return MISCREG_DBGWVR10_EL1;
+ case 7:
+ return MISCREG_DBGWCR10_EL1;
}
break;
case 11:
return MISCREG_DBGBVR11_EL1;
case 5:
return MISCREG_DBGBCR11_EL1;
+ case 6:
+ return MISCREG_DBGWVR11_EL1;
+ case 7:
+ return MISCREG_DBGWCR11_EL1;
}
break;
case 12:
return MISCREG_DBGBVR12_EL1;
case 5:
return MISCREG_DBGBCR12_EL1;
+ case 6:
+ return MISCREG_DBGWVR12_EL1;
+ case 7:
+ return MISCREG_DBGWCR12_EL1;
}
break;
case 13:
return MISCREG_DBGBVR13_EL1;
case 5:
return MISCREG_DBGBCR13_EL1;
+ case 6:
+ return MISCREG_DBGWVR13_EL1;
+ case 7:
+ return MISCREG_DBGWCR13_EL1;
}
break;
case 14:
return MISCREG_DBGBVR14_EL1;
case 5:
return MISCREG_DBGBCR14_EL1;
+ case 6:
+ return MISCREG_DBGWVR14_EL1;
+ case 7:
+ return MISCREG_DBGWCR14_EL1;
}
break;
case 15:
return MISCREG_DBGBVR15_EL1;
case 5:
return MISCREG_DBGBCR15_EL1;
+ case 6:
+ return MISCREG_DBGWVR15_EL1;
+ case 7:
+ return MISCREG_DBGWCR15_EL1;
}
break;
}
InitReg(MISCREG_DBGBCR15)
.allPrivileges().exceptUserMode();
InitReg(MISCREG_DBGWVR0)
- .unimplemented()
- .allPrivileges();
+ .allPrivileges().exceptUserMode();
InitReg(MISCREG_DBGWVR1)
- .unimplemented()
- .allPrivileges();
+ .allPrivileges().exceptUserMode();
InitReg(MISCREG_DBGWVR2)
- .unimplemented()
- .allPrivileges();
+ .allPrivileges().exceptUserMode();
InitReg(MISCREG_DBGWVR3)
- .unimplemented()
- .allPrivileges();
+ .allPrivileges().exceptUserMode();
+ InitReg(MISCREG_DBGWVR4)
+ .allPrivileges().exceptUserMode();
+ InitReg(MISCREG_DBGWVR5)
+ .allPrivileges().exceptUserMode();
+ InitReg(MISCREG_DBGWVR6)
+ .allPrivileges().exceptUserMode();
+ InitReg(MISCREG_DBGWVR7)
+ .allPrivileges().exceptUserMode();
+ InitReg(MISCREG_DBGWVR8)
+ .allPrivileges().exceptUserMode();
+ InitReg(MISCREG_DBGWVR9)
+ .allPrivileges().exceptUserMode();
+ InitReg(MISCREG_DBGWVR10)
+ .allPrivileges().exceptUserMode();
+ InitReg(MISCREG_DBGWVR11)
+ .allPrivileges().exceptUserMode();
+ InitReg(MISCREG_DBGWVR12)
+ .allPrivileges().exceptUserMode();
+ InitReg(MISCREG_DBGWVR13)
+ .allPrivileges().exceptUserMode();
+ InitReg(MISCREG_DBGWVR14)
+ .allPrivileges().exceptUserMode();
+ InitReg(MISCREG_DBGWVR15)
+ .allPrivileges().exceptUserMode();
InitReg(MISCREG_DBGWCR0)
- .unimplemented()
- .allPrivileges();
+ .allPrivileges().exceptUserMode();
InitReg(MISCREG_DBGWCR1)
- .unimplemented()
- .allPrivileges();
+ .allPrivileges().exceptUserMode();
InitReg(MISCREG_DBGWCR2)
- .unimplemented()
- .allPrivileges();
+ .allPrivileges().exceptUserMode();
InitReg(MISCREG_DBGWCR3)
- .unimplemented()
- .allPrivileges();
+ .allPrivileges().exceptUserMode();
+ InitReg(MISCREG_DBGWCR4)
+ .allPrivileges().exceptUserMode();
+ InitReg(MISCREG_DBGWCR5)
+ .allPrivileges().exceptUserMode();
+ InitReg(MISCREG_DBGWCR6)
+ .allPrivileges().exceptUserMode();
+ InitReg(MISCREG_DBGWCR7)
+ .allPrivileges().exceptUserMode();
+ InitReg(MISCREG_DBGWCR8)
+ .allPrivileges().exceptUserMode();
+ InitReg(MISCREG_DBGWCR9)
+ .allPrivileges().exceptUserMode();
+ InitReg(MISCREG_DBGWCR10)
+ .allPrivileges().exceptUserMode();
+ InitReg(MISCREG_DBGWCR11)
+ .allPrivileges().exceptUserMode();
+ InitReg(MISCREG_DBGWCR12)
+ .allPrivileges().exceptUserMode();
+ InitReg(MISCREG_DBGWCR13)
+ .allPrivileges().exceptUserMode();
+ InitReg(MISCREG_DBGWCR14)
+ .allPrivileges().exceptUserMode();
+ InitReg(MISCREG_DBGWCR15)
+ .allPrivileges().exceptUserMode();
InitReg(MISCREG_DBGDRAR)
.unimplemented()
.allPrivileges().monSecureWrite(0).monNonSecureWrite(0);
.allPrivileges().exceptUserMode()
.mapsTo(MISCREG_DBGBCR15);
InitReg(MISCREG_DBGWVR0_EL1)
- .allPrivileges()
+ .allPrivileges().exceptUserMode()
.mapsTo(MISCREG_DBGWVR0);
InitReg(MISCREG_DBGWVR1_EL1)
- .allPrivileges()
+ .allPrivileges().exceptUserMode()
.mapsTo(MISCREG_DBGWVR1);
InitReg(MISCREG_DBGWVR2_EL1)
- .allPrivileges()
+ .allPrivileges().exceptUserMode()
.mapsTo(MISCREG_DBGWVR2);
InitReg(MISCREG_DBGWVR3_EL1)
- .allPrivileges()
+ .allPrivileges().exceptUserMode()
.mapsTo(MISCREG_DBGWVR3);
+ InitReg(MISCREG_DBGWVR4_EL1)
+ .allPrivileges().exceptUserMode()
+ .mapsTo(MISCREG_DBGWVR4);
+ InitReg(MISCREG_DBGWVR5_EL1)
+ .allPrivileges().exceptUserMode()
+ .mapsTo(MISCREG_DBGWVR5);
+ InitReg(MISCREG_DBGWVR6_EL1)
+ .allPrivileges().exceptUserMode()
+ .mapsTo(MISCREG_DBGWVR6);
+ InitReg(MISCREG_DBGWVR7_EL1)
+ .allPrivileges().exceptUserMode()
+ .mapsTo(MISCREG_DBGWVR7);
+ InitReg(MISCREG_DBGWVR8_EL1)
+ .allPrivileges().exceptUserMode()
+ .mapsTo(MISCREG_DBGWVR8);
+ InitReg(MISCREG_DBGWVR9_EL1)
+ .allPrivileges().exceptUserMode()
+ .mapsTo(MISCREG_DBGWVR9);
+ InitReg(MISCREG_DBGWVR10_EL1)
+ .allPrivileges().exceptUserMode()
+ .mapsTo(MISCREG_DBGWVR10);
+ InitReg(MISCREG_DBGWVR11_EL1)
+ .allPrivileges().exceptUserMode()
+ .mapsTo(MISCREG_DBGWVR11);
+ InitReg(MISCREG_DBGWVR12_EL1)
+ .allPrivileges().exceptUserMode()
+ .mapsTo(MISCREG_DBGWVR12);
+ InitReg(MISCREG_DBGWVR13_EL1)
+ .allPrivileges().exceptUserMode()
+ .mapsTo(MISCREG_DBGWVR13);
+ InitReg(MISCREG_DBGWVR14_EL1)
+ .allPrivileges().exceptUserMode()
+ .mapsTo(MISCREG_DBGWVR14);
+ InitReg(MISCREG_DBGWVR15_EL1)
+ .allPrivileges().exceptUserMode()
+ .mapsTo(MISCREG_DBGWVR15);
InitReg(MISCREG_DBGWCR0_EL1)
- .allPrivileges()
+ .allPrivileges().exceptUserMode()
.mapsTo(MISCREG_DBGWCR0);
InitReg(MISCREG_DBGWCR1_EL1)
- .allPrivileges()
+ .allPrivileges().exceptUserMode()
.mapsTo(MISCREG_DBGWCR1);
InitReg(MISCREG_DBGWCR2_EL1)
- .allPrivileges()
+ .allPrivileges().exceptUserMode()
.mapsTo(MISCREG_DBGWCR2);
InitReg(MISCREG_DBGWCR3_EL1)
- .allPrivileges()
+ .allPrivileges().exceptUserMode()
.mapsTo(MISCREG_DBGWCR3);
+ InitReg(MISCREG_DBGWCR4_EL1)
+ .allPrivileges().exceptUserMode()
+ .mapsTo(MISCREG_DBGWCR4);
+ InitReg(MISCREG_DBGWCR5_EL1)
+ .allPrivileges().exceptUserMode()
+ .mapsTo(MISCREG_DBGWCR5);
+ InitReg(MISCREG_DBGWCR6_EL1)
+ .allPrivileges().exceptUserMode()
+ .mapsTo(MISCREG_DBGWCR6);
+ InitReg(MISCREG_DBGWCR7_EL1)
+ .allPrivileges().exceptUserMode()
+ .mapsTo(MISCREG_DBGWCR7);
+ InitReg(MISCREG_DBGWCR8_EL1)
+ .allPrivileges().exceptUserMode()
+ .mapsTo(MISCREG_DBGWCR8);
+ InitReg(MISCREG_DBGWCR9_EL1)
+ .allPrivileges().exceptUserMode()
+ .mapsTo(MISCREG_DBGWCR9);
+ InitReg(MISCREG_DBGWCR10_EL1)
+ .allPrivileges().exceptUserMode()
+ .mapsTo(MISCREG_DBGWCR10);
+ InitReg(MISCREG_DBGWCR11_EL1)
+ .allPrivileges().exceptUserMode()
+ .mapsTo(MISCREG_DBGWCR11);
+ InitReg(MISCREG_DBGWCR12_EL1)
+ .allPrivileges().exceptUserMode()
+ .mapsTo(MISCREG_DBGWCR12);
+ InitReg(MISCREG_DBGWCR13_EL1)
+ .allPrivileges().exceptUserMode()
+ .mapsTo(MISCREG_DBGWCR13);
+ InitReg(MISCREG_DBGWCR14_EL1)
+ .allPrivileges().exceptUserMode()
+ .mapsTo(MISCREG_DBGWCR14);
+ InitReg(MISCREG_DBGWCR15_EL1)
+ .allPrivileges().exceptUserMode()
+ .mapsTo(MISCREG_DBGWCR15);
InitReg(MISCREG_MDCCSR_EL0)
.allPrivileges().monSecureWrite(0).monNonSecureWrite(0)
.mapsTo(MISCREG_DBGDSCRint);
MISCREG_DBGWVR1,
MISCREG_DBGWVR2,
MISCREG_DBGWVR3,
+ MISCREG_DBGWVR4,
+ MISCREG_DBGWVR5,
+ MISCREG_DBGWVR6,
+ MISCREG_DBGWVR7,
+ MISCREG_DBGWVR8,
+ MISCREG_DBGWVR9,
+ MISCREG_DBGWVR10,
+ MISCREG_DBGWVR11,
+ MISCREG_DBGWVR12,
+ MISCREG_DBGWVR13,
+ MISCREG_DBGWVR14,
+ MISCREG_DBGWVR15,
MISCREG_DBGWCR0,
MISCREG_DBGWCR1,
MISCREG_DBGWCR2,
MISCREG_DBGWCR3,
+ MISCREG_DBGWCR4,
+ MISCREG_DBGWCR5,
+ MISCREG_DBGWCR6,
+ MISCREG_DBGWCR7,
+ MISCREG_DBGWCR8,
+ MISCREG_DBGWCR9,
+ MISCREG_DBGWCR10,
+ MISCREG_DBGWCR11,
+ MISCREG_DBGWCR12,
+ MISCREG_DBGWCR13,
+ MISCREG_DBGWCR14,
+ MISCREG_DBGWCR15,
MISCREG_DBGDRAR,
MISCREG_DBGBXVR0,
MISCREG_DBGBXVR1,
MISCREG_DBGWVR1_EL1,
MISCREG_DBGWVR2_EL1,
MISCREG_DBGWVR3_EL1,
+ MISCREG_DBGWVR4_EL1,
+ MISCREG_DBGWVR5_EL1,
+ MISCREG_DBGWVR6_EL1,
+ MISCREG_DBGWVR7_EL1,
+ MISCREG_DBGWVR8_EL1,
+ MISCREG_DBGWVR9_EL1,
+ MISCREG_DBGWVR10_EL1,
+ MISCREG_DBGWVR11_EL1,
+ MISCREG_DBGWVR12_EL1,
+ MISCREG_DBGWVR13_EL1,
+ MISCREG_DBGWVR14_EL1,
+ MISCREG_DBGWVR15_EL1,
MISCREG_DBGWCR0_EL1,
MISCREG_DBGWCR1_EL1,
MISCREG_DBGWCR2_EL1,
MISCREG_DBGWCR3_EL1,
+ MISCREG_DBGWCR4_EL1,
+ MISCREG_DBGWCR5_EL1,
+ MISCREG_DBGWCR6_EL1,
+ MISCREG_DBGWCR7_EL1,
+ MISCREG_DBGWCR8_EL1,
+ MISCREG_DBGWCR9_EL1,
+ MISCREG_DBGWCR10_EL1,
+ MISCREG_DBGWCR11_EL1,
+ MISCREG_DBGWCR12_EL1,
+ MISCREG_DBGWCR13_EL1,
+ MISCREG_DBGWCR14_EL1,
+ MISCREG_DBGWCR15_EL1,
MISCREG_MDCCSR_EL0,
MISCREG_MDDTR_EL0,
MISCREG_MDDTRTX_EL0,
"dbgwvr1",
"dbgwvr2",
"dbgwvr3",
+ "dbgwvr4",
+ "dbgwvr5",
+ "dbgwvr6",
+ "dbgwvr7",
+ "dbgwvr8",
+ "dbgwvr9",
+ "dbgwvr10",
+ "dbgwvr11",
+ "dbgwvr12",
+ "dbgwvr13",
+ "dbgwvr14",
+ "dbgwvr15",
"dbgwcr0",
"dbgwcr1",
"dbgwcr2",
"dbgwcr3",
+ "dbgwcr4",
+ "dbgwcr5",
+ "dbgwcr6",
+ "dbgwcr7",
+ "dbgwcr8",
+ "dbgwcr9",
+ "dbgwcr10",
+ "dbgwcr11",
+ "dbgwcr12",
+ "dbgwcr13",
+ "dbgwcr14",
+ "dbgwcr15",
"dbgdrar",
"dbgbxvr0",
"dbgbxvr1",
"dbgwvr1_el1",
"dbgwvr2_el1",
"dbgwvr3_el1",
+ "dbgwvr4_el1",
+ "dbgwvr5_el1",
+ "dbgwvr6_el1",
+ "dbgwvr7_el1",
+ "dbgwvr8_el1",
+ "dbgwvr9_el1",
+ "dbgwvr10_el1",
+ "dbgwvr11_el1",
+ "dbgwvr12_el1",
+ "dbgwvr13_el1",
+ "dbgwvr14_el1",
+ "dbgwvr15_el1",
"dbgwcr0_el1",
"dbgwcr1_el1",
"dbgwcr2_el1",
"dbgwcr3_el1",
+ "dbgwcr4_el1",
+ "dbgwcr5_el1",
+ "dbgwcr6_el1",
+ "dbgwcr7_el1",
+ "dbgwcr8_el1",
+ "dbgwcr9_el1",
+ "dbgwcr10_el1",
+ "dbgwcr11_el1",
+ "dbgwcr12_el1",
+ "dbgwcr13_el1",
+ "dbgwcr14_el1",
+ "dbgwcr15_el1",
"mdccsr_el0",
"mddtr_el0",
"mddtrtx_el0",
Bitfield<0> e;
EndBitUnion(DBGBCR)
+ BitUnion64(DBGWCR)
+ Bitfield<63, 29> res0_2;
+ Bitfield<28, 24> mask;
+ Bitfield<23, 21> res0_1;
+ Bitfield<20> wt;
+ Bitfield<19, 16> lbn;
+ Bitfield<15, 14> ssc;
+ Bitfield<13> hmc;
+ Bitfield<12, 5> bas;
+ Bitfield<4, 3> lsv;
+ Bitfield<2, 1> pac;
+ Bitfield<0> e;
+ EndBitUnion(DBGWCR)
+
BitUnion32(DBGDS32)
Bitfield<31> tfo;
Bitfield<30> rxfull;
}
}
+Fault
+SelfDebug::testWatchPoints(ThreadContext *tc, Addr vaddr, bool write,
+ bool atomic, unsigned size, bool cm)
+{
+ setAArch32(tc);
+ to32 = targetAArch32(tc);
+ if (!initialized)
+ init(tc);
+ if (!isDebugEnabled(tc) || !enableFlag)
+ return NoFault;
+
+ ExceptionLevel el = (ExceptionLevel) currEL(tc);
+ int idxtmp = -1;
+ for (auto &p: arWatchPoints){
+ idxtmp ++;
+ if (p.getEnable())
+ {
+ bool debug = p.test(tc, vaddr, el, write, atomic, size);
+ if (debug){
+ return triggerWatchpointException(tc, vaddr, write, cm);
+ }
+ }
+ }
+ return NoFault;
+}
+
+Fault
+SelfDebug::triggerWatchpointException(ThreadContext *tc, Addr vaddr,
+ bool write, bool cm)
+{
+ if (isTo32()) {
+ ArmFault::DebugType d = cm? ArmFault::WPOINT_CM:
+ ArmFault::WPOINT_NOCM;
+ return std::make_shared<DataAbort>(vaddr,
+ TlbEntry::DomainType::NoAccess,
+ write, ArmFault::DebugEvent, cm,
+ ArmFault::UnknownTran, d);
+ } else {
+ return std::make_shared<Watchpoint>(0, vaddr, write, cm);
+ }
+}
+
bool
SelfDebug::isDebugEnabledForEL64(ThreadContext *tc, ExceptionLevel el,
bool secure, bool mask)
return bits(tc->readMiscReg(valRegIndex), vmid_index, 32);
}
+
+bool
+WatchPoint::isEnabled(ThreadContext* tc, ExceptionLevel el,
+ bool hmc, uint8_t ssc, uint8_t pac)
+{
+
+ bool v;
+ bool aarch32 = conf->isAArch32();
+ bool noEL2 = !ArmSystem::haveEL(tc, EL2);
+ bool noEL3 = !ArmSystem::haveEL(tc, EL3);
+
+ if (aarch32){
+ // WatchPoint PL2 using aarch32 is disabled except for
+ // debug state. Check G2-5395 table G2-15.
+ if (el==EL2)
+ return false;
+ if (noEL3){
+ if (ssc == 0x01 || ssc == 0x02){
+ return false;
+ }
+ else if (noEL2 && ((!hmc && ssc==0x3) || (hmc && ssc==0x0)))
+ {
+ return false;
+ }
+ }
+ if (noEL2 && hmc && ssc == 0x03 && pac == 0)
+ return false;
+ }
+ switch (el) {
+ case EL0:
+ v = (pac == 0x3 || (pac == 0x2 && !hmc && ssc != 0x3));
+ break;
+ case EL1:
+ v = (pac == 0x1 || pac == 0x3);
+ break;
+ case EL2:
+ v = (hmc && (ssc != 0x2 || pac != 0x0));
+ break;
+ case EL3:
+ v = (hmc && (ssc == 0x2 ||
+ (ssc == 0x1 && (pac == 0x1 || pac == 0x3))));
+ break;
+ default:
+ panic("Unexpected EL in WatchPoint::isEnabled.\n");
+ }
+ return v && SelfDebug::securityStateMatch(tc, ssc, hmc);
+}
+
+bool
+WatchPoint::test(ThreadContext *tc, Addr addr, ExceptionLevel el, bool& wrt,
+ bool atomic, unsigned size)
+{
+
+ bool v = false;
+ const DBGWCR ctr = tc->readMiscReg(ctrlRegIndex);
+ if (isEnabled(tc, el, ctr.hmc, ctr.ssc, ctr.pac) &&
+ ((wrt && (ctr.lsv & 0x2)) || (!wrt && (ctr.lsv & 0x1)) || atomic))
+ {
+ v = compareAddress(tc, addr, ctr.bas, ctr.mask, size);
+ if (ctr.wt){
+ v = v && (conf->getBrkPoint(ctr.lbn))->testLinkedBk(tc, addr, el);
+ }
+ }
+ if (atomic && (ctr.lsv & 0x1)){
+ wrt = false;
+ }
+ return v;
+}
+
+bool
+WatchPoint::compareAddress(ThreadContext *tc, Addr in_addr, uint8_t bas,
+ uint8_t mask, unsigned size)
+{
+ Addr addr_tocmp = getAddrfromReg(tc);
+ int maxAddrSize = getMaxAddrSize();
+ int maxbits = isDoubleAligned(addr_tocmp) ? 4: 8;
+ int bottom = isDoubleAligned(addr_tocmp) ? 2: 3;
+ Addr addr = bits(in_addr, maxAddrSize, 0);
+
+ if (bas == 0x0)
+ return false;
+
+ if (mask == 0x0){
+
+ for (int i=0; i < maxbits; i++){
+ uint8_t bas_m = 0x1 << i;
+ uint8_t masked_bas = bas & bas_m;
+ if (masked_bas == bas_m){
+ uint8_t off = log2(masked_bas);
+ Addr cmpaddr = addr_tocmp | off;
+ for (int j=0; j<size; j++){
+ if ((addr+j) == cmpaddr) {
+ return true;
+ }
+ }
+ }
+ }
+ return false;
+ }
+ else
+ {
+ bool v = false;
+ for (int j=0; j<size; j++)
+ {
+ Addr compaddr;
+ if (mask > bottom){
+ addr = bits((in_addr+j), maxAddrSize, mask);
+ compaddr = bits(addr_tocmp, maxAddrSize, mask);
+ }
+ else{
+ addr = bits((in_addr+j), maxAddrSize, bottom);
+ compaddr = bits(addr_tocmp, maxAddrSize, bottom);
+ }
+ v = v || (addr==compaddr) ;
+ }
+ return v;
+ }
+}
+
};
+class WatchPoint
+{
+ private:
+ MiscRegIndex ctrlRegIndex;
+ MiscRegIndex valRegIndex;
+ SelfDebug * conf;
+ bool enable;
+ int maxAddrSize;
+
+ inline int getMaxAddrSize()
+ {
+ return maxAddrSize;
+ }
+
+
+ public:
+ WatchPoint(MiscRegIndex _ctrlIndex, MiscRegIndex _valIndex,
+ SelfDebug* _conf, bool lva, bool aarch32):
+ ctrlRegIndex(_ctrlIndex),
+ valRegIndex(_valIndex), conf(_conf), enable(false)
+ {
+ maxAddrSize = lva ? 52: 48 ;
+ maxAddrSize = aarch32 ? 31 : maxAddrSize;
+ }
+
+ bool compareAddress(ThreadContext *tc, Addr in_addr,
+ uint8_t bas, uint8_t mask, unsigned size);
+
+ inline Addr getAddrfromReg(ThreadContext *tc)
+ {
+ return bits(tc->readMiscReg(valRegIndex), maxAddrSize, 0);
+
+ }
+
+ inline bool isDoubleAligned(Addr addr)
+ {
+ return addr & 0x4;
+ }
+
+ inline void updateControl(DBGWCR val)
+ {
+ enable = val.e == 0x1;
+ }
+ bool getEnable()
+ {
+ return enable;
+ }
+
+ bool isEnabled(ThreadContext* tc, ExceptionLevel el, bool hmc,
+ uint8_t ssc, uint8_t pac);
+ bool test(ThreadContext *tc, Addr addr, ExceptionLevel el, bool& wrt,
+ bool atomic, unsigned size);
+};
+
class SelfDebug
{
private:
std::vector<BrkPoint> arBrkPoints;
+ std::vector<WatchPoint> arWatchPoints;
bool initialized;
bool enableTdeTge; // MDCR_EL2.TDE || HCR_EL2.TGE
~SelfDebug(){}
Fault testBreakPoints(ThreadContext *tc, Addr vaddr);
+ Fault testWatchPoints(ThreadContext *tc, Addr vaddr, bool write,
+ bool atomic, unsigned size, bool cm);
+ Fault testVectorCatch(ThreadContext *tc, Addr addr, ArmFault* flt);
+
Fault triggerException(ThreadContext * tc, Addr vaddr);
+ Fault triggerWatchpointException(ThreadContext *tc, Addr vaddr,
+ bool write, bool cm);
inline BrkPoint* getBrkPoint(uint8_t index)
{
arBrkPoints[index].updateControl(val);
}
+ inline void updateDBGWCR(int index, DBGWCR val)
+ {
+ arWatchPoints[index].updateControl(val);
+ }
+
inline bool isAArch32()
{
return aarch32;
arBrkPoints.push_back(bkp);
}
+ for (int i=0; i<=dfr.wrps; i++){
+ WatchPoint wtp = WatchPoint((MiscRegIndex)(MISCREG_DBGWCR0+i),
+ (MiscRegIndex)(MISCREG_DBGWVR0+i),
+ this, (bool)mm_fr2.varange, aarch32);
+ const DBGWCR ctr = tc->readMiscReg(MISCREG_DBGWCR0+i);
+
+ wtp.updateControl(ctr);
+ arWatchPoints.push_back(wtp);
+ }
initialized = true;
if (mode == Execute) {
fault = sd->testBreakPoints(tc, req->getVaddr());
}
+ else if (!req->isCacheMaintenance() ||
+ (req->isCacheInvalidate() && !req->isCacheClean()))
+ {
+ bool md = mode == Write ? true: false;
+ fault = sd->testWatchPoints(tc, req->getVaddr(), md,
+ req->isAtomic(),
+ req->getSize(),
+ req->isCacheMaintenance());
+ }
}
return fault;
{ "dbgwvr1", MISCREG_DBGWVR1 },
{ "dbgwvr2", MISCREG_DBGWVR2 },
{ "dbgwvr3", MISCREG_DBGWVR3 },
+ { "dbgwvr4", MISCREG_DBGWVR4 },
+ { "dbgwvr5", MISCREG_DBGWVR5 },
+ { "dbgwvr6", MISCREG_DBGWVR6 },
+ { "dbgwvr7", MISCREG_DBGWVR7 },
+ { "dbgwvr8", MISCREG_DBGWVR8 },
+ { "dbgwvr9", MISCREG_DBGWVR9 },
+ { "dbgwvr10", MISCREG_DBGWVR10 },
+ { "dbgwvr11", MISCREG_DBGWVR11 },
+ { "dbgwvr12", MISCREG_DBGWVR12 },
+ { "dbgwvr13", MISCREG_DBGWVR13 },
+ { "dbgwvr14", MISCREG_DBGWVR14 },
+ { "dbgwvr15", MISCREG_DBGWVR15 },
{ "dbgwcr0", MISCREG_DBGWCR0 },
{ "dbgwcr1", MISCREG_DBGWCR1 },
{ "dbgwcr2", MISCREG_DBGWCR2 },
{ "dbgwcr3", MISCREG_DBGWCR3 },
+ { "dbgwcr4", MISCREG_DBGWCR4 },
+ { "dbgwcr5", MISCREG_DBGWCR5 },
+ { "dbgwcr6", MISCREG_DBGWCR6 },
+ { "dbgwcr7", MISCREG_DBGWCR7 },
+ { "dbgwcr8", MISCREG_DBGWCR8 },
+ { "dbgwcr9", MISCREG_DBGWCR9 },
+ { "dbgwcr10", MISCREG_DBGWCR10 },
+ { "dbgwcr11", MISCREG_DBGWCR11 },
+ { "dbgwcr12", MISCREG_DBGWCR12 },
+ { "dbgwcr13", MISCREG_DBGWCR13 },
+ { "dbgwcr14", MISCREG_DBGWCR14 },
+ { "dbgwcr15", MISCREG_DBGWCR15 },
{ "dbgdrar", MISCREG_DBGDRAR },
{ "dbgbxvr0", MISCREG_DBGBXVR0 },
{ "dbgbxvr1", MISCREG_DBGBXVR1 },
{ "dbgwvr1_el1", MISCREG_DBGWVR1_EL1 },
{ "dbgwvr2_el1", MISCREG_DBGWVR2_EL1 },
{ "dbgwvr3_el1", MISCREG_DBGWVR3_EL1 },
+ { "dbgwvr4_el1", MISCREG_DBGWVR4_EL1 },
+ { "dbgwvr5_el1", MISCREG_DBGWVR5_EL1 },
+ { "dbgwvr6_el1", MISCREG_DBGWVR6_EL1 },
+ { "dbgwvr7_el1", MISCREG_DBGWVR7_EL1 },
+ { "dbgwvr8_el1", MISCREG_DBGWVR8_EL1 },
+ { "dbgwvr9_el1", MISCREG_DBGWVR9_EL1 },
+ { "dbgwvr10_el1", MISCREG_DBGWVR10_EL1 },
+ { "dbgwvr11_el1", MISCREG_DBGWVR11_EL1 },
+ { "dbgwvr12_el1", MISCREG_DBGWVR12_EL1 },
+ { "dbgwvr13_el1", MISCREG_DBGWVR13_EL1 },
+ { "dbgwvr14_el1", MISCREG_DBGWVR14_EL1 },
+ { "dbgwvr15_el1", MISCREG_DBGWVR15_EL1 },
{ "dbgwcr0_el1", MISCREG_DBGWCR0_EL1 },
{ "dbgwcr1_el1", MISCREG_DBGWCR1_EL1 },
{ "dbgwcr2_el1", MISCREG_DBGWCR2_EL1 },
{ "dbgwcr3_el1", MISCREG_DBGWCR3_EL1 },
+ { "dbgwcr4_el1", MISCREG_DBGWCR4_EL1 },
+ { "dbgwcr5_el1", MISCREG_DBGWCR5_EL1 },
+ { "dbgwcr6_el1", MISCREG_DBGWCR6_EL1 },
+ { "dbgwcr7_el1", MISCREG_DBGWCR7_EL1 },
+ { "dbgwcr8_el1", MISCREG_DBGWCR8_EL1 },
+ { "dbgwcr9_el1", MISCREG_DBGWCR9_EL1 },
+ { "dbgwcr10_el1", MISCREG_DBGWCR10_EL1 },
+ { "dbgwcr11_el1", MISCREG_DBGWCR11_EL1 },
+ { "dbgwcr12_el1", MISCREG_DBGWCR12_EL1 },
+ { "dbgwcr13_el1", MISCREG_DBGWCR13_EL1 },
+ { "dbgwcr14_el1", MISCREG_DBGWCR14_EL1 },
+ { "dbgwcr15_el1", MISCREG_DBGWCR15_EL1 },
{ "mdccsr_el0", MISCREG_MDCCSR_EL0 },
{ "mddtr_el0", MISCREG_MDDTR_EL0 },
{ "mddtrtx_el0", MISCREG_MDDTRTX_EL0 },
EC_HW_BREAKPOINT = 0x30,
EC_HW_BREAKPOINT_LOWER_EL = 0x30,
EC_HW_BREAKPOINT_CURR_EL = 0x31,
+ EC_WATCHPOINT = 0x34,
+ EC_WATCHPOINT_LOWER_EL = 0x34,
+ EC_WATCHPOINT_CURR_EL = 0x35,
EC_SOFTWARE_BREAKPOINT = 0x38,
EC_SOFTWARE_BREAKPOINT_64 = 0x3C,
};
bool ELIsInHost(ThreadContext *tc, ExceptionLevel el);
ExceptionLevel debugTargetFrom(ThreadContext *tc, bool secure);
+
bool isBigEndian64(const ThreadContext *tc);