From 046645a4db646ec30cc36b0f5433114e8777dc44 Mon Sep 17 00:00:00 2001 From: Jordi Vaquero Date: Tue, 29 Oct 2019 18:32:45 +0100 Subject: [PATCH] arch-arm: Implementation of Vector Catch debug exception This commit implements Vector Catch exception as they are described in Armv8 reference manual chapter G2. This exception is just for AArch32. + tlb.cc: Implements the entry point for vector catch in addres mode + faults.hh/cc: Implements the entry point for vector catch in exception trap mode. + miscregs.cc: enables the use of vector catch releated registers + miscregs_types.hh: New bitwise type for vector catch control registers. + types.hh: declaration of EC for vector catch exception + self_debug.hh/cc: Main implementation of the vector catch functions to match address and exceptions type. Change-Id: Idbef26b16eff059e94ff16fac13bf5708dfe647f Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/30618 Reviewed-by: Giacomo Travaglini Maintainer: Giacomo Travaglini Tested-by: kokoro --- src/arch/arm/faults.cc | 25 ++++++- src/arch/arm/faults.hh | 14 +++- src/arch/arm/miscregs.cc | 14 ++-- src/arch/arm/miscregs_types.hh | 38 +++++++++++ src/arch/arm/self_debug.cc | 120 +++++++++++++++++++++++++++++++++ src/arch/arm/self_debug.hh | 49 ++++++++++++++ src/arch/arm/tlb.cc | 7 +- src/arch/arm/types.hh | 1 + 8 files changed, 259 insertions(+), 9 deletions(-) diff --git a/src/arch/arm/faults.cc b/src/arch/arm/faults.cc index 6a3ee18ee..ecc9e4dd5 100644 --- a/src/arch/arm/faults.cc +++ b/src/arch/arm/faults.cc @@ -42,6 +42,8 @@ #include "arch/arm/faults.hh" #include "arch/arm/insts/static_inst.hh" +#include "arch/arm/isa.hh" +#include "arch/arm/self_debug.hh" #include "arch/arm/system.hh" #include "arch/arm/utility.hh" #include "base/compiler.hh" @@ -480,7 +482,6 @@ ArmFault::update(ThreadContext *tc) void ArmFault::invoke(ThreadContext *tc, const StaticInstPtr &inst) { - // Update fault state informations, like the starting mode (aarch32) // or EL (aarch64) and the ending mode or EL. // From the update function we are also evaluating if the fault must @@ -493,6 +494,9 @@ ArmFault::invoke(ThreadContext *tc, const StaticInstPtr &inst) return; } + if (vectorCatch(tc, inst)) + return; + // ARMv7 (ARM ARM issue C B1.9) bool have_security = ArmSystem::haveSecurity(tc); @@ -716,6 +720,21 @@ ArmFault::invoke64(ThreadContext *tc, const StaticInstPtr &inst) setSyndrome(tc, getSyndromeReg64()); } +bool +ArmFault::vectorCatch(ThreadContext *tc, const StaticInstPtr &inst) +{ + auto *isa = static_cast(tc->getIsaPtr()); + SelfDebug * sd = isa->getSelfDebug(); + VectorCatch* vc = sd->getVectorCatch(tc); + if (!vc->isVCMatch()) { + Fault fault = sd->testVectorCatch(tc, 0x0, this); + if (fault != NoFault) + fault->invoke(tc, inst); + return true; + } + return false; +} + ArmStaticInst * ArmFault::instrAnnotate(const StaticInstPtr &inst) { @@ -1094,7 +1113,9 @@ AbortFault::invoke(ThreadContext *tc, const StaticInstPtr &inst) tc->setMiscReg(T::FarIndex, faultAddr); if (debug == ArmFault::BRKPOINT){ Rext.moe = 0x1; - } else if (debug > ArmFault::BRKPOINT) { + } else if (debug == ArmFault::VECTORCATCH){ + Rext.moe = 0x5; + } else if (debug > ArmFault::VECTORCATCH) { Rext.moe = 0xa; fsr.cm = (debug == ArmFault::WPOINT_CM)? 1 : 0; } diff --git a/src/arch/arm/faults.hh b/src/arch/arm/faults.hh index 8a127ffdb..a552757d5 100644 --- a/src/arch/arm/faults.hh +++ b/src/arch/arm/faults.hh @@ -154,6 +154,7 @@ class ArmFault : public FaultBase { NODEBUG = 0, BRKPOINT, + VECTORCATCH, WPOINT_CM, WPOINT_NOCM }; @@ -226,6 +227,8 @@ class ArmFault : public FaultBase void update(ThreadContext *tc); bool isResetSPSR(){ return bStep; } + bool vectorCatch(ThreadContext *tc, const StaticInstPtr &inst); + ArmStaticInst *instrAnnotate(const StaticInstPtr &inst); virtual void annotate(AnnotationIDs id, uint64_t val) {} virtual FaultStat& countStat() = 0; @@ -241,12 +244,13 @@ class ArmFault : public FaultBase virtual bool abortDisable(ThreadContext *tc) = 0; virtual bool fiqDisable(ThreadContext *tc) = 0; virtual ExceptionClass ec(ThreadContext *tc) const = 0; + virtual uint32_t vectorCatchFlag() const { return 0x0; } virtual uint32_t iss() const = 0; virtual bool isStage2() const { return false; } virtual FSR getFsr(ThreadContext *tc) const { return 0; } virtual void setSyndrome(ThreadContext *tc, MiscRegIndex syndrome_reg); virtual bool getFaultVAddr(Addr &va) const { return false; } - + OperatingMode getToMode() const { return toMode; } }; template @@ -323,6 +327,7 @@ class UndefinedInstruction : public ArmFaultVals bool routeToHyp(ThreadContext *tc) const override; ExceptionClass ec(ThreadContext *tc) const override; uint32_t iss() const override; + uint32_t vectorCatchFlag() const override { return 0x02000002; } }; class SupervisorCall : public ArmFaultVals @@ -343,6 +348,7 @@ class SupervisorCall : public ArmFaultVals bool routeToHyp(ThreadContext *tc) const override; ExceptionClass ec(ThreadContext *tc) const override; uint32_t iss() const override; + uint32_t vectorCatchFlag() const override { return 0x04000404; } }; class SecureMonitorCall : public ArmFaultVals @@ -358,6 +364,7 @@ class SecureMonitorCall : public ArmFaultVals StaticInst::nullStaticInstPtr) override; ExceptionClass ec(ThreadContext *tc) const override; uint32_t iss() const override; + uint32_t vectorCatchFlag() const override { return 0x00000400; } }; class SupervisorTrap : public ArmFaultVals @@ -400,6 +407,7 @@ class HypervisorCall : public ArmFaultVals HypervisorCall(ExtMachInst _machInst, uint32_t _imm); ExceptionClass ec(ThreadContext *tc) const override; + uint32_t vectorCatchFlag() const override { return 0xFFFFFFFF; } }; class HypervisorTrap : public ArmFaultVals @@ -487,6 +495,7 @@ class PrefetchAbort : public AbortFault // @todo: external aborts should be routed if SCR.EA == 1 bool routeToMonitor(ThreadContext *tc) const override; bool routeToHyp(ThreadContext *tc) const override; + uint32_t vectorCatchFlag() const override { return 0x08000808; } }; class DataAbort : public AbortFault @@ -520,6 +529,7 @@ class DataAbort : public AbortFault bool routeToHyp(ThreadContext *tc) const override; uint32_t iss() const override; void annotate(AnnotationIDs id, uint64_t val) override; + uint32_t vectorCatchFlag() const override { return 0x10001010; } }; class VirtualDataAbort : public AbortFault @@ -543,6 +553,7 @@ class Interrupt : public ArmFaultVals bool routeToMonitor(ThreadContext *tc) const override; bool routeToHyp(ThreadContext *tc) const override; bool abortDisable(ThreadContext *tc) override; + uint32_t vectorCatchFlag() const override { return 0x40004040; } }; class VirtualInterrupt : public ArmFaultVals @@ -558,6 +569,7 @@ class FastInterrupt : public ArmFaultVals bool routeToHyp(ThreadContext *tc) const override; bool abortDisable(ThreadContext *tc) override; bool fiqDisable(ThreadContext *tc) override; + uint32_t vectorCatchFlag() const override { return 0x80008080; } }; class VirtualFastInterrupt : public ArmFaultVals diff --git a/src/arch/arm/miscregs.cc b/src/arch/arm/miscregs.cc index 2dd1d78e3..cc451c6c1 100644 --- a/src/arch/arm/miscregs.cc +++ b/src/arch/arm/miscregs.cc @@ -61,6 +61,8 @@ decodeCP14Reg(unsigned crn, unsigned opc1, unsigned crm, unsigned opc2) return MISCREG_DBGDIDR; case 1: return MISCREG_DBGDSCRint; + case 7: + return MISCREG_DBGVCR; } break; case 2: @@ -563,6 +565,12 @@ decodeCP15Reg(unsigned crn, unsigned opc1, unsigned crm, unsigned opc2) return MISCREG_BPIALLIS; } break; + case 2: + switch (opc2) { + case 7: + return MISCREG_DBGDEVID0; + } + break; case 4: if (opc2 == 0) { return MISCREG_PAR; @@ -3417,8 +3425,7 @@ ISA::initializeMiscRegMetadata() .unimplemented() .allPrivileges(); InitReg(MISCREG_DBGVCR) - .unimplemented() - .allPrivileges(); + .allPrivileges().exceptUserMode(); InitReg(MISCREG_DBGDTRRXext) .unimplemented() .allPrivileges(); @@ -3625,7 +3632,6 @@ ISA::initializeMiscRegMetadata() .unimplemented() .allPrivileges().monSecureWrite(0).monNonSecureWrite(0); InitReg(MISCREG_DBGDEVID0) - .unimplemented() .allPrivileges().monSecureWrite(0).monNonSecureWrite(0); InitReg(MISCREG_TEECR) .unimplemented() @@ -4532,7 +4538,7 @@ ISA::initializeMiscRegMetadata() InitReg(MISCREG_MDDTRRX_EL0) .allPrivileges(); InitReg(MISCREG_DBGVCR32_EL2) - .allPrivileges() + .hyp().mon() .mapsTo(MISCREG_DBGVCR); InitReg(MISCREG_MDRAR_EL1) .allPrivileges().monSecureWrite(0).monNonSecureWrite(0) diff --git a/src/arch/arm/miscregs_types.hh b/src/arch/arm/miscregs_types.hh index 301d6fb2e..d3787ffae 100644 --- a/src/arch/arm/miscregs_types.hh +++ b/src/arch/arm/miscregs_types.hh @@ -735,6 +735,44 @@ namespace ArmISA Bitfield<5, 2> moe; Bitfield<1, 0> res0_1; EndBitUnion(DBGDS32) + + BitUnion32(DBGVCR) + Bitfield<31> nsf; + Bitfield<30> nsi; + Bitfield<29> res0_5; + Bitfield<28> nsd; + Bitfield<27> nsp; + Bitfield<26> nss; + Bitfield<25> nsu; + Bitfield<24, 16> res0_4; + Bitfield<15> mf; + Bitfield<14> mi; + Bitfield<13> res0_3; + Bitfield<12> md; + Bitfield<11> mp; + Bitfield<10> ms; + Bitfield<9,8> res0_2; + Bitfield<7> sf; + Bitfield<6> si; + Bitfield<5> res0_1; + Bitfield<4> sd; + Bitfield<3> sp; + Bitfield<2> ss; + Bitfield<1> su; + Bitfield<0> res0_0; + EndBitUnion(DBGVCR) + + BitUnion32(DEVID) + Bitfield<31,28> cidmask; + Bitfield<27,24> auxregs; + Bitfield<23,20> doublelock; + Bitfield<19,16> virtextns; + Bitfield<15,12> vectorcatch; + Bitfield<11,8> bpaddremask; + Bitfield<7,4> wpaddrmask; + Bitfield<3,0> pcsample; + EndBitUnion(DEVID) + } #endif // __ARCH_ARM_MISCREGS_TYPES_HH__ diff --git a/src/arch/arm/self_debug.cc b/src/arch/arm/self_debug.cc index f0f420db5..9a60aab68 100644 --- a/src/arch/arm/self_debug.cc +++ b/src/arch/arm/self_debug.cc @@ -618,3 +618,123 @@ SoftwareStep::advanceSS(ThreadContext * tc) return res; } +Fault +SelfDebug::testVectorCatch(ThreadContext *tc, Addr addr, + ArmFault* fault) +{ + + setAArch32(tc); + to32 = targetAArch32(tc); + if (!initialized) + init(tc); + if (!isDebugEnabled(tc) || !enableFlag || !aarch32) + return NoFault; + + ExceptionLevel el = (ExceptionLevel) currEL(tc); + bool debug; + if (fault == nullptr) + debug = vcExcpt->addressMatching(tc, addr, el); + else + debug = vcExcpt->exceptionTrapping(tc, el, fault); + if (debug) { + if (enableTdeTge) { + return std::make_shared(0, 0x22, + EC_PREFETCH_ABORT_TO_HYP); + } else { + return std::make_shared(addr, + ArmFault::DebugEvent, false, + ArmFault::UnknownTran, + ArmFault::VECTORCATCH); + } + } + + return NoFault; +} + +bool +VectorCatch::addressMatching(ThreadContext *tc, Addr addr, ExceptionLevel el) +{ + // Each bit position in this string corresponds to a bit in DBGVCR + // and an exception vector. + bool enabled; + if (conf->isAArch32() && ELIs32(tc, EL1) && + (addr & 0x3) == 0 && el != EL2 ) { + + DBGVCR match_word = 0x0; + + Addr vbase = getVectorBase(tc, false); + Addr vaddress = addr & ~ 0x1f; + Addr low_addr = bits(addr, 5, 2); + if (vaddress == vbase) { + if (ArmSystem::haveEL(tc, EL3) && !inSecureState(tc)) { + uint32_t bmask = 1UL << (low_addr + 24); + match_word = match_word | (DBGVCR) bmask; + // Non-secure vectors + } else { + uint32_t bmask = 1UL << (low_addr); + match_word = match_word | (DBGVCR) bmask; + // Secure vectors (or no EL3) + } + } + uint32_t mvbase = getVectorBase(tc, true); + if (ArmSystem::haveEL(tc, EL3) && ELIs32(tc, EL3) && + inSecureState(tc) && (vaddress == mvbase)) { + uint32_t bmask = 1UL << (low_addr + 8); + match_word = match_word | (DBGVCR) bmask; + // Monitor vectors + } + + DBGVCR mask; + + // Mask out bits not corresponding to vectors. + if (!ArmSystem::haveEL(tc, EL3)) { + mask = (DBGVCR) 0xDE; + } else if (!ELIs32(tc, EL3)) { + mask = (DBGVCR) 0xDE0000DE; + } else { + mask = (DBGVCR) 0xDE00DEDE; + } + DBGVCR dbgvcr = tc->readMiscReg(MISCREG_DBGVCR); + match_word = match_word & dbgvcr & mask; + enabled = match_word != 0x0; + // Check for UNPREDICTABLE case - match on Prefetch Abort and + // Data Abort vectors + ExceptionLevel ELd = debugTargetFrom(tc, inSecureState(tc)); + if (((match_word & 0x18001818) != 0x0) && ELd == el) { + enabled = false; + } + } else { + enabled = false; + } + return enabled; +} + +bool +VectorCatch::exceptionTrapping(ThreadContext *tc, ExceptionLevel el, + ArmFault* fault) +{ + if (conf->isAArch32() && ELIs32(tc, EL1) && el != EL2) { + + DBGVCR dbgvcr = tc->readMiscReg(MISCREG_DBGVCR); + DBGVCR match_type = fault->vectorCatchFlag(); + DBGVCR mask; + + if (!ArmSystem::haveEL(tc, EL3)) { + mask = (DBGVCR) 0xDE; + } else if (ELIs32(tc, EL3) && fault->getToMode() == MODE_MON) { + mask = (DBGVCR) 0x0000DE00; + } else { + if (inSecureState(tc)) + mask = (DBGVCR) 0x000000DE; + else + mask = (DBGVCR) 0xDE000000; + } + match_type = match_type & mask & dbgvcr; + + if (match_type != 0x0) { + return true; + } + } + return false; +} + diff --git a/src/arch/arm/self_debug.hh b/src/arch/arm/self_debug.hh index 48d784cd5..9739c77d7 100644 --- a/src/arch/arm/self_debug.hh +++ b/src/arch/arm/self_debug.hh @@ -257,12 +257,49 @@ class SoftwareStep } }; +class VectorCatch +{ + private: + bool vcmatch; + SelfDebug *conf; + std::vector vectorTypes(); + + public: + VectorCatch(bool _vcmatch, SelfDebug* s) : vcmatch(_vcmatch), conf(s) + {} + + bool addressMatching(ThreadContext *tc, Addr addr, ExceptionLevel el); + bool exceptionTrapping(ThreadContext *tc, ExceptionLevel el, + ArmFault* fault); + bool isVCMatch() + { + return vcmatch; + } + + private: + Addr getVectorBase(ThreadContext *tc, bool monitor) + { + if (monitor) { + return tc->readMiscReg(MISCREG_MVBAR) & ~0x1F; + } + SCTLR sctlr = tc->readMiscReg(MISCREG_SCTLR_EL1); + if (sctlr.v) { + return (Addr) 0xFFFF0000; + } else { + Addr vbar = tc->readMiscReg(MISCREG_VBAR) & ~0x1F; + return vbar; + } + } + +}; + class SelfDebug { private: std::vector arBrkPoints; std::vector arWatchPoints; SoftwareStep * softStep; + VectorCatch * vcExcpt; bool initialized; bool enableTdeTge; // MDCR_EL2.TDE || HCR_EL2.TGE @@ -287,6 +324,7 @@ class SelfDebug ~SelfDebug() { delete softStep; + delete vcExcpt; } Fault testBreakPoints(ThreadContext *tc, Addr vaddr); @@ -387,6 +425,7 @@ class SelfDebug { softStep->setCPSRD(mask); } + inline bool isAArch32() { return aarch32; @@ -410,6 +449,12 @@ class SelfDebug return softStep; } + VectorCatch* getVectorCatch(ThreadContext* tc) + { + if (!initialized) + init(tc); + return vcExcpt; + } bool targetAArch32(ThreadContext * tc) { @@ -468,6 +513,10 @@ class SelfDebug const HDCR mdcr = tc->readMiscRegNoEffect(MISCREG_MDCR_EL2); setenableTDETGE(hcr, mdcr); + // Enable Vector Catch Exceptions + const DEVID dvid = tc->readMiscReg(MISCREG_DBGDEVID0); + vcExcpt = new VectorCatch(dvid.vectorcatch==0x0, this); + } }; diff --git a/src/arch/arm/tlb.cc b/src/arch/arm/tlb.cc index 1a26ab5a1..f92f8e00d 100644 --- a/src/arch/arm/tlb.cc +++ b/src/arch/arm/tlb.cc @@ -1196,10 +1196,13 @@ TLB::translateFs(const RequestPtr &req, ThreadContext *tc, Mode mode, if (fault == NoFault) { auto *isa = static_cast(tc->getIsaPtr()); SelfDebug * sd = isa->getSelfDebug(); - if (mode == Execute) { + if (mode == Execute) + { const bool d_step = sd->getSstep()->advanceSS(tc); if (!d_step) { - fault = sd->testBreakPoints(tc, req->getVaddr()); + fault = sd->testVectorCatch(tc, req->getVaddr(), nullptr); + if (fault == NoFault) + fault = sd->testBreakPoints(tc, req->getVaddr()); } } else if (!req->isCacheMaintenance() || diff --git a/src/arch/arm/types.hh b/src/arch/arm/types.hh index 0119e4e66..fa877be06 100644 --- a/src/arch/arm/types.hh +++ b/src/arch/arm/types.hh @@ -693,6 +693,7 @@ namespace ArmISA EC_WATCHPOINT_LOWER_EL = 0x34, EC_WATCHPOINT_CURR_EL = 0x35, EC_SOFTWARE_BREAKPOINT = 0x38, + EC_VECTOR_CATCH = 0x3A, EC_SOFTWARE_BREAKPOINT_64 = 0x3C, }; -- 2.30.2