Giacomo Travaglini has submitted this change. ( https://gem5-review.googlesource.com/c/public/gem5/+/48149 )

Change subject: arch-arm: Provide support for a multilevel-TLB in the ArmMMU
......................................................................

arch-arm: Provide support for a multilevel-TLB in the ArmMMU

This is an initial implementation. It adapts the current MMU code
to account for extra levels of TLBs but it is still missing the
configurability we are looking for (to select the associativity
of the TLB and the replacement policy as an example)

JIRA: https://gem5.atlassian.net/browse/GEM5-790

Change-Id: I938ec38183337cd0e839bf3e3cd03594126128cd
Signed-off-by: Giacomo Travaglini <[email protected]>
Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/48149
Tested-by: kokoro <[email protected]>
Reviewed-by: Andreas Sandberg <[email protected]>
Maintainer: Andreas Sandberg <[email protected]>
---
M src/arch/arm/mmu.cc
M src/arch/arm/mmu.hh
M src/arch/arm/table_walker.cc
M src/arch/arm/tlb.cc
M src/arch/arm/tlb.hh
5 files changed, 148 insertions(+), 22 deletions(-)

Approvals:
  Andreas Sandberg: Looks good to me, approved; Looks good to me, approved
  kokoro: Regressions pass



diff --git a/src/arch/arm/mmu.cc b/src/arch/arm/mmu.cc
index 257b3e6..d2fc706 100644
--- a/src/arch/arm/mmu.cc
+++ b/src/arch/arm/mmu.cc
@@ -1089,8 +1089,16 @@

         itbStage2->setVMID(state.vmid);
         dtbStage2->setVMID(state.vmid);
-        getITBPtr()->setVMID(state.vmid);
-        getDTBPtr()->setVMID(state.vmid);
+
+        for (auto tlb : instruction) {
+            static_cast<TLB*>(tlb)->setVMID(state.vmid);
+        }
+        for (auto tlb : data) {
+            static_cast<TLB*>(tlb)->setVMID(state.vmid);
+        }
+        for (auto tlb : unified) {
+            static_cast<TLB*>(tlb)->setVMID(state.vmid);
+        }

         miscRegContext = tc->contextId();
     }
@@ -1309,6 +1317,16 @@
         is_secure, tran_type, stage2 ? s2State : s1State);
 }

+TlbEntry*
+MMU::lookup(Addr va, uint16_t asid, vmid_t vmid, bool hyp, bool secure,
+            bool functional, bool ignore_asn, ExceptionLevel target_el,
+            bool in_host, bool stage2, BaseMMU::Mode mode)
+{
+    TLB *tlb = getTlb(mode, stage2);
+    return tlb->multiLookup(va, asid, vmid, hyp, secure, functional,
+                            ignore_asn, target_el, in_host, mode);
+}
+
 Fault
MMU::getTE(TlbEntry **te, const RequestPtr &req, ThreadContext *tc, Mode mode,
         Translation *translation, bool timing, bool functional,
@@ -1331,9 +1349,9 @@
         vaddr = vaddr_tainted;
     }

-    auto tlb = getTlb(mode, state.isStage2);
- *te = tlb->lookup(vaddr, state.asid, state.vmid, state.isHyp, is_secure,
-                      false, false, target_el, false, mode);
+ *te = lookup(vaddr, state.asid, state.vmid, state.isHyp, is_secure, false,
+                 false, target_el, false, state.isStage2, mode);
+
     if (*te == NULL) {
         if (req->isPrefetch()) {
// if the request is a prefetch don't attempt to fill the TLB or go
@@ -1361,10 +1379,8 @@
             return fault;
         }

- *te = tlb->lookup(vaddr, state.asid, state.vmid, state.isHyp, is_secure,
-                          true, false, target_el, false, mode);
-        if (!*te)
-            tlb->printTlb();
+        *te = lookup(vaddr, state.asid, state.vmid, state.isHyp, is_secure,
+                     true, false, target_el, false, state.isStage2, mode);
         assert(*te);
     }
     return NoFault;
diff --git a/src/arch/arm/mmu.hh b/src/arch/arm/mmu.hh
index fddaa1f..0e1fd87 100644
--- a/src/arch/arm/mmu.hh
+++ b/src/arch/arm/mmu.hh
@@ -269,8 +269,15 @@
     void
     flushStage1(const OP &tlbi_op)
     {
-        iflush(tlbi_op);
-        dflush(tlbi_op);
+        for (auto tlb : instruction) {
+            static_cast<TLB*>(tlb)->flush(tlbi_op);
+        }
+        for (auto tlb : data) {
+            static_cast<TLB*>(tlb)->flush(tlbi_op);
+        }
+        for (auto tlb : unified) {
+            static_cast<TLB*>(tlb)->flush(tlbi_op);
+        }
     }

     template <typename OP>
