Jordi Vaquero has submitted this change. ( https://gem5-review.googlesource.com/c/public/gem5/+/30618 )

Change subject: arch-arm: Implementation of Vector Catch debug exception
......................................................................

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 <giacomo.travagl...@arm.com>
Maintainer: Giacomo Travaglini <giacomo.travagl...@arm.com>
Tested-by: kokoro <noreply+kok...@google.com>
---
M src/arch/arm/faults.cc
M src/arch/arm/faults.hh
M src/arch/arm/miscregs.cc
M src/arch/arm/miscregs_types.hh
M src/arch/arm/self_debug.cc
M src/arch/arm/self_debug.hh
M src/arch/arm/tlb.cc
M src/arch/arm/types.hh
8 files changed, 259 insertions(+), 9 deletions(-)

Approvals:
  Giacomo Travaglini: Looks good to me, approved; Looks good to me, approved
  kokoro: Regressions pass



diff --git a/src/arch/arm/faults.cc b/src/arch/arm/faults.cc
index 6a3ee18..ecc9e4d 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 @@
 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 @@
         return;
     }

+    if (vectorCatch(tc, inst))
+        return;
+
     // ARMv7 (ARM ARM issue C B1.9)

     bool have_security       = ArmSystem::haveSecurity(tc);
@@ -716,6 +720,21 @@
         setSyndrome(tc, getSyndromeReg64());
 }

+bool
+ArmFault::vectorCatch(ThreadContext *tc, const StaticInstPtr &inst)
+{
+    auto *isa = static_cast<ArmISA::ISA *>(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 @@
             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 8a127ff..a552757 100644
--- a/src/arch/arm/faults.hh
+++ b/src/arch/arm/faults.hh
@@ -154,6 +154,7 @@
     {
         NODEBUG = 0,
         BRKPOINT,
+        VECTORCATCH,
         WPOINT_CM,
         WPOINT_NOCM
     };
@@ -226,6 +227,8 @@
     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 @@
     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<typename T>
@@ -323,6 +327,7 @@
     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<SupervisorCall>
@@ -343,6 +348,7 @@
     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<SecureMonitorCall>
@@ -358,6 +364,7 @@
                 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<SupervisorTrap>
@@ -400,6 +407,7 @@
     HypervisorCall(ExtMachInst _machInst, uint32_t _imm);

     ExceptionClass ec(ThreadContext *tc) const override;
+    uint32_t vectorCatchFlag() const override { return 0xFFFFFFFF; }
 };

 class HypervisorTrap : public ArmFaultVals<HypervisorTrap>
@@ -487,6 +495,7 @@
     // @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<DataAbort>
@@ -520,6 +529,7 @@
     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<VirtualDataAbort>
@@ -543,6 +553,7 @@
     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<VirtualInterrupt>
@@ -558,6 +569,7 @@
     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<VirtualFastInterrupt>
diff --git a/src/arch/arm/miscregs.cc b/src/arch/arm/miscregs.cc
index 2dd1d78..cc451c6 100644
--- a/src/arch/arm/miscregs.cc
+++ b/src/arch/arm/miscregs.cc
@@ -61,6 +61,8 @@
                     return MISCREG_DBGDIDR;
                   case 1:
                     return MISCREG_DBGDSCRint;
+                  case 7:
+                    return MISCREG_DBGVCR;
                 }
                 break;
               case 2:
@@ -563,6 +565,12 @@
                     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 @@
       .unimplemented()
       .allPrivileges();
     InitReg(MISCREG_DBGVCR)
-      .unimplemented()
-      .allPrivileges();
+      .allPrivileges().exceptUserMode();
     InitReg(MISCREG_DBGDTRRXext)
       .unimplemented()
       .allPrivileges();
@@ -3625,7 +3632,6 @@
       .unimplemented()
       .allPrivileges().monSecureWrite(0).monNonSecureWrite(0);
     InitReg(MISCREG_DBGDEVID0)
