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:
@@ -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,
|
||||
|
||||
@@ -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>;
|
||||
|
||||
@@ -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;
|
||||
|
||||
/**
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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 },
|
||||
|
||||
@@ -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,
|
||||
};
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user