From f9db8ab3065b8019667ca1e5653d30773cc935c8 Mon Sep 17 00:00:00 2001 From: Jordi Vaquero Date: Tue, 11 Feb 2020 17:22:25 +0100 Subject: [PATCH] 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 Maintainer: Giacomo Travaglini Tested-by: kokoro --- src/arch/arm/ArmISA.py | 4 +- src/arch/arm/SConscript | 1 + src/arch/arm/faults.cc | 74 ++++- src/arch/arm/faults.hh | 30 +- src/arch/arm/insts/static_inst.cc | 5 +- src/arch/arm/insts/static_inst.hh | 13 + src/arch/arm/isa.cc | 179 ++++++++++- src/arch/arm/isa.hh | 7 + src/arch/arm/miscregs.cc | 436 +++++++++++++++++++++++--- src/arch/arm/miscregs.hh | 110 +++++++ src/arch/arm/miscregs_types.hh | 45 +++ src/arch/arm/self_debug.cc | 388 +++++++++++++++++++++++ src/arch/arm/self_debug.hh | 329 +++++++++++++++++++ src/arch/arm/tlb.cc | 22 +- src/arch/arm/tracers/tarmac_parser.cc | 54 ++++ src/arch/arm/types.hh | 3 + src/arch/arm/utility.cc | 49 ++- src/arch/arm/utility.hh | 10 + 18 files changed, 1687 insertions(+), 72 deletions(-) create mode 100644 src/arch/arm/self_debug.cc create mode 100644 src/arch/arm/self_debug.hh diff --git a/src/arch/arm/ArmISA.py b/src/arch/arm/ArmISA.py index 2641ec3fb..b030e6c94 100644 --- a/src/arch/arm/ArmISA.py +++ b/src/arch/arm/ArmISA.py @@ -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, diff --git a/src/arch/arm/SConscript b/src/arch/arm/SConscript index 73ebcacf2..3f3421647 100644 --- a/src/arch/arm/SConscript +++ b/src/arch/arm/SConscript @@ -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') diff --git a/src/arch/arm/faults.cc b/src/arch/arm/faults.cc index 22894f3ef..ba8369ac5 100644 --- a/src/arch/arm/faults.cc +++ b/src/arch/arm/faults.cc @@ -281,6 +281,10 @@ template<> ArmFault::FaultVals ArmFaultVals::vals( "Software Breakpoint", 0x000, 0x000, 0x200, 0x400, 0x600, MODE_SVC, 0, 0, 0, 0, true, false, false, EC_SOFTWARE_BREAKPOINT ); +template<> ArmFault::FaultVals ArmFaultVals::vals( + "Hardware Breakpoint", 0x000, 0x000, 0x200, 0x400, 0x600, MODE_SVC, + 0, 0, 0, 0, true, false, false, EC_HW_BREAKPOINT +); template<> ArmFault::FaultVals ArmFaultVals::vals( // Some dummy values "ArmSev Flush", 0x000, 0x000, 0x000, 0x000, 0x000, MODE_SVC, @@ -1075,6 +1079,16 @@ AbortFault::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(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::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"); diff --git a/src/arch/arm/faults.hh b/src/arch/arm/faults.hh index 1d8f782d7..2db0e8d40 100644 --- a/src/arch/arm/faults.hh +++ b/src/arch/arm/faults.hh @@ -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 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 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(_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 ExceptionClass ec(ThreadContext *tc) const override; }; +class HardwareBreakpoint : public ArmFaultVals +{ + 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 { @@ -630,6 +651,7 @@ template<> ArmFault::FaultVals ArmFaultVals::vals; template<> ArmFault::FaultVals ArmFaultVals::vals; template<> ArmFault::FaultVals ArmFaultVals::vals; template<> ArmFault::FaultVals ArmFaultVals::vals; +template<> ArmFault::FaultVals ArmFaultVals::vals; template<> ArmFault::FaultVals ArmFaultVals::vals; /** diff --git a/src/arch/arm/insts/static_inst.cc b/src/arch/arm/insts/static_inst.cc index 9966b9ee5..f23cc7978 100644 --- a/src/arch/arm/insts/static_inst.cc +++ b/src/arch/arm/insts/static_inst.cc @@ -640,7 +640,10 @@ ArmStaticInst::softwareBreakpoint32(ExecContext *xc, uint16_t imm) const } else { // Execute AArch32 Software Breakpoint return std::make_shared(readPC(xc), - ArmFault::DebugEvent); + ArmFault::DebugEvent, + false, + ArmFault::UnknownTran, + ArmFault::BRKPOINT); } } diff --git a/src/arch/arm/insts/static_inst.hh b/src/arch/arm/insts/static_inst.hh index bee39036b..82bf61d0f 100644 --- a/src/arch/arm/insts/static_inst.hh +++ b/src/arch/arm/insts/static_inst.hh @@ -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(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); diff --git a/src/arch/arm/isa.cc b/src/arch/arm/isa.cc index 29c553878..f88d2ef07 100644 --- a/src/arch/arm/isa.cc +++ b/src/arch/arm/isa.cc @@ -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(_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( @@ -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; diff --git a/src/arch/arm/isa.hh b/src/arch/arm/isa.hh index e7c81802d..be57f4115 100644 --- a/src/arch/arm/isa.hh +++ b/src/arch/arm/isa.hh @@ -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); diff --git a/src/arch/arm/miscregs.cc b/src/arch/arm/miscregs.cc index 3c80de4bf..86b3aaa94 100644 --- a/src/arch/arm/miscregs.cc +++ b/src/arch/arm/miscregs.cc @@ -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); diff --git a/src/arch/arm/miscregs.hh b/src/arch/arm/miscregs.hh index 550b51cd9..1f053e35d 100644 --- a/src/arch/arm/miscregs.hh +++ b/src/arch/arm/miscregs.hh @@ -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", diff --git a/src/arch/arm/miscregs_types.hh b/src/arch/arm/miscregs_types.hh index cbc7adb16..642fa6eed 100644 --- a/src/arch/arm/miscregs_types.hh +++ b/src/arch/arm/miscregs_types.hh @@ -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__ diff --git a/src/arch/arm/self_debug.cc b/src/arch/arm/self_debug.cc new file mode 100644 index 000000000..5234be44e --- /dev/null +++ b/src/arch/arm/self_debug.cc @@ -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(vaddr, + ArmFault::DebugEvent, false, + ArmFault::UnknownTran, + ArmFault::BRKPOINT); + } else { + return std::make_shared(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); +} + diff --git a/src/arch/arm/self_debug.hh b/src/arch/arm/self_debug.hh new file mode 100644 index 000000000..4453e7c9f --- /dev/null +++ b/src/arch/arm/self_debug.hh @@ -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 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 diff --git a/src/arch/arm/tlb.cc b/src/arch/arm/tlb.cc index 84160bba8..a00cba857 100644 --- a/src/arch/arm/tlb.cc +++ b/src/arch/arm/tlb.cc @@ -45,7 +45,9 @@ #include #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(tc->getIsaPtr()); + SelfDebug * sd = isa->getSelfDebug(); + if (mode == Execute) { + fault = sd->testBreakPoints(tc, req->getVaddr()); + } + } + + return fault; } Fault diff --git a/src/arch/arm/tracers/tarmac_parser.cc b/src/arch/arm/tracers/tarmac_parser.cc index 96678b07b..fa7f1be84 100644 --- a/src/arch/arm/tracers/tarmac_parser.cc +++ b/src/arch/arm/tracers/tarmac_parser.cc @@ -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 }, diff --git a/src/arch/arm/types.hh b/src/arch/arm/types.hh index 83248b351..0dd3dac9f 100644 --- a/src/arch/arm/types.hh +++ b/src/arch/arm/types.hh @@ -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, }; diff --git a/src/arch/arm/utility.cc b/src/arch/arm/utility.cc index 9947bdd28..e72c2301a 100644 --- a/src/arch/arm/utility.cc +++ b/src/arch/arm/utility.cc @@ -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 ELUsingAArch32K(ThreadContext *tc, ExceptionLevel el) +{ + bool secure = isSecureBelowEL3(tc); + return ELStateUsingAArch32K(tc, el, secure); +} + +std::pair +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) { diff --git a/src/arch/arm/utility.hh b/src/arch/arm/utility.hh index 231b8b957..87e51d97e 100644 --- a/src/arch/arm/utility.hh +++ b/src/arch/arm/utility.hh @@ -172,6 +172,12 @@ bool EL2Enabled(ThreadContext *tc); std::pair ELUsingAArch32K(ThreadContext *tc, ExceptionLevel el); +std::pair +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 -- 2.30.2