summaryrefslogtreecommitdiff
path: root/src/arch/arm/stage2_lookup.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/arch/arm/stage2_lookup.cc')
-rwxr-xr-xsrc/arch/arm/stage2_lookup.cc200
1 files changed, 200 insertions, 0 deletions
diff --git a/src/arch/arm/stage2_lookup.cc b/src/arch/arm/stage2_lookup.cc
new file mode 100755
index 000000000..1299ade68
--- /dev/null
+++ b/src/arch/arm/stage2_lookup.cc
@@ -0,0 +1,200 @@
+/*
+ * Copyright (c) 2010-2013 ARM Limited
+ * All rights reserved
+ *
+ * The license below extends only to copyright in the software and shall
+ * not be construed as granting a license to any other intellectual
+ * property including but not limited to intellectual property relating
+ * to a hardware implementation of the functionality of the software
+ * licensed hereunder. You may use the software subject to the license
+ * terms below provided that you ensure that this notice is replicated
+ * unmodified and in its entirety in all distributions of the software,
+ * modified or unmodified, in source code or in binary form.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Authors: Ali Saidi
+ * Giacomo Gabrielli
+ */
+
+#include "arch/arm/faults.hh"
+#include "arch/arm/stage2_lookup.hh"
+#include "arch/arm/system.hh"
+#include "arch/arm/table_walker.hh"
+#include "arch/arm/tlb.hh"
+#include "cpu/base.hh"
+#include "cpu/thread_context.hh"
+#include "debug/Checkpoint.hh"
+#include "debug/TLB.hh"
+#include "debug/TLBVerbose.hh"
+#include "sim/system.hh"
+
+using namespace ArmISA;
+
+Fault
+Stage2LookUp::getTe(ThreadContext *tc, TlbEntry *destTe)
+
+{
+ fault = stage2Tlb->getTE(&stage2Te, &req, tc, mode, this, timing,
+ functional, false, tranType);
+ // Call finish if we're done already
+ if ((fault != NoFault) || (stage2Te != NULL)) {
+ mergeTe(&req, mode);
+ *destTe = stage1Te;
+ }
+ return fault;
+}
+
+void
+Stage2LookUp::mergeTe(RequestPtr req, BaseTLB::Mode mode)
+{
+ // Since we directly requested the table entry (which we need later on to
+ // merge the attributes) then we've skipped some stage 2 permissinos
+ // checking. So call translate on stage 2 to do the checking. As the entry
+ // is now in the TLB this should always hit the cache.
+ if (fault == NoFault) {
+ fault = stage2Tlb->checkPermissions(stage2Te, req, mode);
+ }
+
+ // Check again that we haven't got a fault
+ if (fault == NoFault) {
+ assert(stage2Te != NULL);
+
+ // Now we have the table entries for both stages of translation
+ // merge them and insert the result into the stage 1 TLB. See
+ // CombineS1S2Desc() in pseudocode
+ stage1Te.N = stage2Te->N;
+ stage1Te.nonCacheable |= stage2Te->nonCacheable;
+ stage1Te.xn |= stage2Te->xn;
+
+ if (stage1Te.size > stage2Te->size) {
+ // Size mismatch also implies vpn mismatch (this is shifted by
+ // sizebits!).
+ stage1Te.vpn = s1Req->getVaddr() / (stage2Te->size+1);
+ stage1Te.pfn = stage2Te->pfn;
+ stage1Te.size = stage2Te->size;
+ } else if (stage1Te.size < stage2Te->size) {
+ // Guest 4K could well be section-backed by host hugepage! In this
+ // case a 4K entry is added but pfn needs to be adjusted. New PFN =
+ // offset into section PFN given by stage2 IPA treated as a stage1
+ // page size.
+ stage1Te.pfn = (stage2Te->pfn * ((stage2Te->size+1) / (stage1Te.size+1))) +
+ (stage2Te->vpn / (stage1Te.size+1));
+ // Size remains smaller of the two.
+ } else {
+ // Matching sizes
+ stage1Te.pfn = stage2Te->pfn;
+ }
+
+ if (stage2Te->mtype == TlbEntry::MemoryType::StronglyOrdered ||
+ stage1Te.mtype == TlbEntry::MemoryType::StronglyOrdered) {
+ stage1Te.mtype = TlbEntry::MemoryType::StronglyOrdered;
+ } else if (stage2Te->mtype == TlbEntry::MemoryType::Device ||
+ stage1Te.mtype == TlbEntry::MemoryType::Device) {
+ stage1Te.mtype = TlbEntry::MemoryType::Device;
+ } else {
+ stage1Te.mtype = TlbEntry::MemoryType::Normal;
+ }
+
+ if (stage1Te.mtype == TlbEntry::MemoryType::Normal) {
+
+ if (stage2Te->innerAttrs == 0 ||
+ stage1Te.innerAttrs == 0) {
+ // either encoding Non-cacheable
+ stage1Te.innerAttrs = 0;
+ } else if (stage2Te->innerAttrs == 2 ||
+ stage1Te.innerAttrs == 2) {
+ // either encoding Write-Through cacheable
+ stage1Te.innerAttrs = 2;
+ } else {
+ // both encodings Write-Back
+ stage1Te.innerAttrs = 3;
+ }
+
+ if (stage2Te->outerAttrs == 0 ||
+ stage1Te.outerAttrs == 0) {
+ // either encoding Non-cacheable
+ stage1Te.outerAttrs = 0;
+ } else if (stage2Te->outerAttrs == 2 ||
+ stage1Te.outerAttrs == 2) {
+ // either encoding Write-Through cacheable
+ stage1Te.outerAttrs = 2;
+ } else {
+ // both encodings Write-Back
+ stage1Te.outerAttrs = 3;
+ }
+
+ stage1Te.shareable |= stage2Te->shareable;
+ stage1Te.outerShareable |= stage2Te->outerShareable;
+ if (stage1Te.innerAttrs == 0 &&
+ stage1Te.outerAttrs == 0) {
+ // something Non-cacheable at each level is outer shareable
+ stage1Te.shareable = true;
+ stage1Te.outerShareable = true;
+ }
+ } else {
+ stage1Te.shareable = true;
+ stage1Te.outerShareable = true;
+ }
+ stage1Te.updateAttributes();
+ }
+
+ // if there's a fault annotate it,
+ if (fault != NoFault) {
+ // If the second stage of translation generated a fault add the
+ // details of the original stage 1 virtual address
+ reinterpret_cast<ArmFault *>(fault.get())->annotate(ArmFault::OVA,
+ s1Req->getVaddr());
+ }
+ complete = true;
+}
+
+void
+Stage2LookUp::finish(Fault _fault, RequestPtr req,
+ ThreadContext *tc, BaseTLB::Mode mode)
+{
+ fault = _fault;
+ // if we haven't got the table entry get it now
+ if ((fault == NoFault) && (stage2Te == NULL)) {
+ fault = stage2Tlb->getTE(&stage2Te, req, tc, mode, this,
+ timing, functional, false, tranType);
+ }
+
+ // Now we have the stage 2 table entry we need to merge it with the stage
+ // 1 entry we were given at the start
+ mergeTe(req, mode);
+
+ if (fault != NoFault) {
+ transState->finish(fault, req, tc, mode);
+ } else if (timing) {
+ // Now notify the original stage 1 translation that we finally have
+ // a result
+ stage1Tlb->translateComplete(s1Req, tc, transState, mode, tranType, true);
+ }
+ // if we have been asked to delete ourselfs do it now
+ if (selfDelete) {
+ delete this;
+ }
+}
+