@@ -285,14 +292,24 @@
     void
     iflush(const OP &tlbi_op)
     {
-        getITBPtr()->flush(tlbi_op);
+        for (auto tlb : instruction) {
+            static_cast<TLB*>(tlb)->flush(tlbi_op);
+        }
+        for (auto tlb : unified) {
+            static_cast<TLB*>(tlb)->flush(tlbi_op);
+        }
     }

     template <typename OP>
     void
     dflush(const OP &tlbi_op)
     {
-        getDTBPtr()->flush(tlbi_op);
+        for (auto tlb : data) {
+            static_cast<TLB*>(tlb)->flush(tlbi_op);
+        }
+        for (auto tlb : unified) {
+            static_cast<TLB*>(tlb)->flush(tlbi_op);
+        }
     }

     void
@@ -325,6 +342,24 @@
     static ExceptionLevel tranTypeEL(CPSR cpsr, ArmTranslationType type);

   public:
+    /** Lookup an entry in the TLB
+     * @param vpn virtual address
+     * @param asn context id/address space id to use
+     * @param vmid The virtual machine ID used for stage 2 translation
+     * @param secure if the lookup is secure
+     * @param hyp if the lookup is done from hyp mode
+     * @param functional if the lookup should modify state
+     * @param ignore_asn if on lookup asn should be ignored
+     * @param target_el selecting the translation regime
+     * @param in_host if we are in host (EL2&0 regime)
+     * @param mode to differentiate between read/writes/fetches.
+     * @return pointer to TLB entry if it exists
+     */
+    TlbEntry *lookup(Addr vpn, uint16_t asn, vmid_t vmid, bool hyp,
+                     bool secure, bool functional,
+                     bool ignore_asn, ExceptionLevel target_el,
+                     bool in_host, bool stage2, BaseMMU::Mode mode);
+
     Fault getTE(TlbEntry **te, const RequestPtr &req,
                 ThreadContext *tc, Mode mode,
                 Translation *translation, bool timing, bool functional,
diff --git a/src/arch/arm/table_walker.cc b/src/arch/arm/table_walker.cc
index 2d1cfa6..4cc0fff 100644
--- a/src/arch/arm/table_walker.cc
+++ b/src/arch/arm/table_walker.cc
@@ -478,9 +478,9 @@

     // Check if a previous walk filled this request already
// @TODO Should this always be the TLB or should we look in the stage2 TLB?
-    TlbEntry* te = tlb->lookup(currState->vaddr, currState->asid,
- currState->vmid, currState->isHyp, currState->isSecure, true, false,
-            currState->el, false, BaseMMU::Read);
+    TlbEntry* te = mmu->lookup(currState->vaddr, currState->asid,
+ currState->vmid, currState->isHyp, currState->isSecure, true, false,
+        currState->el, false, isStage2, currState->mode);

// Check if we still need to have a walk for this request. If the requesting // instruction has been squashed, or a previous walk has filled the TLB with
@@ -544,9 +544,9 @@
         // peak at the next one
         if (pendingQueue.size()) {
             currState = pendingQueue.front();
-            te = tlb->lookup(currState->vaddr, currState->asid,
+            te = mmu->lookup(currState->vaddr, currState->asid,
currState->vmid, currState->isHyp, currState->isSecure, true,
-                false, currState->el, false, BaseMMU::Read);
+                false, currState->el, false, isStage2, currState->mode);
         } else {
             // Terminate the loop, nothing more to do
             currState = NULL;
@@ -2354,8 +2354,8 @@
descriptor.lookupLevel, static_cast<uint8_t>(descriptor.domain()),
             descriptor.getRawData());

-    // Insert the entry into the TLB
-    tlb->insert(te);
+    // Insert the entry into the TLBs
+    tlb->multiInsert(te);
     if (!currState->timing) {
         currState->tc  = NULL;
         currState->req = NULL;
diff --git a/src/arch/arm/tlb.cc b/src/arch/arm/tlb.cc
index 666836b..9143723 100644
--- a/src/arch/arm/tlb.cc
+++ b/src/arch/arm/tlb.cc
@@ -141,6 +141,41 @@
     return retval;
 }

+TlbEntry*
+TLB::multiLookup(Addr va, uint16_t asid, vmid_t vmid, bool hyp, bool secure, + bool functional, bool ignore_asn, ExceptionLevel target_el,
+                 bool in_host, BaseMMU::Mode mode)
+{
+    TlbEntry* te = lookup(va, asid, vmid, hyp, secure, functional,
+                          ignore_asn, target_el, in_host, mode);
+
+    if (te) {
+        checkPromotion(te, mode);
+    } else {
+        if (auto tlb = static_cast<TLB*>(nextLevel())) {
+            te = tlb->multiLookup(va, asid, vmid, hyp, secure, functional,
+                                  ignore_asn, target_el, in_host, mode);
+            if (te && !functional)
+                insert(*te);
+        }
+    }
+
+    return te;
+}
+
+void
+TLB::checkPromotion(TlbEntry *entry, BaseMMU::Mode mode)
+{
+    TypeTLB acc_type = (mode == BaseMMU::Execute) ?
+       TypeTLB::instruction : TypeTLB::data;
+
+    // Hitting an instruction TLB entry on a data access or
+    // a data TLB entry on an instruction access:
+    // promoting the entry to unified
+    if (!(entry->type & acc_type))
+       entry->type = TypeTLB::unified;
+}
+
 // insert a new TLB entry
 void
 TLB::insert(TlbEntry &entry)
@@ -162,8 +197,7 @@
table[size-1].nstid, table[size-1].global, table[size-1].isHyp,
                 table[size-1].el);

