arm: Refactor the TLB test interface
authorAndreas Sandberg <andreas.sandberg@arm.com>
Mon, 21 Mar 2016 15:54:58 +0000 (15:54 +0000)
committerAndreas Sandberg <andreas.sandberg@arm.com>
Mon, 21 Mar 2016 15:54:58 +0000 (15:54 +0000)
Refactor the TLB and page table walker test interface to use a dynamic
registration mechanism. Instead of patching a couple of empty methods
to wire up a TLB tester, this change allows such testers to register
themselves using the setTestInterface() method.

src/arch/arm/table_walker.cc
src/arch/arm/table_walker.hh
src/arch/arm/tlb.cc
src/arch/arm/tlb.hh

index fd8645e9761771b9270f8d21577229d03fc46ec4..e1e00442d6949f4d4e0a8d7967ee3b8c9085693e 100644 (file)
@@ -502,9 +502,8 @@ TableWalker::processWalk()
 
     // Trickbox address check
     Fault f;
-    f = tlb->walkTrickBoxCheck(l1desc_addr, currState->isSecure,
-            currState->vaddr, sizeof(uint32_t), currState->isFetch,
-            currState->isWrite, TlbEntry::DomainType::NoAccess, L1);
+    f = testWalk(l1desc_addr, sizeof(uint32_t),
+                 TlbEntry::DomainType::NoAccess, L1);
     if (f) {
         DPRINTF(TLB, "Trickbox check caused fault on %#x\n", currState->vaddr_tainted);
         if (currState->timing) {
@@ -668,10 +667,8 @@ TableWalker::processWalkLPAE()
     }
 
     // Trickbox address check
-    Fault f = tlb->walkTrickBoxCheck(desc_addr, currState->isSecure,
-                        currState->vaddr, sizeof(uint64_t), currState->isFetch,
-                        currState->isWrite, TlbEntry::DomainType::NoAccess,
-                        start_lookup_level);
+    Fault f = testWalk(desc_addr, sizeof(uint64_t),
+                       TlbEntry::DomainType::NoAccess, start_lookup_level);
     if (f) {
         DPRINTF(TLB, "Trickbox check caused fault on %#x\n", currState->vaddr_tainted);
         if (currState->timing) {
@@ -913,10 +910,8 @@ TableWalker::processWalkAArch64()
               stride * (3 - start_lookup_level) + tg) << 3);
 
     // Trickbox address check
-    Fault f = tlb->walkTrickBoxCheck(desc_addr, currState->isSecure,
-                        currState->vaddr, sizeof(uint64_t), currState->isFetch,
-                        currState->isWrite, TlbEntry::DomainType::NoAccess,
-                        start_lookup_level);
+    Fault f = testWalk(desc_addr, sizeof(uint64_t),
+                       TlbEntry::DomainType::NoAccess, start_lookup_level);
     if (f) {
         DPRINTF(TLB, "Trickbox check caused fault on %#x\n", currState->vaddr_tainted);
         if (currState->timing) {
@@ -1437,10 +1432,8 @@ TableWalker::doL1Descriptor()
                     l2desc_addr, currState->isSecure ? "s" : "ns");
 
             // Trickbox address check
-            currState->fault = tlb->walkTrickBoxCheck(
-                l2desc_addr, currState->isSecure, currState->vaddr,
-                sizeof(uint32_t), currState->isFetch, currState->isWrite,
-                currState->l1Desc.domain(), L2);
+            currState->fault = testWalk(l2desc_addr, sizeof(uint32_t),
+                                        currState->l1Desc.domain(), L2);
 
             if (currState->fault) {
                 if (!currState->timing) {
@@ -1616,12 +1609,9 @@ TableWalker::doLongDescriptor()
             }
 
             // Trickbox address check
-            currState->fault = tlb->walkTrickBoxCheck(
-                            next_desc_addr, currState->vaddr,
-                            currState->vaddr, sizeof(uint64_t),
-                            currState->isFetch, currState->isWrite,
-                            TlbEntry::DomainType::Client,
-                            toLookupLevel(currState->longDesc.lookupLevel +1));
+            currState->fault = testWalk(
+                next_desc_addr, sizeof(uint64_t), TlbEntry::DomainType::Client,
+                toLookupLevel(currState->longDesc.lookupLevel +1));
 
             if (currState->fault) {
                 if (!currState->timing) {
@@ -2096,6 +2086,15 @@ TableWalker::pendingChange()
     }
 }
 
+Fault
+TableWalker::testWalk(Addr pa, Addr size, TlbEntry::DomainType domain,
+                      LookupLevel lookup_level)
+{
+    return tlb->testWalk(pa, size, currState->vaddr, currState->isSecure,
+                         currState->mode, domain, lookup_level);
+}
+
+
 uint8_t
 TableWalker::pageSizeNtoStatBin(uint8_t N)
 {
index b960c320ba58574a18b4aeecfff2b78bfc3bb3ae..743b8aa937ead69c1cc2848b37f9adb31ed447c6 100644 (file)
@@ -966,6 +966,9 @@ class TableWalker : public MemObject
     void pendingChange();
 
     static uint8_t pageSizeNtoStatBin(uint8_t N);
+
+    Fault testWalk(Addr pa, Addr size, TlbEntry::DomainType domain,
+                   LookupLevel lookup_level);
 };
 
 } // namespace ArmISA
index bdcb91facc8b5847a8cca889307a1321d5fbd276..1bce0f7989a046c1398f03f74d4cf2b02895ac54 100644 (file)
@@ -75,7 +75,7 @@ TLB::TLB(const ArmTLBParams *p)
     : BaseTLB(p), table(new TlbEntry[p->size]), size(p->size),
       isStage2(p->is_stage2), stage2Req(false), _attr(0),
       directToStage2(false), tableWalker(p->walker), stage2Tlb(NULL),
-      stage2Mmu(NULL), rangeMRU(1),
+      stage2Mmu(NULL), test(nullptr), rangeMRU(1),
       aarch64(false), aarch64EL(EL0), isPriv(false), isSecure(false),
       isHyp(false), asid(0), vmid(0), dacr(0),
       miscRegValid(false), miscRegContext(0), curTranType(NormalTran)
@@ -576,19 +576,6 @@ TLB::translateSe(RequestPtr req, ThreadContext *tc, Mode mode,
     return NoFault;
 }
 
-Fault
-TLB::trickBoxCheck(RequestPtr req, Mode mode, TlbEntry::DomainType domain)
-{
-    return NoFault;
-}
-
-Fault
-TLB::walkTrickBoxCheck(Addr pa, bool is_secure, Addr va, Addr sz, bool is_exec,
-        bool is_write, TlbEntry::DomainType domain, LookupLevel lookup_level)
-{
-    return NoFault;
-}
-
 Fault
 TLB::checkPermissions(TlbEntry *te, RequestPtr req, Mode mode)
 {
@@ -1038,7 +1025,7 @@ TLB::translateFs(RequestPtr req, ThreadContext *tc, Mode mode,
                 isStage2);
         setAttr(temp_te.attributes);
 
-        return trickBoxCheck(req, mode, TlbEntry::DomainType::NoAccess);
+        return testTranslation(req, mode, TlbEntry::DomainType::NoAccess);
     }
 
     DPRINTF(TLBVerbose, "Translating %s=%#x context=%d\n",
@@ -1091,9 +1078,8 @@ TLB::translateFs(RequestPtr req, ThreadContext *tc, Mode mode,
         }
 
         // Check for a trickbox generated address fault
-        if (fault == NoFault) {
-            fault = trickBoxCheck(req, mode, te->domain);
-        }
+        if (fault == NoFault)
+            fault = testTranslation(req, mode, te->domain);
     }
 
     // Generate Illegal Inst Set State fault if IL bit is set in CPSR
@@ -1419,6 +1405,41 @@ TLB::getResultTe(TlbEntry **te, RequestPtr req, ThreadContext *tc, Mode mode,
     return fault;
 }
 
+void
+TLB::setTestInterface(SimObject *_ti)
+{
+    if (!_ti) {
+        test = nullptr;
+    } else {
+        TlbTestInterface *ti(dynamic_cast<TlbTestInterface *>(_ti));
+        fatal_if(!ti, "%s is not a valid ARM TLB tester\n", _ti->name());
+        test = ti;
+    }
+}
+
+Fault
+TLB::testTranslation(RequestPtr req, Mode mode, TlbEntry::DomainType domain)
+{
+    if (!test) {
+        return NoFault;
+    } else {
+        return test->translationCheck(req, isPriv, mode, domain);
+    }
+}
+
+Fault
+TLB::testWalk(Addr pa, Addr size, Addr va, bool is_secure, Mode mode,
+              TlbEntry::DomainType domain, LookupLevel lookup_level)
+{
+    if (!test) {
+        return NoFault;
+    } else {
+        return test->walkCheck(pa, size, va, is_secure, isPriv, mode,
+                               domain, lookup_level);
+    }
+}
+
+
 ArmISA::TLB *
 ArmTLBParams::create()
 {
index 1f9ec01ec54f6e81819a61a5f772331a8d403020..298c603b9856fabd1c086196fb1b59c6e55175c0 100644 (file)
@@ -61,6 +61,43 @@ namespace ArmISA {
 class TableWalker;
 class Stage2LookUp;
 class Stage2MMU;
+class TLB;
+
+class TlbTestInterface
+{
+  public:
+    TlbTestInterface() {}
+    virtual ~TlbTestInterface() {}
+
+    /**
+     * Check if a TLB translation should be forced to fail.
+     *
+     * @param req Request requiring a translation.
+     * @param is_priv Access from a privileged mode (i.e., not EL0)
+     * @param mode Access type
+     * @param domain Domain type
+     */
+    virtual Fault translationCheck(RequestPtr req, bool is_priv,
+                                   BaseTLB::Mode mode,
+                                   TlbEntry::DomainType domain) = 0;
+
+    /**
+     * Check if a page table walker access should be forced to fail.
+     *
+     * @param pa Physical address the walker is accessing
+     * @param size Walker access size
+     * @param va Virtual address that initiated the walk
+     * @param is_secure Access from secure state
+     * @param is_priv Access from a privileged mode (i.e., not EL0)
+     * @param mode Access type
+     * @param domain Domain type
+     * @param lookup_level Page table walker level
+     */
+    virtual Fault walkCheck(Addr pa, Addr size, Addr va, bool is_secure,
+                            Addr is_priv, BaseTLB::Mode mode,
+                            TlbEntry::DomainType domain,
+                            LookupLevel lookup_level) = 0;
+};
 
 class TLB : public BaseTLB
 {
@@ -105,6 +142,8 @@ class TLB : public BaseTLB
     TLB *stage2Tlb;
     Stage2MMU *stage2Mmu;
 
+    TlbTestInterface *test;
+
     // Access Stats
     mutable Stats::Scalar instHits;
     mutable Stats::Scalar instMisses;
@@ -160,6 +199,8 @@ class TLB : public BaseTLB
     /// setup all the back pointers
     void init() override;
 
+    void setTestInterface(SimObject *ti);
+
     TableWalker *getTableWalker() { return tableWalker; }
 
     void setMMU(Stage2MMU *m, MasterID master_id);
@@ -224,10 +265,6 @@ class TLB : public BaseTLB
      */
     void flushMva(Addr mva, bool secure_lookup, bool hyp, uint8_t target_el);
 
-    Fault trickBoxCheck(RequestPtr req, Mode mode, TlbEntry::DomainType domain);
-    Fault walkTrickBoxCheck(Addr pa, bool is_secure, Addr va, Addr sz, bool is_exec,
-            bool is_write, TlbEntry::DomainType domain, LookupLevel lookup_level);
-
     void printTlb() const;
 
     void demapPage(Addr vaddr, uint64_t asn) override
@@ -356,6 +393,13 @@ private:
                    bool hyp, bool ignore_asn, uint8_t target_el);
 
     bool checkELMatch(uint8_t target_el, uint8_t tentry_el, bool ignore_el);
+
+  public: /* Testing */
+    Fault testTranslation(RequestPtr req, Mode mode,
+                          TlbEntry::DomainType domain);
+    Fault testWalk(Addr pa, Addr size, Addr va, bool is_secure, Mode mode,
+                   TlbEntry::DomainType domain,
+                   LookupLevel lookup_level);
 };
 
 } // namespace ArmISA