arch-arm: Split translateFs to distinguish when MMU is on/off

This patch is splitting the big translateFs method so that it is
using different methods when the MMU is on/off

Change-Id: I198851bdbedf8a8e69730693ff87ffb9ed535ea3
Signed-off-by: Giacomo Travaglini <giacomo.travaglini@arm.com>
Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/24985
Reviewed-by: Nikos Nikoleris <nikos.nikoleris@arm.com>
Tested-by: kokoro <noreply+kokoro@google.com>
diff --git a/src/arch/arm/tlb.cc b/src/arch/arm/tlb.cc
index af0f862..ff5bc6f 100644
--- a/src/arch/arm/tlb.cc
+++ b/src/arch/arm/tlb.cc
@@ -999,6 +999,126 @@
 }
 
 Fault
+TLB::translateMmuOff(ThreadContext *tc, const RequestPtr &req, Mode mode,
+        TLB::ArmTranslationType tranType, Addr vaddr, bool long_desc_format)
+{
+    bool is_fetch  = (mode == Execute);
+    req->setPaddr(vaddr);
+    // When the MMU is off the security attribute corresponds to the
+    // security state of the processor
+    if (isSecure)
+        req->setFlags(Request::SECURE);
+
+    // @todo: double check this (ARM ARM issue C B3.2.1)
+    if (long_desc_format || sctlr.tre == 0 || nmrr.ir0 == 0 ||
+        nmrr.or0 == 0 || prrr.tr0 != 0x2) {
+        if (!req->isCacheMaintenance()) {
+            req->setFlags(Request::UNCACHEABLE);
+        }
+        req->setFlags(Request::STRICT_ORDER);
+    }
+
+    // Set memory attributes
+    TlbEntry temp_te;
+    temp_te.ns = !isSecure;
+    if (isStage2 || hcr.dc == 0 || isSecure ||
+       (isHyp && !(tranType & S1CTran))) {
+
+        temp_te.mtype      = is_fetch ? TlbEntry::MemoryType::Normal
+                                      : TlbEntry::MemoryType::StronglyOrdered;
+        temp_te.innerAttrs = 0x0;
+        temp_te.outerAttrs = 0x0;
+        temp_te.shareable  = true;
+        temp_te.outerShareable = true;
+    } else {
+        temp_te.mtype      = TlbEntry::MemoryType::Normal;
+        temp_te.innerAttrs = 0x3;
+        temp_te.outerAttrs = 0x3;
+        temp_te.shareable  = false;
+        temp_te.outerShareable = false;
+    }
+    temp_te.setAttributes(long_desc_format);
+    DPRINTF(TLBVerbose, "(No MMU) setting memory attributes: shareable: "
+            "%d, innerAttrs: %d, outerAttrs: %d, isStage2: %d\n",
+            temp_te.shareable, temp_te.innerAttrs, temp_te.outerAttrs,
+            isStage2);
+    setAttr(temp_te.attributes);
+
+    return testTranslation(req, mode, TlbEntry::DomainType::NoAccess);
+}
+
+Fault
+TLB::translateMmuOn(ThreadContext* tc, const RequestPtr &req, Mode mode,
+                    Translation *translation, bool &delay, bool timing,
+                    bool functional, Addr vaddr,
+                    ArmFault::TranMethod tranMethod)
+{
+    TlbEntry *te = NULL;
+    bool is_fetch  = (mode == Execute);
+    TlbEntry mergeTe;
+
+    Request::Flags flags = req->getFlags();
+    Addr vaddr_tainted = req->getVaddr();
+
+    Fault fault = getResultTe(&te, req, tc, mode, translation, timing,
+                              functional, &mergeTe);
+    // only proceed if we have a valid table entry
+    if ((te == NULL) && (fault == NoFault)) delay = true;
+
+    // If we have the table entry transfer some of the attributes to the
+    // request that triggered the translation
+    if (te != NULL) {
+        // Set memory attributes
+        DPRINTF(TLBVerbose,
+                "Setting memory attributes: shareable: %d, innerAttrs: %d, "
+                "outerAttrs: %d, mtype: %d, isStage2: %d\n",
+                te->shareable, te->innerAttrs, te->outerAttrs,
+                static_cast<uint8_t>(te->mtype), isStage2);
+        setAttr(te->attributes);
+
+        if (te->nonCacheable && !req->isCacheMaintenance())
+            req->setFlags(Request::UNCACHEABLE);
+
+        // Require requests to be ordered if the request goes to
+        // strongly ordered or device memory (i.e., anything other
+        // than normal memory requires strict order).
+        if (te->mtype != TlbEntry::MemoryType::Normal)
+            req->setFlags(Request::STRICT_ORDER);
+
+        Addr pa = te->pAddr(vaddr);
+        req->setPaddr(pa);
+
+        if (isSecure && !te->ns) {
+            req->setFlags(Request::SECURE);
+        }
+        if ((!is_fetch) && (vaddr & mask(flags & AlignmentMask)) &&
+            (te->mtype != TlbEntry::MemoryType::Normal)) {
+                // Unaligned accesses to Device memory should always cause an
+                // abort regardless of sctlr.a
+                alignFaults++;
+                bool is_write  = (mode == Write);
+                return std::make_shared<DataAbort>(
+                    vaddr_tainted,
+                    TlbEntry::DomainType::NoAccess, is_write,
+                    ArmFault::AlignmentFault, isStage2,
+                    tranMethod);
+        }
+
+        // Check for a trickbox generated address fault
+        if (fault == NoFault)
+            fault = testTranslation(req, mode, te->domain);
+    }
+
+    if (fault == NoFault) {
+        // Don't try to finalize a physical address unless the
+        // translation has completed (i.e., there is a table entry).
+        return te ? finalizePhysical(req, tc, mode) : NoFault;
+    } else {
+        return fault;
+    }
+}
+
+Fault
 TLB::translateFs(const RequestPtr &req, ThreadContext *tc, Mode mode,
         Translation *translation, bool &delay, bool timing,
         TLB::ArmTranslationType tranType, bool functional)
