stats: update stats for mmap() change.
[gem5.git] / src / arch / arm / vtophys.cc
index 45e6f184966e55890452e97e66643e38edd2449a..3aad35818b8459e7d02c61a42aa5b35c7f82d494 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010 ARM Limited
+ * Copyright (c) 2010, 2012-2013 ARM Limited
  * All rights reserved
  *
  * The license below extends only to copyright in the software and shall
@@ -45,6 +45,7 @@
 
 #include <string>
 
+#include "arch/arm/faults.hh"
 #include "arch/arm/table_walker.hh"
 #include "arch/arm/tlb.hh"
 #include "arch/arm/vtophys.hh"
@@ -62,77 +63,52 @@ ArmISA::vtophys(Addr vaddr)
     fatal("VTOPHYS: Can't convert vaddr to paddr on ARM without a thread context");
 }
 
-Addr
-ArmISA::vtophys(ThreadContext *tc, Addr addr)
+static std::pair<bool, Addr>
+try_translate(ThreadContext *tc, Addr addr)
 {
-    SCTLR sctlr = tc->readMiscReg(MISCREG_SCTLR);
-    if (!sctlr.m) {
-        // Translation is currently disabled PA == VA
-        return addr;
-    }
-    bool success;
-    Addr pa;
+    Fault fault;
+    // Set up a functional memory Request to pass to the TLB
+    // to get it to translate the vaddr to a paddr
+    Request req(0, addr, 64, 0x40, -1, 0, 0, 0);
     ArmISA::TLB *tlb;
 
-    // Check the TLBs far a translation
-    // It's possible that there is a validy translation in the tlb
+    // Check the TLBs for a translation
+    // It's possible that there is a valid translation in the tlb
     // that is no loger valid in the page table in memory
     // so we need to check here first
+    //
+    // Calling translateFunctional invokes a table-walk if required
+    // so we should always succeed
     tlb = static_cast<ArmISA::TLB*>(tc->getDTBPtr());
-    success = tlb->translateFunctional(tc, addr, pa);
-    if (success)
-        return pa;
+    fault = tlb->translateFunctional(&req, tc, BaseTLB::Read, TLB::NormalTran);
+    if (fault == NoFault)
+        return std::make_pair(true, req.getPaddr());
 
     tlb = static_cast<ArmISA::TLB*>(tc->getITBPtr());
-    success = tlb->translateFunctional(tc, addr, pa);
-    if (success)
-        return pa;
-
-    // We've failed everything, so we need to do a
-    // hardware tlb walk without messing with any
-    // state
-
-    uint32_t N = tc->readMiscReg(MISCREG_TTBCR);
-    Addr ttbr;
-    if (N == 0 || !mbits(addr, 31, 32-N)) {
-        ttbr = tc->readMiscReg(MISCREG_TTBR0);
-    } else {
-        ttbr = tc->readMiscReg(MISCREG_TTBR1);
-        N = 0;
-    }
-
-    PortProxy* port = tc->getPhysProxy();
-    Addr l1desc_addr = mbits(ttbr, 31, 14-N) | (bits(addr,31-N,20) << 2);
-
-    TableWalker::L1Descriptor l1desc;
-    l1desc.data = port->read<uint32_t>(l1desc_addr);
-    if (l1desc.type() == TableWalker::L1Descriptor::Ignore ||
-            l1desc.type() == TableWalker::L1Descriptor::Reserved) {
-        warn("Unable to translate virtual address: %#x\n", addr);
-        return -1;
-    }
-    if (l1desc.type() == TableWalker::L1Descriptor::Section)
-        return l1desc.paddr(addr);
+    fault = tlb->translateFunctional(&req, tc, BaseTLB::Read, TLB::NormalTran);
+    if (fault == NoFault)
+        return std::make_pair(true, req.getPaddr());
 
-    // Didn't find it at the first level, try againt
-    Addr l2desc_addr = l1desc.l2Addr() | (bits(addr, 19, 12) << 2);
-    TableWalker::L2Descriptor l2desc;
-    l2desc.data = port->read<uint32_t>(l2desc_addr);
+    return std::make_pair(false, 0);
+}
 
-    if (l2desc.invalid()) {
-        warn("Unable to translate virtual address: %#x\n", addr);
-        return -1;
-    }
+Addr
+ArmISA::vtophys(ThreadContext *tc, Addr addr)
+{
+    const std::pair<bool, Addr> translation(try_translate(tc, addr));
 
-    return l2desc.paddr(addr);
+    if (translation.first)
+        return translation.second;
+    else
+        panic("Table walkers support functional accesses. We should never get here\n");
 }
 
 bool
 ArmISA::virtvalid(ThreadContext *tc, Addr vaddr)
 {
-    if (vtophys(tc, vaddr) != -1)
-        return true;
-    return false;
+    const std::pair<bool, Addr> translation(try_translate(tc, vaddr));
+
+    return translation.first;
 }