-    //inserting to MRU position and evicting the LRU one
-
+    // inserting to MRU position and evicting the LRU one
     for (int i = size - 1; i > 0; --i)
         table[i] = table[i-1];
     table[0] = entry;
@@ -173,6 +207,16 @@
 }

 void
+TLB::multiInsert(TlbEntry &entry)
+{
+    insert(entry);
+
+    if (auto next_level = static_cast<TLB*>(nextLevel())) {
+        next_level->multiInsert(entry);
+    }
+}
+
+void
 TLB::printTlb() const
 {
     int x = 0;
diff --git a/src/arch/arm/tlb.hh b/src/arch/arm/tlb.hh
index fa5e894..4b3c829 100644
--- a/src/arch/arm/tlb.hh
+++ b/src/arch/arm/tlb.hh
@@ -175,6 +175,26 @@
                      bool ignore_asn, ExceptionLevel target_el,
                      bool in_host, BaseMMU::Mode mode);

+    /** Lookup an entry in the TLB and in the next levels by
+     * following the nextLevel pointer
+     *
+     * @param vpn virtual address
+     * @param asn context id/address space id to use
+     * @param vmid The virtual machine ID used for stage 2 translation
+     * @param secure if the lookup is secure
+     * @param hyp if the lookup is done from hyp mode
+     * @param functional if the lookup should modify state
+     * @param ignore_asn if on lookup asn should be ignored
+     * @param target_el selecting the translation regime
+     * @param in_host if we are in host (EL2&0 regime)
+     * @param mode to differentiate between read/writes/fetches.
+     * @return pointer to TLB entry if it exists
+     */
+    TlbEntry *multiLookup(Addr vpn, uint16_t asn, vmid_t vmid, bool hyp,
+                          bool secure, bool functional,
+                          bool ignore_asn, ExceptionLevel target_el,
+                          bool in_host, BaseMMU::Mode mode);
+
     virtual ~TLB();

     void takeOverFrom(BaseTLB *otlb) override;
@@ -187,8 +207,12 @@

     void setVMID(vmid_t _vmid) { vmid = _vmid; }

+    /** Insert a PTE in the current TLB */
     void insert(TlbEntry &pte);

+    /** Insert a PTE in the current TLB and in the higher levels */
+    void multiInsert(TlbEntry &pte);
+
     /** Reset the entire TLB. Used for CPU switching to prevent stale
      * translations after multiple switches
      */
@@ -301,6 +325,13 @@
     void _flushMva(Addr mva, uint64_t asn, bool secure_lookup,
                    bool ignore_asn, ExceptionLevel target_el,
                    bool in_host, TypeTLB entry_type);
+
+    /** Check if the tlb entry passed as an argument needs to
+     * be "promoted" as a unified entry:
+     * this should happen if we are hitting an instruction TLB entry on a
+     * data access or a data TLB entry on an instruction access:
+     */
+    void checkPromotion(TlbEntry *entry, BaseMMU::Mode mode);
 };

 } // namespace ArmISA



9 is the latest approved patch-set.
No files were changed between the latest approved patch-set and the submitted one.
--
To view, visit https://gem5-review.googlesource.com/c/public/gem5/+/48149
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: I938ec38183337cd0e839bf3e3cd03594126128cd
Gerrit-Change-Number: 48149
Gerrit-PatchSet: 13
Gerrit-Owner: Giacomo Travaglini <[email protected]>
Gerrit-Reviewer: Andreas Sandberg <[email protected]>
Gerrit-Reviewer: Giacomo Travaglini <[email protected]>
Gerrit-Reviewer: kokoro <[email protected]>
Gerrit-MessageType: merged
_______________________________________________
gem5-dev mailing list -- [email protected]
To unsubscribe send an email to [email protected]
%(web_page_url)slistinfo%(cgiext)s/%(_internal_name)s

Reply via email to