/*
 * Copyright (c) 2010-2013, 2016-2022 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.
 *
 * Copyright (c) 2001-2005 The Regents of The University of Michigan
 * All rights reserved.
 *
 * 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.
 */

#include "arch/arm/mmu.hh"

#include "arch/arm/isa.hh"
#include "arch/arm/reg_abi.hh"
#include "arch/arm/stage2_lookup.hh"
#include "arch/arm/table_walker.hh"
#include "arch/arm/tlbi_op.hh"
#include "debug/TLB.hh"
#include "debug/TLBVerbose.hh"
#include "mem/packet_access.hh"
#include "sim/pseudo_inst.hh"
#include "sim/process.hh"

namespace gem5
{

using namespace ArmISA;

MMU::MMU(const ArmMMUParams &p)
  : BaseMMU(p),
    itbStage2(p.stage2_itb), dtbStage2(p.stage2_dtb),
    itbWalker(p.itb_walker), dtbWalker(p.dtb_walker),
    itbStage2Walker(p.stage2_itb_walker),
    dtbStage2Walker(p.stage2_dtb_walker),
    test(nullptr),
    miscRegContext(0),
    s1State(this, false), s2State(this, true),
    _attr(0),
    _release(nullptr),
    _hasWalkCache(false),
    stats(this)
{
    // Cache system-level properties
    if (FullSystem) {
        ArmSystem *arm_sys = dynamic_cast<ArmSystem *>(p.sys);
        assert(arm_sys);
        haveLargeAsid64 = arm_sys->haveLargeAsid64();
        physAddrRange = arm_sys->physAddrRange();

        _release = arm_sys->releaseFS();
    } else {
        haveLargeAsid64 = false;
        physAddrRange = 48;

        _release = p.release_se;
    }

    m5opRange = p.sys->m5opRange();
}

void
MMU::init()
{
    itbWalker->setMmu(this);
    dtbWalker->setMmu(this);
    itbStage2Walker->setMmu(this);
    dtbStage2Walker->setMmu(this);

    itbStage2->setTableWalker(itbStage2Walker);
    dtbStage2->setTableWalker(dtbStage2Walker);

    getITBPtr()->setTableWalker(itbWalker);
    getDTBPtr()->setTableWalker(dtbWalker);

    BaseMMU::init();

    _hasWalkCache = checkWalkCache();
}

bool
MMU::checkWalkCache() const
{
    for (auto tlb : instruction) {
        if (static_cast<TLB*>(tlb)->walkCache())
            return true;
    }
    for (auto tlb : data) {
        if (static_cast<TLB*>(tlb)->walkCache())
            return true;
    }
    for (auto tlb : unified) {
        if (static_cast<TLB*>(tlb)->walkCache())
            return true;
    }

    return false;
}

void
MMU::drainResume()
{
    s1State.miscRegValid = false;
    s2State.miscRegValid = false;
}

TLB *
MMU::getTlb(BaseMMU::Mode mode, bool stage2) const
{
    if (mode == BaseMMU::Execute) {
        if (stage2)
            return itbStage2;
        else
            return getITBPtr();
    } else {
        if (stage2)
            return dtbStage2;
        else
            return getDTBPtr();
    }
}

TableWalker *
MMU::getTableWalker(BaseMMU::Mode mode, bool stage2) const
{
    if (mode == BaseMMU::Execute) {
        if (stage2)
            return itbStage2Walker;
        else
            return itbWalker;
    } else {
        if (stage2)
            return dtbStage2Walker;
        else
            return dtbWalker;
    }
}

bool
MMU::translateFunctional(ThreadContext *tc, Addr va, Addr &pa)
{
    CachedState& state = updateMiscReg(tc, NormalTran, false);

    auto tlb = getTlb(BaseMMU::Read, state.directToStage2);

    TlbEntry::Lookup lookup_data;

    lookup_data.va = va;
    lookup_data.asn = state.asid;
    lookup_data.ignoreAsn = false;
    lookup_data.vmid = state.vmid;
    lookup_data.hyp = state.isHyp;
    lookup_data.secure = state.isSecure;
    lookup_data.functional = true;
    lookup_data.targetEL = state.aarch64 ? state.aarch64EL : EL1;
    lookup_data.inHost = false;
    lookup_data.mode = BaseMMU::Read;

    TlbEntry *e = tlb->multiLookup(lookup_data);

    if (!e)
        return false;
    pa = e->pAddr(va);
    return true;
}

void
MMU::invalidateMiscReg()
{
    s1State.miscRegValid = false;
    s1State.computeAddrTop.flush();
    s2State.computeAddrTop.flush();
}

Fault
MMU::finalizePhysical(const RequestPtr &req,
                      ThreadContext *tc, Mode mode) const
{
    const Addr paddr = req->getPaddr();

    if (m5opRange.contains(paddr)) {
        uint8_t func;
        pseudo_inst::decodeAddrOffset(paddr - m5opRange.start(), func);
        req->setLocalAccessor(
            [func, mode](ThreadContext *tc, PacketPtr pkt) -> Cycles
            {
                uint64_t ret;
                if (inAArch64(tc))
                    pseudo_inst::pseudoInst<RegABI64>(tc, func, ret);
                else
                    pseudo_inst::pseudoInst<RegABI32>(tc, func, ret);

                if (mode == Read)
                    pkt->setLE(ret);

                return Cycles(1);
            }
        );
    }

    return NoFault;
}


Fault
MMU::translateSe(const RequestPtr &req, ThreadContext *tc, Mode mode,
                 Translation *translation, bool &delay, bool timing,
                 CachedState &state)
{
    updateMiscReg(tc, NormalTran, state.isStage2);
    Addr vaddr_tainted = req->getVaddr();
    Addr vaddr = 0;
    if (state.aarch64) {
        vaddr = purifyTaggedAddr(vaddr_tainted, tc, state.aarch64EL,
            static_cast<TCR>(state.ttbcr), mode==Execute, state);
    } else {
        vaddr = vaddr_tainted;
    }
    Request::Flags flags = req->getFlags();

    bool is_fetch = (mode == Execute);
    bool is_write = (mode == Write);

    if (!is_fetch) {
        if (state.sctlr.a || !(flags & AllowUnaligned)) {
            if (vaddr & mask(flags & AlignmentMask)) {
                // LPAE is always disabled in SE mode
                return std::make_shared<DataAbort>(
                    vaddr_tainted,
                    TlbEntry::DomainType::NoAccess, is_write,
                    ArmFault::AlignmentFault, state.isStage2,
                    ArmFault::VmsaTran);
            }
        }
    }

    Addr paddr;
    Process *p = tc->getProcessPtr();

    if (!p->pTable->translate(vaddr, paddr))
        return std::make_shared<GenericPageTableFault>(vaddr_tainted);
    req->setPaddr(paddr);

    return finalizePhysical(req, tc, mode);
}

Fault
MMU::checkPermissions(TlbEntry *te, const RequestPtr &req, Mode mode,
                      bool stage2)
{
    return checkPermissions(te, req, mode, stage2 ? s2State : s1State);
}

Fault
MMU::checkPermissions(TlbEntry *te, const RequestPtr &req, Mode mode,
                      CachedState &state)
{
    // a data cache maintenance instruction that operates by MVA does
    // not generate a Data Abort exeception due to a Permission fault
    if (req->isCacheMaintenance()) {
        return NoFault;
    }

    Addr vaddr = req->getVaddr(); // 32-bit don't have to purify
    Request::Flags flags = req->getFlags();
    bool is_fetch  = (mode == Execute);
    bool is_write  = (mode == Write);
    bool is_priv   = state.isPriv && !(flags & UserMode);

    // Get the translation type from the actuall table entry
    ArmFault::TranMethod tranMethod = te->longDescFormat ? ArmFault::LpaeTran
                                                         : ArmFault::VmsaTran;

    // If this is the second stage of translation and the request is for a
    // stage 1 page table walk then we need to check the HCR.PTW bit. This
    // allows us to generate a fault if the request targets an area marked
    // as a device or strongly ordered.
    if (state.isStage2 && req->isPTWalk() && state.hcr.ptw &&
        (te->mtype != TlbEntry::MemoryType::Normal)) {
        return std::make_shared<DataAbort>(
            vaddr, te->domain, is_write,
            ArmFault::PermissionLL + te->lookupLevel,
            state.isStage2, tranMethod);
    }

    // Generate an alignment fault for unaligned data accesses to device or
    // strongly ordered memory
    if (!is_fetch) {
        if (te->mtype != TlbEntry::MemoryType::Normal) {
            if (vaddr & mask(flags & AlignmentMask)) {
                stats.alignFaults++;
                return std::make_shared<DataAbort>(
                    vaddr, TlbEntry::DomainType::NoAccess, is_write,
                    ArmFault::AlignmentFault, state.isStage2,
                    tranMethod);
            }
        }
    }

    if (te->nonCacheable) {
        // Prevent prefetching from I/O devices.
        if (req->isPrefetch()) {
            // Here we can safely use the fault status for the short
            // desc. format in all cases
            return std::make_shared<PrefetchAbort>(
                vaddr, ArmFault::PrefetchUncacheable,
                state.isStage2, tranMethod);
        }
    }

    if (!te->longDescFormat) {
        switch ((state.dacr >> (static_cast<uint8_t>(te->domain) * 2)) & 0x3) {
          case 0:
            stats.domainFaults++;
            DPRINTF(TLB, "TLB Fault: Data abort on domain. DACR: %#x"
                    " domain: %#x write:%d\n", state.dacr,
                    static_cast<uint8_t>(te->domain), is_write);
            if (is_fetch) {
                // Use PC value instead of vaddr because vaddr might
                // be aligned to cache line and should not be the
                // address reported in FAR
                return std::make_shared<PrefetchAbort>(
                    req->getPC(),
                    ArmFault::DomainLL + te->lookupLevel,
                    state.isStage2, tranMethod);
            } else
                return std::make_shared<DataAbort>(
                    vaddr, te->domain, is_write,
                    ArmFault::DomainLL + te->lookupLevel,
                    state.isStage2, tranMethod);
          case 1:
            // Continue with permissions check
            break;
          case 2:
            panic("UNPRED domain\n");
          case 3:
            return NoFault;
        }
    }

    // The 'ap' variable is AP[2:0] or {AP[2,1],1b'0}, i.e. always three bits
    uint8_t ap  = te->longDescFormat ? te->ap << 1 : te->ap;
    uint8_t hap = te->hap;

    if (state.sctlr.afe == 1 || te->longDescFormat)
        ap |= 1;

    bool abt;
    bool isWritable = true;
    // If this is a stage 2 access (eg for reading stage 1 page table entries)
    // then don't perform the AP permissions check, we stil do the HAP check
    // below.
    if (state.isStage2) {
        abt = false;
    } else {
        switch (ap) {
          case 0:
            DPRINTF(TLB, "Access permissions 0, checking rs:%#x\n",
                    (int)state.sctlr.rs);
            if (!state.sctlr.xp) {
                switch ((int)state.sctlr.rs) {
                  case 2:
                    abt = is_write;
                    break;
                  case 1:
                    abt = is_write || !is_priv;
                    break;
                  case 0:
                  case 3:
                  default:
                    abt = true;
                    break;
                }
            } else {
                abt = true;
            }
            break;
          case 1:
            abt = !is_priv;
            break;
          case 2:
            abt = !is_priv && is_write;
            isWritable = is_priv;
            break;
          case 3:
            abt = false;
            break;
          case 4:
            panic("UNPRED premissions\n");
          case 5:
            abt = !is_priv || is_write;
            isWritable = false;
            break;
          case 6:
          case 7:
            abt        = is_write;
            isWritable = false;
            break;
          default:
            panic("Unknown permissions %#x\n", ap);
        }
    }

    bool hapAbt = is_write ? !(hap & 2) : !(hap & 1);
    bool xn     = te->xn || (isWritable && state.sctlr.wxn) ||
                            (ap == 3    && state.sctlr.uwxn && is_priv);
    if (is_fetch && (abt || xn ||
                     (te->longDescFormat && te->pxn && is_priv) ||
                     (state.isSecure && te->ns && state.scr.sif))) {
        stats.permsFaults++;
        DPRINTF(TLB, "TLB Fault: Prefetch abort on permission check. AP:%d "
                     "priv:%d write:%d ns:%d sif:%d sctlr.afe: %d \n",
                     ap, is_priv, is_write, te->ns,
                     state.scr.sif, state.sctlr.afe);
        // Use PC value instead of vaddr because vaddr might be aligned to
        // cache line and should not be the address reported in FAR
        return std::make_shared<PrefetchAbort>(
            req->getPC(),
            ArmFault::PermissionLL + te->lookupLevel,
            state.isStage2, tranMethod);
    } else if (abt | hapAbt) {
        stats.permsFaults++;
        DPRINTF(TLB, "TLB Fault: Data abort on permission check. AP:%d priv:%d"
               " write:%d\n", ap, is_priv, is_write);
        return std::make_shared<DataAbort>(
            vaddr, te->domain, is_write,
            ArmFault::PermissionLL + te->lookupLevel,
            state.isStage2 | !abt, tranMethod);
    }
    return NoFault;
}

Fault
MMU::checkPermissions64(TlbEntry *te, const RequestPtr &req, Mode mode,
                        ThreadContext *tc, bool stage2)
{
    return checkPermissions64(te, req, mode, tc, stage2 ? s2State : s1State);
}

Fault
MMU::checkPermissions64(TlbEntry *te, const RequestPtr &req, Mode mode,
                        ThreadContext *tc, CachedState &state)
{
    assert(state.aarch64);

    // A data cache maintenance instruction that operates by VA does
    // not generate a Permission fault unless:
    // * It is a data cache invalidate (dc ivac) which requires write
    //   permissions to the VA, or
    // * It is executed from EL0
    if (req->isCacheClean() && state.aarch64EL != EL0 && !state.isStage2) {
        return NoFault;
    }

    Addr vaddr_tainted = req->getVaddr();
    Addr vaddr = purifyTaggedAddr(vaddr_tainted, tc, state.aarch64EL,
        static_cast<TCR>(state.ttbcr), mode==Execute, state);

    Request::Flags flags = req->getFlags();
    bool is_fetch  = (mode == Execute);
    // Cache clean operations require read permissions to the specified VA
    bool is_write = !req->isCacheClean() && mode == Write;
    bool is_atomic = req->isAtomic();

    updateMiscReg(tc, state.curTranType, state.isStage2);

    // If this is the second stage of translation and the request is for a
    // stage 1 page table walk then we need to check the HCR.PTW bit. This
    // allows us to generate a fault if the request targets an area marked
    // as a device or strongly ordered.
    if (state.isStage2 && req->isPTWalk() && state.hcr.ptw &&
        (te->mtype != TlbEntry::MemoryType::Normal)) {
        return std::make_shared<DataAbort>(
            vaddr_tainted, te->domain, is_write,
            ArmFault::PermissionLL + te->lookupLevel,
            state.isStage2, ArmFault::LpaeTran);
    }

    // Generate an alignment fault for unaligned accesses to device or
    // strongly ordered memory
    if (!is_fetch) {
        if (te->mtype != TlbEntry::MemoryType::Normal) {
            if (vaddr & mask(flags & AlignmentMask)) {
                stats.alignFaults++;
                return std::make_shared<DataAbort>(
                    vaddr_tainted,
                    TlbEntry::DomainType::NoAccess,
                    is_atomic ? false : is_write,
                    ArmFault::AlignmentFault, state.isStage2,
                    ArmFault::LpaeTran);
            }
        }
    }

    if (te->nonCacheable) {
        // Prevent prefetching from I/O devices.
        if (req->isPrefetch()) {
            // Here we can safely use the fault status for the short
            // desc. format in all cases
            return std::make_shared<PrefetchAbort>(
                vaddr_tainted,
                ArmFault::PrefetchUncacheable,
                state.isStage2, ArmFault::LpaeTran);
        }
    }

    bool grant = false;
    // grant_read is used for faults from an atomic instruction that
    // both reads and writes from a memory location. From a ISS point
    // of view they count as read if a read to that address would have
    // generated the fault; they count as writes otherwise
    bool grant_read = true;

    if (state.isStage2) {
        std::tie(grant, grant_read) = s2PermBits64(te, req, mode, tc, state,
            (!is_write && !is_fetch), is_write, is_fetch);
    } else {
        std::tie(grant, grant_read) = s1PermBits64(te, req, mode, tc, state,
            (!is_write && !is_fetch), is_write, is_fetch);
    }

    if (!grant) {
        if (is_fetch) {
            stats.permsFaults++;
            DPRINTF(TLB, "TLB Fault: Prefetch abort on permission check. "
                    "ns:%d scr.sif:%d sctlr.afe: %d\n",
                    te->ns, state.scr.sif, state.sctlr.afe);
            // Use PC value instead of vaddr because vaddr might be aligned to
            // cache line and should not be the address reported in FAR
            return std::make_shared<PrefetchAbort>(
                req->getPC(),
                ArmFault::PermissionLL + te->lookupLevel,
                state.isStage2, ArmFault::LpaeTran);
        } else {
            stats.permsFaults++;
            DPRINTF(TLB, "TLB Fault: Data abort on permission check."
                    "ns:%d", te->ns);
            return std::make_shared<DataAbort>(
                vaddr_tainted, te->domain,
                (is_atomic && !grant_read) ? false : is_write,
                ArmFault::PermissionLL + te->lookupLevel,
                state.isStage2, ArmFault::LpaeTran);
        }
    }

    return NoFault;
}

std::pair<bool, bool>
MMU::s2PermBits64(TlbEntry *te, const RequestPtr &req, Mode mode,
                  ThreadContext *tc, CachedState &state, bool r, bool w, bool x)
{
    assert(ArmSystem::haveEL(tc, EL2) && state.aarch64EL != EL2);

    // In stage 2 we use the hypervisor access permission bits.
    // The following permissions are described in ARM DDI 0487A.f
    // D4-1802
    bool grant = false;
    bool grant_read = te->hap & 0b01;
    bool grant_write = te->hap & 0b10;

    uint8_t xn =  te->xn;
    uint8_t pxn = te->pxn;

    if (ArmSystem::haveEL(tc, EL3) && state.isSecure &&
        te->ns && state.scr.sif) {
        xn = true;
    }

    DPRINTF(TLBVerbose,
            "Checking S2 permissions: hap:%d, xn:%d, pxn:%d, r:%d, "
            "w:%d, x:%d\n", te->hap, xn, pxn, r, w, x);

    if (x) {
        grant = grant_read && !xn;
    } else if (req->isAtomic()) {
        grant = grant_read || grant_write;
    } else if (w) {
        grant = grant_write;
    } else if (r) {
        grant = grant_read;
    } else {
        panic("Invalid Operation\n");
    }

    return std::make_pair(grant, grant_read);
}

std::pair<bool, bool>
MMU::s1PermBits64(TlbEntry *te, const RequestPtr &req, Mode mode,
                  ThreadContext *tc, CachedState &state, bool r, bool w, bool x)
{
    bool grant = false, grant_read = true;

    const uint8_t ap  = te->ap & 0b11;  // 2-bit access protection field
    const bool is_priv = state.isPriv && !(req->getFlags() & UserMode);

    bool wxn = state.sctlr.wxn;
    uint8_t xn =  te->xn;
    uint8_t pxn = te->pxn;

    if (ArmSystem::haveEL(tc, EL3) && state.isSecure &&
        te->ns && state.scr.sif) {
        xn = true;
    }

    DPRINTF(TLBVerbose, "Checking S1 permissions: ap:%d, xn:%d, pxn:%d, r:%d, "
                        "w:%d, x:%d, is_priv: %d, wxn: %d\n", ap, xn,
                        pxn, r, w, x, is_priv, wxn);

    if (faultPAN(tc, ap, req, mode, is_priv, state)) {
        return std::make_pair(false, false);
    }

    ExceptionLevel regime = !is_priv ? EL0 : state.aarch64EL;
    switch (regime) {
      case EL0:
        {
            grant_read = ap & 0x1;
            uint8_t perm = (ap << 2)  | (xn << 1) | pxn;
            switch (perm) {
              case 0:
              case 1:
              case 8:
              case 9:
                grant = x;
                break;
              case 4:
              case 5:
                grant = r || w || (x && !wxn);
                break;
              case 6:
              case 7:
                grant = r || w;
                break;
              case 12:
              case 13:
                grant = r || x;
                break;
              case 14:
              case 15:
                grant = r;
                break;
              default:
                grant = false;
            }
        }
        break;
      case EL1:
        {
            uint8_t perm = (ap << 2)  | (xn << 1) | pxn;
            switch (perm) {
              case 0:
              case 2:
                grant = r || w || (x && !wxn);
                break;
              case 1:
              case 3:
              case 4:
              case 5:
              case 6:
              case 7:
                // regions that are writeable at EL0 should not be
                // executable at EL1
                grant = r || w;
                break;
              case 8:
              case 10:
              case 12:
              case 14:
                grant = r || x;
                break;
              case 9:
              case 11:
              case 13:
              case 15:
                grant = r;
                break;
              default:
                grant = false;
            }
        }
        break;
      case EL2:
      case EL3:
        {
            uint8_t perm = (ap & 0x2) | xn;
            switch (perm) {
              case 0:
                grant = r || w || (x && !wxn);
                break;
              case 1:
                grant = r || w;
                break;
              case 2:
                grant = r || x;
                break;
              case 3:
                grant = r;
                break;
              default:
                grant = false;
            }
        }
        break;
    }

    return std::make_pair(grant, grant_read);
}

bool
MMU::faultPAN(ThreadContext *tc, uint8_t ap, const RequestPtr &req, Mode mode,
              const bool is_priv, CachedState &state)
{
    bool exception = false;
    switch (state.aarch64EL) {
      case EL0:
        break;
      case EL1:
        if (checkPAN(tc, ap, req, mode, is_priv, state)) {
            exception = true;;
        }
        break;
      case EL2:
        if (state.hcr.e2h && checkPAN(tc, ap, req, mode, is_priv, state)) {
            exception = true;;
        }
        break;
      case EL3:
        break;
    }

    return exception;
}

bool
MMU::checkPAN(ThreadContext *tc, uint8_t ap, const RequestPtr &req, Mode mode,
              const bool is_priv, CachedState &state)
{
    // The PAN bit has no effect on:
    // 1) Instruction accesses.
    // 2) Data Cache instructions other than DC ZVA
    // 3) Address translation instructions, other than ATS1E1RP and
    // ATS1E1WP when ARMv8.2-ATS1E1 is implemented. (Unimplemented in
    // gem5)
    // 4) Instructions to be treated as unprivileged, unless
    // HCR_EL2.{E2H, TGE} == {1, 0}
    if (HaveExt(tc, ArmExtension::FEAT_PAN) && state.cpsr.pan && (ap & 0x1) &&
        mode != BaseMMU::Execute) {

        if (req->isCacheMaintenance() &&
            !(req->getFlags() & Request::CACHE_BLOCK_ZERO)) {
            // Cache maintenance other than DC ZVA
            return false;
        } else if (!is_priv && !(state.hcr.e2h && !state.hcr.tge)) {
            // Treated as unprivileged unless HCR_EL2.{E2H, TGE} == {1, 0}
            return false;
        }
        return true;
    }

    return false;
}

Addr
MMU::purifyTaggedAddr(Addr vaddr_tainted, ThreadContext *tc, ExceptionLevel el,
                      TCR tcr, bool is_inst, CachedState& state)
{
    const bool selbit = bits(vaddr_tainted, 55);

    // Call the memoized version of computeAddrTop
    const auto topbit = state.computeAddrTop(tc, selbit, is_inst, tcr, el);

    return maskTaggedAddr(vaddr_tainted, tc, el, topbit);
}

Fault
MMU::translateMmuOff(ThreadContext *tc, const RequestPtr &req, Mode mode,
        ArmTranslationType tran_type, Addr vaddr, bool long_desc_format,
        CachedState &state)
{
    bool is_fetch  = (mode == Execute);
    bool is_atomic = req->isAtomic();
    req->setPaddr(vaddr);
    // When the MMU is off the security attribute corresponds to the
    // security state of the processor
    if (state.isSecure)
        req->setFlags(Request::SECURE);

    if (state.aarch64) {
        bool selbit = bits(vaddr, 55);
        TCR tcr1 = tc->readMiscReg(MISCREG_TCR_EL1);
        int topbit = computeAddrTop(tc, selbit, is_fetch, tcr1, currEL(tc));
        int addr_sz = bits(vaddr, topbit, physAddrRange);
        if (addr_sz != 0){
            Fault f;
            if (is_fetch)
                f = std::make_shared<PrefetchAbort>(vaddr,
                    ArmFault::AddressSizeLL, state.isStage2,
                    ArmFault::LpaeTran);
            else
                f = std::make_shared<DataAbort>( vaddr,
                    TlbEntry::DomainType::NoAccess,
                    is_atomic ? false : mode==Write,
                    ArmFault::AddressSizeLL, state.isStage2,
                    ArmFault::LpaeTran);
            return f;
        }
    }

    // @todo: double check this (ARM ARM issue C B3.2.1)
    if (long_desc_format || state.sctlr.tre == 0 || state.nmrr.ir0 == 0 ||
        state.nmrr.or0 == 0 || state.prrr.tr0 != 0x2) {
        if (!req->isCacheMaintenance()) {
            req->setFlags(Request::UNCACHEABLE);
        }
        req->setFlags(Request::STRICT_ORDER);
    }

    // Set memory attributes
    TlbEntry temp_te;
    temp_te.ns = !state.isSecure;
    bool dc = (HaveExt(tc, ArmExtension::FEAT_VHE) &&
               state.hcr.e2h == 1 && state.hcr.tge == 1) ? 0: state.hcr.dc;
    bool i_cacheability = state.sctlr.i && !state.sctlr.m;
    if (state.isStage2 || !dc || state.isSecure ||
       (state.isHyp && !(tran_type & S1CTran))) {

        temp_te.mtype      = is_fetch ? TlbEntry::MemoryType::Normal
                                      : TlbEntry::MemoryType::StronglyOrdered;
        temp_te.innerAttrs = i_cacheability? 0x2: 0x0;
        temp_te.outerAttrs = i_cacheability? 0x2: 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, stage2: %d\n",
            temp_te.shareable, temp_te.innerAttrs, temp_te.outerAttrs,
            state.isStage2);
    setAttr(temp_te.attributes);

    return testTranslation(req, mode, TlbEntry::DomainType::NoAccess, state);
}

Fault
MMU::translateMmuOn(ThreadContext* tc, const RequestPtr &req, Mode mode,
                    Translation *translation, bool &delay, bool timing,
                    bool functional, Addr vaddr,
                    ArmFault::TranMethod tranMethod, CachedState &state)
{
    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, state);
    // only proceed if we have a valid table entry
    if (!isCompleteTranslation(te) && (fault == NoFault)) delay = true;

