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:
@@ -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,
|
||||
|
||||
@@ -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')
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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;
|
||||
|
||||
/**
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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
388
src/arch/arm/self_debug.cc
Normal 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
329
src/arch/arm/self_debug.hh
Normal 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
|
||||
@@ -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
|
||||
|
||||
@@ -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 },
|
||||
|
||||
@@ -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,
|
||||
};
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user