@@ -1054,111 +1174,14 @@
 
     // If guest MMU is off or hcr.vm=0 go straight to stage2
     if ((isStage2 && !hcr.vm) || (!isStage2 && !sctlr.m)) {
-
-        req->setPaddr(vaddr);
-        // When the MMU is off the security attribute corresponds to the
-        // security state of the processor
-        if (isSecure)
-            req->setFlags(Request::SECURE);
-
-        // @todo: double check this (ARM ARM issue C B3.2.1)
-        if (long_desc_format || sctlr.tre == 0 || nmrr.ir0 == 0 ||
-            nmrr.or0 == 0 || prrr.tr0 != 0x2) {
-            if (!req->isCacheMaintenance()) {
-                req->setFlags(Request::UNCACHEABLE);
-            }
-            req->setFlags(Request::STRICT_ORDER);
-        }
-
-        // Set memory attributes
-        TlbEntry temp_te;
-        temp_te.ns = !isSecure;
-        if (isStage2 || hcr.dc == 0 || isSecure ||
-           (isHyp && !(tranType & S1CTran))) {
-
-            temp_te.mtype      = is_fetch ? TlbEntry::MemoryType::Normal
-                                          : TlbEntry::MemoryType::StronglyOrdered;
-            temp_te.innerAttrs = 0x0;
-            temp_te.outerAttrs = 0x0;
-            temp_te.shareable  = true;
-            temp_te.outerShareable = true;
-        } else {
-            temp_te.mtype      = TlbEntry::MemoryType::Normal;
-            temp_te.innerAttrs = 0x3;
-            temp_te.outerAttrs = 0x3;
-            temp_te.shareable  = false;
-            temp_te.outerShareable = false;
-        }
-        temp_te.setAttributes(long_desc_format);
-        DPRINTF(TLBVerbose, "(No MMU) setting memory attributes: shareable: "
-                "%d, innerAttrs: %d, outerAttrs: %d, isStage2: %d\n",
-                temp_te.shareable, temp_te.innerAttrs, temp_te.outerAttrs,
-                isStage2);
-        setAttr(temp_te.attributes);
-
-        return testTranslation(req, mode, TlbEntry::DomainType::NoAccess);
-    }
-
-    DPRINTF(TLBVerbose, "Translating %s=%#x context=%d\n",
-            isStage2 ? "IPA" : "VA", vaddr_tainted, asid);
-    // Translation enabled
-
-    TlbEntry *te = NULL;
-    TlbEntry mergeTe;
-    Fault fault = getResultTe(&te, req, tc, mode, translation, timing,
-                              functional, &mergeTe);
-    // only proceed if we have a valid table entry
-    if ((te == NULL) && (fault == NoFault)) delay = true;
-
-    // If we have the table entry transfer some of the attributes to the
-    // request that triggered the translation
-    if (te != NULL) {
-        // Set memory attributes
-        DPRINTF(TLBVerbose,
-                "Setting memory attributes: shareable: %d, innerAttrs: %d, "
-                "outerAttrs: %d, mtype: %d, isStage2: %d\n",
-                te->shareable, te->innerAttrs, te->outerAttrs,
-                static_cast<uint8_t>(te->mtype), isStage2);
-        setAttr(te->attributes);
-
-        if (te->nonCacheable && !req->isCacheMaintenance())
-            req->setFlags(Request::UNCACHEABLE);
-
-        // Require requests to be ordered if the request goes to
-        // strongly ordered or device memory (i.e., anything other
-        // than normal memory requires strict order).
-        if (te->mtype != TlbEntry::MemoryType::Normal)
-            req->setFlags(Request::STRICT_ORDER);
-
-        Addr pa = te->pAddr(vaddr);
-        req->setPaddr(pa);
-
-        if (isSecure && !te->ns) {
-            req->setFlags(Request::SECURE);
-        }
-        if ((!is_fetch) && (vaddr & mask(flags & AlignmentMask)) &&
-            (te->mtype != TlbEntry::MemoryType::Normal)) {
-                // Unaligned accesses to Device memory should always cause an
-                // abort regardless of sctlr.a
-                alignFaults++;
-                return std::make_shared<DataAbort>(
-                    vaddr_tainted,
-                    TlbEntry::DomainType::NoAccess, is_write,
-                    ArmFault::AlignmentFault, isStage2,
-                    tranMethod);
-        }
-
-        // Check for a trickbox generated address fault
-        if (fault == NoFault)
-            fault = testTranslation(req, mode, te->domain);
-    }
-
-    if (fault == NoFault) {
-        // Don't try to finalize a physical address unless the
-        // translation has completed (i.e., there is a table entry).
-        return te ? finalizePhysical(req, tc, mode) : NoFault;
+        return translateMmuOff(tc, req, mode, tranType, vaddr,
+                               long_desc_format);
     } else {
-        return fault;
+        DPRINTF(TLBVerbose, "Translating %s=%#x context=%d\n",
+                isStage2 ? "IPA" : "VA", vaddr_tainted, asid);
+        // Translation enabled
+        return translateMmuOn(tc, req, mode, translation, delay, timing,
+                              functional, vaddr, tranMethod);
     }
 }
 
diff --git a/src/arch/arm/tlb.hh b/src/arch/arm/tlb.hh
index 6314ef2..a344cd4 100644
--- a/src/arch/arm/tlb.hh
+++ b/src/arch/arm/tlb.hh
@@ -44,6 +44,7 @@
 #define __ARCH_ARM_TLB_HH__
 
 
+#include "arch/arm/faults.hh"
 #include "arch/arm/isa_traits.hh"
 #include "arch/arm/pagetable.hh"
 #include "arch/arm/utility.hh"
@@ -351,6 +352,12 @@
         return _attr;
     }
 
+    Fault translateMmuOff(ThreadContext *tc, const RequestPtr &req, Mode mode,
+        TLB::ArmTranslationType tranType, Addr vaddr, bool long_desc_format);
+    Fault translateMmuOn(ThreadContext *tc, const RequestPtr &req, Mode mode,
+        Translation *translation, bool &delay, bool timing, bool functional,
+        Addr vaddr, ArmFault::TranMethod tranMethod);
+
     Fault translateFs(const RequestPtr &req, ThreadContext *tc, Mode mode,
             Translation *translation, bool &delay,
             bool timing, ArmTranslationType tranType, bool functional = false);