diff options
Diffstat (limited to 'src/arch/arm/stage2_lookup.cc')
-rwxr-xr-x | src/arch/arm/stage2_lookup.cc | 200 |
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; + } +} + |