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);