/*
- * Copyright (c) 2010-2013, 2016 ARM Limited
+ * Copyright (c) 2010-2013, 2016, 2018 ARM Limited
* All rights reserved
*
* The license below extends only to copyright in the software and shall
* Giacomo Gabrielli
*/
-#include "arch/arm/faults.hh"
#include "arch/arm/stage2_lookup.hh"
+
+#include "arch/arm/faults.hh"
#include "arch/arm/system.hh"
#include "arch/arm/table_walker.hh"
#include "arch/arm/tlb.hh"
Stage2LookUp::getTe(ThreadContext *tc, TlbEntry *destTe)
{
- fault = stage2Tlb->getTE(&stage2Te, &req, tc, mode, this, timing,
+ fault = stage2Tlb->getTE(&stage2Te, req, tc, mode, this, timing,
functional, false, tranType);
// Call finish if we're done already
if ((fault != NoFault) || (stage2Te != NULL)) {
// 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) {
- if (inAArch64(tc))
- fault = stage2Tlb->checkPermissions64(stage2Te, &req, mode, tc);
+ if (ELIs64(tc, EL2))
+ fault = stage2Tlb->checkPermissions64(stage2Te, req, mode, tc);
else
- fault = stage2Tlb->checkPermissions(stage2Te, &req, mode);
+ fault = stage2Tlb->checkPermissions(stage2Te, req, mode);
}
- mergeTe(&req, mode);
+ mergeTe(req, mode);
*destTe = stage1Te;
}
return fault;
}
void
-Stage2LookUp::mergeTe(RequestPtr req, BaseTLB::Mode mode)
+Stage2LookUp::mergeTe(const RequestPtr &req, BaseTLB::Mode mode)
{
// Check again that we haven't got a fault
if (fault == NoFault) {
// 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.vpn = s1Req->getVaddr() >> stage2Te->N;
stage1Te.pfn = stage2Te->pfn;
stage1Te.size = stage2Te->size;
+ stage1Te.N = stage2Te->N;
} 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));
+ const Addr pa = (stage2Te->pfn << stage2Te->N);
+ const Addr ipa = (stage1Te.pfn << stage1Te.N);
+ stage1Te.pfn = (pa | (ipa & mask(stage2Te->N))) >> stage1Te.N;
// Size remains smaller of the two.
} else {
// Matching sizes
}
void
-Stage2LookUp::finish(const Fault &_fault, RequestPtr req,
+Stage2LookUp::finish(const Fault &_fault, const RequestPtr &req,
ThreadContext *tc, BaseTLB::Mode mode)
{
fault = _fault;
mergeTe(req, mode);
if (fault != NoFault) {
- transState->finish(fault, req, tc, mode);
+ // Returning with a fault requires the original request
+ transState->finish(fault, s1Req, tc, mode);
} else if (timing) {
// Now notify the original stage 1 translation that we finally have
// a result