arch-arm: Implementation of ARMv8 SelfDebug Watchpoints

This change includes ArmV8 SelfDebug Watchpoint implementation
as is described in Armv8 Reference manual D2/G2
The changes specific descriptions are as follow:
+ ArmISA.py: Enable up to 16 DBGWn registers
+ isa.cc: Include in setMiscReg specific cases for DBGWCn registers enable bit
+ miscregs_types.hh: Define DBGWC bitwise types
+ miscregs.hh/cc: Definition of watchpoint registers and its initialization
+ tlb.cc: Call for watchpoint entry point on tlb translation for dtlb.
+ fault.cc/hh: Definition/implementation of Watchpoint exception and
               modification on DataAbort Exception accordingly to handle
               AArch32 Watchpoint exceptions.
+ types.hh: Exception Code for watchpoint.
+ self_debug.cc/hh: Watchpoint check and comparison. Definition and
                    implementation of all the watchpoint auxiliar functions.

Change-Id: If275e4df0d28918dd887ab78166e653da875310a
Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/28589
Maintainer: Giacomo Travaglini <giacomo.travaglini@arm.com>
Tested-by: kokoro <noreply+kokoro@google.com>
Reviewed-by: Giacomo Travaglini <giacomo.travaglini@arm.com>
This commit is contained in:
Jordi Vaquero
2019-10-29 16:01:56 +01:00
parent 835c07eb0f
commit 3db58b4fc0
13 changed files with 863 additions and 32 deletions

View File

@@ -90,8 +90,8 @@ class ArmISA(BaseISA):
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,

View File

@@ -285,6 +285,10 @@ template<> ArmFault::FaultVals ArmFaultVals<HardwareBreakpoint>::vals(
"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,
@@ -1084,6 +1088,9 @@ AbortFault<T>::invoke(ThreadContext *tc, const StaticInstPtr &inst)
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);
@@ -1354,10 +1361,10 @@ DataAbort::routeToHyp(ThreadContext *tc) const
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;
}
@@ -1668,6 +1675,70 @@ HardwareBreakpoint::invoke(ThreadContext *tc, const StaticInstPtr &inst)
}
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");
@@ -1701,6 +1772,8 @@ template class ArmFaultVals<PCAlignmentFault>;
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>;

View File

@@ -153,6 +153,8 @@ class ArmFault : public FaultBase
{
NODEBUG = 0,
BRKPOINT,
WPOINT_CM,
WPOINT_NOCM
};
struct FaultVals
@@ -498,9 +500,11 @@ class DataAbort : public AbortFault<DataAbort>
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)
{}
@@ -611,6 +615,23 @@ class HardwareBreakpoint : public ArmFaultVals<HardwareBreakpoint>
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>
{
@@ -652,6 +673,7 @@ template<> ArmFault::FaultVals ArmFaultVals<SPAlignmentFault>::vals;
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;
/**

View File

@@ -1127,6 +1127,54 @@ ISA::setMiscReg(int misc_reg, RegVal val)
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:
{
@@ -1217,6 +1265,54 @@ ISA::setMiscReg(int misc_reg, RegVal val)
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

View File

@@ -147,6 +147,79 @@ decodeCP14Reg(unsigned crn, unsigned opc1, unsigned crm, unsigned opc2)
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:
@@ -1687,6 +1760,10 @@ decodeAArch64SysReg(unsigned op0, unsigned op1,
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:
@@ -1695,6 +1772,10 @@ decodeAArch64SysReg(unsigned op0, unsigned op1,
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:
@@ -1705,6 +1786,10 @@ decodeAArch64SysReg(unsigned op0, unsigned op1,
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:
@@ -1713,6 +1798,10 @@ decodeAArch64SysReg(unsigned op0, unsigned op1,
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:
@@ -1721,6 +1810,10 @@ decodeAArch64SysReg(unsigned op0, unsigned op1,
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:
@@ -1729,6 +1822,10 @@ decodeAArch64SysReg(unsigned op0, unsigned op1,
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:
@@ -1737,6 +1834,10 @@ decodeAArch64SysReg(unsigned op0, unsigned op1,
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:
@@ -1745,6 +1846,10 @@ decodeAArch64SysReg(unsigned op0, unsigned op1,
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:
@@ -1753,6 +1858,10 @@ decodeAArch64SysReg(unsigned op0, unsigned op1,
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:
@@ -1761,6 +1870,10 @@ decodeAArch64SysReg(unsigned op0, unsigned op1,
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:
@@ -1769,6 +1882,10 @@ decodeAArch64SysReg(unsigned op0, unsigned op1,
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:
@@ -1777,6 +1894,10 @@ decodeAArch64SysReg(unsigned op0, unsigned op1,
return MISCREG_DBGBVR15_EL1;
case 5:
return MISCREG_DBGBCR15_EL1;
case 6:
return MISCREG_DBGWVR15_EL1;
case 7:
return MISCREG_DBGWCR15_EL1;
}
break;
}
@@ -3374,29 +3495,69 @@ ISA::initializeMiscRegMetadata()
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);
@@ -4266,29 +4427,101 @@ ISA::initializeMiscRegMetadata()
.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);

View File

@@ -135,10 +135,34 @@ namespace ArmISA
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,
@@ -461,10 +485,34 @@ namespace ArmISA
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,
@@ -1167,10 +1215,34 @@ namespace ArmISA
"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",
@@ -1491,10 +1563,34 @@ namespace ArmISA
"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",

View File

@@ -697,6 +697,20 @@ namespace ArmISA
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;

View File

@@ -94,6 +94,48 @@ SelfDebug::triggerException(ThreadContext * tc, Addr vaddr)
}
}
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)
@@ -386,3 +428,122 @@ BrkPoint::getVMIDfromReg(ThreadContext *tc)
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;
}
}

View File

@@ -147,11 +147,66 @@ class BrkPoint
};
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
@@ -174,7 +229,13 @@ class SelfDebug
~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)
{
@@ -255,6 +316,11 @@ class SelfDebug
arBrkPoints[index].updateControl(val);
}
inline void updateDBGWCR(int index, DBGWCR val)
{
arWatchPoints[index].updateControl(val);
}
inline bool isAArch32()
{
return aarch32;
@@ -306,6 +372,15 @@ class SelfDebug
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;

View File

@@ -1199,6 +1199,15 @@ TLB::translateFs(const RequestPtr &req, ThreadContext *tc, Mode mode,
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;

View File

@@ -123,10 +123,34 @@ TarmacParserRecord::MiscRegMap TarmacParserRecord::miscRegMap = {
{ "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 },
@@ -418,10 +442,34 @@ TarmacParserRecord::MiscRegMap TarmacParserRecord::miscRegMap = {
{ "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 },

View File

@@ -648,6 +648,9 @@ namespace ArmISA
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,
};

View File

@@ -189,6 +189,7 @@ bool ELIs64(ThreadContext *tc, ExceptionLevel el);
bool ELIsInHost(ThreadContext *tc, ExceptionLevel el);
ExceptionLevel debugTargetFrom(ThreadContext *tc, bool secure);
bool isBigEndian64(const ThreadContext *tc);