    // If we have the table entry transfer some of the attributes to the
    // request that triggered the translation
    if (isCompleteTranslation(te)) {
        // Set memory attributes
        DPRINTF(TLBVerbose,
                "Setting memory attributes: shareable: %d, innerAttrs: %d, "
                "outerAttrs: %d, mtype: %d, stage2: %d\n",
                te->shareable, te->innerAttrs, te->outerAttrs,
                static_cast<uint8_t>(te->mtype), state.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 (state.isSecure && !te->ns) {
            req->setFlags(Request::SECURE);
        }
        if (!is_fetch && fault == NoFault &&
            (vaddr & mask(flags & AlignmentMask)) &&
            (te->mtype != TlbEntry::MemoryType::Normal)) {
                // Unaligned accesses to Device memory should always cause an
                // abort regardless of sctlr.a
                stats.alignFaults++;
                bool is_write  = (mode == Write);
                return std::make_shared<DataAbort>(
                    vaddr_tainted,
                    TlbEntry::DomainType::NoAccess, is_write,
                    ArmFault::AlignmentFault, state.isStage2,
                    tranMethod);
        }

        // Check for a trickbox generated address fault
        if (fault == NoFault)
            fault = testTranslation(req, mode, te->domain, state);
    }

    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
MMU::translateFs(const RequestPtr &req, ThreadContext *tc, Mode mode,
        Translation *translation, bool &delay, bool timing,
        ArmTranslationType tran_type, bool functional,
        CachedState &state)
{
    // No such thing as a functional timing access
    assert(!(timing && functional));

    Addr vaddr_tainted = req->getVaddr();
    Addr vaddr = 0;
    if (state.aarch64) {
        vaddr = purifyTaggedAddr(vaddr_tainted, tc, state.aarch64EL,
            static_cast<TCR>(state.ttbcr), mode==Execute, state);
    } else {
        vaddr = vaddr_tainted;
    }
    Request::Flags flags = req->getFlags();

    bool is_fetch  = (mode == Execute);
    bool is_write  = (mode == Write);
    bool long_desc_format = state.aarch64 || longDescFormatInUse(tc);
    ArmFault::TranMethod tranMethod = long_desc_format ? ArmFault::LpaeTran
                                                       : ArmFault::VmsaTran;

    DPRINTF(TLBVerbose,
            "CPSR is priv:%d UserMode:%d secure:%d S1S2NsTran:%d\n",
            state.isPriv, flags & UserMode, state.isSecure,
            tran_type & S1S2NsTran);

    DPRINTF(TLB, "translateFs addr %#x, mode %d, st2 %d, scr %#x sctlr %#x "
                 "flags %#lx tranType 0x%x\n", vaddr_tainted, mode,
                 state.isStage2, state.scr, state.sctlr, flags, tran_type);

    if (!state.isStage2) {
        if ((req->isInstFetch() && (!state.sctlr.i)) ||
            ((!req->isInstFetch()) && (!state.sctlr.c))){
            if (!req->isCacheMaintenance()) {
                req->setFlags(Request::UNCACHEABLE);
            }
            req->setFlags(Request::STRICT_ORDER);
        }
    }
    if (!is_fetch) {
        if (state.sctlr.a || !(flags & AllowUnaligned)) {
            if (vaddr & mask(flags & AlignmentMask)) {
                stats.alignFaults++;
                return std::make_shared<DataAbort>(
                    vaddr_tainted,
                    TlbEntry::DomainType::NoAccess, is_write,
                    ArmFault::AlignmentFault, state.isStage2,
                    tranMethod);
            }
        }
    }

    bool vm = state.hcr.vm;
    if (HaveExt(tc, ArmExtension::FEAT_VHE) &&
        state.hcr.e2h == 1 && state.hcr.tge == 1)
        vm = 0;
    else if (state.hcr.dc == 1)
        vm = 1;

    Fault fault = NoFault;
    // If guest MMU is off or hcr.vm=0 go straight to stage2
    if ((state.isStage2 && !vm) || (!state.isStage2 && !state.sctlr.m)) {
        fault = translateMmuOff(tc, req, mode, tran_type, vaddr,
                                long_desc_format, state);
    } else {
        DPRINTF(TLBVerbose, "Translating %s=%#x context=%d\n",
                state.isStage2 ? "IPA" : "VA", vaddr_tainted, state.asid);
        // Translation enabled
        fault = translateMmuOn(tc, req, mode, translation, delay, timing,
                               functional, vaddr, tranMethod, state);
    }

    // Check for Debug Exceptions
    SelfDebug *sd = ArmISA::ISA::getSelfDebug(tc);

    if (sd->enabled() && fault == NoFault) {
        fault = sd->testDebug(tc, req, mode);
    }

    return fault;
}

Fault
MMU::translateAtomic(const RequestPtr &req, ThreadContext *tc, Mode mode,
    ArmTranslationType tran_type)
{
    return translateAtomic(req, tc, mode, tran_type, false);
}

Fault
MMU::translateAtomic(const RequestPtr &req, ThreadContext *tc, Mode mode,
    ArmTranslationType tran_type, bool stage2)
{
    auto& state = updateMiscReg(tc, tran_type, stage2);

    bool delay = false;
    Fault fault;
    if (FullSystem)
        fault = translateFs(req, tc, mode, NULL, delay, false,
            tran_type, false, state);
    else
        fault = translateSe(req, tc, mode, NULL, delay, false, state);
    assert(!delay);
    return fault;
}

Fault
MMU::translateFunctional(const RequestPtr &req, ThreadContext *tc, Mode mode)
{
    return translateFunctional(req, tc, mode, NormalTran, false);
}

Fault
MMU::translateFunctional(const RequestPtr &req, ThreadContext *tc, Mode mode,
    ArmTranslationType tran_type)
{
    return translateFunctional(req, tc, mode, tran_type, false);
}

Fault
MMU::translateFunctional(const RequestPtr &req, ThreadContext *tc, Mode mode,
    ArmTranslationType tran_type, bool stage2)
{
    auto& state = updateMiscReg(tc, tran_type, stage2);

    bool delay = false;
    Fault fault;
    if (FullSystem)
        fault = translateFs(req, tc, mode, NULL, delay, false,
            tran_type, true, state);
   else
        fault = translateSe(req, tc, mode, NULL, delay, false, state);
    assert(!delay);
    return fault;
}

void
MMU::translateTiming(const RequestPtr &req, ThreadContext *tc,
    Translation *translation, Mode mode, ArmTranslationType tran_type,
    bool stage2)
{
    auto& state = updateMiscReg(tc, tran_type, stage2);

    assert(translation);

    translateComplete(req, tc, translation, mode, tran_type,
        stage2, state);
}

Fault
MMU::translateComplete(const RequestPtr &req, ThreadContext *tc,
        Translation *translation, Mode mode, ArmTranslationType tran_type,
        bool call_from_s2)
{
    return translateComplete(req, tc, translation, mode, tran_type,
        call_from_s2, s1State);
}

Fault
MMU::translateComplete(const RequestPtr &req, ThreadContext *tc,
        Translation *translation, Mode mode, ArmTranslationType tran_type,
        bool call_from_s2, CachedState &state)
{
    bool delay = false;
    Fault fault;
    if (FullSystem)
        fault = translateFs(req, tc, mode, translation, delay, true, tran_type,
            false, state);
    else
        fault = translateSe(req, tc, mode, translation, delay, true, state);

    DPRINTF(TLBVerbose, "Translation returning delay=%d fault=%d\n", delay,
            fault != NoFault);
    // If we have a translation, and we're not in the middle of doing a stage
    // 2 translation tell the translation that we've either finished or its
    // going to take a while. By not doing this when we're in the middle of a
    // stage 2 translation we prevent marking the translation as delayed twice,
    // one when the translation starts and again when the stage 1 translation
    // completes.

    if (translation && (call_from_s2 || !state.stage2Req || req->hasPaddr() ||
        fault != NoFault)) {
        if (!delay)
            translation->finish(fault, req, tc, mode);
        else
            translation->markDelayed();
    }
    return fault;
}

vmid_t
MMU::CachedState::getVMID(ThreadContext *tc) const
{
    AA64MMFR1 mmfr1 = tc->readMiscReg(MISCREG_ID_AA64MMFR1_EL1);
    VTCR_t vtcr = tc->readMiscReg(MISCREG_VTCR_EL2);
    vmid_t vmid = 0;

    switch (mmfr1.vmidbits) {
      case 0b0000:
        // 8 bits
        vmid = bits(tc->readMiscReg(MISCREG_VTTBR_EL2), 55, 48);
        break;
      case 0b0010:
        if (vtcr.vs && ELIs64(tc, EL2)) {
            // 16 bits
            vmid = bits(tc->readMiscReg(MISCREG_VTTBR_EL2), 63, 48);
        } else {
            // 8 bits
            vmid = bits(tc->readMiscReg(MISCREG_VTTBR_EL2), 55, 48);
        }
        break;
      default:
        panic("Reserved ID_AA64MMFR1_EL1.VMIDBits value: %#x",
              mmfr1.vmidbits);
    }

    return vmid;
}

MMU::CachedState&
MMU::updateMiscReg(ThreadContext *tc,
    ArmTranslationType tran_type, bool stage2)
{
    // check if the regs have changed, or the translation mode is different.
    // NOTE: the tran type doesn't affect stage 2 TLB's as they only handle
    // one type of translation anyway

    auto& state = stage2 ? s2State : s1State;
    if (state.miscRegValid && miscRegContext == tc->contextId() &&
        ((tran_type == state.curTranType) || stage2)) {

    } else {
        DPRINTF(TLBVerbose, "TLB variables changed!\n");
        state.updateMiscReg(tc, tran_type);

        itbStage2->setVMID(state.vmid);
        dtbStage2->setVMID(state.vmid);

        for (auto tlb : instruction) {
            static_cast<TLB*>(tlb)->setVMID(state.vmid);
        }
        for (auto tlb : data) {
            static_cast<TLB*>(tlb)->setVMID(state.vmid);
        }
        for (auto tlb : unified) {
            static_cast<TLB*>(tlb)->setVMID(state.vmid);
        }

        miscRegContext = tc->contextId();
    }

    if (state.directToStage2) {
        s2State.updateMiscReg(tc, tran_type);
        return s2State;
    } else {
        return state;
    }
}

void
MMU::CachedState::updateMiscReg(ThreadContext *tc,
    ArmTranslationType tran_type)
{
    cpsr = tc->readMiscReg(MISCREG_CPSR);

    // Dependencies: SCR/SCR_EL3, CPSR
    isSecure = ArmISA::isSecure(tc) &&
        !(tran_type & HypMode) && !(tran_type & S1S2NsTran);

    aarch64EL = tranTypeEL(cpsr, tran_type);
    aarch64 = isStage2 ?
        ELIs64(tc, EL2) :
        ELIs64(tc, aarch64EL == EL0 ? EL1 : aarch64EL);

    hcr = tc->readMiscReg(MISCREG_HCR_EL2);
    if (aarch64) {  // AArch64
        // determine EL we need to translate in
        switch (aarch64EL) {
          case EL0:
            if (HaveExt(tc, ArmExtension::FEAT_VHE) &&
                hcr.tge == 1 && hcr.e2h == 1) {
                // VHE code for EL2&0 regime
                sctlr = tc->readMiscReg(MISCREG_SCTLR_EL2);
                ttbcr = tc->readMiscReg(MISCREG_TCR_EL2);
                uint64_t ttbr_asid = ttbcr.a1 ?
                    tc->readMiscReg(MISCREG_TTBR1_EL2) :
                    tc->readMiscReg(MISCREG_TTBR0_EL2);
                asid = bits(ttbr_asid,
                            (mmu->haveLargeAsid64 && ttbcr.as) ? 63 : 55, 48);

            } else {
                sctlr = tc->readMiscReg(MISCREG_SCTLR_EL1);
                ttbcr = tc->readMiscReg(MISCREG_TCR_EL1);
                uint64_t ttbr_asid = ttbcr.a1 ?
                    tc->readMiscReg(MISCREG_TTBR1_EL1) :
                    tc->readMiscReg(MISCREG_TTBR0_EL1);
                asid = bits(ttbr_asid,
                            (mmu->haveLargeAsid64 && ttbcr.as) ? 63 : 55, 48);

            }
            break;
          case EL1:
            {
                sctlr = tc->readMiscReg(MISCREG_SCTLR_EL1);
                ttbcr = tc->readMiscReg(MISCREG_TCR_EL1);
                uint64_t ttbr_asid = ttbcr.a1 ?
                    tc->readMiscReg(MISCREG_TTBR1_EL1) :
                    tc->readMiscReg(MISCREG_TTBR0_EL1);
                asid = bits(ttbr_asid,
                            (mmu->haveLargeAsid64 && ttbcr.as) ? 63 : 55, 48);
            }
            break;
          case EL2:
            sctlr = tc->readMiscReg(MISCREG_SCTLR_EL2);
            ttbcr = tc->readMiscReg(MISCREG_TCR_EL2);
            if (hcr.e2h == 1) {
                // VHE code for EL2&0 regime
                uint64_t ttbr_asid = ttbcr.a1 ?
                    tc->readMiscReg(MISCREG_TTBR1_EL2) :
                    tc->readMiscReg(MISCREG_TTBR0_EL2);
                asid = bits(ttbr_asid,
                            (mmu->haveLargeAsid64 && ttbcr.as) ? 63 : 55, 48);
            } else {
                asid = -1;
            }
            break;
          case EL3:
            sctlr = tc->readMiscReg(MISCREG_SCTLR_EL3);
            ttbcr = tc->readMiscReg(MISCREG_TCR_EL3);
            asid = -1;
            break;
        }

        scr = tc->readMiscReg(MISCREG_SCR_EL3);
        isPriv = aarch64EL != EL0;
        if (mmu->release()->has(ArmExtension::VIRTUALIZATION)) {
            vmid = getVMID(tc);
            isHyp = aarch64EL == EL2;
            isHyp |= tran_type & HypMode;
            isHyp &= (tran_type & S1S2NsTran) == 0;
            isHyp &= (tran_type & S1CTran)    == 0;
            bool vm = hcr.vm;
            if (HaveExt(tc, ArmExtension::FEAT_VHE) &&
                hcr.e2h == 1 && hcr.tge ==1) {
                vm = 0;
            }

            if (hcr.e2h == 1 && (aarch64EL == EL2
                                  || (hcr.tge ==1 && aarch64EL == EL0))) {
                isHyp = true;
                directToStage2 = false;
                stage2Req      = false;
                stage2DescReq  = false;
            } else {
            // Work out if we should skip the first stage of translation and go
            // directly to stage 2. This value is cached so we don't have to
            // compute it for every translation.
                bool sec = !isSecure || (isSecure && IsSecureEL2Enabled(tc));
                stage2Req = isStage2 ||
                            (vm && !isHyp && sec &&
                             !(tran_type & S1CTran) && (aarch64EL < EL2) &&
                             !(tran_type & S1E1Tran)); // <--- FIX THIS HACK
                stage2DescReq = isStage2 ||  (vm && !isHyp && sec &&
                                (aarch64EL < EL2));
                directToStage2 = !isStage2 && stage2Req && !sctlr.m;
            }
        } else {
            vmid           = 0;
            isHyp          = false;
            directToStage2 = false;
            stage2Req      = false;
            stage2DescReq  = false;
        }
    } else {  // AArch32
        sctlr  = tc->readMiscReg(snsBankedIndex(MISCREG_SCTLR, tc,
                                 !isSecure));
        ttbcr  = tc->readMiscReg(snsBankedIndex(MISCREG_TTBCR, tc,
                                 !isSecure));
        scr    = tc->readMiscReg(MISCREG_SCR);
        isPriv = cpsr.mode != MODE_USER;
        if (longDescFormatInUse(tc)) {
            uint64_t ttbr_asid = tc->readMiscReg(
                snsBankedIndex(ttbcr.a1 ? MISCREG_TTBR1 :
                                          MISCREG_TTBR0,
                                       tc, !isSecure));
            asid = bits(ttbr_asid, 55, 48);
        } else { // Short-descriptor translation table format in use
            CONTEXTIDR context_id = tc->readMiscReg(snsBankedIndex(
                MISCREG_CONTEXTIDR, tc,!isSecure));
            asid = context_id.asid;
        }
        prrr = tc->readMiscReg(snsBankedIndex(MISCREG_PRRR, tc,
                               !isSecure));
        nmrr = tc->readMiscReg(snsBankedIndex(MISCREG_NMRR, tc,
                               !isSecure));
        dacr = tc->readMiscReg(snsBankedIndex(MISCREG_DACR, tc,
                               !isSecure));
        hcr  = tc->readMiscReg(MISCREG_HCR);

        if (mmu->release()->has(ArmExtension::VIRTUALIZATION)) {
            vmid   = bits(tc->readMiscReg(MISCREG_VTTBR), 55, 48);
            isHyp  = cpsr.mode == MODE_HYP;
            isHyp |=  tran_type & HypMode;
            isHyp &= (tran_type & S1S2NsTran) == 0;
            isHyp &= (tran_type & S1CTran)    == 0;
            if (isHyp) {
                sctlr = tc->readMiscReg(MISCREG_HSCTLR);
            }
            // Work out if we should skip the first stage of translation and go
            // directly to stage 2. This value is cached so we don't have to
            // compute it for every translation.
            bool sec = !isSecure || (isSecure && IsSecureEL2Enabled(tc));
            stage2Req      = hcr.vm && !isStage2 && !isHyp && sec &&
                             !(tran_type & S1CTran);
            stage2DescReq  = hcr.vm && !isStage2 && !isHyp && sec;
            directToStage2 = stage2Req && !sctlr.m;
        } else {
            vmid           = 0;
            stage2Req      = false;
            isHyp          = false;
            directToStage2 = false;
            stage2DescReq  = false;
        }
    }
    miscRegValid = true;
    curTranType  = tran_type;
}

ExceptionLevel
MMU::tranTypeEL(CPSR cpsr, ArmTranslationType type)
{
    switch (type) {
      case S1E0Tran:
      case S12E0Tran:
        return EL0;

      case S1E1Tran:
      case S12E1Tran:
        return EL1;

      case S1E2Tran:
        return EL2;

      case S1E3Tran:
        return EL3;

      case NormalTran:
      case S1CTran:
      case S1S2NsTran:
      case HypMode:
        return currEL(cpsr);

      default:
        panic("Unknown translation mode!\n");
    }
}

Fault
MMU::getTE(TlbEntry **te, const RequestPtr &req, ThreadContext *tc, Mode mode,
        Translation *translation, bool timing, bool functional,
        bool is_secure, ArmTranslationType tran_type,
        bool stage2)
{
    return getTE(te, req, tc, mode, translation, timing, functional,
        is_secure, tran_type, stage2 ? s2State : s1State);
}

TlbEntry*
MMU::lookup(Addr va, uint16_t asid, vmid_t vmid, bool hyp, bool secure,
            bool functional, bool ignore_asn, ExceptionLevel target_el,
            bool in_host, bool stage2, BaseMMU::Mode mode)
{
    TLB *tlb = getTlb(mode, stage2);

    TlbEntry::Lookup lookup_data;

    lookup_data.va = va;
    lookup_data.asn = asid;
    lookup_data.ignoreAsn = ignore_asn;
    lookup_data.vmid = vmid;
    lookup_data.hyp = hyp;
    lookup_data.secure = secure;
    lookup_data.functional = functional;
    lookup_data.targetEL = target_el;
    lookup_data.inHost = in_host;
    lookup_data.mode = mode;

    return tlb->multiLookup(lookup_data);
}

Fault
MMU::getTE(TlbEntry **te, const RequestPtr &req, ThreadContext *tc, Mode mode,
        Translation *translation, bool timing, bool functional,
        bool is_secure, ArmTranslationType tran_type,
        CachedState& state)
{
    // In a 2-stage system, the IPA->PA translation can be started via this
    // call so make sure the miscRegs are correct.
    if (state.isStage2) {
        updateMiscReg(tc, tran_type, true);
    }

    Addr vaddr_tainted = req->getVaddr();
    Addr vaddr = 0;
    ExceptionLevel target_el = state.aarch64 ? state.aarch64EL : EL1;
    if (state.aarch64) {
        vaddr = purifyTaggedAddr(vaddr_tainted, tc, target_el,
            static_cast<TCR>(state.ttbcr), mode==Execute, state);
    } else {
        vaddr = vaddr_tainted;
    }

    *te = lookup(vaddr, state.asid, state.vmid, state.isHyp, is_secure, false,
                 false, target_el, false, state.isStage2, mode);

    if (!isCompleteTranslation(*te)) {
        if (req->isPrefetch()) {
            // if the request is a prefetch don't attempt to fill the TLB or go
            // any further with the memory access (here we can safely use the
            // fault status for the short desc. format in all cases)
           stats.prefetchFaults++;
           return std::make_shared<PrefetchAbort>(
               vaddr_tainted, ArmFault::PrefetchTLBMiss, state.isStage2);
        }

        // start translation table walk, pass variables rather than
        // re-retreaving in table walker for speed
        DPRINTF(TLB,
                "TLB Miss: Starting hardware table walker for %#x(%d:%d)\n",
                vaddr_tainted, state.asid, state.vmid);

        Fault fault;
        fault = getTableWalker(mode, state.isStage2)->walk(
            req, tc, state.asid, state.vmid, state.isHyp, mode,
            translation, timing, functional, is_secure,
            tran_type, state.stage2DescReq, *te);

        // for timing mode, return and wait for table walk,
        if (timing || fault != NoFault) {
            return fault;
        }

        *te = lookup(vaddr, state.asid, state.vmid, state.isHyp, is_secure,
                     true, false, target_el, false, state.isStage2, mode);
        assert(*te);
    }
    return NoFault;
}

Fault
MMU::getResultTe(TlbEntry **te, const RequestPtr &req,
        ThreadContext *tc, Mode mode,
        Translation *translation, bool timing, bool functional,
        TlbEntry *mergeTe, CachedState &state)
{
    Fault fault;

    if (state.isStage2) {
        // We are already in the stage 2 TLB. Grab the table entry for stage
        // 2 only. We are here because stage 1 translation is disabled.
        TlbEntry *s2_te = nullptr;
        // Get the stage 2 table entry
        fault = getTE(&s2_te, req, tc, mode, translation, timing, functional,
                      state.isSecure, state.curTranType, state);
        // Check permissions of stage 2
        if (isCompleteTranslation(s2_te) && (fault == NoFault)) {
            if (state.aarch64)
                fault = checkPermissions64(s2_te, req, mode, tc, state);
            else
                fault = checkPermissions(s2_te, req, mode, state);
        }
        *te = s2_te;
        return fault;
    }

    TlbEntry *s1_te = nullptr;

    Addr vaddr_tainted = req->getVaddr();

    // Get the stage 1 table entry
    fault = getTE(&s1_te, req, tc, mode, translation, timing, functional,
                  state.isSecure, state.curTranType, state);
    // only proceed if we have a valid table entry
    if (isCompleteTranslation(s1_te) && (fault == NoFault)) {
        // Check stage 1 permissions before checking stage 2
        if (state.aarch64)
            fault = checkPermissions64(s1_te, req, mode, tc, state);
        else
            fault = checkPermissions(s1_te, req, mode, state);
        if (state.stage2Req & (fault == NoFault)) {
            Stage2LookUp *s2_lookup = new Stage2LookUp(this, *s1_te,
                req, translation, mode, timing, functional, state.isSecure,
                state.curTranType);
            fault = s2_lookup->getTe(tc, mergeTe);
            if (s2_lookup->isComplete()) {
                *te = mergeTe;
                // We've finished with the lookup so delete it
                delete s2_lookup;
            } else {
                // The lookup hasn't completed, so we can't delete it now. We
                // get round this by asking the object to self delete when the
                // translation is complete.
                s2_lookup->setSelfDelete();
            }
        } else {
            // This case deals with an S1 hit (or bypass), followed by
            // an S2 hit-but-perms issue
            if (state.isStage2) {
                DPRINTF(TLBVerbose, "s2TLB: reqVa %#x, reqPa %#x, fault %p\n",
                        vaddr_tainted, req->hasPaddr() ? req->getPaddr() : ~0,
                        fault);
                if (fault != NoFault) {
                    auto arm_fault = reinterpret_cast<ArmFault*>(fault.get());
                    arm_fault->annotate(ArmFault::S1PTW, false);
                    arm_fault->annotate(ArmFault::OVA, vaddr_tainted);
                }
            }
            *te = s1_te;
        }
    }
    return fault;
}

bool
MMU::isCompleteTranslation(TlbEntry *entry) const
{
    return entry && !entry->partial;
}

void
MMU::takeOverFrom(BaseMMU *old_mmu)
{
    BaseMMU::takeOverFrom(old_mmu);

    auto *ommu = dynamic_cast<MMU*>(old_mmu);
    assert(ommu);

    _attr = ommu->_attr;

    s1State = ommu->s1State;
    s2State = ommu->s2State;
}

void
MMU::setTestInterface(SimObject *_ti)
{
    if (!_ti) {
        test = nullptr;
    } else {
        TlbTestInterface *ti(dynamic_cast<TlbTestInterface *>(_ti));
        fatal_if(!ti, "%s is not a valid ARM TLB tester\n", _ti->name());
        test = ti;
    }
}

Fault
MMU::testTranslation(const RequestPtr &req, Mode mode,
                     TlbEntry::DomainType domain, CachedState &state)
{
    if (!test || !req->hasSize() || req->getSize() == 0 ||
        req->isCacheMaintenance()) {
        return NoFault;
    } else {
        return test->translationCheck(req, state.isPriv, mode, domain);
    }
}

Fault
MMU::testWalk(Addr pa, Addr size, Addr va, bool is_secure, Mode mode,
              TlbEntry::DomainType domain, LookupLevel lookup_level,
              bool stage2)
{
    return testWalk(pa, size, va, is_secure, mode, domain, lookup_level,
        stage2 ? s2State : s1State);
}

Fault
MMU::testWalk(Addr pa, Addr size, Addr va, bool is_secure, Mode mode,
              TlbEntry::DomainType domain, LookupLevel lookup_level,
              CachedState &state)
{
    if (!test) {
        return NoFault;
    } else {
        return test->walkCheck(pa, size, va, is_secure, state.isPriv, mode,
                               domain, lookup_level);
    }
}

MMU::Stats::Stats(statistics::Group *parent)
  : statistics::Group(parent),
    ADD_STAT(alignFaults, statistics::units::Count::get(),
             "Number of MMU faults due to alignment restrictions"),
    ADD_STAT(prefetchFaults, statistics::units::Count::get(),
             "Number of MMU faults due to prefetch"),
    ADD_STAT(domainFaults, statistics::units::Count::get(),
             "Number of MMU faults due to domain restrictions"),
    ADD_STAT(permsFaults, statistics::units::Count::get(),
             "Number of MMU faults due to permissions restrictions")
{
}

} // namespace gem5