-      .unimplemented()
       .allPrivileges().monSecureWrite(0).monNonSecureWrite(0);
     InitReg(MISCREG_TEECR)
       .unimplemented()
@@ -4532,7 +4538,7 @@
     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 301d6fb..d3787ff 100644
--- a/src/arch/arm/miscregs_types.hh
+++ b/src/arch/arm/miscregs_types.hh
@@ -735,6 +735,44 @@
         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 f0f420d..9a60aab 100644
--- a/src/arch/arm/self_debug.cc
+++ b/src/arch/arm/self_debug.cc
@@ -618,3 +618,123 @@
     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<HypervisorTrap>(0, 0x22,
+                                        EC_PREFETCH_ABORT_TO_HYP);
+        } else {
+            return std::make_shared<PrefetchAbort>(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 48d784c..9739c77 100644
--- a/src/arch/arm/self_debug.hh
+++ b/src/arch/arm/self_debug.hh
@@ -257,12 +257,49 @@
     }
 };

+class VectorCatch
+{
+  private:
+    bool vcmatch;
+    SelfDebug *conf;
+    std::vector<Fault *> 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<BrkPoint> arBrkPoints;
     std::vector<WatchPoint> arWatchPoints;
     SoftwareStep * softStep;
+    VectorCatch * vcExcpt;

     bool initialized;
     bool enableTdeTge; // MDCR_EL2.TDE || HCR_EL2.TGE
@@ -287,6 +324,7 @@
     ~SelfDebug()
     {
         delete softStep;
+        delete vcExcpt;
     }

     Fault testBreakPoints(ThreadContext *tc, Addr vaddr);
@@ -387,6 +425,7 @@
     {
         softStep->setCPSRD(mask);
     }
+
     inline bool isAArch32()
     {
         return aarch32;
@@ -410,6 +449,12 @@
         return softStep;
     }

+    VectorCatch* getVectorCatch(ThreadContext* tc)
+    {
+        if (!initialized)
+            init(tc);
+        return vcExcpt;
+    }

     bool targetAArch32(ThreadContext * tc)
     {
@@ -468,6 +513,10 @@
         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 1a26ab5..f92f8e0 100644
--- a/src/arch/arm/tlb.cc
+++ b/src/arch/arm/tlb.cc
@@ -1196,10 +1196,13 @@
     if (fault == NoFault) {
         auto *isa = static_cast<ArmISA::ISA *>(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 0119e4e..fa877be 100644
--- a/src/arch/arm/types.hh
+++ b/src/arch/arm/types.hh
@@ -693,6 +693,7 @@
         EC_WATCHPOINT_LOWER_EL     = 0x34,
         EC_WATCHPOINT_CURR_EL      = 0x35,
         EC_SOFTWARE_BREAKPOINT     = 0x38,
+        EC_VECTOR_CATCH            = 0x3A,
         EC_SOFTWARE_BREAKPOINT_64  = 0x3C,
     };


--
To view, visit https://gem5-review.googlesource.com/c/public/gem5/+/30618
To unsubscribe, or for help writing mail filters, visit https://gem5-review.googlesource.com/settings

Gerrit-Project: public/gem5
Gerrit-Branch: develop
Gerrit-Change-Id: Idbef26b16eff059e94ff16fac13bf5708dfe647f
Gerrit-Change-Number: 30618
Gerrit-PatchSet: 8
Gerrit-Owner: Jordi Vaquero <jordi.vaqu...@metempsy.com>
Gerrit-Reviewer: Giacomo Travaglini <giacomo.travagl...@arm.com>
Gerrit-Reviewer: Jordi Vaquero <jordi.vaqu...@metempsy.com>
Gerrit-Reviewer: kokoro <noreply+kok...@google.com>
Gerrit-MessageType: merged
_______________________________________________
gem5-dev mailing list -- gem5-dev@gem5.org
To unsubscribe send an email to gem5-dev-le...@gem5.org
%(web_page_url)slistinfo%(cgiext)s/%(_internal_name)s

Reply via email to