Jordi Vaquero has uploaded this change for review. ( 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
---
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, 321 insertions(+), 7 deletions(-)



diff --git a/src/arch/arm/faults.cc b/src/arch/arm/faults.cc
index fde28d6..422e801 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"
@@ -481,6 +483,16 @@
 ArmFault::invoke(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 flt = sd->testVectorCatch(tc, 0x0, this);
+        if (flt != NoFault)
+            flt->invoke(tc, inst);
+        return;
+    }
+
     // 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
@@ -1094,7 +1106,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 703d6bb..a7bda4f 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
     };
@@ -246,7 +247,7 @@
     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>
diff --git a/src/arch/arm/miscregs.cc b/src/arch/arm/miscregs.cc
index aae12d5..d5eb757 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:
@@ -564,6 +566,12 @@
                     return MISCREG_BPIALLIS;
                 }
                 break;
+              case 2:
+                switch (opc2){
+                  case 7:
+                    return MISCREG_DBGDEVID0;
+                }
+                break;
               case 4:
                 if (opc2 == 0) {
                     return MISCREG_PAR;
@@ -3418,8 +3426,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()
+      .allPrivileges().exceptUserMode()
       .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 53cbb8e..5bc4ad4 100644
--- a/src/arch/arm/self_debug.cc
+++ b/src/arch/arm/self_debug.cc
@@ -620,3 +620,196 @@
     return res;
 }

+Fault
+SelfDebug::testVectorCatch(ThreadContext *tc, Addr addr,
+                           ArmFault* flt)
+{
+
+    setAArch32(tc);
+    to32 = targetAArch32(tc);
+    if (!initialized)
+        init(tc);
+    if (!isDebugEnabled(tc) || !enableFlag || !aarch32)
+        return NoFault;
+
+    ExceptionLevel el = (ExceptionLevel) currEL(tc);
+    bool debug;
+    if (flt == nullptr)
+        debug = vcExcpt->VCRtest(tc, addr, el);
+    else
+        debug = vcExcpt->trapTest(tc, el, flt);
+    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);
+        }
+        //cctypd = AccType_IFETCH;
+        //iswrite = FALSE;
+        //debugmoe = DebugException_VectorCatch;
+        //return trigger Exception Vector Catch
+    }
+
+    return NoFault;
+}
+
+bool
+VectorCatch::VCRtest(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;
+
+        uint32_t vbase = getVectorBase(tc, false);
+        Addr vaddress = addr & ~ 0x1f;
+        uint32_t low_addr = bits(addr, 5, 2);
+        if (vaddress == vbase)
+        {
+            if (ArmSystem::haveEL(tc, EL3) && !inSecureState(tc)){
+                uint32_t bmask = pow(2, low_addr +24);
+                match_word = match_word | (DBGVCR) bmask;
+                // Non-secure vectors
+            }
+            else
+            {
+                uint32_t bmask = pow(2, 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 = pow(2, 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;
+}
+
+
+uint32_t
+VectorCatch::faultTypeToFlag(ArmFault* flt)
+{
+    {
+        FastInterrupt* f = dynamic_cast<FastInterrupt*>(flt);
+        if (f != nullptr)
+        {
+            return 0x80008080;
+        }
+    }
+    {
+        Interrupt* f = dynamic_cast<Interrupt*>(flt);
+        if (f != nullptr)
+        {
+            return 0x40004040;
+        }
+    }
+    {
+        DataAbort* f = dynamic_cast<DataAbort*>(flt);
+        if (f != nullptr)
+        {
+            return 0x10001010;
+        }
+    }
+    {
+        PrefetchAbort* f = dynamic_cast<PrefetchAbort*>(flt);
+        if (f != nullptr)
+        {
+            return 0x08000808;
+        }
+    }
+    {
+        SupervisorCall* f = dynamic_cast<SupervisorCall*>(flt);
+        if (f != nullptr)
+        {
+            return 0x04000404;
+        }
+    }
+    {
+        UndefinedInstruction* f = dynamic_cast<UndefinedInstruction*>(flt);
+        if (f != nullptr)
+        {
+            return 0x02000002;
+        }
+    }
+    {
+        HypervisorTrap* f = dynamic_cast<HypervisorTrap*>(flt);
+        if (f != nullptr)
+        {
+ // HYP does not have flag, so is always accepted if EL enables it.
+            return 0xFFFFFFFF;
+        }
+    }
+    {
+        SecureMonitorCall* f = dynamic_cast<SecureMonitorCall*>(flt);
+        if (f != nullptr)
+        {
+            return 0x00000400;
+        }
+    }
+    return 0x0;
+}
+
+bool
+VectorCatch::trapTest(ThreadContext *tc, ExceptionLevel el, ArmFault * flt)
+{
+    if (conf->isAArch32() && ELIs32(tc, EL1)
+        && el != EL2){
+        DBGVCR dbgvcr = tc->readMiscReg(MISCREG_DBGVCR);
+
+        DBGVCR match_type = faultTypeToFlag(flt);
+
+        DBGVCR mask;
+        if (!ArmSystem::haveEL(tc, EL3)){
+            mask = (DBGVCR) 0xDE;
+        }else if (ELIs32(tc, EL3) && flt->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 1404d27..8f7e0bc 100644
--- a/src/arch/arm/self_debug.hh
+++ b/src/arch/arm/self_debug.hh
@@ -263,12 +263,60 @@
     }
 };

+class VectorCatch
+{
+  private:
+    bool vcmatch;
+    SelfDebug * conf;
+    std::vector<Fault *> vectorTypes();
+
+
+  public:
+    VectorCatch(bool _vcmatch, SelfDebug* s) : vcmatch(_vcmatch), conf(s)
+    {
+
+
+    }
+
+    ~VectorCatch()
+    {}
+
+    bool VCRtest(ThreadContext *tc, Addr addr, ExceptionLevel el);
+    bool trapTest(ThreadContext *tc, ExceptionLevel el, ArmFault * flt);
+    bool isVCMatch()
+    {
+        return vcmatch;
+    }
+
+
+  private:
+    uint32_t faultTypeToFlag(ArmFault* flt);
+    uint32_t getVectorBase(ThreadContext *tc, bool monitor)
+    {
+        if (monitor){
+
+            return tc->readMiscReg(MISCREG_MVBAR) & ~0x1F;
+        }
+        SCTLR sctlr = tc->readMiscReg(MISCREG_SCTLR_EL1);
+        if (sctlr.v){
+            return 0xFFFF0000;
+        }
+        else
+        {
+            uint32_t 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
@@ -292,6 +340,7 @@

     ~SelfDebug(){
         delete softStep;
+        delete vcExcpt;
     }

     Fault testBreakPoints(ThreadContext *tc, Addr vaddr);
@@ -392,6 +441,7 @@
     {
         softStep->setCPSR_D(mask);
     }
+
     inline bool isAArch32()
     {
         return aarch32;
@@ -414,6 +464,11 @@
         return softStep;
     }

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

     bool targetAArch32(ThreadContext * tc)
     {
@@ -472,6 +527,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 4fa9590..fdfc6b7 100644
--- a/src/arch/arm/tlb.cc
+++ b/src/arch/arm/tlb.cc
@@ -1201,7 +1201,9 @@
         {
             const bool d_step = sd->get_Sstep()->advanceSS(tc, true);
             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 6e502bb..d3fd912 100644
--- a/src/arch/arm/types.hh
+++ b/src/arch/arm/types.hh
@@ -712,6 +712,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: 1
Gerrit-Owner: Jordi Vaquero <jordi.vaqu...@metempsy.com>
Gerrit-MessageType: newchange
_______________________________________________
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