arch-arm: Implementation of Hardware Breakpoint exception

This code implementes hardware breakpoint exception as part of
software debug explained in ARMv8 reference manual ChapterD2.

+ ArmISA.py: Modify register to allow up to 15 Breakpoint registers
+ Sconscript: Add new file self_debug
+ faults.cc/hh: Defintion and implementation of HardwareBreakpoint
                exception inheriting ArmFault.
+ isa.cc/hh: ArmISA contains now an attribute pointing to the SelfDebug
             object that will be used to be access SelfDebug infrastructure
             Added special cases for setMiscReg to cache debug enable bits.
+ miscregs.hh/cc: Definition and initialization of DBGDCn and DBGDVn
                  registers.
+ tlb.cc/hh: We include the access to check for breakpoint instruction as
             part of the tlb translation process, checking if it comes from a
             fetch in the itlb
+ types.hh: Definition of new bitwise register types.
+ utility.cc/hh: Definition and implementation of auxiliar functions for
                the selfDebug.
+ self_debug.hh/cc: Main files that include the implemenattion of
            breakpoint checks, selfdebug enable and auxiliar functions.

Change-Id: I0e2a4be7f778de560c512253a9148da61e3e7e7a
Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/27967
Reviewed-by: Giacomo Travaglini <giacomo.travaglini@arm.com>
Maintainer: Giacomo Travaglini <giacomo.travaglini@arm.com>
Tested-by: kokoro <noreply+kokoro@google.com>
This commit is contained in:
Jordi Vaquero
2020-02-11 17:22:25 +01:00
parent bbab876c32
commit f9db8ab306
18 changed files with 1687 additions and 72 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 | 2 BRPs | !PMU | !Trace | Debug v8-A
id_aa64dfr0_el1 = Param.UInt64(0x0000000000101006,
# 1 CTX CMPs | 2 WRPs | 16 BRPs | !PMU | !Trace | Debug v8-A
id_aa64dfr0_el1 = Param.UInt64(0x000000000010F006,
"AArch64 Debug Feature Register 0")
# Reserved for future expansion
id_aa64dfr1_el1 = Param.UInt64(0x0000000000000000,

View File

@@ -85,6 +85,7 @@ if env['TARGET_ISA'] == 'arm':
Source('stacktrace.cc')
Source('system.cc')
Source('table_walker.cc')
Source('self_debug.cc')
Source('stage2_mmu.cc')
Source('stage2_lookup.cc')
Source('tlb.cc')

View File

@@ -281,6 +281,10 @@ template<> ArmFault::FaultVals ArmFaultVals<SoftwareBreakpoint>::vals(
"Software Breakpoint", 0x000, 0x000, 0x200, 0x400, 0x600, MODE_SVC,
0, 0, 0, 0, true, false, false, EC_SOFTWARE_BREAKPOINT
);
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<ArmSev>::vals(
// Some dummy values
"ArmSev Flush", 0x000, 0x000, 0x000, 0x000, 0x000, MODE_SVC,
@@ -1075,6 +1079,16 @@ AbortFault<T>::invoke(ThreadContext *tc, const StaticInstPtr &inst)
} else if (stage2) {
tc->setMiscReg(MISCREG_HPFAR, (faultAddr >> 8) & ~0xf);
tc->setMiscReg(T::HFarIndex, OVAddr);
} else if (debug > ArmFault::NODEBUG) {
DBGDS32 Rext = tc->readMiscReg(MISCREG_DBGDSCRext);
tc->setMiscReg(T::FarIndex, faultAddr);
if (debug == ArmFault::BRKPOINT){
Rext.moe = 0x1;
}
tc->setMiscReg(T::FsrIndex, fsr);
tc->setMiscReg(MISCREG_DBGDSCRext, Rext);
} else {
tc->setMiscReg(T::FsrIndex, fsr);
tc->setMiscReg(T::FarIndex, faultAddr);
@@ -1277,9 +1291,10 @@ PrefetchAbort::routeToHyp(ThreadContext *tc) const
toHyp = scr.ns && (currEL(tc) == EL2);
// otherwise, check whether to take to Hyp mode through Hyp Trap vector
toHyp |= (stage2 ||
((source == DebugEvent) && hdcr.tde && (currEL(tc) != EL2)) ||
((source == SynchronousExternalAbort) && hcr.tge &&
(currEL(tc) == EL0))) && !inSecureState(tc);
((source == DebugEvent) && (hdcr.tde || hcr.tge) &&
(currEL(tc) != EL2)) ||
((source == SynchronousExternalAbort) && hcr.tge &&
(currEL(tc) == EL0))) && !inSecureState(tc);
return toHyp;
}
@@ -1600,6 +1615,59 @@ SoftwareBreakpoint::ec(ThreadContext *tc) const
return from64 ? EC_SOFTWARE_BREAKPOINT_64 : vals.ec;
}
HardwareBreakpoint::HardwareBreakpoint(Addr _vaddr, uint32_t _iss)
: ArmFaultVals<HardwareBreakpoint>(0x0, _iss), vAddr(_vaddr)
{}
bool
HardwareBreakpoint::routeToHyp(ThreadContext *tc) const
{
const bool have_el2 = ArmSystem::haveVirtualization(tc);
const HCR hcr = tc->readMiscRegNoEffect(MISCREG_HCR_EL2);
const HDCR mdcr = tc->readMiscRegNoEffect(MISCREG_MDCR_EL2);
return have_el2 && !inSecureState(tc) && fromEL <= EL1 &&
(hcr.tge || mdcr.tde);
}
ExceptionClass
HardwareBreakpoint::ec(ThreadContext *tc) const
{
// AArch64
if (toEL == fromEL)
return EC_HW_BREAKPOINT_CURR_EL;
else
return EC_HW_BREAKPOINT_LOWER_EL;
}
void
HardwareBreakpoint::invoke(ThreadContext *tc, const StaticInstPtr &inst)
{
ArmFaultVals<HardwareBreakpoint>::invoke(tc, inst);
MiscRegIndex elr_idx;
switch (toEL) {
case EL1:
elr_idx = MISCREG_ELR_EL1;
break;
case EL2:
assert(ArmSystem::haveVirtualization(tc));
elr_idx = MISCREG_ELR_EL2;
break;
case EL3:
assert(ArmSystem::haveSecurity(tc));
elr_idx = MISCREG_ELR_EL3;
break;
default:
panic("Invalid target exception level");
break;
}
tc->setMiscReg(elr_idx, vAddr);
}
void
ArmSev::invoke(ThreadContext *tc, const StaticInstPtr &inst) {
DPRINTF(Faults, "Invoking ArmSev Fault\n");

View File

@@ -149,6 +149,12 @@ class ArmFault : public FaultBase
UnknownTran
};
enum DebugType
{
NODEBUG = 0,
BRKPOINT,
};
struct FaultVals
{
const FaultName name;
@@ -428,14 +434,16 @@ class AbortFault : public ArmFaultVals<T>
bool stage2;
bool s1ptw;
ArmFault::TranMethod tranMethod;
ArmFault::DebugType debug;
public:
AbortFault(Addr _faultAddr, bool _write, TlbEntry::DomainType _domain,
uint8_t _source, bool _stage2,
ArmFault::TranMethod _tranMethod = ArmFault::UnknownTran) :
ArmFault::TranMethod _tranMethod = ArmFault::UnknownTran,
ArmFault::DebugType _debug = ArmFault::NODEBUG) :
faultAddr(_faultAddr), OVAddr(0), write(_write),
domain(_domain), source(_source), srcEncoded(0),
stage2(_stage2), s1ptw(false), tranMethod(_tranMethod)
stage2(_stage2), s1ptw(false), tranMethod(_tranMethod), debug(_debug)
{}
bool getFaultVAddr(Addr &va) const override;
@@ -461,9 +469,10 @@ class PrefetchAbort : public AbortFault<PrefetchAbort>
static const MiscRegIndex HFarIndex = MISCREG_HIFAR;
PrefetchAbort(Addr _addr, uint8_t _source, bool _stage2 = false,
ArmFault::TranMethod _tranMethod = ArmFault::UnknownTran) :
ArmFault::TranMethod _tranMethod = ArmFault::UnknownTran,
ArmFault::DebugType _debug = ArmFault::NODEBUG) :
AbortFault<PrefetchAbort>(_addr, false, TlbEntry::DomainType::NoAccess,
_source, _stage2, _tranMethod)
_source, _stage2, _tranMethod, _debug)
{}
ExceptionClass ec(ThreadContext *tc) const override;
@@ -590,6 +599,18 @@ class SoftwareBreakpoint : public ArmFaultVals<SoftwareBreakpoint>
ExceptionClass ec(ThreadContext *tc) const override;
};
class HardwareBreakpoint : public ArmFaultVals<HardwareBreakpoint>
{
private:
Addr vAddr;
public:
void invoke(ThreadContext *tc, const StaticInstPtr &inst =
StaticInst::nullStaticInstPtr) override;
HardwareBreakpoint(Addr _vaddr, uint32_t _iss);
bool routeToHyp(ThreadContext *tc) const override;
ExceptionClass ec(ThreadContext *tc) const override;
};
// A fault that flushes the pipe, excluding the faulting instructions
class ArmSev : public ArmFaultVals<ArmSev>
{
@@ -630,6 +651,7 @@ template<> ArmFault::FaultVals ArmFaultVals<PCAlignmentFault>::vals;
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<ArmSev>::vals;
/**

View File

@@ -640,7 +640,10 @@ ArmStaticInst::softwareBreakpoint32(ExecContext *xc, uint16_t imm) const
} else {
// Execute AArch32 Software Breakpoint
return std::make_shared<PrefetchAbort>(readPC(xc),
ArmFault::DebugEvent);
ArmFault::DebugEvent,
false,
ArmFault::UnknownTran,
ArmFault::BRKPOINT);
}
}

View File

@@ -45,6 +45,8 @@
#include "arch/arm/faults.hh"
#include "arch/arm/utility.hh"
#include "arch/arm/isa.hh"
#include "arch/arm/self_debug.hh"
#include "arch/arm/system.hh"
#include "base/trace.hh"
#include "cpu/exec_context.hh"
@@ -198,6 +200,14 @@ class ArmStaticInst : public StaticInst
std::string generateDisassembly(
Addr pc, const Loader::SymbolTable *symtab) const override;
static void
activateBreakpoint(ThreadContext *tc)
{
auto *isa = static_cast<ArmISA::ISA *>(tc->getIsaPtr());
SelfDebug * sd = isa->getSelfDebug();
sd->activateDebug();
}
static inline uint32_t
cpsrWriteByInstr(CPSR cpsr, uint32_t val, SCR scr, NSACR nsacr,
uint8_t byteMask, bool affectState, bool nmfi, ThreadContext *tc)
@@ -209,6 +219,9 @@ class ArmStaticInst : public StaticInst
uint32_t bitMask = 0;
if (affectState && byteMask==0xF){
activateBreakpoint(tc);
}
if (bits(byteMask, 3)) {
unsigned lowIdx = affectState ? 24 : 27;
bitMask = bitMask | mask(31, lowIdx);

View File

@@ -40,6 +40,7 @@
#include "arch/arm/faults.hh"
#include "arch/arm/interrupts.hh"
#include "arch/arm/pmu.hh"
#include "arch/arm/self_debug.hh"
#include "arch/arm/system.hh"
#include "arch/arm/tlb.hh"
#include "arch/arm/tlbi_op.hh"
@@ -105,6 +106,7 @@ ISA::ISA(Params *p) : BaseISA(p), system(NULL),
const_cast<Enums::VecRegRenameMode&>(_vecRegRenameMode) =
highestELIs64 ? Enums::Full : Enums::Elem;
selfDebug = new SelfDebug();
initializeMiscRegMetadata();
preUnflattenMiscReg();
@@ -426,6 +428,7 @@ ISA::startup()
setupThreadContext();
afterStartup = true;
selfDebug->init(tc);
}
void
@@ -698,7 +701,7 @@ ISA::readMiscReg(int misc_reg)
*/
return 0x5 << 16;
case MISCREG_DBGDSCRint:
return 0;
return readMiscRegNoEffect(MISCREG_DBGDSCRint);
case MISCREG_ISR:
{
auto ic = dynamic_cast<ArmISA::Interrupts *>(
@@ -1047,11 +1050,172 @@ ISA::setMiscReg(int misc_reg, RegVal val)
(readMiscRegNoEffect(MISCREG_FPEXC) & ~fpexcMask);
}
break;
case MISCREG_HCR:
case MISCREG_HCR2:
if (!haveVirtualization)
return;
break;
case MISCREG_HCR:
{
const HDCR mdcr = tc->readMiscRegNoEffect(MISCREG_MDCR_EL2);
selfDebug->setenableTDETGE((HCR)val, mdcr);
if (!haveVirtualization)
return;
}
break;
case MISCREG_HDCR:
{
const HCR hcr = tc->readMiscReg(MISCREG_HCR_EL2);
selfDebug->setenableTDETGE(hcr, (HDCR)val);
}
break;
case MISCREG_DBGOSLAR:
{
OSL r = tc->readMiscReg(MISCREG_DBGOSLSR);
const uint32_t temp = (val == 0xC5ACCE55)? 0x1 : 0x0;
selfDebug->updateOSLock((RegVal) temp);
r.oslk = bits(temp,0);
tc->setMiscReg(MISCREG_DBGOSLSR, r);
}
break;
case MISCREG_DBGBCR0:
selfDebug->updateDBGBCR(0, val);
break;
case MISCREG_DBGBCR1:
selfDebug->updateDBGBCR(1, val);
break;
case MISCREG_DBGBCR2:
selfDebug->updateDBGBCR(2, val);
break;
case MISCREG_DBGBCR3:
selfDebug->updateDBGBCR(3, val);
break;
case MISCREG_DBGBCR4:
selfDebug->updateDBGBCR(4, val);
break;
case MISCREG_DBGBCR5:
selfDebug->updateDBGBCR(5, val);
break;
case MISCREG_DBGBCR6:
selfDebug->updateDBGBCR(6, val);
break;
case MISCREG_DBGBCR7:
selfDebug->updateDBGBCR(7, val);
break;
case MISCREG_DBGBCR8:
selfDebug->updateDBGBCR(8, val);
break;
case MISCREG_DBGBCR9:
selfDebug->updateDBGBCR(9, val);
break;
case MISCREG_DBGBCR10:
selfDebug->updateDBGBCR(10, val);
break;
case MISCREG_DBGBCR11:
selfDebug->updateDBGBCR(11, val);
break;
case MISCREG_DBGBCR12:
selfDebug->updateDBGBCR(12, val);
break;
case MISCREG_DBGBCR13:
selfDebug->updateDBGBCR(13, val);
break;
case MISCREG_DBGBCR14:
selfDebug->updateDBGBCR(14, val);
break;
case MISCREG_DBGBCR15:
selfDebug->updateDBGBCR(15, val);
break;
case MISCREG_MDCR_EL2:
{
const HCR hcr = tc->readMiscReg(MISCREG_HCR_EL2);
selfDebug->setenableTDETGE(hcr, (HDCR)val);
}
break;
case MISCREG_SDCR:
case MISCREG_MDCR_EL3:
{
selfDebug->setbSDD(val);
}
break;
case MISCREG_DBGDSCRext:
{
selfDebug->setMDBGen(val);
DBGDS32 r = tc->readMiscReg(MISCREG_DBGDSCRint);
DBGDS32 v = val;
r.moe = v.moe;
r.udccdis = v.udccdis;
r.mdbgen = v.mdbgen;
tc->setMiscReg(MISCREG_DBGDSCRint, r);
r = tc->readMiscReg(MISCREG_DBGDSCRint);
}
break;
case MISCREG_MDSCR_EL1:
{
selfDebug->setMDSCRvals(val);
}
break;
case MISCREG_OSLAR_EL1:
{
selfDebug->updateOSLock(val);
OSL r = tc->readMiscReg(MISCREG_OSLSR_EL1);
r.oslk = bits(val, 0);
r.oslm_3 = 1;
tc->setMiscReg(MISCREG_OSLSR_EL1, r);
}
break;
case MISCREG_DBGBCR0_EL1:
selfDebug->updateDBGBCR(0, val);
break;
case MISCREG_DBGBCR1_EL1:
selfDebug->updateDBGBCR(1, val);
break;
case MISCREG_DBGBCR2_EL1:
selfDebug->updateDBGBCR(2, val);
break;
case MISCREG_DBGBCR3_EL1:
selfDebug->updateDBGBCR(3, val);
break;
case MISCREG_DBGBCR4_EL1:
selfDebug->updateDBGBCR(4, val);
break;
case MISCREG_DBGBCR5_EL1:
selfDebug->updateDBGBCR(5, val);
break;
case MISCREG_DBGBCR6_EL1:
selfDebug->updateDBGBCR(6, val);
break;
case MISCREG_DBGBCR7_EL1:
selfDebug->updateDBGBCR(7, val);
break;
case MISCREG_DBGBCR8_EL1:
selfDebug->updateDBGBCR(8, val);
break;
case MISCREG_DBGBCR9_EL1:
selfDebug->updateDBGBCR(9, val);
break;
case MISCREG_DBGBCR10_EL1:
selfDebug->updateDBGBCR(10, val);
break;
case MISCREG_DBGBCR11_EL1:
selfDebug->updateDBGBCR(11, val);
break;
case MISCREG_DBGBCR12_EL1:
selfDebug->updateDBGBCR(12, val);
break;
case MISCREG_DBGBCR13_EL1:
selfDebug->updateDBGBCR(13, val);
break;
case MISCREG_DBGBCR14_EL1:
selfDebug->updateDBGBCR(14, val);
break;
case MISCREG_DBGBCR15_EL1:
selfDebug->updateDBGBCR(15, val);
break;
case MISCREG_IFSR:
{
// ARM ARM (ARM DDI 0406C.b) B4.1.96
@@ -1868,7 +2032,6 @@ ISA::setMiscReg(int misc_reg, RegVal val)
case MISCREG_DACR:
case MISCREG_VTTBR:
case MISCREG_SCR_EL3:
case MISCREG_HCR_EL2:
case MISCREG_TCR_EL1:
case MISCREG_TCR_EL2:
case MISCREG_TCR_EL3:
@@ -1883,6 +2046,14 @@ ISA::setMiscReg(int misc_reg, RegVal val)
getITBPtr(tc)->invalidateMiscReg();
getDTBPtr(tc)->invalidateMiscReg();
break;
case MISCREG_HCR_EL2:
{
const HDCR mdcr = tc->readMiscRegNoEffect(MISCREG_MDCR_EL2);
selfDebug->setenableTDETGE((HCR)val, mdcr);
getITBPtr(tc)->invalidateMiscReg();
getDTBPtr(tc)->invalidateMiscReg();
}
break;
case MISCREG_NZCV:
{
CPSR cpsr = val;
@@ -2070,7 +2241,7 @@ ISA::setMiscReg(int misc_reg, RegVal val)
case MISCREG_SPSR_EL1:
{
RegVal spsr_mask = havePAN ?
~(0x5 << 21) : ~(0x7 << 21);
~(0x2 << 22) : ~(0x3 << 22);
newVal = val & spsr_mask;
break;

View File

@@ -44,6 +44,7 @@
#include "arch/arm/isa_device.hh"
#include "arch/arm/miscregs.hh"
#include "arch/arm/registers.hh"
#include "arch/arm/self_debug.hh"
#include "arch/arm/system.hh"
#include "arch/arm/tlb.hh"
#include "arch/arm/types.hh"
@@ -106,6 +107,8 @@ namespace ArmISA
bool afterStartup;
SelfDebug * selfDebug;
/** MiscReg metadata **/
struct MiscRegLUTEntry {
uint32_t lower; // Lower half mapped to this register
@@ -462,6 +465,10 @@ namespace ArmISA
void initID64(const ArmISAParams *p);
public:
SelfDebug * getSelfDebug()
{
return selfDebug;
}
RegVal readMiscRegNoEffect(int misc_reg) const;
RegVal readMiscReg(int misc_reg);
void setMiscRegNoEffect(int misc_reg, RegVal val);

View File

@@ -63,6 +63,90 @@ decodeCP14Reg(unsigned crn, unsigned opc1, unsigned crm, unsigned opc2)
return MISCREG_DBGDSCRint;
}
break;
case 2:
switch (crm) {
case 0:
return MISCREG_DBGDTRRXext;
case 2:
return MISCREG_DBGDSCRext;
case 3:
return MISCREG_DBGDTRTXext;
case 6:
return MISCREG_DBGOSECCR;
}
break;
case 4:
switch (crm) {
case 0:
return MISCREG_DBGBVR0;
case 1:
return MISCREG_DBGBVR1;
case 2:
return MISCREG_DBGBVR2;
case 3:
return MISCREG_DBGBVR3;
case 4:
return MISCREG_DBGBVR4;
case 5:
return MISCREG_DBGBVR5;
case 6:
return MISCREG_DBGBVR6;
case 7:
return MISCREG_DBGBVR7;
case 8:
return MISCREG_DBGBVR8;
case 9:
return MISCREG_DBGBVR9;
case 10:
return MISCREG_DBGBVR10;
case 11:
return MISCREG_DBGBVR11;
case 12:
return MISCREG_DBGBVR12;
case 13:
return MISCREG_DBGBVR13;
case 14:
return MISCREG_DBGBVR14;
case 15:
return MISCREG_DBGBVR15;
}
break;
case 5:
switch (crm) {
case 0:
return MISCREG_DBGBCR0;
case 1:
return MISCREG_DBGBCR1;
case 2:
return MISCREG_DBGBCR2;
case 3:
return MISCREG_DBGBCR3;
case 4:
return MISCREG_DBGBCR4;
case 5:
return MISCREG_DBGBCR5;
case 6:
return MISCREG_DBGBCR6;
case 7:
return MISCREG_DBGBCR7;
case 8:
return MISCREG_DBGBCR8;
case 9:
return MISCREG_DBGBCR9;
case 10:
return MISCREG_DBGBCR10;
case 11:
return MISCREG_DBGBCR11;
case 12:
return MISCREG_DBGBCR12;
case 13:
return MISCREG_DBGBCR13;
case 14:
return MISCREG_DBGBCR14;
case 15:
return MISCREG_DBGBCR15;
}
break;
}
break;
case 7:
@@ -79,6 +163,59 @@ decodeCP14Reg(unsigned crn, unsigned opc1, unsigned crm, unsigned opc2)
break;
case 1:
switch (opc1) {
case 0:
switch(opc2) {
case 1:
switch(crm) {
case 0:
return MISCREG_DBGBXVR0;
case 1:
return MISCREG_DBGBXVR1;
case 2:
return MISCREG_DBGBXVR2;
case 3:
return MISCREG_DBGBXVR3;
case 4:
return MISCREG_DBGBXVR4;
case 5:
return MISCREG_DBGBXVR5;
case 6:
return MISCREG_DBGBXVR6;
case 7:
return MISCREG_DBGBXVR7;
case 8:
return MISCREG_DBGBXVR8;
case 9:
return MISCREG_DBGBXVR9;
case 10:
return MISCREG_DBGBXVR10;
case 11:
return MISCREG_DBGBXVR11;
case 12:
return MISCREG_DBGBXVR12;
case 13:
return MISCREG_DBGBXVR13;
case 14:
return MISCREG_DBGBXVR14;
case 15:
return MISCREG_DBGBXVR15;
}
break;
}
switch (opc2) {
case 4:
switch (crm) {
case 0:
return MISCREG_DBGOSLAR;
case 1:
return MISCREG_DBGOSLSR;
case 3:
return MISCREG_DBGOSDLR;
case 4:
return MISCREG_DBGPRCR;
}
break;
}
case 6:
switch (crm) {
case 0:
@@ -238,6 +375,9 @@ decodeCP15Reg(unsigned crn, unsigned opc1, unsigned crm, unsigned opc2)
case 2:
return MISCREG_NSACR;
}
} else if (crm == 3) {
if ( opc2 == 1)
return MISCREG_SDCR;
}
} else if (opc1 == 4) {
if (crm == 0) {
@@ -1562,6 +1702,82 @@ decodeAArch64SysReg(unsigned op0, unsigned op1,
switch (op2) {
case 2:
return MISCREG_OSECCR_EL1;
case 4:
return MISCREG_DBGBVR6_EL1;
case 5:
return MISCREG_DBGBCR6_EL1;
}
break;
case 7:
switch (op2) {
case 4:
return MISCREG_DBGBVR7_EL1;
case 5:
return MISCREG_DBGBCR7_EL1;
}
break;
case 8:
switch (op2) {
case 4:
return MISCREG_DBGBVR8_EL1;
case 5:
return MISCREG_DBGBCR8_EL1;
}
break;
case 9:
switch (op2) {
case 4:
return MISCREG_DBGBVR9_EL1;
case 5:
return MISCREG_DBGBCR9_EL1;
}
break;
case 10:
switch (op2) {
case 4:
return MISCREG_DBGBVR10_EL1;
case 5:
return MISCREG_DBGBCR10_EL1;
}
break;
case 11:
switch (op2) {
case 4:
return MISCREG_DBGBVR11_EL1;
case 5:
return MISCREG_DBGBCR11_EL1;
}
break;
case 12:
switch (op2) {
case 4:
return MISCREG_DBGBVR12_EL1;
case 5:
return MISCREG_DBGBCR12_EL1;
}
break;
case 13:
switch (op2) {
case 4:
return MISCREG_DBGBVR13_EL1;
case 5:
return MISCREG_DBGBCR13_EL1;
}
break;
case 14:
switch (op2) {
case 4:
return MISCREG_DBGBVR14_EL1;
case 5:
return MISCREG_DBGBCR14_EL1;
}
break;
case 15:
switch (op2) {
case 4:
return MISCREG_DBGBVR15_EL1;
case 5:
return MISCREG_DBGBCR15_EL1;
}
break;
}
@@ -3087,8 +3303,6 @@ ISA::initializeMiscRegMetadata()
.unimplemented()
.allPrivileges();
InitReg(MISCREG_DBGDSCRext)
.unimplemented()
.warnNotFail()
.allPrivileges();
InitReg(MISCREG_DBGDTRTXext)
.unimplemented()
@@ -3097,41 +3311,69 @@ ISA::initializeMiscRegMetadata()
.unimplemented()
.allPrivileges();
InitReg(MISCREG_DBGBVR0)
.unimplemented()
.allPrivileges();
.allPrivileges().exceptUserMode();
InitReg(MISCREG_DBGBVR1)
.unimplemented()
.allPrivileges();
.allPrivileges().exceptUserMode();
InitReg(MISCREG_DBGBVR2)
.unimplemented()
.allPrivileges();
.allPrivileges().exceptUserMode();
InitReg(MISCREG_DBGBVR3)
.unimplemented()
.allPrivileges();
.allPrivileges().exceptUserMode();
InitReg(MISCREG_DBGBVR4)
.unimplemented()
.allPrivileges();
.allPrivileges().exceptUserMode();
InitReg(MISCREG_DBGBVR5)
.unimplemented()
.allPrivileges();
.allPrivileges().exceptUserMode();
InitReg(MISCREG_DBGBVR6)
.allPrivileges().exceptUserMode();
InitReg(MISCREG_DBGBVR7)
.allPrivileges().exceptUserMode();
InitReg(MISCREG_DBGBVR8)
.allPrivileges().exceptUserMode();
InitReg(MISCREG_DBGBVR9)
.allPrivileges().exceptUserMode();
InitReg(MISCREG_DBGBVR10)
.allPrivileges().exceptUserMode();
InitReg(MISCREG_DBGBVR11)
.allPrivileges().exceptUserMode();
InitReg(MISCREG_DBGBVR12)
.allPrivileges().exceptUserMode();
InitReg(MISCREG_DBGBVR13)
.allPrivileges().exceptUserMode();
InitReg(MISCREG_DBGBVR14)
.allPrivileges().exceptUserMode();
InitReg(MISCREG_DBGBVR15)
.allPrivileges().exceptUserMode();
InitReg(MISCREG_DBGBCR0)
.unimplemented()
.allPrivileges();
.allPrivileges().exceptUserMode();
InitReg(MISCREG_DBGBCR1)
.unimplemented()
.allPrivileges();
.allPrivileges().exceptUserMode();
InitReg(MISCREG_DBGBCR2)
.unimplemented()
.allPrivileges();
.allPrivileges().exceptUserMode();
InitReg(MISCREG_DBGBCR3)
.unimplemented()
.allPrivileges();
.allPrivileges().exceptUserMode();
InitReg(MISCREG_DBGBCR4)
.unimplemented()
.allPrivileges();
.allPrivileges().exceptUserMode();
InitReg(MISCREG_DBGBCR5)
.unimplemented()
.allPrivileges();
.allPrivileges().exceptUserMode();
InitReg(MISCREG_DBGBCR6)
.allPrivileges().exceptUserMode();
InitReg(MISCREG_DBGBCR7)
.allPrivileges().exceptUserMode();
InitReg(MISCREG_DBGBCR8)
.allPrivileges().exceptUserMode();
InitReg(MISCREG_DBGBCR9)
.allPrivileges().exceptUserMode();
InitReg(MISCREG_DBGBCR10)
.allPrivileges().exceptUserMode();
InitReg(MISCREG_DBGBCR11)
.allPrivileges().exceptUserMode();
InitReg(MISCREG_DBGBCR12)
.allPrivileges().exceptUserMode();
InitReg(MISCREG_DBGBCR13)
.allPrivileges().exceptUserMode();
InitReg(MISCREG_DBGBCR14)
.allPrivileges().exceptUserMode();
InitReg(MISCREG_DBGBCR15)
.allPrivileges().exceptUserMode();
InitReg(MISCREG_DBGWVR0)
.unimplemented()
.allPrivileges();
@@ -3159,20 +3401,47 @@ ISA::initializeMiscRegMetadata()
InitReg(MISCREG_DBGDRAR)
.unimplemented()
.allPrivileges().monSecureWrite(0).monNonSecureWrite(0);
InitReg(MISCREG_DBGBXVR0)
.allPrivileges().exceptUserMode();
InitReg(MISCREG_DBGBXVR1)
.allPrivileges().exceptUserMode();
InitReg(MISCREG_DBGBXVR2)
.allPrivileges().exceptUserMode();
InitReg(MISCREG_DBGBXVR3)
.allPrivileges().exceptUserMode();
InitReg(MISCREG_DBGBXVR4)
.unimplemented()
.allPrivileges();
.allPrivileges().exceptUserMode();
InitReg(MISCREG_DBGBXVR5)
.unimplemented()
.allPrivileges();
.allPrivileges().exceptUserMode();
InitReg(MISCREG_DBGBXVR0)
.allPrivileges().exceptUserMode();
InitReg(MISCREG_DBGBXVR6)
.allPrivileges().exceptUserMode();
InitReg(MISCREG_DBGBXVR7)
.allPrivileges().exceptUserMode();
InitReg(MISCREG_DBGBXVR8)
.allPrivileges().exceptUserMode();
InitReg(MISCREG_DBGBXVR9)
.allPrivileges().exceptUserMode();
InitReg(MISCREG_DBGBXVR10)
.allPrivileges().exceptUserMode();
InitReg(MISCREG_DBGBXVR11)
.allPrivileges().exceptUserMode();
InitReg(MISCREG_DBGBXVR12)
.allPrivileges().exceptUserMode();
InitReg(MISCREG_DBGBXVR13)
.allPrivileges().exceptUserMode();
InitReg(MISCREG_DBGBXVR14)
.allPrivileges().exceptUserMode();
InitReg(MISCREG_DBGBXVR15)
.allPrivileges().exceptUserMode();
InitReg(MISCREG_DBGOSLAR)
.unimplemented()
.allPrivileges().monSecureRead(0).monNonSecureRead(0);
.allPrivileges().monSecureRead(0).monNonSecureRead(0);
InitReg(MISCREG_DBGOSLSR)
.unimplemented()
.allPrivileges().monSecureWrite(0).monNonSecureWrite(0);
InitReg(MISCREG_DBGOSDLR)
.unimplemented()
.warnNotFail()
.allPrivileges();
InitReg(MISCREG_DBGPRCR)
.unimplemented()
@@ -3298,6 +3567,8 @@ ISA::initializeMiscRegMetadata()
.secure().exceptUserMode();
InitReg(MISCREG_CPACR)
.allPrivileges().exceptUserMode();
InitReg(MISCREG_SDCR)
.mon();
InitReg(MISCREG_SCR)
.mon().secure().exceptUserMode()
.res0(0xff40) // [31:16], [6]
@@ -3900,41 +4171,101 @@ ISA::initializeMiscRegMetadata()
.allPrivileges()
.mapsTo(MISCREG_DBGOSECCR);
InitReg(MISCREG_DBGBVR0_EL1)
.allPrivileges()
.mapsTo(MISCREG_DBGBVR0 /*, MISCREG_DBGBXVR0 */);
.allPrivileges().exceptUserMode()
.mapsTo(MISCREG_DBGBVR0, MISCREG_DBGBXVR0);
InitReg(MISCREG_DBGBVR1_EL1)
.allPrivileges()
.mapsTo(MISCREG_DBGBVR1 /*, MISCREG_DBGBXVR1 */);
.allPrivileges().exceptUserMode()
.mapsTo(MISCREG_DBGBVR1, MISCREG_DBGBXVR1);
InitReg(MISCREG_DBGBVR2_EL1)
.allPrivileges()
.mapsTo(MISCREG_DBGBVR2 /*, MISCREG_DBGBXVR2 */);
.allPrivileges().exceptUserMode()
.mapsTo(MISCREG_DBGBVR2, MISCREG_DBGBXVR2);
InitReg(MISCREG_DBGBVR3_EL1)
.allPrivileges()
.mapsTo(MISCREG_DBGBVR3 /*, MISCREG_DBGBXVR3 */);
.allPrivileges().exceptUserMode()
.mapsTo(MISCREG_DBGBVR3, MISCREG_DBGBXVR3);
InitReg(MISCREG_DBGBVR4_EL1)
.allPrivileges()
.mapsTo(MISCREG_DBGBVR4 /*, MISCREG_DBGBXVR4 */);
.allPrivileges().exceptUserMode()
.mapsTo(MISCREG_DBGBVR4, MISCREG_DBGBXVR4);
InitReg(MISCREG_DBGBVR5_EL1)
.allPrivileges()
.mapsTo(MISCREG_DBGBVR5 /*, MISCREG_DBGBXVR5 */);
.allPrivileges().exceptUserMode()
.mapsTo(MISCREG_DBGBVR5, MISCREG_DBGBXVR5);
InitReg(MISCREG_DBGBVR6_EL1)
.allPrivileges().exceptUserMode()
.mapsTo(MISCREG_DBGBVR6, MISCREG_DBGBXVR6);
InitReg(MISCREG_DBGBVR7_EL1)
.allPrivileges().exceptUserMode()
.mapsTo(MISCREG_DBGBVR7, MISCREG_DBGBXVR7);
InitReg(MISCREG_DBGBVR8_EL1)
.allPrivileges().exceptUserMode()
.mapsTo(MISCREG_DBGBVR8, MISCREG_DBGBXVR8);
InitReg(MISCREG_DBGBVR9_EL1)
.allPrivileges().exceptUserMode()
.mapsTo(MISCREG_DBGBVR9, MISCREG_DBGBXVR9);
InitReg(MISCREG_DBGBVR10_EL1)
.allPrivileges().exceptUserMode()
.mapsTo(MISCREG_DBGBVR10, MISCREG_DBGBXVR10);
InitReg(MISCREG_DBGBVR11_EL1)
.allPrivileges().exceptUserMode()
.mapsTo(MISCREG_DBGBVR11, MISCREG_DBGBXVR11);
InitReg(MISCREG_DBGBVR12_EL1)
.allPrivileges().exceptUserMode()
.mapsTo(MISCREG_DBGBVR12, MISCREG_DBGBXVR12);
InitReg(MISCREG_DBGBVR13_EL1)
.allPrivileges().exceptUserMode()
.mapsTo(MISCREG_DBGBVR13, MISCREG_DBGBXVR13);
InitReg(MISCREG_DBGBVR14_EL1)
.allPrivileges().exceptUserMode()
.mapsTo(MISCREG_DBGBVR14, MISCREG_DBGBXVR14);
InitReg(MISCREG_DBGBVR15_EL1)
.allPrivileges().exceptUserMode()
.mapsTo(MISCREG_DBGBVR15, MISCREG_DBGBXVR15);
InitReg(MISCREG_DBGBCR0_EL1)
.allPrivileges()
.allPrivileges().exceptUserMode()
.mapsTo(MISCREG_DBGBCR0);
InitReg(MISCREG_DBGBCR1_EL1)
.allPrivileges()
.allPrivileges().exceptUserMode()
.mapsTo(MISCREG_DBGBCR1);
InitReg(MISCREG_DBGBCR2_EL1)
.allPrivileges()
.allPrivileges().exceptUserMode()
.mapsTo(MISCREG_DBGBCR2);
InitReg(MISCREG_DBGBCR3_EL1)
.allPrivileges()
.allPrivileges().exceptUserMode()
.mapsTo(MISCREG_DBGBCR3);
InitReg(MISCREG_DBGBCR4_EL1)
.allPrivileges()
.allPrivileges().exceptUserMode()
.mapsTo(MISCREG_DBGBCR4);
InitReg(MISCREG_DBGBCR5_EL1)
.allPrivileges()
.allPrivileges().exceptUserMode()
.mapsTo(MISCREG_DBGBCR5);
InitReg(MISCREG_DBGBCR6_EL1)
.allPrivileges().exceptUserMode()
.mapsTo(MISCREG_DBGBCR6);
InitReg(MISCREG_DBGBCR7_EL1)
.allPrivileges().exceptUserMode()
.mapsTo(MISCREG_DBGBCR7);
InitReg(MISCREG_DBGBCR8_EL1)
.allPrivileges().exceptUserMode()
.mapsTo(MISCREG_DBGBCR8);
InitReg(MISCREG_DBGBCR9_EL1)
.allPrivileges().exceptUserMode()
.mapsTo(MISCREG_DBGBCR9);
InitReg(MISCREG_DBGBCR10_EL1)
.allPrivileges().exceptUserMode()
.mapsTo(MISCREG_DBGBCR10);
InitReg(MISCREG_DBGBCR11_EL1)
.allPrivileges().exceptUserMode()
.mapsTo(MISCREG_DBGBCR11);
InitReg(MISCREG_DBGBCR12_EL1)
.allPrivileges().exceptUserMode()
.mapsTo(MISCREG_DBGBCR12);
InitReg(MISCREG_DBGBCR13_EL1)
.allPrivileges().exceptUserMode()
.mapsTo(MISCREG_DBGBCR13);
InitReg(MISCREG_DBGBCR14_EL1)
.allPrivileges().exceptUserMode()
.mapsTo(MISCREG_DBGBCR14);
InitReg(MISCREG_DBGBCR15_EL1)
.allPrivileges().exceptUserMode()
.mapsTo(MISCREG_DBGBCR15);
InitReg(MISCREG_DBGWVR0_EL1)
.allPrivileges()
.mapsTo(MISCREG_DBGWVR0);
@@ -4179,7 +4510,8 @@ ISA::initializeMiscRegMetadata()
InitReg(MISCREG_CPTR_EL3)
.mon();
InitReg(MISCREG_MDCR_EL3)
.mon();
.mon()
.mapsTo(MISCREG_SDCR);
InitReg(MISCREG_TTBR0_EL1)
.allPrivileges().exceptUserMode()
.mapsTo(MISCREG_TTBR0_NS);

View File

@@ -105,12 +105,32 @@ namespace ArmISA
MISCREG_DBGBVR3,
MISCREG_DBGBVR4,
MISCREG_DBGBVR5,
MISCREG_DBGBVR6,
MISCREG_DBGBVR7,
MISCREG_DBGBVR8,
MISCREG_DBGBVR9,
MISCREG_DBGBVR10,
MISCREG_DBGBVR11,
MISCREG_DBGBVR12,
MISCREG_DBGBVR13,
MISCREG_DBGBVR14,
MISCREG_DBGBVR15,
MISCREG_DBGBCR0,
MISCREG_DBGBCR1,
MISCREG_DBGBCR2,
MISCREG_DBGBCR3,
MISCREG_DBGBCR4,
MISCREG_DBGBCR5,
MISCREG_DBGBCR6,
MISCREG_DBGBCR7,
MISCREG_DBGBCR8,
MISCREG_DBGBCR9,
MISCREG_DBGBCR10,
MISCREG_DBGBCR11,
MISCREG_DBGBCR12,
MISCREG_DBGBCR13,
MISCREG_DBGBCR14,
MISCREG_DBGBCR15,
MISCREG_DBGWVR0,
MISCREG_DBGWVR1,
MISCREG_DBGWVR2,
@@ -120,8 +140,22 @@ namespace ArmISA
MISCREG_DBGWCR2,
MISCREG_DBGWCR3,
MISCREG_DBGDRAR,
MISCREG_DBGBXVR0,
MISCREG_DBGBXVR1,
MISCREG_DBGBXVR2,
MISCREG_DBGBXVR3,
MISCREG_DBGBXVR4,
MISCREG_DBGBXVR5,
MISCREG_DBGBXVR6,
MISCREG_DBGBXVR7,
MISCREG_DBGBXVR8,
MISCREG_DBGBXVR9,
MISCREG_DBGBXVR10,
MISCREG_DBGBXVR11,
MISCREG_DBGBXVR12,
MISCREG_DBGBXVR13,
MISCREG_DBGBXVR14,
MISCREG_DBGBXVR15,
MISCREG_DBGOSLAR,
MISCREG_DBGOSLSR,
MISCREG_DBGOSDLR,
@@ -175,6 +209,7 @@ namespace ArmISA
MISCREG_ACTLR_NS,
MISCREG_ACTLR_S,
MISCREG_CPACR,
MISCREG_SDCR,
MISCREG_SCR,
MISCREG_SDER,
MISCREG_NSACR,
@@ -396,12 +431,32 @@ namespace ArmISA
MISCREG_DBGBVR3_EL1,
MISCREG_DBGBVR4_EL1,
MISCREG_DBGBVR5_EL1,
MISCREG_DBGBVR6_EL1,
MISCREG_DBGBVR7_EL1,
MISCREG_DBGBVR8_EL1,
MISCREG_DBGBVR9_EL1,
MISCREG_DBGBVR10_EL1,
MISCREG_DBGBVR11_EL1,
MISCREG_DBGBVR12_EL1,
MISCREG_DBGBVR13_EL1,
MISCREG_DBGBVR14_EL1,
MISCREG_DBGBVR15_EL1,
MISCREG_DBGBCR0_EL1,
MISCREG_DBGBCR1_EL1,
MISCREG_DBGBCR2_EL1,
MISCREG_DBGBCR3_EL1,
MISCREG_DBGBCR4_EL1,
MISCREG_DBGBCR5_EL1,
MISCREG_DBGBCR6_EL1,
MISCREG_DBGBCR7_EL1,
MISCREG_DBGBCR8_EL1,
MISCREG_DBGBCR9_EL1,
MISCREG_DBGBCR10_EL1,
MISCREG_DBGBCR11_EL1,
MISCREG_DBGBCR12_EL1,
MISCREG_DBGBCR13_EL1,
MISCREG_DBGBCR14_EL1,
MISCREG_DBGBCR15_EL1,
MISCREG_DBGWVR0_EL1,
MISCREG_DBGWVR1_EL1,
MISCREG_DBGWVR2_EL1,
@@ -1082,12 +1137,32 @@ namespace ArmISA
"dbgbvr3",
"dbgbvr4",
"dbgbvr5",
"dbgbvr6",
"dbgbvr7",
"dbgbvr8",
"dbgbvr9",
"dbgbvr10",
"dbgbvr11",
"dbgbvr12",
"dbgbvr13",
"dbgbvr14",
"dbgbvr15",
"dbgbcr0",
"dbgbcr1",
"dbgbcr2",
"dbgbcr3",
"dbgbcr4",
"dbgbcr5",
"dbgbcr6",
"dbgbcr7",
"dbgbcr8",
"dbgbcr9",
"dbgbcr10",
"dbgbcr11",
"dbgbcr12",
"dbgbcr13",
"dbgbcr14",
"dbgbcr15",
"dbgwvr0",
"dbgwvr1",
"dbgwvr2",
@@ -1097,8 +1172,22 @@ namespace ArmISA
"dbgwcr2",
"dbgwcr3",
"dbgdrar",
"dbgbxvr0",
"dbgbxvr1",
"dbgbxvr2",
"dbgbxvr3",
"dbgbxvr4",
"dbgbxvr5",
"dbgbxvr6",
"dbgbxvr7",
"dbgbxvr8",
"dbgbxvr9",
"dbgbxvr10",
"dbgbxvr11",
"dbgbxvr12",
"dbgbxvr13",
"dbgbxvr14",
"dbgbxvr15",
"dbgoslar",
"dbgoslsr",
"dbgosdlr",
@@ -1152,6 +1241,7 @@ namespace ArmISA
"actlr_ns",
"actlr_s",
"cpacr",
"sdrc",
"scr",
"sder",
"nsacr",
@@ -1371,12 +1461,32 @@ namespace ArmISA
"dbgbvr3_el1",
"dbgbvr4_el1",
"dbgbvr5_el1",
"dbgbvr6_el1",
"dbgbvr7_el1",
"dbgbvr8_el1",
"dbgbvr9_el1",
"dbgbvr10_el1",
"dbgbvr11_el1",
"dbgbvr12_el1",
"dbgbvr13_el1",
"dbgbvr14_el1",
"dbgbvr15_el1",
"dbgbcr0_el1",
"dbgbcr1_el1",
"dbgbcr2_el1",
"dbgbcr3_el1",
"dbgbcr4_el1",
"dbgbcr5_el1",
"dbgbcr6_el1",
"dbgbcr7_el1",
"dbgbcr8_el1",
"dbgbcr9_el1",
"dbgbcr10_el1",
"dbgbcr11_el1",
"dbgbcr12_el1",
"dbgbcr13_el1",
"dbgbcr14_el1",
"dbgbcr15_el1",
"dbgwvr0_el1",
"dbgwvr1_el1",
"dbgwvr2_el1",

View File

@@ -676,6 +676,51 @@ namespace ArmISA
Bitfield<3, 0> len;
EndBitUnion(ZCR)
BitUnion32(OSL)
Bitfield<64, 4> res0;
Bitfield<3> oslm_3;
Bitfield<2> nTT;
Bitfield<1> oslk;
Bitfield<0> oslm_0;
EndBitUnion(OSL)
BitUnion64(DBGBCR)
Bitfield<63, 24> res0_2;
Bitfield<23, 20> bt;
Bitfield<19, 16> lbn;
Bitfield<15, 14> ssc;
Bitfield<13> hmc;
Bitfield<12, 9> res0_1;
Bitfield<8, 5> bas;
Bitfield<4, 3> res0_0;
Bitfield<2, 1> pmc;
Bitfield<0> e;
EndBitUnion(DBGBCR)
BitUnion32(DBGDS32)
Bitfield<31> tfo;
Bitfield<30> rxfull;
Bitfield<29> txfull;
Bitfield<28> res0_5;
Bitfield<27> rxo;
Bitfield<26> txu;
Bitfield<25, 24> res0_4;
Bitfield<23, 22> intdis;
Bitfield<21> tda;
Bitfield<20> res0_3;
Bitfield<19> sc2;
Bitfield<18> ns;
Bitfield<17> spniddis;
Bitfield<16> spiddis;
Bitfield<15> mdbgen;
Bitfield<14> hde;
Bitfield<13> res0_;
Bitfield<12> udccdis;
Bitfield<11, 7> res0_2;
Bitfield<6> err;
Bitfield<5, 2> moe;
Bitfield<1, 0> res0_1;
EndBitUnion(DBGDS32)
}
#endif // __ARCH_ARM_MISCREGS_TYPES_HH__

388
src/arch/arm/self_debug.cc Normal file
View File

@@ -0,0 +1,388 @@
/*
* Copyright (c) 2019 Metempsy Technology LSC
* All rights reserved
*
* The license below extends only to copyright in the software and shall
* not be construed as granting a license to any other intellectual
* property including but not limited to intellectual property relating
* to a hardware implementation of the functionality of the software
* licensed hereunder. You may use the software subject to the license
* terms below provided that you ensure that this notice is replicated
* unmodified and in its entirety in all distributions of the software,
* modified or unmodified, in source code or in binary form.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer;
* redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution;
* neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "arch/arm/self_debug.hh"
#include "arch/arm/faults.hh"
#include "arch/arm/miscregs_types.hh"
#include "base/bitfield.hh"
using namespace ArmISA;
using namespace std;
Fault
SelfDebug::testBreakPoints(ThreadContext *tc, Addr vaddr)
{
if (!enableFlag)
return NoFault;
setAArch32(tc);
to32 = targetAArch32(tc);
init(tc);
if (!isDebugEnabled(tc))
return NoFault;
ExceptionLevel el = (ExceptionLevel) currEL(tc);
for (auto &p: arBrkPoints){
PCState pcst = tc->pcState();
Addr pc = vaddr;
if (pcst.itstate() != 0x0)
pc = pcst.pc();
if (p.getEnable() && p.isActive(pc) &&(!to32 || !p.isSet())){
const DBGBCR ctr = p.getControlReg(tc);
if (p.isEnabled(tc, el, ctr.hmc, ctr.ssc, ctr.pmc)) {
bool debug = p.test(tc, pc, el, ctr, false);
if (debug){
if (to32)
p.setOnUse();
return triggerException(tc, pc);
}
}
}
}
return NoFault;
}
Fault
SelfDebug::triggerException(ThreadContext * tc, Addr vaddr)
{
if (isTo32()) {
return std::make_shared<PrefetchAbort>(vaddr,
ArmFault::DebugEvent, false,
ArmFault::UnknownTran,
ArmFault::BRKPOINT);
} else {
return std::make_shared<HardwareBreakpoint>(vaddr, 0x22);
}
}
bool
SelfDebug::isDebugEnabledForEL64(ThreadContext *tc, ExceptionLevel el,
bool secure, bool mask)
{
bool route_to_el2 = ArmSystem::haveEL(tc, EL2)
&& !secure && enableTdeTge;
ExceptionLevel target_el = route_to_el2? EL2 : EL1;
if (oslk || (bSDD && secure && ArmSystem::haveEL(tc, EL3))){
return false;
}
if (el == target_el){
return bKDE && !mask;
}else{
return target_el > el;
}
}
bool
SelfDebug::isDebugEnabledForEL32(ThreadContext *tc, ExceptionLevel el,
bool secure, bool mask)
{
if (el==EL0 && !ELStateUsingAArch32(tc, EL1, secure)){
return isDebugEnabledForEL64(tc, el, secure, mask);
}
if (oslk){
return false;
}
bool enabled;
if (secure && ArmSystem::haveEL(tc, EL3)){
// We ignore the check for invasive External debug checking SPIDEN
// and DBGEN signals. They are not implemented
bool spd32 = bits(tc->readMiscReg(MISCREG_MDCR_EL3), 14);
enabled = spd32;
bool suiden = bits(tc->readMiscReg(MISCREG_SDER), 0);
enabled = el == EL0 ? (enabled || suiden) : enabled;
}
else
{
enabled = el != EL2;
}
return enabled;
}
bool
BrkPoint::testLinkedBk(ThreadContext *tc, Addr vaddr, ExceptionLevel el)
{
bool debug = false;
const DBGBCR ctr = getControlReg(tc);
if ((ctr.bt & 0x1) && getEnable()){
debug = test(tc, vaddr, el, ctr, true);
}
return debug;
}
bool
BrkPoint::test(ThreadContext *tc, Addr pc, ExceptionLevel el, DBGBCR ctr,
bool from_link)
{
bool v = false;
switch (ctr.bt)
{
case 0x0:
v = testAddrMatch(tc, pc, ctr.bas);
break;
case 0x1:
v = testAddrMatch(tc, pc, ctr.bas); // linked
if (v){
v = (conf->getBrkPoint(ctr.lbn))->testLinkedBk(tc, pc, el);
}
break;
case 0x2:
v = testContextMatch(tc, true);
break;
case 0x3:
if (from_link){
v = testContextMatch(tc, true); //linked
}
break;
case 0x4:
v = testAddrMissMatch(tc, pc, ctr.bas);
break;
case 0x5:
v = testAddrMissMatch(tc, pc, ctr.bas); // linked
if (v && !from_link)
v = v && (conf->getBrkPoint(ctr.lbn))->testLinkedBk(tc,
pc, el);
break;
case 0x6:
// VHE not implemented
// v = testContextMatch(tc, true);
break;
case 0x7:
// VHE not implemented
// if (from_link)
// v = testContextMatch(tc, true);
break;
case 0x8:
v = testVMIDMatch(tc);
break;
case 0x9:
if (from_link && ArmSystem::haveEL(tc, EL2)){
v = testVMIDMatch(tc); // linked
}
break;
case 0xa:
if (ArmSystem::haveEL(tc, EL2)){
v = testContextMatch(tc, true);
if (v && !from_link)
v = v && testVMIDMatch(tc);
}
break;
case 0xb:
if (from_link && ArmSystem::haveEL(tc, EL2)){
v = testContextMatch(tc, true);
v = v && testVMIDMatch(tc);
}
break;
case 0xc:
// VHE not implemented
// v = testContextMatch(tc, false); // CONTEXTIDR_EL2
break;
case 0xd:
// VHE not implemented
// if (from_link)
// v = testContextMatch(tc, false);
// CONTEXTIDR_EL2 AND LINKED
break;
case 0xe:
// VHE not implemented
// v = testContextMatch(tc, true); // CONTEXTIDR_EL1
// v = v && testContextMatch(tc, false); // CONTEXTIDR_EL2
break;
case 0xf:
// VHE not implemented
// if (from_link){
// v = testContextMatch(tc, true); // CONTEXTIDR_EL1
// v = v && testContextMatch(tc, false); // CONTEXTIDR_EL2
// }
break;
}
return v;
}
bool
BrkPoint::testAddrMatch(ThreadContext *tc, Addr in_pc, uint8_t bas)
{
Addr pc_tocmp = getAddrfromReg(tc);
Addr pc = bits(in_pc, maxAddrSize, 2);
bool prs = true;
CPSR cpsr = tc->readMiscReg(MISCREG_CPSR);
bool thumb = cpsr.t;
if (thumb){
if (bas == 0xc)
prs = bits(in_pc, 1, 0) == 0x2;
else if (bas == 0x3)
prs = bits(in_pc, 1, 0) == 0x0;
}
return (pc == pc_tocmp) && prs;
}
bool
BrkPoint::testAddrMissMatch(ThreadContext *tc, Addr in_pc, uint8_t bas)
{
if (bas == 0x0)
return true;
Addr pc_tocmp = getAddrfromReg(tc);
Addr pc = bits(in_pc, maxAddrSize, 2);
bool prs = false;
CPSR cpsr = tc->readMiscReg(MISCREG_CPSR);
bool thumb = cpsr.t;
if (thumb){
if (bas == 0xc)
prs = bits(in_pc, 1, 0) == 0x2;
else if (bas == 0x3)
prs = bits(in_pc, 1, 0) == 0x0;
}
return (pc != pc_tocmp) && !prs;
}
bool
BrkPoint::testContextMatch(ThreadContext *tc, bool ctx1)
{
if (!isCntxtAware)
return false;
MiscRegIndex miscridx;
ExceptionLevel el = currEL(tc);
bool a32 = conf->isAArch32();
if (ctx1){
miscridx = a32? MISCREG_CONTEXTIDR: MISCREG_CONTEXTIDR_EL1;
if ((el == EL3 && !a32) || el ==EL2)
return false;
}else{
miscridx = MISCREG_CONTEXTIDR_EL2;
if (el == EL2 && a32)
return false;
}
RegVal ctxid = tc->readMiscReg(miscridx);
RegVal v = getContextfromReg(tc, ctx1);
return (v== ctxid);
}
bool
BrkPoint::testVMIDMatch(ThreadContext *tc)
{
uint32_t vmid_index = 55;
if (VMID16enabled)
vmid_index = 63;
ExceptionLevel el = currEL(tc);
if (el == EL2)
return false;
uint32_t vmid = bits(tc->readMiscReg(MISCREG_VTTBR_EL2), vmid_index, 48);
uint32_t v = getVMIDfromReg(tc);
return (v == vmid);
}
bool
BrkPoint::isEnabled(ThreadContext* tc, ExceptionLevel el,
uint8_t hmc, uint8_t ssc, uint8_t pmc){
bool v;
bool aarch32 = conf->isAArch32();
bool noEL2 = !ArmSystem::haveEL(tc, EL2);
bool noEL3 = !ArmSystem::haveEL(tc, EL3);
if (noEL3 && !noEL2 && (ssc==0x1 || ssc==0x2)
&& !(hmc && ssc == 0x1 && pmc==0x0)){
return false;
}
else if (noEL3 && noEL2 &&( hmc != 0x0 || ssc !=0x0)
&& !(!aarch32 && ((hmc && ssc == 0x1 && pmc == 0x0)
|| ssc == 0x3))){
return false;
}
else if (noEL2 && hmc && ssc == 0x3 && pmc == 0x0){
return false;
}
else if (ssc == 0x11 && pmc==0x1 &&
!(!aarch32 && hmc && ssc == 0x3 &&pmc == 0x0)){
// AND secureEL2 not implemented
return false;
}
else if (hmc && ssc == 0x1 && pmc == 0x0){//AND secureEL2 not implemented
return false;
}
switch (el) {
case EL0:
v = (pmc == 0x3) || (pmc == 0x2 && hmc == 0x0) ;
if (aarch32)
v = v || (pmc == 0x0 && ssc != 0x3 && hmc == 0x0);
if (v && ssc == 0x3)
panic("Unexpected EL in SelfDebug::isDebugEnabled.\n");
break;
case EL1:
v = (pmc == 0x3) || (pmc == 0x1);
if (aarch32)
v = v || (pmc == 0x0 && hmc == 0x0 && ssc !=0x3);
break;
case EL2:
v = (ssc == 0x3) ||
((hmc == 0x1) && !((ssc==0x2) && (pmc = 0x0)));
if (v && pmc == 0x2)
panic("Unexpected EL in SelfDebug::isDebugEnabled.\n");
break;
case EL3:
if (ssc == 0x1)
panic("Unexpected EL in SelfDebug::isDebugEnabled.\n");
v = (hmc == 0x1) & (ssc != 0x3);
break;
default:
panic("Unexpected EL %d in BrkPoint::isEnabled.\n", el);
}
return v && SelfDebug::securityStateMatch(tc, ssc, hmc || !aarch32);
}
uint32_t
BrkPoint::getVMIDfromReg(ThreadContext *tc)
{
uint32_t vmid_index = 39;
if (VMID16enabled)
vmid_index = 47;
return bits(tc->readMiscReg(valRegIndex), vmid_index, 32);
}

329
src/arch/arm/self_debug.hh Normal file
View File

@@ -0,0 +1,329 @@
/*
* Copyright (c) 2019 Metempsy Technology LSC
* All rights reserved
*
* The license below extends only to copyright in the software and shall
* not be construed as granting a license to any other intellectual
* property including but not limited to intellectual property relating
* to a hardware implementation of the functionality of the software
* licensed hereunder. You may use the software subject to the license
* terms below provided that you ensure that this notice is replicated
* unmodified and in its entirety in all distributions of the software,
* modified or unmodified, in source code or in binary form.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer;
* redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution;
* neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef __ARCH_ARM_SELF_DEBUG_HH__
#define __ARCH_ARM_SELF_DEBUG_HH__
#include "arch/arm/faults.hh"
#include "arch/arm/miscregs.hh"
#include "arch/arm/system.hh"
#include "arch/arm/types.hh"
#include "arch/arm/utility.hh"
#include "cpu/thread_context.hh"
class ThreadContext;
namespace ArmISA
{
class SelfDebug;
class BrkPoint
{
private:
MiscRegIndex ctrlRegIndex;
MiscRegIndex valRegIndex;
MiscRegIndex xRegIndex;
SelfDebug * conf;
bool isCntxtAware;
bool VMID16enabled;
Addr active_pc;
bool enable;
int maxAddrSize;
bool onUse;
public:
BrkPoint(MiscRegIndex _ctrlIndex, MiscRegIndex _valIndex,
MiscRegIndex _xIndex, SelfDebug* _conf, bool _ctxAw, bool lva,
bool vmid16, bool aarch32):
ctrlRegIndex(_ctrlIndex), valRegIndex(_valIndex),
xRegIndex(_xIndex), conf(_conf), isCntxtAware(_ctxAw),
VMID16enabled(vmid16), active_pc(0x0), enable(false)
{
maxAddrSize = lva ? 52: 48 ;
maxAddrSize = aarch32 ? 31 : maxAddrSize;
onUse=false;
}
void setOnUse()
{
onUse = true;
}
void unsetOnUse()
{
onUse = false;
}
bool isSet()
{
return onUse;
}
bool testLinkedBk(ThreadContext *tc, Addr vaddr, ExceptionLevel el);
bool test(ThreadContext *tc, Addr pc, ExceptionLevel el, DBGBCR ctr,
bool from_link);
protected:
inline Addr getAddrfromReg(ThreadContext *tc)
{
return bits(tc->readMiscReg(valRegIndex), maxAddrSize, 2);
}
inline RegVal getContextfromReg(ThreadContext *tc, bool ctxid1)
{
if (ctxid1)
return bits(tc->readMiscReg(valRegIndex), 31, 0);
else
return bits(tc->readMiscReg(valRegIndex), 63, 32);
}
inline uint32_t getVMIDfromReg(ThreadContext *tc);
public:
bool testAddrMatch(ThreadContext *tc, Addr pc, uint8_t bas);
bool testAddrMissMatch(ThreadContext *tc, Addr pc, uint8_t bas);
bool testContextMatch(ThreadContext *tc, bool ctx1);
bool testVMIDMatch(ThreadContext *tc);
const DBGBCR getControlReg(ThreadContext *tc)
{
const DBGBCR ctr = tc->readMiscReg(ctrlRegIndex);
return ctr;
}
bool isEnabled(ThreadContext* tc, ExceptionLevel el,
uint8_t hmc, uint8_t ssc, uint8_t pmc);
bool isActive(Addr vaddr)
{
if (vaddr==active_pc){
active_pc = 0x0;
return false;
}else{
active_pc = vaddr;
return true;
}
}
inline void updateControl(DBGBCR val)
{
enable = val.e == 0x1;
}
bool getEnable()
{
return enable;
}
};
class SelfDebug
{
private:
std::vector<BrkPoint> arBrkPoints;
bool initialized;
bool enableTdeTge; // MDCR_EL2.TDE || HCR_EL2.TGE
// THIS is MDSCR_EL1.MDE in aarch64 and DBGDSCRext.MDBGen in aarch32
bool enableFlag;
bool bSDD; // MDCR_EL3.SDD
bool bKDE; // MDSCR_EL1.KDE
bool oslk; // OS lock flag
bool aarch32; // updates with stage1 aarch64/32
bool to32;
public:
SelfDebug(): initialized(false), enableTdeTge(false),
enableFlag(false), bSDD(false), bKDE(false), oslk(false)
{}
~SelfDebug(){}
Fault testBreakPoints(ThreadContext *tc, Addr vaddr);
Fault triggerException(ThreadContext * tc, Addr vaddr);
inline BrkPoint* getBrkPoint(uint8_t index)
{
return &arBrkPoints[index];
}
static inline bool
securityStateMatch(ThreadContext *tc, uint8_t ssc, bool hmc)
{
switch(ssc)
{
case 0x0: return true;
case 0x1: return !inSecureState(tc);
case 0x2: return inSecureState(tc);
case 0x3:
{
bool b = hmc? true: inSecureState(tc);
return b;
}
default: panic("Unreachable value");
}
return false;
}
bool isDebugEnabledForEL64(ThreadContext *tc, ExceptionLevel el,
bool secure, bool mask);
bool isDebugEnabledForEL32(ThreadContext *tc, ExceptionLevel el,
bool secure, bool mask);
void activateDebug()
{
for (auto &p: arBrkPoints){
p.unsetOnUse();
}
}
inline bool isDebugEnabled(ThreadContext *tc)
{
CPSR cpsr = tc->readMiscReg(MISCREG_CPSR);
ExceptionLevel el = (ExceptionLevel) currEL(tc);
if (aarch32){
return isDebugEnabledForEL32(tc, el, inSecureState(tc),
(bool)cpsr.d == 1);
}else{
return isDebugEnabledForEL64(tc, el, inSecureState(tc),
(bool)cpsr.d == 1 );
}
}
inline void setbSDD(RegVal val)
{
bSDD = bits(val, 16);
}
inline void setMDSCRvals(RegVal val)
{
enableFlag = bits(val, 15);
bKDE = bits(val, 13);
}
inline void setMDBGen(RegVal val)
{
enableFlag = bits(val, 15);
}
inline void setenableTDETGE(HCR hcr, HDCR mdcr)
{
enableTdeTge = (mdcr.tde == 0x1 || hcr.tge == 0x1);
}
inline void updateOSLock(RegVal val)
{
oslk = bool(bits(val, 0));
}
inline void updateDBGBCR(int index, DBGBCR val)
{
arBrkPoints[index].updateControl(val);
}
inline bool isAArch32()
{
return aarch32;
}
inline bool isTo32()
{
return to32;
}
inline void setAArch32(ThreadContext * tc)
{
ExceptionLevel fromEL = (ExceptionLevel) currEL(tc);
if (fromEL == EL0)
aarch32 = ELIs32(tc, EL0) && ELIs32(tc, EL1);
else
aarch32 = ELIs32(tc, fromEL);
return;
}
bool targetAArch32(ThreadContext * tc)
{
ExceptionLevel ELd = debugTargetFrom(tc, inSecureState(tc));
return ELIs32(tc, ELd) && aarch32;
}
void init(ThreadContext *tc)
{
if (initialized)
return;
CPSR cpsr = tc->readMiscReg(MISCREG_CPSR);
aarch32 = cpsr.width == 1;
const AA64DFR0 dfr = tc->readMiscReg(MISCREG_ID_AA64DFR0_EL1);
const AA64MMFR2 mm_fr2 = tc->readMiscReg(MISCREG_ID_AA64MMFR2_EL1);
const AA64MMFR1 mm_fr1 = tc->readMiscReg(MISCREG_ID_AA64MMFR1_EL1);
const uint8_t nCtxtAwareBp = dfr.ctx_cmps;
const bool VMIDBits = mm_fr1.vmidbits;
for (int i=0; i<=dfr.brps; i++){
const bool isctxaw = i>=(dfr.brps-nCtxtAwareBp);
BrkPoint bkp = BrkPoint((MiscRegIndex)(MISCREG_DBGBCR0_EL1+i),
(MiscRegIndex)(MISCREG_DBGBVR0_EL1+i),
(MiscRegIndex)(MISCREG_DBGBXVR0+i),
this, isctxaw, (bool)mm_fr2.varange,
VMIDBits, aarch32);
const DBGBCR ctr = tc->readMiscReg(MISCREG_DBGBCR0_EL1+i);
bkp.updateControl(ctr);
arBrkPoints.push_back(bkp);
}
initialized = true;
RegVal oslar_el1 = tc->readMiscReg(MISCREG_OSLAR_EL1);
updateOSLock(oslar_el1);
// Initialize preloaded control booleans
uint64_t mdscr_el1 = tc->readMiscReg(MISCREG_MDSCR_EL1);
setMDSCRvals(mdscr_el1);
const uint64_t mdcr_el3 = tc->readMiscReg(MISCREG_MDCR_EL3);
setbSDD(mdcr_el3);
const HCR hcr = tc->readMiscReg(MISCREG_HCR_EL2);
const HDCR mdcr = tc->readMiscRegNoEffect(MISCREG_MDCR_EL2);
setenableTDETGE(hcr, mdcr);
}
};
}
#endif

View File

@@ -45,7 +45,9 @@
#include <vector>
#include "arch/arm/faults.hh"
#include "arch/arm/isa.hh"
#include "arch/arm/pagetable.hh"
#include "arch/arm/self_debug.hh"
#include "arch/arm/stage2_lookup.hh"
#include "arch/arm/stage2_mmu.hh"
#include "arch/arm/system.hh"
@@ -1177,17 +1179,29 @@ TLB::translateFs(const RequestPtr &req, ThreadContext *tc, Mode mode,
}
}
Fault fault = NoFault;
// If guest MMU is off or hcr.vm=0 go straight to stage2
if ((isStage2 && !hcr.vm) || (!isStage2 && !sctlr.m)) {
return translateMmuOff(tc, req, mode, tranType, vaddr,
long_desc_format);
fault = translateMmuOff(tc, req, mode, tranType, vaddr,
long_desc_format);
} else {
DPRINTF(TLBVerbose, "Translating %s=%#x context=%d\n",
isStage2 ? "IPA" : "VA", vaddr_tainted, asid);
// Translation enabled
return translateMmuOn(tc, req, mode, translation, delay, timing,
functional, vaddr, tranMethod);
fault = translateMmuOn(tc, req, mode, translation, delay, timing,
functional, vaddr, tranMethod);
}
//Check for Debug Exceptions
if (fault == NoFault) {
auto *isa = static_cast<ArmISA::ISA *>(tc->getIsaPtr());
SelfDebug * sd = isa->getSelfDebug();
if (mode == Execute) {
fault = sd->testBreakPoints(tc, req->getVaddr());
}
}
return fault;
}
Fault

View File

@@ -93,12 +93,32 @@ TarmacParserRecord::MiscRegMap TarmacParserRecord::miscRegMap = {
{ "dbgbvr3", MISCREG_DBGBVR3 },
{ "dbgbvr4", MISCREG_DBGBVR4 },
{ "dbgbvr5", MISCREG_DBGBVR5 },
{ "dbgbvr6", MISCREG_DBGBVR6 },
{ "dbgbvr7", MISCREG_DBGBVR7 },
{ "dbgbvr8", MISCREG_DBGBVR8 },
{ "dbgbvr9", MISCREG_DBGBVR9 },
{ "dbgbvr10", MISCREG_DBGBVR10 },
{ "dbgbvr11", MISCREG_DBGBVR11 },
{ "dbgbvr12", MISCREG_DBGBVR12 },
{ "dbgbvr13", MISCREG_DBGBVR13 },
{ "dbgbvr14", MISCREG_DBGBVR14 },
{ "dbgbvr15", MISCREG_DBGBVR15 },
{ "dbgbcr0", MISCREG_DBGBCR0 },
{ "dbgbcr1", MISCREG_DBGBCR1 },
{ "dbgbcr2", MISCREG_DBGBCR2 },
{ "dbgbcr3", MISCREG_DBGBCR3 },
{ "dbgbcr4", MISCREG_DBGBCR4 },
{ "dbgbcr5", MISCREG_DBGBCR5 },
{ "dbgbcr6", MISCREG_DBGBCR6 },
{ "dbgbcr7", MISCREG_DBGBCR7 },
{ "dbgbcr8", MISCREG_DBGBCR8 },
{ "dbgbcr9", MISCREG_DBGBCR9 },
{ "dbgbcr10", MISCREG_DBGBCR10 },
{ "dbgbcr11", MISCREG_DBGBCR11 },
{ "dbgbcr12", MISCREG_DBGBCR12 },
{ "dbgbcr13", MISCREG_DBGBCR13 },
{ "dbgbcr14", MISCREG_DBGBCR14 },
{ "dbgbcr15", MISCREG_DBGBCR15 },
{ "dbgwvr0", MISCREG_DBGWVR0 },
{ "dbgwvr1", MISCREG_DBGWVR1 },
{ "dbgwvr2", MISCREG_DBGWVR2 },
@@ -108,8 +128,22 @@ TarmacParserRecord::MiscRegMap TarmacParserRecord::miscRegMap = {
{ "dbgwcr2", MISCREG_DBGWCR2 },
{ "dbgwcr3", MISCREG_DBGWCR3 },
{ "dbgdrar", MISCREG_DBGDRAR },
{ "dbgbxvr0", MISCREG_DBGBXVR0 },
{ "dbgbxvr1", MISCREG_DBGBXVR1 },
{ "dbgbxvr2", MISCREG_DBGBXVR2 },
{ "dbgbxvr3", MISCREG_DBGBXVR3 },
{ "dbgbxvr4", MISCREG_DBGBXVR4 },
{ "dbgbxvr5", MISCREG_DBGBXVR5 },
{ "dbgbxvr6", MISCREG_DBGBXVR6 },
{ "dbgbxvr7", MISCREG_DBGBXVR7 },
{ "dbgbxvr8", MISCREG_DBGBXVR8 },
{ "dbgbxvr9", MISCREG_DBGBXVR9 },
{ "dbgbxvr10", MISCREG_DBGBXVR10 },
{ "dbgbxvr11", MISCREG_DBGBXVR11 },
{ "dbgbxvr12", MISCREG_DBGBXVR12 },
{ "dbgbxvr13", MISCREG_DBGBXVR13 },
{ "dbgbxvr14", MISCREG_DBGBXVR14 },
{ "dbgbxvr15", MISCREG_DBGBXVR15 },
{ "dbgoslar", MISCREG_DBGOSLAR },
{ "dbgoslsr", MISCREG_DBGOSLSR },
{ "dbgosdlr", MISCREG_DBGOSDLR },
@@ -354,12 +388,32 @@ TarmacParserRecord::MiscRegMap TarmacParserRecord::miscRegMap = {
{ "dbgbvr3_el1", MISCREG_DBGBVR3_EL1 },
{ "dbgbvr4_el1", MISCREG_DBGBVR4_EL1 },
{ "dbgbvr5_el1", MISCREG_DBGBVR5_EL1 },
{ "dbgbvr6_el1", MISCREG_DBGBVR6_EL1 },
{ "dbgbvr7_el1", MISCREG_DBGBVR7_EL1 },
{ "dbgbvr8_el1", MISCREG_DBGBVR8_EL1 },
{ "dbgbvr9_el1", MISCREG_DBGBVR9_EL1 },
{ "dbgbvr10_el1", MISCREG_DBGBVR10_EL1 },
{ "dbgbvr11_el1", MISCREG_DBGBVR11_EL1 },
{ "dbgbvr12_el1", MISCREG_DBGBVR12_EL1 },
{ "dbgbvr13_el1", MISCREG_DBGBVR13_EL1 },
{ "dbgbvr14_el1", MISCREG_DBGBVR14_EL1 },
{ "dbgbvr15_el1", MISCREG_DBGBVR15_EL1 },
{ "dbgbcr0_el1", MISCREG_DBGBCR0_EL1 },
{ "dbgbcr1_el1", MISCREG_DBGBCR1_EL1 },
{ "dbgbcr2_el1", MISCREG_DBGBCR2_EL1 },
{ "dbgbcr3_el1", MISCREG_DBGBCR3_EL1 },
{ "dbgbcr4_el1", MISCREG_DBGBCR4_EL1 },
{ "dbgbcr5_el1", MISCREG_DBGBCR5_EL1 },
{ "dbgbcr6_el1", MISCREG_DBGBCR6_EL1 },
{ "dbgbcr7_el1", MISCREG_DBGBCR7_EL1 },
{ "dbgbcr8_el1", MISCREG_DBGBCR8_EL1 },
{ "dbgbcr9_el1", MISCREG_DBGBCR9_EL1 },
{ "dbgbcr10_el1", MISCREG_DBGBCR10_EL1 },
{ "dbgbcr11_el1", MISCREG_DBGBCR11_EL1 },
{ "dbgbcr12_el1", MISCREG_DBGBCR12_EL1 },
{ "dbgbcr13_el1", MISCREG_DBGBCR13_EL1 },
{ "dbgbcr14_el1", MISCREG_DBGBCR14_EL1 },
{ "dbgbcr15_el1", MISCREG_DBGBCR15_EL1 },
{ "dbgwvr0_el1", MISCREG_DBGWVR0_EL1 },
{ "dbgwvr1_el1", MISCREG_DBGWVR1_EL1 },
{ "dbgwvr2_el1", MISCREG_DBGWVR2_EL1 },

View File

@@ -645,6 +645,9 @@ namespace ArmISA
EC_FP_EXCEPTION = 0x28,
EC_FP_EXCEPTION_64 = 0x2C,
EC_SERROR = 0x2F,
EC_HW_BREAKPOINT = 0x30,
EC_HW_BREAKPOINT_LOWER_EL = 0x30,
EC_HW_BREAKPOINT_CURR_EL = 0x31,
EC_SOFTWARE_BREAKPOINT = 0x38,
EC_SOFTWARE_BREAKPOINT_64 = 0x3C,
};

View File

@@ -179,13 +179,42 @@ inSecureState(ThreadContext *tc)
scr, tc->readMiscReg(MISCREG_CPSR));
}
inline bool
bool
isSecureBelowEL3(ThreadContext *tc)
{
SCR scr = tc->readMiscReg(MISCREG_SCR_EL3);
return ArmSystem::haveEL(tc, EL3) && scr.ns == 0;
}
ExceptionLevel
debugTargetFrom(ThreadContext *tc, bool secure)
{
bool route_to_el2;
if (ArmSystem::haveEL(tc, EL2) && !secure){
if (ELIs32(tc, EL2)){
const HCR hcr = tc->readMiscReg(MISCREG_HCR);
const HDCR hdcr = tc->readMiscRegNoEffect(MISCREG_HDCR);
route_to_el2 = (hdcr.tde == 1 || hcr.tge == 1);
}else{
const HCR hcr = tc->readMiscReg(MISCREG_HCR_EL2);
const HDCR mdcr = tc->readMiscRegNoEffect(MISCREG_MDCR_EL2);
route_to_el2 = (mdcr.tde == 1 || hcr.tge == 1);
}
}else{
route_to_el2 = false;
}
ExceptionLevel target;
if (route_to_el2) {
target = EL2;
}else if (ArmSystem::haveEL(tc, EL3) && !ArmSystem::highestELIs64(tc)
&& secure){
target = EL3;
}else{
target = EL1;
}
return target;
}
bool
inAArch64(ThreadContext *tc)
{
@@ -358,6 +387,13 @@ ELIsInHost(ThreadContext *tc, ExceptionLevel el)
std::pair<bool, bool>
ELUsingAArch32K(ThreadContext *tc, ExceptionLevel el)
{
bool secure = isSecureBelowEL3(tc);
return ELStateUsingAArch32K(tc, el, secure);
}
std::pair<bool, bool>
ELStateUsingAArch32K(ThreadContext *tc, ExceptionLevel el, bool secure)
{
// Return true if the specified EL is in aarch32 state.
const bool have_el3 = ArmSystem::haveSecurity(tc);
@@ -382,7 +418,7 @@ ELUsingAArch32K(ThreadContext *tc, ExceptionLevel el)
HCR hcr = tc->readMiscReg(MISCREG_HCR_EL2);
bool aarch32_at_el1 = (aarch32_below_el3
|| (have_el2
&& !isSecureBelowEL3(tc) && hcr.rw == 0));
&& !secure && hcr.rw == 0));
// Only know if EL0 using AArch32 from PSTATE
if (el == EL0 && !aarch32_at_el1) {
@@ -401,6 +437,15 @@ ELUsingAArch32K(ThreadContext *tc, ExceptionLevel el)
return std::make_pair(known, aarch32);
}
bool ELStateUsingAArch32(ThreadContext *tc, ExceptionLevel el, bool secure)
{
bool known, aarch32;
std::tie(known, aarch32) = ELStateUsingAArch32K(tc, el, secure);
panic_if(!known, "EL state is UNKNOWN");
return aarch32;
}
bool
isBigEndian64(const ThreadContext *tc)
{

View File

@@ -172,6 +172,12 @@ bool EL2Enabled(ThreadContext *tc);
std::pair<bool, bool>
ELUsingAArch32K(ThreadContext *tc, ExceptionLevel el);
std::pair<bool, bool>
ELStateUsingAArch32K(ThreadContext *tc, ExceptionLevel el, bool secure);
bool
ELStateUsingAArch32(ThreadContext *tc, ExceptionLevel el, bool secure);
bool ELIs32(ThreadContext *tc, ExceptionLevel el);
bool ELIs64(ThreadContext *tc, ExceptionLevel el);
@@ -182,8 +188,10 @@ bool ELIs64(ThreadContext *tc, ExceptionLevel el);
*/
bool ELIsInHost(ThreadContext *tc, ExceptionLevel el);
ExceptionLevel debugTargetFrom(ThreadContext *tc, bool secure);
bool isBigEndian64(const ThreadContext *tc);
/**
* badMode is checking if the execution mode provided as an argument is
* valid and implemented for AArch32
@@ -249,6 +257,8 @@ inSecureState(SCR scr, CPSR cpsr)
bool inSecureState(ThreadContext *tc);
bool isSecureBelowEL3(ThreadContext *tc);
bool longDescFormatInUse(ThreadContext *tc);
/** This helper function is either returing the value of