table_walker.cc revision 11395
17404SAli.Saidi@ARM.com/*
210717Sandreas.hansson@arm.com * Copyright (c) 2010, 2012-2015 ARM Limited
37404SAli.Saidi@ARM.com * All rights reserved
47404SAli.Saidi@ARM.com *
57404SAli.Saidi@ARM.com * The license below extends only to copyright in the software and shall
67404SAli.Saidi@ARM.com * not be construed as granting a license to any other intellectual
77404SAli.Saidi@ARM.com * property including but not limited to intellectual property relating
87404SAli.Saidi@ARM.com * to a hardware implementation of the functionality of the software
97404SAli.Saidi@ARM.com * licensed hereunder.  You may use the software subject to the license
107404SAli.Saidi@ARM.com * terms below provided that you ensure that this notice is replicated
117404SAli.Saidi@ARM.com * unmodified and in its entirety in all distributions of the software,
127404SAli.Saidi@ARM.com * modified or unmodified, in source code or in binary form.
137404SAli.Saidi@ARM.com *
147404SAli.Saidi@ARM.com * Redistribution and use in source and binary forms, with or without
157404SAli.Saidi@ARM.com * modification, are permitted provided that the following conditions are
167404SAli.Saidi@ARM.com * met: redistributions of source code must retain the above copyright
177404SAli.Saidi@ARM.com * notice, this list of conditions and the following disclaimer;
187404SAli.Saidi@ARM.com * redistributions in binary form must reproduce the above copyright
197404SAli.Saidi@ARM.com * notice, this list of conditions and the following disclaimer in the
207404SAli.Saidi@ARM.com * documentation and/or other materials provided with the distribution;
217404SAli.Saidi@ARM.com * neither the name of the copyright holders nor the names of its
227404SAli.Saidi@ARM.com * contributors may be used to endorse or promote products derived from
237404SAli.Saidi@ARM.com * this software without specific prior written permission.
247404SAli.Saidi@ARM.com *
257404SAli.Saidi@ARM.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
267404SAli.Saidi@ARM.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
277404SAli.Saidi@ARM.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
287404SAli.Saidi@ARM.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
297404SAli.Saidi@ARM.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
307404SAli.Saidi@ARM.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
317404SAli.Saidi@ARM.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
327404SAli.Saidi@ARM.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
337404SAli.Saidi@ARM.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
347404SAli.Saidi@ARM.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
357404SAli.Saidi@ARM.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
367404SAli.Saidi@ARM.com *
377404SAli.Saidi@ARM.com * Authors: Ali Saidi
3810037SARM gem5 Developers *          Giacomo Gabrielli
397404SAli.Saidi@ARM.com */
4010873Sandreas.sandberg@arm.com#include "arch/arm/table_walker.hh"
417404SAli.Saidi@ARM.com
4210474Sandreas.hansson@arm.com#include <memory>
4310474Sandreas.hansson@arm.com
447404SAli.Saidi@ARM.com#include "arch/arm/faults.hh"
4510037SARM gem5 Developers#include "arch/arm/stage2_mmu.hh"
4610037SARM gem5 Developers#include "arch/arm/system.hh"
477404SAli.Saidi@ARM.com#include "arch/arm/tlb.hh"
487728SAli.Saidi@ARM.com#include "cpu/base.hh"
497404SAli.Saidi@ARM.com#include "cpu/thread_context.hh"
508245Snate@binkert.org#include "debug/Checkpoint.hh"
519152Satgutier@umich.edu#include "debug/Drain.hh"
528245Snate@binkert.org#include "debug/TLB.hh"
538245Snate@binkert.org#include "debug/TLBVerbose.hh"
5410873Sandreas.sandberg@arm.com#include "dev/dma_device.hh"
557748SAli.Saidi@ARM.com#include "sim/system.hh"
567404SAli.Saidi@ARM.com
577404SAli.Saidi@ARM.comusing namespace ArmISA;
587404SAli.Saidi@ARM.com
597404SAli.Saidi@ARM.comTableWalker::TableWalker(const Params *p)
6010913Sandreas.sandberg@arm.com    : MemObject(p),
6110717Sandreas.hansson@arm.com      stage2Mmu(NULL), port(NULL), masterId(Request::invldMasterId),
6210717Sandreas.hansson@arm.com      isStage2(p->is_stage2), tlb(NULL),
6310717Sandreas.hansson@arm.com      currState(NULL), pending(false),
649258SAli.Saidi@ARM.com      numSquashable(p->num_squash_per_cycle),
6510621SCurtis.Dunham@arm.com      pendingReqs(0),
6610621SCurtis.Dunham@arm.com      pendingChangeTick(curTick()),
6710037SARM gem5 Developers      doL1DescEvent(this), doL2DescEvent(this),
6810037SARM gem5 Developers      doL0LongDescEvent(this), doL1LongDescEvent(this), doL2LongDescEvent(this),
6910037SARM gem5 Developers      doL3LongDescEvent(this),
7010037SARM gem5 Developers      doProcessEvent(this)
717439Sdam.sunwoo@arm.com{
727576SAli.Saidi@ARM.com    sctlr = 0;
7310037SARM gem5 Developers
7410037SARM gem5 Developers    // Cache system-level properties
7510037SARM gem5 Developers    if (FullSystem) {
7610717Sandreas.hansson@arm.com        ArmSystem *armSys = dynamic_cast<ArmSystem *>(p->sys);
7710037SARM gem5 Developers        assert(armSys);
7810037SARM gem5 Developers        haveSecurity = armSys->haveSecurity();
7910037SARM gem5 Developers        _haveLPAE = armSys->haveLPAE();
8010037SARM gem5 Developers        _haveVirtualization = armSys->haveVirtualization();
8110037SARM gem5 Developers        physAddrRange = armSys->physAddrRange();
8210037SARM gem5 Developers        _haveLargeAsid64 = armSys->haveLargeAsid64();
8310037SARM gem5 Developers    } else {
8410037SARM gem5 Developers        haveSecurity = _haveLPAE = _haveVirtualization = false;
8510037SARM gem5 Developers        _haveLargeAsid64 = false;
8610037SARM gem5 Developers        physAddrRange = 32;
8710037SARM gem5 Developers    }
8810037SARM gem5 Developers
897439Sdam.sunwoo@arm.com}
907404SAli.Saidi@ARM.com
917404SAli.Saidi@ARM.comTableWalker::~TableWalker()
927404SAli.Saidi@ARM.com{
937404SAli.Saidi@ARM.com    ;
947404SAli.Saidi@ARM.com}
957404SAli.Saidi@ARM.com
9610717Sandreas.hansson@arm.comvoid
9710717Sandreas.hansson@arm.comTableWalker::setMMU(Stage2MMU *m, MasterID master_id)
9810717Sandreas.hansson@arm.com{
9910717Sandreas.hansson@arm.com    stage2Mmu = m;
10010717Sandreas.hansson@arm.com    port = &m->getPort();
10110717Sandreas.hansson@arm.com    masterId = master_id;
10210717Sandreas.hansson@arm.com}
10310717Sandreas.hansson@arm.com
10410717Sandreas.hansson@arm.comvoid
10510717Sandreas.hansson@arm.comTableWalker::init()
10610717Sandreas.hansson@arm.com{
10710717Sandreas.hansson@arm.com    fatal_if(!stage2Mmu, "Table walker must have a valid stage-2 MMU\n");
10810717Sandreas.hansson@arm.com    fatal_if(!port, "Table walker must have a valid port\n");
10910717Sandreas.hansson@arm.com    fatal_if(!tlb, "Table walker must have a valid TLB\n");
11010717Sandreas.hansson@arm.com}
11110717Sandreas.hansson@arm.com
11210717Sandreas.hansson@arm.comBaseMasterPort&
11310717Sandreas.hansson@arm.comTableWalker::getMasterPort(const std::string &if_name, PortID idx)
11410717Sandreas.hansson@arm.com{
11510717Sandreas.hansson@arm.com    if (if_name == "port") {
11610717Sandreas.hansson@arm.com        if (!isStage2) {
11710717Sandreas.hansson@arm.com            return *port;
11810717Sandreas.hansson@arm.com        } else {
11910717Sandreas.hansson@arm.com            fatal("Cannot access table walker port through stage-two walker\n");
12010717Sandreas.hansson@arm.com        }
12110717Sandreas.hansson@arm.com    }
12210717Sandreas.hansson@arm.com    return MemObject::getMasterPort(if_name, idx);
12310717Sandreas.hansson@arm.com}
12410717Sandreas.hansson@arm.com
12510537Sandreas.hansson@arm.comTableWalker::WalkerState::WalkerState() :
12610537Sandreas.hansson@arm.com    tc(nullptr), aarch64(false), el(EL0), physAddrRange(0), req(nullptr),
12710537Sandreas.hansson@arm.com    asid(0), vmid(0), isHyp(false), transState(nullptr),
12810537Sandreas.hansson@arm.com    vaddr(0), vaddr_tainted(0), isWrite(false), isFetch(false), isSecure(false),
12910537Sandreas.hansson@arm.com    secureLookup(false), rwTable(false), userTable(false), xnTable(false),
13010537Sandreas.hansson@arm.com    pxnTable(false), stage2Req(false), doingStage2(false),
13110537Sandreas.hansson@arm.com    stage2Tran(nullptr), timing(false), functional(false),
13210537Sandreas.hansson@arm.com    mode(BaseTLB::Read), tranType(TLB::NormalTran), l2Desc(l1Desc),
13310537Sandreas.hansson@arm.com    delayed(false), tableWalker(nullptr)
13410037SARM gem5 Developers{
13510037SARM gem5 Developers}
13610037SARM gem5 Developers
1379152Satgutier@umich.eduvoid
1389152Satgutier@umich.eduTableWalker::completeDrain()
1399152Satgutier@umich.edu{
14010913Sandreas.sandberg@arm.com    if (drainState() == DrainState::Draining &&
14110913Sandreas.sandberg@arm.com        stateQueues[L1].empty() && stateQueues[L2].empty() &&
1429152Satgutier@umich.edu        pendingQueue.empty()) {
14310913Sandreas.sandberg@arm.com
1449152Satgutier@umich.edu        DPRINTF(Drain, "TableWalker done draining, processing drain event\n");
14510913Sandreas.sandberg@arm.com        signalDrainDone();
1469152Satgutier@umich.edu    }
1479152Satgutier@umich.edu}
1489152Satgutier@umich.edu
14910913Sandreas.sandberg@arm.comDrainState
15010913Sandreas.sandberg@arm.comTableWalker::drain()
1517404SAli.Saidi@ARM.com{
15210037SARM gem5 Developers    bool state_queues_not_empty = false;
1539152Satgutier@umich.edu
15410037SARM gem5 Developers    for (int i = 0; i < MAX_LOOKUP_LEVELS; ++i) {
15510037SARM gem5 Developers        if (!stateQueues[i].empty()) {
15610037SARM gem5 Developers            state_queues_not_empty = true;
15710037SARM gem5 Developers            break;
15810037SARM gem5 Developers        }
15910037SARM gem5 Developers    }
16010037SARM gem5 Developers
16110037SARM gem5 Developers    if (state_queues_not_empty || pendingQueue.size()) {
1629152Satgutier@umich.edu        DPRINTF(Drain, "TableWalker not drained\n");
16310913Sandreas.sandberg@arm.com        return DrainState::Draining;
16410037SARM gem5 Developers    } else {
16510037SARM gem5 Developers        DPRINTF(Drain, "TableWalker free, no need to drain\n");
16610913Sandreas.sandberg@arm.com        return DrainState::Drained;
1677733SAli.Saidi@ARM.com    }
1687404SAli.Saidi@ARM.com}
1697404SAli.Saidi@ARM.com
1707748SAli.Saidi@ARM.comvoid
1719342SAndreas.Sandberg@arm.comTableWalker::drainResume()
1727748SAli.Saidi@ARM.com{
1739524SAndreas.Sandberg@ARM.com    if (params()->sys->isTimingMode() && currState) {
1749152Satgutier@umich.edu        delete currState;
1759152Satgutier@umich.edu        currState = NULL;
17610621SCurtis.Dunham@arm.com        pendingChange();
1777748SAli.Saidi@ARM.com    }
1787748SAli.Saidi@ARM.com}
1797748SAli.Saidi@ARM.com
1807404SAli.Saidi@ARM.comFault
18110037SARM gem5 DevelopersTableWalker::walk(RequestPtr _req, ThreadContext *_tc, uint16_t _asid,
18210037SARM gem5 Developers                  uint8_t _vmid, bool _isHyp, TLB::Mode _mode,
18310037SARM gem5 Developers                  TLB::Translation *_trans, bool _timing, bool _functional,
18410037SARM gem5 Developers                  bool secure, TLB::ArmTranslationType tranType)
1857404SAli.Saidi@ARM.com{
1868733Sgeoffrey.blake@arm.com    assert(!(_functional && _timing));
18710621SCurtis.Dunham@arm.com    ++statWalks;
18810621SCurtis.Dunham@arm.com
18910109SGeoffrey.Blake@arm.com    WalkerState *savedCurrState = NULL;
19010037SARM gem5 Developers
19110109SGeoffrey.Blake@arm.com    if (!currState && !_functional) {
1927439Sdam.sunwoo@arm.com        // For atomic mode, a new WalkerState instance should be only created
1937439Sdam.sunwoo@arm.com        // once per TLB. For timing mode, a new instance is generated for every
1947439Sdam.sunwoo@arm.com        // TLB miss.
1957439Sdam.sunwoo@arm.com        DPRINTF(TLBVerbose, "creating new instance of WalkerState\n");
1967404SAli.Saidi@ARM.com
1977439Sdam.sunwoo@arm.com        currState = new WalkerState();
1987439Sdam.sunwoo@arm.com        currState->tableWalker = this;
19910109SGeoffrey.Blake@arm.com    } else if (_functional) {
20010109SGeoffrey.Blake@arm.com        // If we are mixing functional mode with timing (or even
20110109SGeoffrey.Blake@arm.com        // atomic), we need to to be careful and clean up after
20210109SGeoffrey.Blake@arm.com        // ourselves to not risk getting into an inconsistent state.
20310109SGeoffrey.Blake@arm.com        DPRINTF(TLBVerbose, "creating functional instance of WalkerState\n");
20410109SGeoffrey.Blake@arm.com        savedCurrState = currState;
20510109SGeoffrey.Blake@arm.com        currState = new WalkerState();
20610109SGeoffrey.Blake@arm.com        currState->tableWalker = this;
2078202SAli.Saidi@ARM.com    } else if (_timing) {
2088202SAli.Saidi@ARM.com        // This is a translation that was completed and then faulted again
2098202SAli.Saidi@ARM.com        // because some underlying parameters that affect the translation
2108202SAli.Saidi@ARM.com        // changed out from under us (e.g. asid). It will either be a
2118202SAli.Saidi@ARM.com        // misprediction, in which case nothing will happen or we'll use
2128202SAli.Saidi@ARM.com        // this fault to re-execute the faulting instruction which should clean
2138202SAli.Saidi@ARM.com        // up everything.
21410037SARM gem5 Developers        if (currState->vaddr_tainted == _req->getVaddr()) {
21510621SCurtis.Dunham@arm.com            ++statSquashedBefore;
21610474Sandreas.hansson@arm.com            return std::make_shared<ReExec>();
2178202SAli.Saidi@ARM.com        }
2187439Sdam.sunwoo@arm.com    }
21910621SCurtis.Dunham@arm.com    pendingChange();
2207439Sdam.sunwoo@arm.com
22110621SCurtis.Dunham@arm.com    currState->startTime = curTick();
2227439Sdam.sunwoo@arm.com    currState->tc = _tc;
22310037SARM gem5 Developers    currState->aarch64 = opModeIs64(currOpMode(_tc));
22410037SARM gem5 Developers    currState->el = currEL(_tc);
2257439Sdam.sunwoo@arm.com    currState->transState = _trans;
2267439Sdam.sunwoo@arm.com    currState->req = _req;
2277439Sdam.sunwoo@arm.com    currState->fault = NoFault;
22810037SARM gem5 Developers    currState->asid = _asid;
22910037SARM gem5 Developers    currState->vmid = _vmid;
23010037SARM gem5 Developers    currState->isHyp = _isHyp;
2317439Sdam.sunwoo@arm.com    currState->timing = _timing;
2328733Sgeoffrey.blake@arm.com    currState->functional = _functional;
2337439Sdam.sunwoo@arm.com    currState->mode = _mode;
23410037SARM gem5 Developers    currState->tranType = tranType;
23510037SARM gem5 Developers    currState->isSecure = secure;
23610037SARM gem5 Developers    currState->physAddrRange = physAddrRange;
2377404SAli.Saidi@ARM.com
2387436Sdam.sunwoo@arm.com    /** @todo These should be cached or grabbed from cached copies in
2397436Sdam.sunwoo@arm.com     the TLB, all these miscreg reads are expensive */
24010037SARM gem5 Developers    currState->vaddr_tainted = currState->req->getVaddr();
24110037SARM gem5 Developers    if (currState->aarch64)
24210037SARM gem5 Developers        currState->vaddr = purifyTaggedAddr(currState->vaddr_tainted,
24310037SARM gem5 Developers                                            currState->tc, currState->el);
24410037SARM gem5 Developers    else
24510037SARM gem5 Developers        currState->vaddr = currState->vaddr_tainted;
24610037SARM gem5 Developers
24710037SARM gem5 Developers    if (currState->aarch64) {
24810037SARM gem5 Developers        switch (currState->el) {
24910037SARM gem5 Developers          case EL0:
25010037SARM gem5 Developers          case EL1:
25110037SARM gem5 Developers            currState->sctlr = currState->tc->readMiscReg(MISCREG_SCTLR_EL1);
25210324SCurtis.Dunham@arm.com            currState->tcr = currState->tc->readMiscReg(MISCREG_TCR_EL1);
25310037SARM gem5 Developers            break;
25410037SARM gem5 Developers          // @todo: uncomment this to enable Virtualization
25510037SARM gem5 Developers          // case EL2:
25610037SARM gem5 Developers          //   assert(haveVirtualization);
25710037SARM gem5 Developers          //   currState->sctlr = currState->tc->readMiscReg(MISCREG_SCTLR_EL2);
25810324SCurtis.Dunham@arm.com          //   currState->tcr = currState->tc->readMiscReg(MISCREG_TCR_EL2);
25910037SARM gem5 Developers          //   break;
26010037SARM gem5 Developers          case EL3:
26110037SARM gem5 Developers            assert(haveSecurity);
26210037SARM gem5 Developers            currState->sctlr = currState->tc->readMiscReg(MISCREG_SCTLR_EL3);
26310324SCurtis.Dunham@arm.com            currState->tcr = currState->tc->readMiscReg(MISCREG_TCR_EL3);
26410037SARM gem5 Developers            break;
26510037SARM gem5 Developers          default:
26610037SARM gem5 Developers            panic("Invalid exception level");
26710037SARM gem5 Developers            break;
26810037SARM gem5 Developers        }
26910037SARM gem5 Developers    } else {
27010037SARM gem5 Developers        currState->sctlr = currState->tc->readMiscReg(flattenMiscRegNsBanked(
27110037SARM gem5 Developers            MISCREG_SCTLR, currState->tc, !currState->isSecure));
27210037SARM gem5 Developers        currState->ttbcr = currState->tc->readMiscReg(flattenMiscRegNsBanked(
27310037SARM gem5 Developers            MISCREG_TTBCR, currState->tc, !currState->isSecure));
27410037SARM gem5 Developers        currState->htcr  = currState->tc->readMiscReg(MISCREG_HTCR);
27510037SARM gem5 Developers        currState->hcr   = currState->tc->readMiscReg(MISCREG_HCR);
27610037SARM gem5 Developers        currState->vtcr  = currState->tc->readMiscReg(MISCREG_VTCR);
27710037SARM gem5 Developers    }
2787439Sdam.sunwoo@arm.com    sctlr = currState->sctlr;
2797439Sdam.sunwoo@arm.com
2807439Sdam.sunwoo@arm.com    currState->isFetch = (currState->mode == TLB::Execute);
2817439Sdam.sunwoo@arm.com    currState->isWrite = (currState->mode == TLB::Write);
2827439Sdam.sunwoo@arm.com
28310621SCurtis.Dunham@arm.com    statRequestOrigin[REQUESTED][currState->isFetch]++;
28410621SCurtis.Dunham@arm.com
28510037SARM gem5 Developers    // We only do a second stage of translation if we're not secure, or in
28610037SARM gem5 Developers    // hyp mode, the second stage MMU is enabled, and this table walker
28710037SARM gem5 Developers    // instance is the first stage.
28810037SARM gem5 Developers    currState->doingStage2 = false;
28910037SARM gem5 Developers    // @todo: for now disable this in AArch64 (HCR is not set)
29010037SARM gem5 Developers    currState->stage2Req = !currState->aarch64 && currState->hcr.vm &&
29110037SARM gem5 Developers                           !isStage2 && !currState->isSecure && !currState->isHyp;
2927728SAli.Saidi@ARM.com
29310037SARM gem5 Developers    bool long_desc_format = currState->aarch64 ||
29410037SARM gem5 Developers                            (_haveLPAE && currState->ttbcr.eae) ||
29510037SARM gem5 Developers                            _isHyp || isStage2;
29610037SARM gem5 Developers
29710037SARM gem5 Developers    if (long_desc_format) {
29810037SARM gem5 Developers        // Helper variables used for hierarchical permissions
29910037SARM gem5 Developers        currState->secureLookup = currState->isSecure;
30010037SARM gem5 Developers        currState->rwTable = true;
30110037SARM gem5 Developers        currState->userTable = true;
30210037SARM gem5 Developers        currState->xnTable = false;
30310037SARM gem5 Developers        currState->pxnTable = false;
30410621SCurtis.Dunham@arm.com
30510621SCurtis.Dunham@arm.com        ++statWalksLongDescriptor;
30610621SCurtis.Dunham@arm.com    } else {
30710621SCurtis.Dunham@arm.com        ++statWalksShortDescriptor;
30810037SARM gem5 Developers    }
30910037SARM gem5 Developers
31010037SARM gem5 Developers    if (!currState->timing) {
31110109SGeoffrey.Blake@arm.com        Fault fault = NoFault;
31210037SARM gem5 Developers        if (currState->aarch64)
31310109SGeoffrey.Blake@arm.com            fault = processWalkAArch64();
31410037SARM gem5 Developers        else if (long_desc_format)
31510109SGeoffrey.Blake@arm.com            fault = processWalkLPAE();
31610037SARM gem5 Developers        else
31710109SGeoffrey.Blake@arm.com            fault = processWalk();
31810109SGeoffrey.Blake@arm.com
31910109SGeoffrey.Blake@arm.com        // If this was a functional non-timing access restore state to
32010109SGeoffrey.Blake@arm.com        // how we found it.
32110109SGeoffrey.Blake@arm.com        if (currState->functional) {
32210109SGeoffrey.Blake@arm.com            delete currState;
32310109SGeoffrey.Blake@arm.com            currState = savedCurrState;
32410109SGeoffrey.Blake@arm.com        }
32510109SGeoffrey.Blake@arm.com        return fault;
32610037SARM gem5 Developers    }
3277728SAli.Saidi@ARM.com
3288067SAli.Saidi@ARM.com    if (pending || pendingQueue.size()) {
3297728SAli.Saidi@ARM.com        pendingQueue.push_back(currState);
3307728SAli.Saidi@ARM.com        currState = NULL;
33110621SCurtis.Dunham@arm.com        pendingChange();
3327728SAli.Saidi@ARM.com    } else {
3337728SAli.Saidi@ARM.com        pending = true;
33410621SCurtis.Dunham@arm.com        pendingChange();
33510037SARM gem5 Developers        if (currState->aarch64)
33610037SARM gem5 Developers            return processWalkAArch64();
33710037SARM gem5 Developers        else if (long_desc_format)
33810037SARM gem5 Developers            return processWalkLPAE();
33910037SARM gem5 Developers        else
34010037SARM gem5 Developers            return processWalk();
3417728SAli.Saidi@ARM.com    }
3427728SAli.Saidi@ARM.com
3437728SAli.Saidi@ARM.com    return NoFault;
3447728SAli.Saidi@ARM.com}
3457728SAli.Saidi@ARM.com
3467728SAli.Saidi@ARM.comvoid
3477728SAli.Saidi@ARM.comTableWalker::processWalkWrapper()
3487728SAli.Saidi@ARM.com{
3497728SAli.Saidi@ARM.com    assert(!currState);
3507728SAli.Saidi@ARM.com    assert(pendingQueue.size());
35110621SCurtis.Dunham@arm.com    pendingChange();
3527728SAli.Saidi@ARM.com    currState = pendingQueue.front();
3539258SAli.Saidi@ARM.com
35410037SARM gem5 Developers    ExceptionLevel target_el = EL0;
35510037SARM gem5 Developers    if (currState->aarch64)
35610037SARM gem5 Developers        target_el = currEL(currState->tc);
35710037SARM gem5 Developers    else
35810037SARM gem5 Developers        target_el = EL1;
35910037SARM gem5 Developers
3609535Smrinmoy.ghosh@arm.com    // Check if a previous walk filled this request already
36110037SARM gem5 Developers    // @TODO Should this always be the TLB or should we look in the stage2 TLB?
36210037SARM gem5 Developers    TlbEntry* te = tlb->lookup(currState->vaddr, currState->asid,
36310037SARM gem5 Developers            currState->vmid, currState->isHyp, currState->isSecure, true, false,
36410037SARM gem5 Developers            target_el);
3659258SAli.Saidi@ARM.com
3669535Smrinmoy.ghosh@arm.com    // Check if we still need to have a walk for this request. If the requesting
3679535Smrinmoy.ghosh@arm.com    // instruction has been squashed, or a previous walk has filled the TLB with
3689535Smrinmoy.ghosh@arm.com    // a match, we just want to get rid of the walk. The latter could happen
3699535Smrinmoy.ghosh@arm.com    // when there are multiple outstanding misses to a single page and a
3709535Smrinmoy.ghosh@arm.com    // previous request has been successfully translated.
3719535Smrinmoy.ghosh@arm.com    if (!currState->transState->squashed() && !te) {
3729258SAli.Saidi@ARM.com        // We've got a valid request, lets process it
3739258SAli.Saidi@ARM.com        pending = true;
3749258SAli.Saidi@ARM.com        pendingQueue.pop_front();
37510579SAndrew.Bardsley@arm.com        // Keep currState in case one of the processWalk... calls NULLs it
37610579SAndrew.Bardsley@arm.com        WalkerState *curr_state_copy = currState;
37710579SAndrew.Bardsley@arm.com        Fault f;
37810037SARM gem5 Developers        if (currState->aarch64)
37910579SAndrew.Bardsley@arm.com            f = processWalkAArch64();
38010037SARM gem5 Developers        else if ((_haveLPAE && currState->ttbcr.eae) || currState->isHyp || isStage2)
38110579SAndrew.Bardsley@arm.com            f = processWalkLPAE();
38210037SARM gem5 Developers        else
38310579SAndrew.Bardsley@arm.com            f = processWalk();
38410579SAndrew.Bardsley@arm.com
38510579SAndrew.Bardsley@arm.com        if (f != NoFault) {
38610579SAndrew.Bardsley@arm.com            curr_state_copy->transState->finish(f, curr_state_copy->req,
38710579SAndrew.Bardsley@arm.com                    curr_state_copy->tc, curr_state_copy->mode);
38810579SAndrew.Bardsley@arm.com
38910579SAndrew.Bardsley@arm.com            delete curr_state_copy;
39010579SAndrew.Bardsley@arm.com        }
3919258SAli.Saidi@ARM.com        return;
3929258SAli.Saidi@ARM.com    }
3939258SAli.Saidi@ARM.com
3949258SAli.Saidi@ARM.com
3959258SAli.Saidi@ARM.com    // If the instruction that we were translating for has been
3969258SAli.Saidi@ARM.com    // squashed we shouldn't bother.
3979258SAli.Saidi@ARM.com    unsigned num_squashed = 0;
3989258SAli.Saidi@ARM.com    ThreadContext *tc = currState->tc;
3999258SAli.Saidi@ARM.com    while ((num_squashed < numSquashable) && currState &&
4009535Smrinmoy.ghosh@arm.com           (currState->transState->squashed() || te)) {
4019258SAli.Saidi@ARM.com        pendingQueue.pop_front();
4029258SAli.Saidi@ARM.com        num_squashed++;
40310621SCurtis.Dunham@arm.com        statSquashedBefore++;
4049258SAli.Saidi@ARM.com
40510037SARM gem5 Developers        DPRINTF(TLB, "Squashing table walk for address %#x\n",
40610037SARM gem5 Developers                      currState->vaddr_tainted);
4079258SAli.Saidi@ARM.com
4089535Smrinmoy.ghosh@arm.com        if (currState->transState->squashed()) {
4099535Smrinmoy.ghosh@arm.com            // finish the translation which will delete the translation object
41010474Sandreas.hansson@arm.com            currState->transState->finish(
41110474Sandreas.hansson@arm.com                std::make_shared<UnimpFault>("Squashed Inst"),
41210474Sandreas.hansson@arm.com                currState->req, currState->tc, currState->mode);
4139535Smrinmoy.ghosh@arm.com        } else {
4149535Smrinmoy.ghosh@arm.com            // translate the request now that we know it will work
41510621SCurtis.Dunham@arm.com            statWalkServiceTime.sample(curTick() - currState->startTime);
41610037SARM gem5 Developers            tlb->translateTiming(currState->req, currState->tc,
41710037SARM gem5 Developers                        currState->transState, currState->mode);
41810037SARM gem5 Developers
4199535Smrinmoy.ghosh@arm.com        }
4209258SAli.Saidi@ARM.com
4219258SAli.Saidi@ARM.com        // delete the current request
4229258SAli.Saidi@ARM.com        delete currState;
4239258SAli.Saidi@ARM.com
4249258SAli.Saidi@ARM.com        // peak at the next one
4259535Smrinmoy.ghosh@arm.com        if (pendingQueue.size()) {
4269258SAli.Saidi@ARM.com            currState = pendingQueue.front();
42710037SARM gem5 Developers            te = tlb->lookup(currState->vaddr, currState->asid,
42810037SARM gem5 Developers                currState->vmid, currState->isHyp, currState->isSecure, true,
42910037SARM gem5 Developers                false, target_el);
4309535Smrinmoy.ghosh@arm.com        } else {
4319535Smrinmoy.ghosh@arm.com            // Terminate the loop, nothing more to do
4329258SAli.Saidi@ARM.com            currState = NULL;
4339535Smrinmoy.ghosh@arm.com        }
4349258SAli.Saidi@ARM.com    }
43510621SCurtis.Dunham@arm.com    pendingChange();
4369258SAli.Saidi@ARM.com
43710621SCurtis.Dunham@arm.com    // if we still have pending translations, schedule more work
4389258SAli.Saidi@ARM.com    nextWalk(tc);
4399258SAli.Saidi@ARM.com    currState = NULL;
4407728SAli.Saidi@ARM.com}
4417728SAli.Saidi@ARM.com
4427728SAli.Saidi@ARM.comFault
4437728SAli.Saidi@ARM.comTableWalker::processWalk()
4447728SAli.Saidi@ARM.com{
4457404SAli.Saidi@ARM.com    Addr ttbr = 0;
4467404SAli.Saidi@ARM.com
4477404SAli.Saidi@ARM.com    // If translation isn't enabled, we shouldn't be here
44810037SARM gem5 Developers    assert(currState->sctlr.m || isStage2);
4497404SAli.Saidi@ARM.com
45010037SARM gem5 Developers    DPRINTF(TLB, "Beginning table walk for address %#x, TTBCR: %#x, bits:%#x\n",
45110037SARM gem5 Developers            currState->vaddr_tainted, currState->ttbcr, mbits(currState->vaddr, 31,
45210037SARM gem5 Developers                                                      32 - currState->ttbcr.n));
4537406SAli.Saidi@ARM.com
45410621SCurtis.Dunham@arm.com    statWalkWaitTime.sample(curTick() - currState->startTime);
45510621SCurtis.Dunham@arm.com
45610037SARM gem5 Developers    if (currState->ttbcr.n == 0 || !mbits(currState->vaddr, 31,
45710037SARM gem5 Developers                                          32 - currState->ttbcr.n)) {
4587406SAli.Saidi@ARM.com        DPRINTF(TLB, " - Selecting TTBR0\n");
45910037SARM gem5 Developers        // Check if table walk is allowed when Security Extensions are enabled
46010037SARM gem5 Developers        if (haveSecurity && currState->ttbcr.pd0) {
46110037SARM gem5 Developers            if (currState->isFetch)
46210474Sandreas.hansson@arm.com                return std::make_shared<PrefetchAbort>(
46310474Sandreas.hansson@arm.com                    currState->vaddr_tainted,
46410474Sandreas.hansson@arm.com                    ArmFault::TranslationLL + L1,
46510474Sandreas.hansson@arm.com                    isStage2,
46610474Sandreas.hansson@arm.com                    ArmFault::VmsaTran);
46710037SARM gem5 Developers            else
46810474Sandreas.hansson@arm.com                return std::make_shared<DataAbort>(
46910474Sandreas.hansson@arm.com                    currState->vaddr_tainted,
47010474Sandreas.hansson@arm.com                    TlbEntry::DomainType::NoAccess, currState->isWrite,
47110474Sandreas.hansson@arm.com                    ArmFault::TranslationLL + L1, isStage2,
47210474Sandreas.hansson@arm.com                    ArmFault::VmsaTran);
47310037SARM gem5 Developers        }
47410037SARM gem5 Developers        ttbr = currState->tc->readMiscReg(flattenMiscRegNsBanked(
47510037SARM gem5 Developers            MISCREG_TTBR0, currState->tc, !currState->isSecure));
4767404SAli.Saidi@ARM.com    } else {
4777406SAli.Saidi@ARM.com        DPRINTF(TLB, " - Selecting TTBR1\n");
47810037SARM gem5 Developers        // Check if table walk is allowed when Security Extensions are enabled
47910037SARM gem5 Developers        if (haveSecurity && currState->ttbcr.pd1) {
48010037SARM gem5 Developers            if (currState->isFetch)
48110474Sandreas.hansson@arm.com                return std::make_shared<PrefetchAbort>(
48210474Sandreas.hansson@arm.com                    currState->vaddr_tainted,
48310474Sandreas.hansson@arm.com                    ArmFault::TranslationLL + L1,
48410474Sandreas.hansson@arm.com                    isStage2,
48510474Sandreas.hansson@arm.com                    ArmFault::VmsaTran);
48610037SARM gem5 Developers            else
48710474Sandreas.hansson@arm.com                return std::make_shared<DataAbort>(
48810474Sandreas.hansson@arm.com                    currState->vaddr_tainted,
48910474Sandreas.hansson@arm.com                    TlbEntry::DomainType::NoAccess, currState->isWrite,
49010474Sandreas.hansson@arm.com                    ArmFault::TranslationLL + L1, isStage2,
49110474Sandreas.hansson@arm.com                    ArmFault::VmsaTran);
49210037SARM gem5 Developers        }
49310037SARM gem5 Developers        ttbr = currState->tc->readMiscReg(flattenMiscRegNsBanked(
49410037SARM gem5 Developers            MISCREG_TTBR1, currState->tc, !currState->isSecure));
49510037SARM gem5 Developers        currState->ttbcr.n = 0;
4967404SAli.Saidi@ARM.com    }
4977404SAli.Saidi@ARM.com
49810037SARM gem5 Developers    Addr l1desc_addr = mbits(ttbr, 31, 14 - currState->ttbcr.n) |
49910037SARM gem5 Developers        (bits(currState->vaddr, 31 - currState->ttbcr.n, 20) << 2);
50010037SARM gem5 Developers    DPRINTF(TLB, " - Descriptor at address %#x (%s)\n", l1desc_addr,
50110037SARM gem5 Developers            currState->isSecure ? "s" : "ns");
5027404SAli.Saidi@ARM.com
5037404SAli.Saidi@ARM.com    // Trickbox address check
5047439Sdam.sunwoo@arm.com    Fault f;
50511395Sandreas.sandberg@arm.com    f = testWalk(l1desc_addr, sizeof(uint32_t),
50611395Sandreas.sandberg@arm.com                 TlbEntry::DomainType::NoAccess, L1);
5077439Sdam.sunwoo@arm.com    if (f) {
50810037SARM gem5 Developers        DPRINTF(TLB, "Trickbox check caused fault on %#x\n", currState->vaddr_tainted);
5097579Sminkyu.jeong@arm.com        if (currState->timing) {
5107728SAli.Saidi@ARM.com            pending = false;
5117728SAli.Saidi@ARM.com            nextWalk(currState->tc);
5127579Sminkyu.jeong@arm.com            currState = NULL;
5137579Sminkyu.jeong@arm.com        } else {
5147579Sminkyu.jeong@arm.com            currState->tc = NULL;
5157579Sminkyu.jeong@arm.com            currState->req = NULL;
5167579Sminkyu.jeong@arm.com        }
5177579Sminkyu.jeong@arm.com        return f;
5187404SAli.Saidi@ARM.com    }
5197404SAli.Saidi@ARM.com
52010836Sandreas.hansson@arm.com    Request::Flags flag = Request::PT_WALK;
5217946SGiacomo.Gabrielli@arm.com    if (currState->sctlr.c == 0) {
52210836Sandreas.hansson@arm.com        flag.set(Request::UNCACHEABLE);
5237946SGiacomo.Gabrielli@arm.com    }
5247946SGiacomo.Gabrielli@arm.com
52511181Snathananel.premillieu@arm.com    if (currState->isSecure) {
52611181Snathananel.premillieu@arm.com        flag.set(Request::SECURE);
52711181Snathananel.premillieu@arm.com    }
52811181Snathananel.premillieu@arm.com
52910037SARM gem5 Developers    bool delayed;
53010037SARM gem5 Developers    delayed = fetchDescriptor(l1desc_addr, (uint8_t*)&currState->l1Desc.data,
53110037SARM gem5 Developers                              sizeof(uint32_t), flag, L1, &doL1DescEvent,
53210037SARM gem5 Developers                              &TableWalker::doL1Descriptor);
53310037SARM gem5 Developers    if (!delayed) {
53410037SARM gem5 Developers       f = currState->fault;
53510037SARM gem5 Developers    }
53610037SARM gem5 Developers
53710037SARM gem5 Developers    return f;
53810037SARM gem5 Developers}
53910037SARM gem5 Developers
54010037SARM gem5 DevelopersFault
54110037SARM gem5 DevelopersTableWalker::processWalkLPAE()
54210037SARM gem5 Developers{
54310037SARM gem5 Developers    Addr ttbr, ttbr0_max, ttbr1_min, desc_addr;
54410037SARM gem5 Developers    int tsz, n;
54510037SARM gem5 Developers    LookupLevel start_lookup_level = L1;
54610037SARM gem5 Developers
54710037SARM gem5 Developers    DPRINTF(TLB, "Beginning table walk for address %#x, TTBCR: %#x\n",
54810037SARM gem5 Developers            currState->vaddr_tainted, currState->ttbcr);
54910037SARM gem5 Developers
55010621SCurtis.Dunham@arm.com    statWalkWaitTime.sample(curTick() - currState->startTime);
55110621SCurtis.Dunham@arm.com
55210836Sandreas.hansson@arm.com    Request::Flags flag = Request::PT_WALK;
55310037SARM gem5 Developers    if (currState->isSecure)
55410037SARM gem5 Developers        flag.set(Request::SECURE);
55510037SARM gem5 Developers
55610037SARM gem5 Developers    // work out which base address register to use, if in hyp mode we always
55710037SARM gem5 Developers    // use HTTBR
55810037SARM gem5 Developers    if (isStage2) {
55910037SARM gem5 Developers        DPRINTF(TLB, " - Selecting VTTBR (long-desc.)\n");
56010037SARM gem5 Developers        ttbr = currState->tc->readMiscReg(MISCREG_VTTBR);
56110037SARM gem5 Developers        tsz  = sext<4>(currState->vtcr.t0sz);
56210037SARM gem5 Developers        start_lookup_level = currState->vtcr.sl0 ? L1 : L2;
56310037SARM gem5 Developers    } else if (currState->isHyp) {
56410037SARM gem5 Developers        DPRINTF(TLB, " - Selecting HTTBR (long-desc.)\n");
56510037SARM gem5 Developers        ttbr = currState->tc->readMiscReg(MISCREG_HTTBR);
56610037SARM gem5 Developers        tsz  = currState->htcr.t0sz;
56710037SARM gem5 Developers    } else {
56810037SARM gem5 Developers        assert(_haveLPAE && currState->ttbcr.eae);
56910037SARM gem5 Developers
57010037SARM gem5 Developers        // Determine boundaries of TTBR0/1 regions
57110037SARM gem5 Developers        if (currState->ttbcr.t0sz)
57210037SARM gem5 Developers            ttbr0_max = (1ULL << (32 - currState->ttbcr.t0sz)) - 1;
57310037SARM gem5 Developers        else if (currState->ttbcr.t1sz)
57410037SARM gem5 Developers            ttbr0_max = (1ULL << 32) -
57510037SARM gem5 Developers                (1ULL << (32 - currState->ttbcr.t1sz)) - 1;
57610037SARM gem5 Developers        else
57710037SARM gem5 Developers            ttbr0_max = (1ULL << 32) - 1;
57810037SARM gem5 Developers        if (currState->ttbcr.t1sz)
57910037SARM gem5 Developers            ttbr1_min = (1ULL << 32) - (1ULL << (32 - currState->ttbcr.t1sz));
58010037SARM gem5 Developers        else
58110037SARM gem5 Developers            ttbr1_min = (1ULL << (32 - currState->ttbcr.t0sz));
58210037SARM gem5 Developers
58310037SARM gem5 Developers        // The following code snippet selects the appropriate translation table base
58410037SARM gem5 Developers        // address (TTBR0 or TTBR1) and the appropriate starting lookup level
58510037SARM gem5 Developers        // depending on the address range supported by the translation table (ARM
58610037SARM gem5 Developers        // ARM issue C B3.6.4)
58710037SARM gem5 Developers        if (currState->vaddr <= ttbr0_max) {
58810037SARM gem5 Developers            DPRINTF(TLB, " - Selecting TTBR0 (long-desc.)\n");
58910037SARM gem5 Developers            // Check if table walk is allowed
59010037SARM gem5 Developers            if (currState->ttbcr.epd0) {
59110037SARM gem5 Developers                if (currState->isFetch)
59210474Sandreas.hansson@arm.com                    return std::make_shared<PrefetchAbort>(
59310474Sandreas.hansson@arm.com                        currState->vaddr_tainted,
59410474Sandreas.hansson@arm.com                        ArmFault::TranslationLL + L1,
59510474Sandreas.hansson@arm.com                        isStage2,
59610474Sandreas.hansson@arm.com                        ArmFault::LpaeTran);
59710037SARM gem5 Developers                else
59810474Sandreas.hansson@arm.com                    return std::make_shared<DataAbort>(
59910474Sandreas.hansson@arm.com                        currState->vaddr_tainted,
60010474Sandreas.hansson@arm.com                        TlbEntry::DomainType::NoAccess,
60110474Sandreas.hansson@arm.com                        currState->isWrite,
60210474Sandreas.hansson@arm.com                        ArmFault::TranslationLL + L1,
60310474Sandreas.hansson@arm.com                        isStage2,
60410474Sandreas.hansson@arm.com                        ArmFault::LpaeTran);
60510037SARM gem5 Developers            }
60610037SARM gem5 Developers            ttbr = currState->tc->readMiscReg(flattenMiscRegNsBanked(
60710037SARM gem5 Developers                MISCREG_TTBR0, currState->tc, !currState->isSecure));
60810037SARM gem5 Developers            tsz = currState->ttbcr.t0sz;
60910037SARM gem5 Developers            if (ttbr0_max < (1ULL << 30))  // Upper limit < 1 GB
61010037SARM gem5 Developers                start_lookup_level = L2;
61110037SARM gem5 Developers        } else if (currState->vaddr >= ttbr1_min) {
61210037SARM gem5 Developers            DPRINTF(TLB, " - Selecting TTBR1 (long-desc.)\n");
61310037SARM gem5 Developers            // Check if table walk is allowed
61410037SARM gem5 Developers            if (currState->ttbcr.epd1) {
61510037SARM gem5 Developers                if (currState->isFetch)
61610474Sandreas.hansson@arm.com                    return std::make_shared<PrefetchAbort>(
61710474Sandreas.hansson@arm.com                        currState->vaddr_tainted,
61810474Sandreas.hansson@arm.com                        ArmFault::TranslationLL + L1,
61910474Sandreas.hansson@arm.com                        isStage2,
62010474Sandreas.hansson@arm.com                        ArmFault::LpaeTran);
62110037SARM gem5 Developers                else
62210474Sandreas.hansson@arm.com                    return std::make_shared<DataAbort>(
62310474Sandreas.hansson@arm.com                        currState->vaddr_tainted,
62410474Sandreas.hansson@arm.com                        TlbEntry::DomainType::NoAccess,
62510474Sandreas.hansson@arm.com                        currState->isWrite,
62610474Sandreas.hansson@arm.com                        ArmFault::TranslationLL + L1,
62710474Sandreas.hansson@arm.com                        isStage2,
62810474Sandreas.hansson@arm.com                        ArmFault::LpaeTran);
62910037SARM gem5 Developers            }
63010037SARM gem5 Developers            ttbr = currState->tc->readMiscReg(flattenMiscRegNsBanked(
63110037SARM gem5 Developers                MISCREG_TTBR1, currState->tc, !currState->isSecure));
63210037SARM gem5 Developers            tsz = currState->ttbcr.t1sz;
63310037SARM gem5 Developers            if (ttbr1_min >= (1ULL << 31) + (1ULL << 30))  // Lower limit >= 3 GB
63410037SARM gem5 Developers                start_lookup_level = L2;
63510037SARM gem5 Developers        } else {
63610037SARM gem5 Developers            // Out of boundaries -> translation fault
63710037SARM gem5 Developers            if (currState->isFetch)
63810474Sandreas.hansson@arm.com                return std::make_shared<PrefetchAbort>(
63910474Sandreas.hansson@arm.com                    currState->vaddr_tainted,
64010474Sandreas.hansson@arm.com                    ArmFault::TranslationLL + L1,
64110474Sandreas.hansson@arm.com                    isStage2,
64210474Sandreas.hansson@arm.com                    ArmFault::LpaeTran);
64310037SARM gem5 Developers            else
64410474Sandreas.hansson@arm.com                return std::make_shared<DataAbort>(
64510474Sandreas.hansson@arm.com                    currState->vaddr_tainted,
64610474Sandreas.hansson@arm.com                    TlbEntry::DomainType::NoAccess,
64710474Sandreas.hansson@arm.com                    currState->isWrite, ArmFault::TranslationLL + L1,
64810474Sandreas.hansson@arm.com                    isStage2, ArmFault::LpaeTran);
64910037SARM gem5 Developers        }
65010037SARM gem5 Developers
65110037SARM gem5 Developers    }
65210037SARM gem5 Developers
65310037SARM gem5 Developers    // Perform lookup (ARM ARM issue C B3.6.6)
65410037SARM gem5 Developers    if (start_lookup_level == L1) {
65510037SARM gem5 Developers        n = 5 - tsz;
65610037SARM gem5 Developers        desc_addr = mbits(ttbr, 39, n) |
65710037SARM gem5 Developers            (bits(currState->vaddr, n + 26, 30) << 3);
65810037SARM gem5 Developers        DPRINTF(TLB, " - Descriptor at address %#x (%s) (long-desc.)\n",
65910037SARM gem5 Developers                desc_addr, currState->isSecure ? "s" : "ns");
66010037SARM gem5 Developers    } else {
66110037SARM gem5 Developers        // Skip first-level lookup
66210037SARM gem5 Developers        n = (tsz >= 2 ? 14 - tsz : 12);
66310037SARM gem5 Developers        desc_addr = mbits(ttbr, 39, n) |
66410037SARM gem5 Developers            (bits(currState->vaddr, n + 17, 21) << 3);
66510037SARM gem5 Developers        DPRINTF(TLB, " - Descriptor at address %#x (%s) (long-desc.)\n",
66610037SARM gem5 Developers                desc_addr, currState->isSecure ? "s" : "ns");
66710037SARM gem5 Developers    }
66810037SARM gem5 Developers
66910037SARM gem5 Developers    // Trickbox address check
67011395Sandreas.sandberg@arm.com    Fault f = testWalk(desc_addr, sizeof(uint64_t),
67111395Sandreas.sandberg@arm.com                       TlbEntry::DomainType::NoAccess, start_lookup_level);
67210037SARM gem5 Developers    if (f) {
67310037SARM gem5 Developers        DPRINTF(TLB, "Trickbox check caused fault on %#x\n", currState->vaddr_tainted);
67410037SARM gem5 Developers        if (currState->timing) {
67510037SARM gem5 Developers            pending = false;
67610037SARM gem5 Developers            nextWalk(currState->tc);
67710037SARM gem5 Developers            currState = NULL;
67810037SARM gem5 Developers        } else {
67910037SARM gem5 Developers            currState->tc = NULL;
68010037SARM gem5 Developers            currState->req = NULL;
68110037SARM gem5 Developers        }
68210037SARM gem5 Developers        return f;
68310037SARM gem5 Developers    }
68410037SARM gem5 Developers
68510037SARM gem5 Developers    if (currState->sctlr.c == 0) {
68610836Sandreas.hansson@arm.com        flag.set(Request::UNCACHEABLE);
68710037SARM gem5 Developers    }
68810037SARM gem5 Developers
68910037SARM gem5 Developers    currState->longDesc.lookupLevel = start_lookup_level;
69010037SARM gem5 Developers    currState->longDesc.aarch64 = false;
69110324SCurtis.Dunham@arm.com    currState->longDesc.grainSize = Grain4KB;
69210037SARM gem5 Developers
69310037SARM gem5 Developers    Event *event = start_lookup_level == L1 ? (Event *) &doL1LongDescEvent
69410037SARM gem5 Developers                                            : (Event *) &doL2LongDescEvent;
69510037SARM gem5 Developers
69610037SARM gem5 Developers    bool delayed = fetchDescriptor(desc_addr, (uint8_t*)&currState->longDesc.data,
69710037SARM gem5 Developers                                   sizeof(uint64_t), flag, start_lookup_level,
69810037SARM gem5 Developers                                   event, &TableWalker::doLongDescriptor);
69910037SARM gem5 Developers    if (!delayed) {
70010037SARM gem5 Developers        f = currState->fault;
70110037SARM gem5 Developers    }
70210037SARM gem5 Developers
70310037SARM gem5 Developers    return f;
70410037SARM gem5 Developers}
70510037SARM gem5 Developers
70610037SARM gem5 Developersunsigned
70710037SARM gem5 DevelopersTableWalker::adjustTableSizeAArch64(unsigned tsz)
70810037SARM gem5 Developers{
70910037SARM gem5 Developers    if (tsz < 25)
71010037SARM gem5 Developers        return 25;
71110037SARM gem5 Developers    if (tsz > 48)
71210037SARM gem5 Developers        return 48;
71310037SARM gem5 Developers    return tsz;
71410037SARM gem5 Developers}
71510037SARM gem5 Developers
71610037SARM gem5 Developersbool
71710037SARM gem5 DevelopersTableWalker::checkAddrSizeFaultAArch64(Addr addr, int currPhysAddrRange)
71810037SARM gem5 Developers{
71910037SARM gem5 Developers    return (currPhysAddrRange != MaxPhysAddrRange &&
72010037SARM gem5 Developers            bits(addr, MaxPhysAddrRange - 1, currPhysAddrRange));
72110037SARM gem5 Developers}
72210037SARM gem5 Developers
72310037SARM gem5 DevelopersFault
72410037SARM gem5 DevelopersTableWalker::processWalkAArch64()
72510037SARM gem5 Developers{
72610037SARM gem5 Developers    assert(currState->aarch64);
72710037SARM gem5 Developers
72810324SCurtis.Dunham@arm.com    DPRINTF(TLB, "Beginning table walk for address %#llx, TCR: %#llx\n",
72910324SCurtis.Dunham@arm.com            currState->vaddr_tainted, currState->tcr);
73010324SCurtis.Dunham@arm.com
73110324SCurtis.Dunham@arm.com    static const GrainSize GrainMapDefault[] =
73210324SCurtis.Dunham@arm.com      { Grain4KB, Grain64KB, Grain16KB, ReservedGrain };
73310324SCurtis.Dunham@arm.com    static const GrainSize GrainMap_EL1_tg1[] =
73410324SCurtis.Dunham@arm.com      { ReservedGrain, Grain16KB, Grain4KB, Grain64KB };
73510037SARM gem5 Developers
73610621SCurtis.Dunham@arm.com    statWalkWaitTime.sample(curTick() - currState->startTime);
73710621SCurtis.Dunham@arm.com
73810037SARM gem5 Developers    // Determine TTBR, table size, granule size and phys. address range
73910037SARM gem5 Developers    Addr ttbr = 0;
74010037SARM gem5 Developers    int tsz = 0, ps = 0;
74110324SCurtis.Dunham@arm.com    GrainSize tg = Grain4KB; // grain size computed from tg* field
74210037SARM gem5 Developers    bool fault = false;
74310037SARM gem5 Developers    switch (currState->el) {
74410037SARM gem5 Developers      case EL0:
74510037SARM gem5 Developers      case EL1:
74610037SARM gem5 Developers        switch (bits(currState->vaddr, 63,48)) {
74710037SARM gem5 Developers          case 0:
74810037SARM gem5 Developers            DPRINTF(TLB, " - Selecting TTBR0 (AArch64)\n");
74910037SARM gem5 Developers            ttbr = currState->tc->readMiscReg(MISCREG_TTBR0_EL1);
75010324SCurtis.Dunham@arm.com            tsz = adjustTableSizeAArch64(64 - currState->tcr.t0sz);
75110324SCurtis.Dunham@arm.com            tg = GrainMapDefault[currState->tcr.tg0];
75210037SARM gem5 Developers            if (bits(currState->vaddr, 63, tsz) != 0x0 ||
75310324SCurtis.Dunham@arm.com                currState->tcr.epd0)
75410037SARM gem5 Developers              fault = true;
75510037SARM gem5 Developers            break;
75610037SARM gem5 Developers          case 0xffff:
75710037SARM gem5 Developers            DPRINTF(TLB, " - Selecting TTBR1 (AArch64)\n");
75810037SARM gem5 Developers            ttbr = currState->tc->readMiscReg(MISCREG_TTBR1_EL1);
75910324SCurtis.Dunham@arm.com            tsz = adjustTableSizeAArch64(64 - currState->tcr.t1sz);
76010324SCurtis.Dunham@arm.com            tg = GrainMap_EL1_tg1[currState->tcr.tg1];
76110037SARM gem5 Developers            if (bits(currState->vaddr, 63, tsz) != mask(64-tsz) ||
76210324SCurtis.Dunham@arm.com                currState->tcr.epd1)
76310037SARM gem5 Developers              fault = true;
76410037SARM gem5 Developers            break;
76510037SARM gem5 Developers          default:
76610037SARM gem5 Developers            // top two bytes must be all 0s or all 1s, else invalid addr
76710037SARM gem5 Developers            fault = true;
76810037SARM gem5 Developers        }
76910324SCurtis.Dunham@arm.com        ps = currState->tcr.ips;
77010037SARM gem5 Developers        break;
77110037SARM gem5 Developers      case EL2:
77210037SARM gem5 Developers      case EL3:
77310037SARM gem5 Developers        switch(bits(currState->vaddr, 63,48)) {
77410037SARM gem5 Developers            case 0:
77510324SCurtis.Dunham@arm.com                DPRINTF(TLB, " - Selecting TTBR0 (AArch64)\n");
77610324SCurtis.Dunham@arm.com                if (currState->el == EL2)
77710324SCurtis.Dunham@arm.com                    ttbr = currState->tc->readMiscReg(MISCREG_TTBR0_EL2);
77810324SCurtis.Dunham@arm.com                else
77910324SCurtis.Dunham@arm.com                    ttbr = currState->tc->readMiscReg(MISCREG_TTBR0_EL3);
78010324SCurtis.Dunham@arm.com                tsz = adjustTableSizeAArch64(64 - currState->tcr.t0sz);
78110324SCurtis.Dunham@arm.com                tg = GrainMapDefault[currState->tcr.tg0];
78210037SARM gem5 Developers                break;
78310037SARM gem5 Developers            default:
78410037SARM gem5 Developers                // invalid addr if top two bytes are not all 0s
78510324SCurtis.Dunham@arm.com                fault = true;
78610037SARM gem5 Developers        }
78710324SCurtis.Dunham@arm.com        ps = currState->tcr.ips;
78810037SARM gem5 Developers        break;
78910037SARM gem5 Developers    }
79010037SARM gem5 Developers
79110037SARM gem5 Developers    if (fault) {
79210037SARM gem5 Developers        Fault f;
79310037SARM gem5 Developers        if (currState->isFetch)
79410474Sandreas.hansson@arm.com            f =  std::make_shared<PrefetchAbort>(
79510474Sandreas.hansson@arm.com                currState->vaddr_tainted,
79610474Sandreas.hansson@arm.com                ArmFault::TranslationLL + L0, isStage2,
79710474Sandreas.hansson@arm.com                ArmFault::LpaeTran);
79810037SARM gem5 Developers        else
79910474Sandreas.hansson@arm.com            f = std::make_shared<DataAbort>(
80010474Sandreas.hansson@arm.com                currState->vaddr_tainted,
80110474Sandreas.hansson@arm.com                TlbEntry::DomainType::NoAccess,
80210474Sandreas.hansson@arm.com                currState->isWrite,
80310474Sandreas.hansson@arm.com                ArmFault::TranslationLL + L0,
80410474Sandreas.hansson@arm.com                isStage2, ArmFault::LpaeTran);
80510037SARM gem5 Developers
80610037SARM gem5 Developers        if (currState->timing) {
80710037SARM gem5 Developers            pending = false;
80810037SARM gem5 Developers            nextWalk(currState->tc);
80910037SARM gem5 Developers            currState = NULL;
81010037SARM gem5 Developers        } else {
81110037SARM gem5 Developers            currState->tc = NULL;
81210037SARM gem5 Developers            currState->req = NULL;
81310037SARM gem5 Developers        }
81410037SARM gem5 Developers        return f;
81510037SARM gem5 Developers
81610037SARM gem5 Developers    }
81710037SARM gem5 Developers
81810324SCurtis.Dunham@arm.com    if (tg == ReservedGrain) {
81910324SCurtis.Dunham@arm.com        warn_once("Reserved granule size requested; gem5's IMPLEMENTATION "
82010324SCurtis.Dunham@arm.com                  "DEFINED behavior takes this to mean 4KB granules\n");
82110324SCurtis.Dunham@arm.com        tg = Grain4KB;
82210324SCurtis.Dunham@arm.com    }
82310324SCurtis.Dunham@arm.com
82410324SCurtis.Dunham@arm.com    int stride = tg - 3;
82510324SCurtis.Dunham@arm.com    LookupLevel start_lookup_level = MAX_LOOKUP_LEVELS;
82610324SCurtis.Dunham@arm.com
82710037SARM gem5 Developers    // Determine starting lookup level
82810324SCurtis.Dunham@arm.com    // See aarch64/translation/walk in Appendix G: ARMv8 Pseudocode Library
82910324SCurtis.Dunham@arm.com    // in ARM DDI 0487A.  These table values correspond to the cascading tests
83010324SCurtis.Dunham@arm.com    // to compute the lookup level and are of the form
83110324SCurtis.Dunham@arm.com    // (grain_size + N*stride), for N = {1, 2, 3}.
83210324SCurtis.Dunham@arm.com    // A value of 64 will never succeed and a value of 0 will always succeed.
83310324SCurtis.Dunham@arm.com    {
83410324SCurtis.Dunham@arm.com        struct GrainMap {
83510324SCurtis.Dunham@arm.com            GrainSize grain_size;
83610324SCurtis.Dunham@arm.com            unsigned lookup_level_cutoff[MAX_LOOKUP_LEVELS];
83710324SCurtis.Dunham@arm.com        };
83810324SCurtis.Dunham@arm.com        static const GrainMap GM[] = {
83910324SCurtis.Dunham@arm.com            { Grain4KB,  { 39, 30,  0, 0 } },
84010324SCurtis.Dunham@arm.com            { Grain16KB, { 47, 36, 25, 0 } },
84110324SCurtis.Dunham@arm.com            { Grain64KB, { 64, 42, 29, 0 } }
84210324SCurtis.Dunham@arm.com        };
84310324SCurtis.Dunham@arm.com
84410324SCurtis.Dunham@arm.com        const unsigned *lookup = NULL; // points to a lookup_level_cutoff
84510324SCurtis.Dunham@arm.com
84610324SCurtis.Dunham@arm.com        for (unsigned i = 0; i < 3; ++i) { // choose entry of GM[]
84710324SCurtis.Dunham@arm.com            if (tg == GM[i].grain_size) {
84810324SCurtis.Dunham@arm.com                lookup = GM[i].lookup_level_cutoff;
84910324SCurtis.Dunham@arm.com                break;
85010324SCurtis.Dunham@arm.com            }
85110324SCurtis.Dunham@arm.com        }
85210324SCurtis.Dunham@arm.com        assert(lookup);
85310324SCurtis.Dunham@arm.com
85410324SCurtis.Dunham@arm.com        for (int L = L0; L != MAX_LOOKUP_LEVELS; ++L) {
85510324SCurtis.Dunham@arm.com            if (tsz > lookup[L]) {
85610324SCurtis.Dunham@arm.com                start_lookup_level = (LookupLevel) L;
85710324SCurtis.Dunham@arm.com                break;
85810324SCurtis.Dunham@arm.com            }
85910324SCurtis.Dunham@arm.com        }
86010324SCurtis.Dunham@arm.com        panic_if(start_lookup_level == MAX_LOOKUP_LEVELS,
86110324SCurtis.Dunham@arm.com                 "Table walker couldn't find lookup level\n");
86210037SARM gem5 Developers    }
86310037SARM gem5 Developers
86410037SARM gem5 Developers    // Determine table base address
86510324SCurtis.Dunham@arm.com    int base_addr_lo = 3 + tsz - stride * (3 - start_lookup_level) - tg;
86610037SARM gem5 Developers    Addr base_addr = mbits(ttbr, 47, base_addr_lo);
86710037SARM gem5 Developers
86810037SARM gem5 Developers    // Determine physical address size and raise an Address Size Fault if
86910037SARM gem5 Developers    // necessary
87010037SARM gem5 Developers    int pa_range = decodePhysAddrRange64(ps);
87110037SARM gem5 Developers    // Clamp to lower limit
87210037SARM gem5 Developers    if (pa_range > physAddrRange)
87310037SARM gem5 Developers        currState->physAddrRange = physAddrRange;
87410037SARM gem5 Developers    else
87510037SARM gem5 Developers        currState->physAddrRange = pa_range;
87610037SARM gem5 Developers    if (checkAddrSizeFaultAArch64(base_addr, currState->physAddrRange)) {
87710037SARM gem5 Developers        DPRINTF(TLB, "Address size fault before any lookup\n");
87810037SARM gem5 Developers        Fault f;
87910037SARM gem5 Developers        if (currState->isFetch)
88010474Sandreas.hansson@arm.com            f = std::make_shared<PrefetchAbort>(
88110474Sandreas.hansson@arm.com                currState->vaddr_tainted,
88210474Sandreas.hansson@arm.com                ArmFault::AddressSizeLL + start_lookup_level,
88310474Sandreas.hansson@arm.com                isStage2,
88410474Sandreas.hansson@arm.com                ArmFault::LpaeTran);
88510037SARM gem5 Developers        else
88610474Sandreas.hansson@arm.com            f = std::make_shared<DataAbort>(
88710474Sandreas.hansson@arm.com                currState->vaddr_tainted,
88810474Sandreas.hansson@arm.com                TlbEntry::DomainType::NoAccess,
88910474Sandreas.hansson@arm.com                currState->isWrite,
89010474Sandreas.hansson@arm.com                ArmFault::AddressSizeLL + start_lookup_level,
89110474Sandreas.hansson@arm.com                isStage2,
89210474Sandreas.hansson@arm.com                ArmFault::LpaeTran);
89310037SARM gem5 Developers
89410037SARM gem5 Developers
89510037SARM gem5 Developers        if (currState->timing) {
89610037SARM gem5 Developers            pending = false;
89710037SARM gem5 Developers            nextWalk(currState->tc);
89810037SARM gem5 Developers            currState = NULL;
89910037SARM gem5 Developers        } else {
90010037SARM gem5 Developers            currState->tc = NULL;
90110037SARM gem5 Developers            currState->req = NULL;
90210037SARM gem5 Developers        }
90310037SARM gem5 Developers        return f;
90410037SARM gem5 Developers
90510037SARM gem5 Developers   }
90610037SARM gem5 Developers
90710037SARM gem5 Developers    // Determine descriptor address
90810037SARM gem5 Developers    Addr desc_addr = base_addr |
90910037SARM gem5 Developers        (bits(currState->vaddr, tsz - 1,
91010324SCurtis.Dunham@arm.com              stride * (3 - start_lookup_level) + tg) << 3);
91110037SARM gem5 Developers
91210037SARM gem5 Developers    // Trickbox address check
91311395Sandreas.sandberg@arm.com    Fault f = testWalk(desc_addr, sizeof(uint64_t),
91411395Sandreas.sandberg@arm.com                       TlbEntry::DomainType::NoAccess, start_lookup_level);
91510037SARM gem5 Developers    if (f) {
91610037SARM gem5 Developers        DPRINTF(TLB, "Trickbox check caused fault on %#x\n", currState->vaddr_tainted);
91710037SARM gem5 Developers        if (currState->timing) {
91810037SARM gem5 Developers            pending = false;
91910037SARM gem5 Developers            nextWalk(currState->tc);
92010037SARM gem5 Developers            currState = NULL;
92110037SARM gem5 Developers        } else {
92210037SARM gem5 Developers            currState->tc = NULL;
92310037SARM gem5 Developers            currState->req = NULL;
92410037SARM gem5 Developers        }
92510037SARM gem5 Developers        return f;
92610037SARM gem5 Developers    }
92710037SARM gem5 Developers
92810836Sandreas.hansson@arm.com    Request::Flags flag = Request::PT_WALK;
92910037SARM gem5 Developers    if (currState->sctlr.c == 0) {
93010836Sandreas.hansson@arm.com        flag.set(Request::UNCACHEABLE);
93110037SARM gem5 Developers    }
93210037SARM gem5 Developers
93311181Snathananel.premillieu@arm.com    if (currState->isSecure) {
93411181Snathananel.premillieu@arm.com        flag.set(Request::SECURE);
93511181Snathananel.premillieu@arm.com    }
93611181Snathananel.premillieu@arm.com
93710037SARM gem5 Developers    currState->longDesc.lookupLevel = start_lookup_level;
93810037SARM gem5 Developers    currState->longDesc.aarch64 = true;
93910324SCurtis.Dunham@arm.com    currState->longDesc.grainSize = tg;
94010037SARM gem5 Developers
9417439Sdam.sunwoo@arm.com    if (currState->timing) {
94210037SARM gem5 Developers        Event *event;
94310037SARM gem5 Developers        switch (start_lookup_level) {
94410037SARM gem5 Developers          case L0:
94510037SARM gem5 Developers            event = (Event *) &doL0LongDescEvent;
94610037SARM gem5 Developers            break;
94710037SARM gem5 Developers          case L1:
94810037SARM gem5 Developers            event = (Event *) &doL1LongDescEvent;
94910037SARM gem5 Developers            break;
95010037SARM gem5 Developers          case L2:
95110037SARM gem5 Developers            event = (Event *) &doL2LongDescEvent;
95210037SARM gem5 Developers            break;
95310037SARM gem5 Developers          case L3:
95410037SARM gem5 Developers            event = (Event *) &doL3LongDescEvent;
95510037SARM gem5 Developers            break;
95610037SARM gem5 Developers          default:
95710037SARM gem5 Developers            panic("Invalid table lookup level");
95810037SARM gem5 Developers            break;
95910037SARM gem5 Developers        }
96010717Sandreas.hansson@arm.com        port->dmaAction(MemCmd::ReadReq, desc_addr, sizeof(uint64_t),
96110621SCurtis.Dunham@arm.com                       event, (uint8_t*) &currState->longDesc.data,
9629180Sandreas.hansson@arm.com                       currState->tc->getCpuPtr()->clockPeriod(), flag);
96310037SARM gem5 Developers        DPRINTF(TLBVerbose,
96410037SARM gem5 Developers                "Adding to walker fifo: queue size before adding: %d\n",
96510037SARM gem5 Developers                stateQueues[start_lookup_level].size());
96610037SARM gem5 Developers        stateQueues[start_lookup_level].push_back(currState);
9677439Sdam.sunwoo@arm.com        currState = NULL;
9688733Sgeoffrey.blake@arm.com    } else if (!currState->functional) {
96910717Sandreas.hansson@arm.com        port->dmaAction(MemCmd::ReadReq, desc_addr, sizeof(uint64_t),
97010037SARM gem5 Developers                       NULL, (uint8_t*) &currState->longDesc.data,
9719180Sandreas.hansson@arm.com                       currState->tc->getCpuPtr()->clockPeriod(), flag);
97210037SARM gem5 Developers        doLongDescriptor();
9737439Sdam.sunwoo@arm.com        f = currState->fault;
9748733Sgeoffrey.blake@arm.com    } else {
97510037SARM gem5 Developers        RequestPtr req = new Request(desc_addr, sizeof(uint64_t), flag,
97610037SARM gem5 Developers                                     masterId);
9778949Sandreas.hansson@arm.com        PacketPtr pkt = new Packet(req, MemCmd::ReadReq);
97810037SARM gem5 Developers        pkt->dataStatic((uint8_t*) &currState->longDesc.data);
97910717Sandreas.hansson@arm.com        port->sendFunctional(pkt);
98010037SARM gem5 Developers        doLongDescriptor();
9818733Sgeoffrey.blake@arm.com        delete req;
9828733Sgeoffrey.blake@arm.com        delete pkt;
9838733Sgeoffrey.blake@arm.com        f = currState->fault;
9847404SAli.Saidi@ARM.com    }
9857404SAli.Saidi@ARM.com
9867439Sdam.sunwoo@arm.com    return f;
9877404SAli.Saidi@ARM.com}
9887404SAli.Saidi@ARM.com
9897404SAli.Saidi@ARM.comvoid
9907439Sdam.sunwoo@arm.comTableWalker::memAttrs(ThreadContext *tc, TlbEntry &te, SCTLR sctlr,
9917439Sdam.sunwoo@arm.com                      uint8_t texcb, bool s)
9927404SAli.Saidi@ARM.com{
9937439Sdam.sunwoo@arm.com    // Note: tc and sctlr local variables are hiding tc and sctrl class
9947439Sdam.sunwoo@arm.com    // variables
9957436Sdam.sunwoo@arm.com    DPRINTF(TLBVerbose, "memAttrs texcb:%d s:%d\n", texcb, s);
9967436Sdam.sunwoo@arm.com    te.shareable = false; // default value
9977582SAli.Saidi@arm.com    te.nonCacheable = false;
99810037SARM gem5 Developers    te.outerShareable = false;
9997439Sdam.sunwoo@arm.com    if (sctlr.tre == 0 || ((sctlr.tre == 1) && (sctlr.m == 0))) {
10007404SAli.Saidi@ARM.com        switch(texcb) {
10017436Sdam.sunwoo@arm.com          case 0: // Stongly-ordered
10027404SAli.Saidi@ARM.com            te.nonCacheable = true;
100310037SARM gem5 Developers            te.mtype = TlbEntry::MemoryType::StronglyOrdered;
10047436Sdam.sunwoo@arm.com            te.shareable = true;
10057436Sdam.sunwoo@arm.com            te.innerAttrs = 1;
10067436Sdam.sunwoo@arm.com            te.outerAttrs = 0;
10077404SAli.Saidi@ARM.com            break;
10087436Sdam.sunwoo@arm.com          case 1: // Shareable Device
10097436Sdam.sunwoo@arm.com            te.nonCacheable = true;
101010037SARM gem5 Developers            te.mtype = TlbEntry::MemoryType::Device;
10117436Sdam.sunwoo@arm.com            te.shareable = true;
10127436Sdam.sunwoo@arm.com            te.innerAttrs = 3;
10137436Sdam.sunwoo@arm.com            te.outerAttrs = 0;
10147436Sdam.sunwoo@arm.com            break;
10157436Sdam.sunwoo@arm.com          case 2: // Outer and Inner Write-Through, no Write-Allocate
101610037SARM gem5 Developers            te.mtype = TlbEntry::MemoryType::Normal;
10177436Sdam.sunwoo@arm.com            te.shareable = s;
10187436Sdam.sunwoo@arm.com            te.innerAttrs = 6;
10197436Sdam.sunwoo@arm.com            te.outerAttrs = bits(texcb, 1, 0);
10207436Sdam.sunwoo@arm.com            break;
10217436Sdam.sunwoo@arm.com          case 3: // Outer and Inner Write-Back, no Write-Allocate
102210037SARM gem5 Developers            te.mtype = TlbEntry::MemoryType::Normal;
10237436Sdam.sunwoo@arm.com            te.shareable = s;
10247436Sdam.sunwoo@arm.com            te.innerAttrs = 7;
10257436Sdam.sunwoo@arm.com            te.outerAttrs = bits(texcb, 1, 0);
10267436Sdam.sunwoo@arm.com            break;
10277436Sdam.sunwoo@arm.com          case 4: // Outer and Inner Non-cacheable
10287436Sdam.sunwoo@arm.com            te.nonCacheable = true;
102910037SARM gem5 Developers            te.mtype = TlbEntry::MemoryType::Normal;
10307436Sdam.sunwoo@arm.com            te.shareable = s;
10317436Sdam.sunwoo@arm.com            te.innerAttrs = 0;
10327436Sdam.sunwoo@arm.com            te.outerAttrs = bits(texcb, 1, 0);
10337436Sdam.sunwoo@arm.com            break;
10347436Sdam.sunwoo@arm.com          case 5: // Reserved
10357439Sdam.sunwoo@arm.com            panic("Reserved texcb value!\n");
10367436Sdam.sunwoo@arm.com            break;
10377436Sdam.sunwoo@arm.com          case 6: // Implementation Defined
10387439Sdam.sunwoo@arm.com            panic("Implementation-defined texcb value!\n");
10397436Sdam.sunwoo@arm.com            break;
10407436Sdam.sunwoo@arm.com          case 7: // Outer and Inner Write-Back, Write-Allocate
104110037SARM gem5 Developers            te.mtype = TlbEntry::MemoryType::Normal;
10427436Sdam.sunwoo@arm.com            te.shareable = s;
10437436Sdam.sunwoo@arm.com            te.innerAttrs = 5;
10447436Sdam.sunwoo@arm.com            te.outerAttrs = 1;
10457436Sdam.sunwoo@arm.com            break;
10467436Sdam.sunwoo@arm.com          case 8: // Non-shareable Device
10477436Sdam.sunwoo@arm.com            te.nonCacheable = true;
104810037SARM gem5 Developers            te.mtype = TlbEntry::MemoryType::Device;
10497436Sdam.sunwoo@arm.com            te.shareable = false;
10507436Sdam.sunwoo@arm.com            te.innerAttrs = 3;
10517436Sdam.sunwoo@arm.com            te.outerAttrs = 0;
10527436Sdam.sunwoo@arm.com            break;
10537436Sdam.sunwoo@arm.com          case 9 ... 15:  // Reserved
10547439Sdam.sunwoo@arm.com            panic("Reserved texcb value!\n");
10557436Sdam.sunwoo@arm.com            break;
10567436Sdam.sunwoo@arm.com          case 16 ... 31: // Cacheable Memory
105710037SARM gem5 Developers            te.mtype = TlbEntry::MemoryType::Normal;
10587436Sdam.sunwoo@arm.com            te.shareable = s;
10597404SAli.Saidi@ARM.com            if (bits(texcb, 1,0) == 0 || bits(texcb, 3,2) == 0)
10607404SAli.Saidi@ARM.com                te.nonCacheable = true;
10617436Sdam.sunwoo@arm.com            te.innerAttrs = bits(texcb, 1, 0);
10627436Sdam.sunwoo@arm.com            te.outerAttrs = bits(texcb, 3, 2);
10637404SAli.Saidi@ARM.com            break;
10647436Sdam.sunwoo@arm.com          default:
10657436Sdam.sunwoo@arm.com            panic("More than 32 states for 5 bits?\n");
10667404SAli.Saidi@ARM.com        }
10677404SAli.Saidi@ARM.com    } else {
10687438SAli.Saidi@ARM.com        assert(tc);
106910037SARM gem5 Developers        PRRR prrr = tc->readMiscReg(flattenMiscRegNsBanked(MISCREG_PRRR,
107010037SARM gem5 Developers                                    currState->tc, !currState->isSecure));
107110037SARM gem5 Developers        NMRR nmrr = tc->readMiscReg(flattenMiscRegNsBanked(MISCREG_NMRR,
107210037SARM gem5 Developers                                    currState->tc, !currState->isSecure));
10737436Sdam.sunwoo@arm.com        DPRINTF(TLBVerbose, "memAttrs PRRR:%08x NMRR:%08x\n", prrr, nmrr);
10747582SAli.Saidi@arm.com        uint8_t curr_tr = 0, curr_ir = 0, curr_or = 0;
10757404SAli.Saidi@ARM.com        switch(bits(texcb, 2,0)) {
10767404SAli.Saidi@ARM.com          case 0:
10777436Sdam.sunwoo@arm.com            curr_tr = prrr.tr0;
10787436Sdam.sunwoo@arm.com            curr_ir = nmrr.ir0;
10797436Sdam.sunwoo@arm.com            curr_or = nmrr.or0;
108010037SARM gem5 Developers            te.outerShareable = (prrr.nos0 == 0);
10817404SAli.Saidi@ARM.com            break;
10827404SAli.Saidi@ARM.com          case 1:
10837436Sdam.sunwoo@arm.com            curr_tr = prrr.tr1;
10847436Sdam.sunwoo@arm.com            curr_ir = nmrr.ir1;
10857436Sdam.sunwoo@arm.com            curr_or = nmrr.or1;
108610037SARM gem5 Developers            te.outerShareable = (prrr.nos1 == 0);
10877404SAli.Saidi@ARM.com            break;
10887404SAli.Saidi@ARM.com          case 2:
10897436Sdam.sunwoo@arm.com            curr_tr = prrr.tr2;
10907436Sdam.sunwoo@arm.com            curr_ir = nmrr.ir2;
10917436Sdam.sunwoo@arm.com            curr_or = nmrr.or2;
109210037SARM gem5 Developers            te.outerShareable = (prrr.nos2 == 0);
10937404SAli.Saidi@ARM.com            break;
10947404SAli.Saidi@ARM.com          case 3:
10957436Sdam.sunwoo@arm.com            curr_tr = prrr.tr3;
10967436Sdam.sunwoo@arm.com            curr_ir = nmrr.ir3;
10977436Sdam.sunwoo@arm.com            curr_or = nmrr.or3;
109810037SARM gem5 Developers            te.outerShareable = (prrr.nos3 == 0);
10997404SAli.Saidi@ARM.com            break;
11007404SAli.Saidi@ARM.com          case 4:
11017436Sdam.sunwoo@arm.com            curr_tr = prrr.tr4;
11027436Sdam.sunwoo@arm.com            curr_ir = nmrr.ir4;
11037436Sdam.sunwoo@arm.com            curr_or = nmrr.or4;
110410037SARM gem5 Developers            te.outerShareable = (prrr.nos4 == 0);
11057404SAli.Saidi@ARM.com            break;
11067404SAli.Saidi@ARM.com          case 5:
11077436Sdam.sunwoo@arm.com            curr_tr = prrr.tr5;
11087436Sdam.sunwoo@arm.com            curr_ir = nmrr.ir5;
11097436Sdam.sunwoo@arm.com            curr_or = nmrr.or5;
111010037SARM gem5 Developers            te.outerShareable = (prrr.nos5 == 0);
11117404SAli.Saidi@ARM.com            break;
11127404SAli.Saidi@ARM.com          case 6:
11137404SAli.Saidi@ARM.com            panic("Imp defined type\n");
11147404SAli.Saidi@ARM.com          case 7:
11157436Sdam.sunwoo@arm.com            curr_tr = prrr.tr7;
11167436Sdam.sunwoo@arm.com            curr_ir = nmrr.ir7;
11177436Sdam.sunwoo@arm.com            curr_or = nmrr.or7;
111810037SARM gem5 Developers            te.outerShareable = (prrr.nos7 == 0);
11197404SAli.Saidi@ARM.com            break;
11207404SAli.Saidi@ARM.com        }
11217436Sdam.sunwoo@arm.com
11227436Sdam.sunwoo@arm.com        switch(curr_tr) {
11237436Sdam.sunwoo@arm.com          case 0:
11247436Sdam.sunwoo@arm.com            DPRINTF(TLBVerbose, "StronglyOrdered\n");
112510037SARM gem5 Developers            te.mtype = TlbEntry::MemoryType::StronglyOrdered;
11267436Sdam.sunwoo@arm.com            te.nonCacheable = true;
11277436Sdam.sunwoo@arm.com            te.innerAttrs = 1;
11287436Sdam.sunwoo@arm.com            te.outerAttrs = 0;
11297436Sdam.sunwoo@arm.com            te.shareable = true;
11307436Sdam.sunwoo@arm.com            break;
11317436Sdam.sunwoo@arm.com          case 1:
11327436Sdam.sunwoo@arm.com            DPRINTF(TLBVerbose, "Device ds1:%d ds0:%d s:%d\n",
11337436Sdam.sunwoo@arm.com                    prrr.ds1, prrr.ds0, s);
113410037SARM gem5 Developers            te.mtype = TlbEntry::MemoryType::Device;
11357436Sdam.sunwoo@arm.com            te.nonCacheable = true;
11367436Sdam.sunwoo@arm.com            te.innerAttrs = 3;
11377436Sdam.sunwoo@arm.com            te.outerAttrs = 0;
11387436Sdam.sunwoo@arm.com            if (prrr.ds1 && s)
11397436Sdam.sunwoo@arm.com                te.shareable = true;
11407436Sdam.sunwoo@arm.com            if (prrr.ds0 && !s)
11417436Sdam.sunwoo@arm.com                te.shareable = true;
11427436Sdam.sunwoo@arm.com            break;
11437436Sdam.sunwoo@arm.com          case 2:
11447436Sdam.sunwoo@arm.com            DPRINTF(TLBVerbose, "Normal ns1:%d ns0:%d s:%d\n",
11457436Sdam.sunwoo@arm.com                    prrr.ns1, prrr.ns0, s);
114610037SARM gem5 Developers            te.mtype = TlbEntry::MemoryType::Normal;
11477436Sdam.sunwoo@arm.com            if (prrr.ns1 && s)
11487436Sdam.sunwoo@arm.com                te.shareable = true;
11497436Sdam.sunwoo@arm.com            if (prrr.ns0 && !s)
11507436Sdam.sunwoo@arm.com                te.shareable = true;
11517436Sdam.sunwoo@arm.com            break;
11527436Sdam.sunwoo@arm.com          case 3:
11537436Sdam.sunwoo@arm.com            panic("Reserved type");
11547436Sdam.sunwoo@arm.com        }
11557436Sdam.sunwoo@arm.com
115610037SARM gem5 Developers        if (te.mtype == TlbEntry::MemoryType::Normal){
11577436Sdam.sunwoo@arm.com            switch(curr_ir) {
11587436Sdam.sunwoo@arm.com              case 0:
11597436Sdam.sunwoo@arm.com                te.nonCacheable = true;
11607436Sdam.sunwoo@arm.com                te.innerAttrs = 0;
11617436Sdam.sunwoo@arm.com                break;
11627436Sdam.sunwoo@arm.com              case 1:
11637436Sdam.sunwoo@arm.com                te.innerAttrs = 5;
11647436Sdam.sunwoo@arm.com                break;
11657436Sdam.sunwoo@arm.com              case 2:
11667436Sdam.sunwoo@arm.com                te.innerAttrs = 6;
11677436Sdam.sunwoo@arm.com                break;
11687436Sdam.sunwoo@arm.com              case 3:
11697436Sdam.sunwoo@arm.com                te.innerAttrs = 7;
11707436Sdam.sunwoo@arm.com                break;
11717436Sdam.sunwoo@arm.com            }
11727436Sdam.sunwoo@arm.com
11737436Sdam.sunwoo@arm.com            switch(curr_or) {
11747436Sdam.sunwoo@arm.com              case 0:
11757436Sdam.sunwoo@arm.com                te.nonCacheable = true;
11767436Sdam.sunwoo@arm.com                te.outerAttrs = 0;
11777436Sdam.sunwoo@arm.com                break;
11787436Sdam.sunwoo@arm.com              case 1:
11797436Sdam.sunwoo@arm.com                te.outerAttrs = 1;
11807436Sdam.sunwoo@arm.com                break;
11817436Sdam.sunwoo@arm.com              case 2:
11827436Sdam.sunwoo@arm.com                te.outerAttrs = 2;
11837436Sdam.sunwoo@arm.com                break;
11847436Sdam.sunwoo@arm.com              case 3:
11857436Sdam.sunwoo@arm.com                te.outerAttrs = 3;
11867436Sdam.sunwoo@arm.com                break;
11877436Sdam.sunwoo@arm.com            }
11887436Sdam.sunwoo@arm.com        }
11897404SAli.Saidi@ARM.com    }
119010367SAndrew.Bardsley@arm.com    DPRINTF(TLBVerbose, "memAttrs: shareable: %d, innerAttrs: %d, "
119110367SAndrew.Bardsley@arm.com            "outerAttrs: %d\n",
11927439Sdam.sunwoo@arm.com            te.shareable, te.innerAttrs, te.outerAttrs);
119310037SARM gem5 Developers    te.setAttributes(false);
119410037SARM gem5 Developers}
11957436Sdam.sunwoo@arm.com
119610037SARM gem5 Developersvoid
119710037SARM gem5 DevelopersTableWalker::memAttrsLPAE(ThreadContext *tc, TlbEntry &te,
119810037SARM gem5 Developers    LongDescriptor &lDescriptor)
119910037SARM gem5 Developers{
120010037SARM gem5 Developers    assert(_haveLPAE);
12017436Sdam.sunwoo@arm.com
120210037SARM gem5 Developers    uint8_t attr;
120310037SARM gem5 Developers    uint8_t sh = lDescriptor.sh();
120410037SARM gem5 Developers    // Different format and source of attributes if this is a stage 2
120510037SARM gem5 Developers    // translation
120610037SARM gem5 Developers    if (isStage2) {
120710037SARM gem5 Developers        attr = lDescriptor.memAttr();
120810037SARM gem5 Developers        uint8_t attr_3_2 = (attr >> 2) & 0x3;
120910037SARM gem5 Developers        uint8_t attr_1_0 =  attr       & 0x3;
12107436Sdam.sunwoo@arm.com
121110037SARM gem5 Developers        DPRINTF(TLBVerbose, "memAttrsLPAE MemAttr:%#x sh:%#x\n", attr, sh);
121210037SARM gem5 Developers
121310037SARM gem5 Developers        if (attr_3_2 == 0) {
121410037SARM gem5 Developers            te.mtype        = attr_1_0 == 0 ? TlbEntry::MemoryType::StronglyOrdered
121510037SARM gem5 Developers                                            : TlbEntry::MemoryType::Device;
121610037SARM gem5 Developers            te.outerAttrs   = 0;
121710037SARM gem5 Developers            te.innerAttrs   = attr_1_0 == 0 ? 1 : 3;
121810037SARM gem5 Developers            te.nonCacheable = true;
121910037SARM gem5 Developers        } else {
122010037SARM gem5 Developers            te.mtype        = TlbEntry::MemoryType::Normal;
122110037SARM gem5 Developers            te.outerAttrs   = attr_3_2 == 1 ? 0 :
122210037SARM gem5 Developers                              attr_3_2 == 2 ? 2 : 1;
122310037SARM gem5 Developers            te.innerAttrs   = attr_1_0 == 1 ? 0 :
122410037SARM gem5 Developers                              attr_1_0 == 2 ? 6 : 5;
122510037SARM gem5 Developers            te.nonCacheable = (attr_3_2 == 1) || (attr_1_0 == 1);
122610037SARM gem5 Developers        }
122710037SARM gem5 Developers    } else {
122810037SARM gem5 Developers        uint8_t attrIndx = lDescriptor.attrIndx();
122910037SARM gem5 Developers
123010037SARM gem5 Developers        // LPAE always uses remapping of memory attributes, irrespective of the
123110037SARM gem5 Developers        // value of SCTLR.TRE
123210421Sandreas.hansson@arm.com        MiscRegIndex reg = attrIndx & 0x4 ? MISCREG_MAIR1 : MISCREG_MAIR0;
123310421Sandreas.hansson@arm.com        int reg_as_int = flattenMiscRegNsBanked(reg, currState->tc,
123410421Sandreas.hansson@arm.com                                                !currState->isSecure);
123510421Sandreas.hansson@arm.com        uint32_t mair = currState->tc->readMiscReg(reg_as_int);
123610037SARM gem5 Developers        attr = (mair >> (8 * (attrIndx % 4))) & 0xff;
123710037SARM gem5 Developers        uint8_t attr_7_4 = bits(attr, 7, 4);
123810037SARM gem5 Developers        uint8_t attr_3_0 = bits(attr, 3, 0);
123910037SARM gem5 Developers        DPRINTF(TLBVerbose, "memAttrsLPAE AttrIndx:%#x sh:%#x, attr %#x\n", attrIndx, sh, attr);
124010037SARM gem5 Developers
124110037SARM gem5 Developers        // Note: the memory subsystem only cares about the 'cacheable' memory
124210037SARM gem5 Developers        // attribute. The other attributes are only used to fill the PAR register
124310037SARM gem5 Developers        // accordingly to provide the illusion of full support
124410037SARM gem5 Developers        te.nonCacheable = false;
124510037SARM gem5 Developers
124610037SARM gem5 Developers        switch (attr_7_4) {
124710037SARM gem5 Developers          case 0x0:
124810037SARM gem5 Developers            // Strongly-ordered or Device memory
124910037SARM gem5 Developers            if (attr_3_0 == 0x0)
125010037SARM gem5 Developers                te.mtype = TlbEntry::MemoryType::StronglyOrdered;
125110037SARM gem5 Developers            else if (attr_3_0 == 0x4)
125210037SARM gem5 Developers                te.mtype = TlbEntry::MemoryType::Device;
125310037SARM gem5 Developers            else
125410037SARM gem5 Developers                panic("Unpredictable behavior\n");
125510037SARM gem5 Developers            te.nonCacheable = true;
125610037SARM gem5 Developers            te.outerAttrs   = 0;
125710037SARM gem5 Developers            break;
125810037SARM gem5 Developers          case 0x4:
125910037SARM gem5 Developers            // Normal memory, Outer Non-cacheable
126010037SARM gem5 Developers            te.mtype = TlbEntry::MemoryType::Normal;
126110037SARM gem5 Developers            te.outerAttrs = 0;
126210037SARM gem5 Developers            if (attr_3_0 == 0x4)
126310037SARM gem5 Developers                // Inner Non-cacheable
126410037SARM gem5 Developers                te.nonCacheable = true;
126510037SARM gem5 Developers            else if (attr_3_0 < 0x8)
126610037SARM gem5 Developers                panic("Unpredictable behavior\n");
126710037SARM gem5 Developers            break;
126810037SARM gem5 Developers          case 0x8:
126910037SARM gem5 Developers          case 0x9:
127010037SARM gem5 Developers          case 0xa:
127110037SARM gem5 Developers          case 0xb:
127210037SARM gem5 Developers          case 0xc:
127310037SARM gem5 Developers          case 0xd:
127410037SARM gem5 Developers          case 0xe:
127510037SARM gem5 Developers          case 0xf:
127610037SARM gem5 Developers            if (attr_7_4 & 0x4) {
127710037SARM gem5 Developers                te.outerAttrs = (attr_7_4 & 1) ? 1 : 3;
127810037SARM gem5 Developers            } else {
127910037SARM gem5 Developers                te.outerAttrs = 0x2;
128010037SARM gem5 Developers            }
128110037SARM gem5 Developers            // Normal memory, Outer Cacheable
128210037SARM gem5 Developers            te.mtype = TlbEntry::MemoryType::Normal;
128310037SARM gem5 Developers            if (attr_3_0 != 0x4 && attr_3_0 < 0x8)
128410037SARM gem5 Developers                panic("Unpredictable behavior\n");
128510037SARM gem5 Developers            break;
128610037SARM gem5 Developers          default:
128710037SARM gem5 Developers            panic("Unpredictable behavior\n");
128810037SARM gem5 Developers            break;
128910037SARM gem5 Developers        }
129010037SARM gem5 Developers
129110037SARM gem5 Developers        switch (attr_3_0) {
129210037SARM gem5 Developers          case 0x0:
129310037SARM gem5 Developers            te.innerAttrs = 0x1;
129410037SARM gem5 Developers            break;
129510037SARM gem5 Developers          case 0x4:
129610037SARM gem5 Developers            te.innerAttrs = attr_7_4 == 0 ? 0x3 : 0;
129710037SARM gem5 Developers            break;
129810037SARM gem5 Developers          case 0x8:
129910037SARM gem5 Developers          case 0x9:
130010037SARM gem5 Developers          case 0xA:
130110037SARM gem5 Developers          case 0xB:
130210037SARM gem5 Developers            te.innerAttrs = 6;
130310037SARM gem5 Developers            break;
130410037SARM gem5 Developers          case 0xC:
130510037SARM gem5 Developers          case 0xD:
130610037SARM gem5 Developers          case 0xE:
130710037SARM gem5 Developers          case 0xF:
130810037SARM gem5 Developers            te.innerAttrs = attr_3_0 & 1 ? 0x5 : 0x7;
130910037SARM gem5 Developers            break;
131010037SARM gem5 Developers          default:
131110037SARM gem5 Developers            panic("Unpredictable behavior\n");
131210037SARM gem5 Developers            break;
131310037SARM gem5 Developers        }
131410037SARM gem5 Developers    }
131510037SARM gem5 Developers
131610037SARM gem5 Developers    te.outerShareable = sh == 2;
131710037SARM gem5 Developers    te.shareable       = (sh & 0x2) ? true : false;
131810037SARM gem5 Developers    te.setAttributes(true);
131910037SARM gem5 Developers    te.attributes |= (uint64_t) attr << 56;
132010037SARM gem5 Developers}
132110037SARM gem5 Developers
132210037SARM gem5 Developersvoid
132310037SARM gem5 DevelopersTableWalker::memAttrsAArch64(ThreadContext *tc, TlbEntry &te, uint8_t attrIndx,
132410037SARM gem5 Developers                             uint8_t sh)
132510037SARM gem5 Developers{
132610037SARM gem5 Developers    DPRINTF(TLBVerbose, "memAttrsAArch64 AttrIndx:%#x sh:%#x\n", attrIndx, sh);
132710037SARM gem5 Developers
132810037SARM gem5 Developers    // Select MAIR
132910037SARM gem5 Developers    uint64_t mair;
133010037SARM gem5 Developers    switch (currState->el) {
133110037SARM gem5 Developers      case EL0:
133210037SARM gem5 Developers      case EL1:
133310037SARM gem5 Developers        mair = tc->readMiscReg(MISCREG_MAIR_EL1);
133410037SARM gem5 Developers        break;
133510037SARM gem5 Developers      case EL2:
133610037SARM gem5 Developers        mair = tc->readMiscReg(MISCREG_MAIR_EL2);
133710037SARM gem5 Developers        break;
133810037SARM gem5 Developers      case EL3:
133910037SARM gem5 Developers        mair = tc->readMiscReg(MISCREG_MAIR_EL3);
134010037SARM gem5 Developers        break;
134110037SARM gem5 Developers      default:
134210037SARM gem5 Developers        panic("Invalid exception level");
134310037SARM gem5 Developers        break;
134410037SARM gem5 Developers    }
134510037SARM gem5 Developers
134610037SARM gem5 Developers    // Select attributes
134710037SARM gem5 Developers    uint8_t attr = bits(mair, 8 * attrIndx + 7, 8 * attrIndx);
134810037SARM gem5 Developers    uint8_t attr_lo = bits(attr, 3, 0);
134910037SARM gem5 Developers    uint8_t attr_hi = bits(attr, 7, 4);
135010037SARM gem5 Developers
135110037SARM gem5 Developers    // Memory type
135210037SARM gem5 Developers    te.mtype = attr_hi == 0 ? TlbEntry::MemoryType::Device : TlbEntry::MemoryType::Normal;
135310037SARM gem5 Developers
135410037SARM gem5 Developers    // Cacheability
135510037SARM gem5 Developers    te.nonCacheable = false;
135610037SARM gem5 Developers    if (te.mtype == TlbEntry::MemoryType::Device ||  // Device memory
135710037SARM gem5 Developers        attr_hi == 0x8 ||  // Normal memory, Outer Non-cacheable
135810037SARM gem5 Developers        attr_lo == 0x8) {  // Normal memory, Inner Non-cacheable
135910037SARM gem5 Developers        te.nonCacheable = true;
136010037SARM gem5 Developers    }
136110037SARM gem5 Developers
136210037SARM gem5 Developers    te.shareable       = sh == 2;
136310037SARM gem5 Developers    te.outerShareable = (sh & 0x2) ? true : false;
136410037SARM gem5 Developers    // Attributes formatted according to the 64-bit PAR
136510037SARM gem5 Developers    te.attributes = ((uint64_t) attr << 56) |
136610037SARM gem5 Developers        (1 << 11) |     // LPAE bit
136710037SARM gem5 Developers        (te.ns << 9) |  // NS bit
136810037SARM gem5 Developers        (sh << 7);
13697404SAli.Saidi@ARM.com}
13707404SAli.Saidi@ARM.com
13717404SAli.Saidi@ARM.comvoid
13727404SAli.Saidi@ARM.comTableWalker::doL1Descriptor()
13737404SAli.Saidi@ARM.com{
137410037SARM gem5 Developers    if (currState->fault != NoFault) {
137510037SARM gem5 Developers        return;
137610037SARM gem5 Developers    }
137710037SARM gem5 Developers
13787439Sdam.sunwoo@arm.com    DPRINTF(TLB, "L1 descriptor for %#x is %#x\n",
137910037SARM gem5 Developers            currState->vaddr_tainted, currState->l1Desc.data);
13807404SAli.Saidi@ARM.com    TlbEntry te;
13817404SAli.Saidi@ARM.com
13827439Sdam.sunwoo@arm.com    switch (currState->l1Desc.type()) {
13837404SAli.Saidi@ARM.com      case L1Descriptor::Ignore:
13847404SAli.Saidi@ARM.com      case L1Descriptor::Reserved:
13857946SGiacomo.Gabrielli@arm.com        if (!currState->timing) {
13867439Sdam.sunwoo@arm.com            currState->tc = NULL;
13877439Sdam.sunwoo@arm.com            currState->req = NULL;
13887437Sdam.sunwoo@arm.com        }
13897406SAli.Saidi@ARM.com        DPRINTF(TLB, "L1 Descriptor Reserved/Ignore, causing fault\n");
13907439Sdam.sunwoo@arm.com        if (currState->isFetch)
13917439Sdam.sunwoo@arm.com            currState->fault =
139210474Sandreas.hansson@arm.com                std::make_shared<PrefetchAbort>(
139310474Sandreas.hansson@arm.com                    currState->vaddr_tainted,
139410474Sandreas.hansson@arm.com                    ArmFault::TranslationLL + L1,
139510474Sandreas.hansson@arm.com                    isStage2,
139610474Sandreas.hansson@arm.com                    ArmFault::VmsaTran);
13977406SAli.Saidi@ARM.com        else
13987439Sdam.sunwoo@arm.com            currState->fault =
139910474Sandreas.hansson@arm.com                std::make_shared<DataAbort>(
140010474Sandreas.hansson@arm.com                    currState->vaddr_tainted,
140110474Sandreas.hansson@arm.com                    TlbEntry::DomainType::NoAccess,
140210474Sandreas.hansson@arm.com                    currState->isWrite,
140310474Sandreas.hansson@arm.com                    ArmFault::TranslationLL + L1, isStage2,
140410474Sandreas.hansson@arm.com                    ArmFault::VmsaTran);
14057404SAli.Saidi@ARM.com        return;
14067404SAli.Saidi@ARM.com      case L1Descriptor::Section:
14077439Sdam.sunwoo@arm.com        if (currState->sctlr.afe && bits(currState->l1Desc.ap(), 0) == 0) {
14087436Sdam.sunwoo@arm.com            /** @todo: check sctlr.ha (bit[17]) if Hardware Access Flag is
14097436Sdam.sunwoo@arm.com              * enabled if set, do l1.Desc.setAp0() instead of generating
14107436Sdam.sunwoo@arm.com              * AccessFlag0
14117436Sdam.sunwoo@arm.com              */
14127436Sdam.sunwoo@arm.com
141310474Sandreas.hansson@arm.com            currState->fault = std::make_shared<DataAbort>(
141410474Sandreas.hansson@arm.com                currState->vaddr_tainted,
141510474Sandreas.hansson@arm.com                currState->l1Desc.domain(),
141610474Sandreas.hansson@arm.com                currState->isWrite,
141710474Sandreas.hansson@arm.com                ArmFault::AccessFlagLL + L1,
141810474Sandreas.hansson@arm.com                isStage2,
141910474Sandreas.hansson@arm.com                ArmFault::VmsaTran);
14207436Sdam.sunwoo@arm.com        }
14217439Sdam.sunwoo@arm.com        if (currState->l1Desc.supersection()) {
14227404SAli.Saidi@ARM.com            panic("Haven't implemented supersections\n");
14237404SAli.Saidi@ARM.com        }
142410037SARM gem5 Developers        insertTableEntry(currState->l1Desc, false);
142510037SARM gem5 Developers        return;
142610037SARM gem5 Developers      case L1Descriptor::PageTable:
142710037SARM gem5 Developers        {
142810037SARM gem5 Developers            Addr l2desc_addr;
142910037SARM gem5 Developers            l2desc_addr = currState->l1Desc.l2Addr() |
143010037SARM gem5 Developers                (bits(currState->vaddr, 19, 12) << 2);
143110037SARM gem5 Developers            DPRINTF(TLB, "L1 descriptor points to page table at: %#x (%s)\n",
143210037SARM gem5 Developers                    l2desc_addr, currState->isSecure ? "s" : "ns");
14337404SAli.Saidi@ARM.com
143410037SARM gem5 Developers            // Trickbox address check
143511395Sandreas.sandberg@arm.com            currState->fault = testWalk(l2desc_addr, sizeof(uint32_t),
143611395Sandreas.sandberg@arm.com                                        currState->l1Desc.domain(), L2);
14377404SAli.Saidi@ARM.com
143810037SARM gem5 Developers            if (currState->fault) {
143910037SARM gem5 Developers                if (!currState->timing) {
144010037SARM gem5 Developers                    currState->tc = NULL;
144110037SARM gem5 Developers                    currState->req = NULL;
144210037SARM gem5 Developers                }
144310037SARM gem5 Developers                return;
144410037SARM gem5 Developers            }
144510037SARM gem5 Developers
144610836Sandreas.hansson@arm.com            Request::Flags flag = Request::PT_WALK;
144710037SARM gem5 Developers            if (currState->isSecure)
144810037SARM gem5 Developers                flag.set(Request::SECURE);
144910037SARM gem5 Developers
145010037SARM gem5 Developers            bool delayed;
145110037SARM gem5 Developers            delayed = fetchDescriptor(l2desc_addr,
145210037SARM gem5 Developers                                      (uint8_t*)&currState->l2Desc.data,
145310037SARM gem5 Developers                                      sizeof(uint32_t), flag, -1, &doL2DescEvent,
145410037SARM gem5 Developers                                      &TableWalker::doL2Descriptor);
145510037SARM gem5 Developers            if (delayed) {
145610037SARM gem5 Developers                currState->delayed = true;
145710037SARM gem5 Developers            }
145810037SARM gem5 Developers
145910037SARM gem5 Developers            return;
146010037SARM gem5 Developers        }
146110037SARM gem5 Developers      default:
146210037SARM gem5 Developers        panic("A new type in a 2 bit field?\n");
146310037SARM gem5 Developers    }
146410037SARM gem5 Developers}
146510037SARM gem5 Developers
146610037SARM gem5 Developersvoid
146710037SARM gem5 DevelopersTableWalker::doLongDescriptor()
146810037SARM gem5 Developers{
146910037SARM gem5 Developers    if (currState->fault != NoFault) {
147010037SARM gem5 Developers        return;
147110037SARM gem5 Developers    }
147210037SARM gem5 Developers
147310037SARM gem5 Developers    DPRINTF(TLB, "L%d descriptor for %#llx is %#llx (%s)\n",
147410037SARM gem5 Developers            currState->longDesc.lookupLevel, currState->vaddr_tainted,
147510037SARM gem5 Developers            currState->longDesc.data,
147610037SARM gem5 Developers            currState->aarch64 ? "AArch64" : "long-desc.");
147710037SARM gem5 Developers
147810037SARM gem5 Developers    if ((currState->longDesc.type() == LongDescriptor::Block) ||
147910037SARM gem5 Developers        (currState->longDesc.type() == LongDescriptor::Page)) {
148010037SARM gem5 Developers        DPRINTF(TLBVerbose, "Analyzing L%d descriptor: %#llx, pxn: %d, "
148110037SARM gem5 Developers                "xn: %d, ap: %d, af: %d, type: %d\n",
148210037SARM gem5 Developers                currState->longDesc.lookupLevel,
148310037SARM gem5 Developers                currState->longDesc.data,
148410037SARM gem5 Developers                currState->longDesc.pxn(),
148510037SARM gem5 Developers                currState->longDesc.xn(),
148610037SARM gem5 Developers                currState->longDesc.ap(),
148710037SARM gem5 Developers                currState->longDesc.af(),
148810037SARM gem5 Developers                currState->longDesc.type());
148910037SARM gem5 Developers    } else {
149010037SARM gem5 Developers        DPRINTF(TLBVerbose, "Analyzing L%d descriptor: %#llx, type: %d\n",
149110037SARM gem5 Developers                currState->longDesc.lookupLevel,
149210037SARM gem5 Developers                currState->longDesc.data,
149310037SARM gem5 Developers                currState->longDesc.type());
149410037SARM gem5 Developers    }
149510037SARM gem5 Developers
149610037SARM gem5 Developers    TlbEntry te;
149710037SARM gem5 Developers
149810037SARM gem5 Developers    switch (currState->longDesc.type()) {
149910037SARM gem5 Developers      case LongDescriptor::Invalid:
15007439Sdam.sunwoo@arm.com        if (!currState->timing) {
15017439Sdam.sunwoo@arm.com            currState->tc = NULL;
15027439Sdam.sunwoo@arm.com            currState->req = NULL;
15037437Sdam.sunwoo@arm.com        }
15047404SAli.Saidi@ARM.com
150510037SARM gem5 Developers        DPRINTF(TLB, "L%d descriptor Invalid, causing fault type %d\n",
150610037SARM gem5 Developers                currState->longDesc.lookupLevel,
150710037SARM gem5 Developers                ArmFault::TranslationLL + currState->longDesc.lookupLevel);
150810037SARM gem5 Developers        if (currState->isFetch)
150910474Sandreas.hansson@arm.com            currState->fault = std::make_shared<PrefetchAbort>(
151010037SARM gem5 Developers                currState->vaddr_tainted,
151110037SARM gem5 Developers                ArmFault::TranslationLL + currState->longDesc.lookupLevel,
151210037SARM gem5 Developers                isStage2,
151310037SARM gem5 Developers                ArmFault::LpaeTran);
151410037SARM gem5 Developers        else
151510474Sandreas.hansson@arm.com            currState->fault = std::make_shared<DataAbort>(
151610037SARM gem5 Developers                currState->vaddr_tainted,
151710037SARM gem5 Developers                TlbEntry::DomainType::NoAccess,
151810037SARM gem5 Developers                currState->isWrite,
151910037SARM gem5 Developers                ArmFault::TranslationLL + currState->longDesc.lookupLevel,
152010037SARM gem5 Developers                isStage2,
152110037SARM gem5 Developers                ArmFault::LpaeTran);
15227404SAli.Saidi@ARM.com        return;
152310037SARM gem5 Developers      case LongDescriptor::Block:
152410037SARM gem5 Developers      case LongDescriptor::Page:
152510037SARM gem5 Developers        {
152610037SARM gem5 Developers            bool fault = false;
152710037SARM gem5 Developers            bool aff = false;
152810037SARM gem5 Developers            // Check for address size fault
152910037SARM gem5 Developers            if (checkAddrSizeFaultAArch64(
153010037SARM gem5 Developers                    mbits(currState->longDesc.data, MaxPhysAddrRange - 1,
153110037SARM gem5 Developers                          currState->longDesc.offsetBits()),
153210037SARM gem5 Developers                    currState->physAddrRange)) {
153310037SARM gem5 Developers                fault = true;
153410037SARM gem5 Developers                DPRINTF(TLB, "L%d descriptor causing Address Size Fault\n",
153510037SARM gem5 Developers                        currState->longDesc.lookupLevel);
153610037SARM gem5 Developers            // Check for access fault
153710037SARM gem5 Developers            } else if (currState->longDesc.af() == 0) {
153810037SARM gem5 Developers                fault = true;
153910037SARM gem5 Developers                DPRINTF(TLB, "L%d descriptor causing Access Fault\n",
154010037SARM gem5 Developers                        currState->longDesc.lookupLevel);
154110037SARM gem5 Developers                aff = true;
154210037SARM gem5 Developers            }
154310037SARM gem5 Developers            if (fault) {
154410037SARM gem5 Developers                if (currState->isFetch)
154510474Sandreas.hansson@arm.com                    currState->fault = std::make_shared<PrefetchAbort>(
154610037SARM gem5 Developers                        currState->vaddr_tainted,
154710037SARM gem5 Developers                        (aff ? ArmFault::AccessFlagLL : ArmFault::AddressSizeLL) +
154810037SARM gem5 Developers                        currState->longDesc.lookupLevel,
154910037SARM gem5 Developers                        isStage2,
155010037SARM gem5 Developers                        ArmFault::LpaeTran);
155110037SARM gem5 Developers                else
155210474Sandreas.hansson@arm.com                    currState->fault = std::make_shared<DataAbort>(
155310037SARM gem5 Developers                        currState->vaddr_tainted,
155410037SARM gem5 Developers                        TlbEntry::DomainType::NoAccess, currState->isWrite,
155510037SARM gem5 Developers                        (aff ? ArmFault::AccessFlagLL : ArmFault::AddressSizeLL) +
155610037SARM gem5 Developers                        currState->longDesc.lookupLevel,
155710037SARM gem5 Developers                        isStage2,
155810037SARM gem5 Developers                        ArmFault::LpaeTran);
155910037SARM gem5 Developers            } else {
156010037SARM gem5 Developers                insertTableEntry(currState->longDesc, true);
156110037SARM gem5 Developers            }
156210037SARM gem5 Developers        }
156310037SARM gem5 Developers        return;
156410037SARM gem5 Developers      case LongDescriptor::Table:
156510037SARM gem5 Developers        {
156610037SARM gem5 Developers            // Set hierarchical permission flags
156710037SARM gem5 Developers            currState->secureLookup = currState->secureLookup &&
156810037SARM gem5 Developers                currState->longDesc.secureTable();
156910037SARM gem5 Developers            currState->rwTable = currState->rwTable &&
157010037SARM gem5 Developers                currState->longDesc.rwTable();
157110037SARM gem5 Developers            currState->userTable = currState->userTable &&
157210037SARM gem5 Developers                currState->longDesc.userTable();
157310037SARM gem5 Developers            currState->xnTable = currState->xnTable ||
157410037SARM gem5 Developers                currState->longDesc.xnTable();
157510037SARM gem5 Developers            currState->pxnTable = currState->pxnTable ||
157610037SARM gem5 Developers                currState->longDesc.pxnTable();
15777404SAli.Saidi@ARM.com
157810037SARM gem5 Developers            // Set up next level lookup
157910037SARM gem5 Developers            Addr next_desc_addr = currState->longDesc.nextDescAddr(
158010037SARM gem5 Developers                currState->vaddr);
15817439Sdam.sunwoo@arm.com
158210037SARM gem5 Developers            DPRINTF(TLB, "L%d descriptor points to L%d descriptor at: %#x (%s)\n",
158310037SARM gem5 Developers                    currState->longDesc.lookupLevel,
158410037SARM gem5 Developers                    currState->longDesc.lookupLevel + 1,
158510037SARM gem5 Developers                    next_desc_addr,
158610037SARM gem5 Developers                    currState->secureLookup ? "s" : "ns");
158710037SARM gem5 Developers
158810037SARM gem5 Developers            // Check for address size fault
158910037SARM gem5 Developers            if (currState->aarch64 && checkAddrSizeFaultAArch64(
159010037SARM gem5 Developers                    next_desc_addr, currState->physAddrRange)) {
159110037SARM gem5 Developers                DPRINTF(TLB, "L%d descriptor causing Address Size Fault\n",
159210037SARM gem5 Developers                        currState->longDesc.lookupLevel);
159310037SARM gem5 Developers                if (currState->isFetch)
159410474Sandreas.hansson@arm.com                    currState->fault = std::make_shared<PrefetchAbort>(
159510037SARM gem5 Developers                        currState->vaddr_tainted,
159610037SARM gem5 Developers                        ArmFault::AddressSizeLL
159710037SARM gem5 Developers                        + currState->longDesc.lookupLevel,
159810037SARM gem5 Developers                        isStage2,
159910037SARM gem5 Developers                        ArmFault::LpaeTran);
160010037SARM gem5 Developers                else
160110474Sandreas.hansson@arm.com                    currState->fault = std::make_shared<DataAbort>(
160210037SARM gem5 Developers                        currState->vaddr_tainted,
160310037SARM gem5 Developers                        TlbEntry::DomainType::NoAccess, currState->isWrite,
160410037SARM gem5 Developers                        ArmFault::AddressSizeLL
160510037SARM gem5 Developers                        + currState->longDesc.lookupLevel,
160610037SARM gem5 Developers                        isStage2,
160710037SARM gem5 Developers                        ArmFault::LpaeTran);
160810037SARM gem5 Developers                return;
16097437Sdam.sunwoo@arm.com            }
16107404SAli.Saidi@ARM.com
161110037SARM gem5 Developers            // Trickbox address check
161211395Sandreas.sandberg@arm.com            currState->fault = testWalk(
161311395Sandreas.sandberg@arm.com                next_desc_addr, sizeof(uint64_t), TlbEntry::DomainType::Client,
161411395Sandreas.sandberg@arm.com                toLookupLevel(currState->longDesc.lookupLevel +1));
16157404SAli.Saidi@ARM.com
161610037SARM gem5 Developers            if (currState->fault) {
161710037SARM gem5 Developers                if (!currState->timing) {
161810037SARM gem5 Developers                    currState->tc = NULL;
161910037SARM gem5 Developers                    currState->req = NULL;
162010037SARM gem5 Developers                }
162110037SARM gem5 Developers                return;
162210037SARM gem5 Developers            }
162310037SARM gem5 Developers
162410836Sandreas.hansson@arm.com            Request::Flags flag = Request::PT_WALK;
162510037SARM gem5 Developers            if (currState->secureLookup)
162610037SARM gem5 Developers                flag.set(Request::SECURE);
162710037SARM gem5 Developers
162810037SARM gem5 Developers            currState->longDesc.lookupLevel =
162910037SARM gem5 Developers                (LookupLevel) (currState->longDesc.lookupLevel + 1);
163010037SARM gem5 Developers            Event *event = NULL;
163110037SARM gem5 Developers            switch (currState->longDesc.lookupLevel) {
163210037SARM gem5 Developers              case L1:
163310037SARM gem5 Developers                assert(currState->aarch64);
163410037SARM gem5 Developers                event = &doL1LongDescEvent;
163510037SARM gem5 Developers                break;
163610037SARM gem5 Developers              case L2:
163710037SARM gem5 Developers                event = &doL2LongDescEvent;
163810037SARM gem5 Developers                break;
163910037SARM gem5 Developers              case L3:
164010037SARM gem5 Developers                event = &doL3LongDescEvent;
164110037SARM gem5 Developers                break;
164210037SARM gem5 Developers              default:
164310037SARM gem5 Developers                panic("Wrong lookup level in table walk\n");
164410037SARM gem5 Developers                break;
164510037SARM gem5 Developers            }
164610037SARM gem5 Developers
164710037SARM gem5 Developers            bool delayed;
164810037SARM gem5 Developers            delayed = fetchDescriptor(next_desc_addr, (uint8_t*)&currState->longDesc.data,
164910037SARM gem5 Developers                                      sizeof(uint64_t), flag, -1, event,
165010037SARM gem5 Developers                                      &TableWalker::doLongDescriptor);
165110037SARM gem5 Developers            if (delayed) {
165210037SARM gem5 Developers                 currState->delayed = true;
165310037SARM gem5 Developers            }
16547404SAli.Saidi@ARM.com        }
16557404SAli.Saidi@ARM.com        return;
16567404SAli.Saidi@ARM.com      default:
16577404SAli.Saidi@ARM.com        panic("A new type in a 2 bit field?\n");
16587404SAli.Saidi@ARM.com    }
16597404SAli.Saidi@ARM.com}
16607404SAli.Saidi@ARM.com
16617404SAli.Saidi@ARM.comvoid
16627404SAli.Saidi@ARM.comTableWalker::doL2Descriptor()
16637404SAli.Saidi@ARM.com{
166410037SARM gem5 Developers    if (currState->fault != NoFault) {
166510037SARM gem5 Developers        return;
166610037SARM gem5 Developers    }
166710037SARM gem5 Developers
16687439Sdam.sunwoo@arm.com    DPRINTF(TLB, "L2 descriptor for %#x is %#x\n",
166910037SARM gem5 Developers            currState->vaddr_tainted, currState->l2Desc.data);
16707404SAli.Saidi@ARM.com    TlbEntry te;
16717404SAli.Saidi@ARM.com
16727439Sdam.sunwoo@arm.com    if (currState->l2Desc.invalid()) {
16737404SAli.Saidi@ARM.com        DPRINTF(TLB, "L2 descriptor invalid, causing fault\n");
16747946SGiacomo.Gabrielli@arm.com        if (!currState->timing) {
16757439Sdam.sunwoo@arm.com            currState->tc = NULL;
16767439Sdam.sunwoo@arm.com            currState->req = NULL;
16777437Sdam.sunwoo@arm.com        }
16787439Sdam.sunwoo@arm.com        if (currState->isFetch)
167910474Sandreas.hansson@arm.com            currState->fault = std::make_shared<PrefetchAbort>(
168010474Sandreas.hansson@arm.com                    currState->vaddr_tainted,
168110474Sandreas.hansson@arm.com                    ArmFault::TranslationLL + L2,
168210474Sandreas.hansson@arm.com                    isStage2,
168310474Sandreas.hansson@arm.com                    ArmFault::VmsaTran);
16847406SAli.Saidi@ARM.com        else
168510474Sandreas.hansson@arm.com            currState->fault = std::make_shared<DataAbort>(
168610474Sandreas.hansson@arm.com                currState->vaddr_tainted, currState->l1Desc.domain(),
168710474Sandreas.hansson@arm.com                currState->isWrite, ArmFault::TranslationLL + L2,
168810474Sandreas.hansson@arm.com                isStage2,
168910474Sandreas.hansson@arm.com                ArmFault::VmsaTran);
16907404SAli.Saidi@ARM.com        return;
16917404SAli.Saidi@ARM.com    }
16927404SAli.Saidi@ARM.com
16937439Sdam.sunwoo@arm.com    if (currState->sctlr.afe && bits(currState->l2Desc.ap(), 0) == 0) {
16947436Sdam.sunwoo@arm.com        /** @todo: check sctlr.ha (bit[17]) if Hardware Access Flag is enabled
16957436Sdam.sunwoo@arm.com          * if set, do l2.Desc.setAp0() instead of generating AccessFlag0
16967436Sdam.sunwoo@arm.com          */
169710037SARM gem5 Developers         DPRINTF(TLB, "Generating access fault at L2, afe: %d, ap: %d\n",
169810037SARM gem5 Developers                 currState->sctlr.afe, currState->l2Desc.ap());
16997436Sdam.sunwoo@arm.com
170010474Sandreas.hansson@arm.com        currState->fault = std::make_shared<DataAbort>(
170110474Sandreas.hansson@arm.com            currState->vaddr_tainted,
170210474Sandreas.hansson@arm.com            TlbEntry::DomainType::NoAccess, currState->isWrite,
170310474Sandreas.hansson@arm.com            ArmFault::AccessFlagLL + L2, isStage2,
170410474Sandreas.hansson@arm.com            ArmFault::VmsaTran);
17057436Sdam.sunwoo@arm.com    }
17067436Sdam.sunwoo@arm.com
170710037SARM gem5 Developers    insertTableEntry(currState->l2Desc, false);
17087437Sdam.sunwoo@arm.com}
17097437Sdam.sunwoo@arm.com
17107437Sdam.sunwoo@arm.comvoid
17117437Sdam.sunwoo@arm.comTableWalker::doL1DescriptorWrapper()
17127437Sdam.sunwoo@arm.com{
171310037SARM gem5 Developers    currState = stateQueues[L1].front();
17147439Sdam.sunwoo@arm.com    currState->delayed = false;
171510037SARM gem5 Developers    // if there's a stage2 translation object we don't need it any more
171610037SARM gem5 Developers    if (currState->stage2Tran) {
171710037SARM gem5 Developers        delete currState->stage2Tran;
171810037SARM gem5 Developers        currState->stage2Tran = NULL;
171910037SARM gem5 Developers    }
172010037SARM gem5 Developers
17217437Sdam.sunwoo@arm.com
17227578Sdam.sunwoo@arm.com    DPRINTF(TLBVerbose, "L1 Desc object host addr: %p\n",&currState->l1Desc.data);
17237578Sdam.sunwoo@arm.com    DPRINTF(TLBVerbose, "L1 Desc object      data: %08x\n",currState->l1Desc.data);
17247578Sdam.sunwoo@arm.com
172510037SARM gem5 Developers    DPRINTF(TLBVerbose, "calling doL1Descriptor for vaddr:%#x\n", currState->vaddr_tainted);
17267437Sdam.sunwoo@arm.com    doL1Descriptor();
17277437Sdam.sunwoo@arm.com
172810037SARM gem5 Developers    stateQueues[L1].pop_front();
17297437Sdam.sunwoo@arm.com    // Check if fault was generated
17307439Sdam.sunwoo@arm.com    if (currState->fault != NoFault) {
17317439Sdam.sunwoo@arm.com        currState->transState->finish(currState->fault, currState->req,
17327439Sdam.sunwoo@arm.com                                      currState->tc, currState->mode);
173310621SCurtis.Dunham@arm.com        statWalksShortTerminatedAtLevel[0]++;
17347437Sdam.sunwoo@arm.com
17357728SAli.Saidi@ARM.com        pending = false;
17367728SAli.Saidi@ARM.com        nextWalk(currState->tc);
17377728SAli.Saidi@ARM.com
17387439Sdam.sunwoo@arm.com        currState->req = NULL;
17397439Sdam.sunwoo@arm.com        currState->tc = NULL;
17407439Sdam.sunwoo@arm.com        currState->delayed = false;
17418510SAli.Saidi@ARM.com        delete currState;
17427437Sdam.sunwoo@arm.com    }
17437439Sdam.sunwoo@arm.com    else if (!currState->delayed) {
17447653Sgene.wu@arm.com        // delay is not set so there is no L2 to do
174510037SARM gem5 Developers        // Don't finish the translation if a stage 2 look up is underway
174610037SARM gem5 Developers        if (!currState->doingStage2) {
174710621SCurtis.Dunham@arm.com            statWalkServiceTime.sample(curTick() - currState->startTime);
174810037SARM gem5 Developers            DPRINTF(TLBVerbose, "calling translateTiming again\n");
174910037SARM gem5 Developers            currState->fault = tlb->translateTiming(currState->req, currState->tc,
175010037SARM gem5 Developers                currState->transState, currState->mode);
175110621SCurtis.Dunham@arm.com            statWalksShortTerminatedAtLevel[0]++;
175210037SARM gem5 Developers        }
17537437Sdam.sunwoo@arm.com
17547728SAli.Saidi@ARM.com        pending = false;
17557728SAli.Saidi@ARM.com        nextWalk(currState->tc);
17567728SAli.Saidi@ARM.com
17577439Sdam.sunwoo@arm.com        currState->req = NULL;
17587439Sdam.sunwoo@arm.com        currState->tc = NULL;
17597439Sdam.sunwoo@arm.com        currState->delayed = false;
17607653Sgene.wu@arm.com        delete currState;
17617653Sgene.wu@arm.com    } else {
17627653Sgene.wu@arm.com        // need to do L2 descriptor
176310037SARM gem5 Developers        stateQueues[L2].push_back(currState);
17647437Sdam.sunwoo@arm.com    }
17657439Sdam.sunwoo@arm.com    currState = NULL;
17667437Sdam.sunwoo@arm.com}
17677437Sdam.sunwoo@arm.com
17687437Sdam.sunwoo@arm.comvoid
17697437Sdam.sunwoo@arm.comTableWalker::doL2DescriptorWrapper()
17707437Sdam.sunwoo@arm.com{
177110037SARM gem5 Developers    currState = stateQueues[L2].front();
17727439Sdam.sunwoo@arm.com    assert(currState->delayed);
177310037SARM gem5 Developers    // if there's a stage2 translation object we don't need it any more
177410037SARM gem5 Developers    if (currState->stage2Tran) {
177510037SARM gem5 Developers        delete currState->stage2Tran;
177610037SARM gem5 Developers        currState->stage2Tran = NULL;
177710037SARM gem5 Developers    }
17787437Sdam.sunwoo@arm.com
17797439Sdam.sunwoo@arm.com    DPRINTF(TLBVerbose, "calling doL2Descriptor for vaddr:%#x\n",
178010037SARM gem5 Developers            currState->vaddr_tainted);
17817437Sdam.sunwoo@arm.com    doL2Descriptor();
17827437Sdam.sunwoo@arm.com
17837437Sdam.sunwoo@arm.com    // Check if fault was generated
17847439Sdam.sunwoo@arm.com    if (currState->fault != NoFault) {
17857439Sdam.sunwoo@arm.com        currState->transState->finish(currState->fault, currState->req,
17867439Sdam.sunwoo@arm.com                                      currState->tc, currState->mode);
178710621SCurtis.Dunham@arm.com        statWalksShortTerminatedAtLevel[1]++;
17887437Sdam.sunwoo@arm.com    }
17897437Sdam.sunwoo@arm.com    else {
179010037SARM gem5 Developers        // Don't finish the translation if a stage 2 look up is underway
179110037SARM gem5 Developers        if (!currState->doingStage2) {
179210621SCurtis.Dunham@arm.com            statWalkServiceTime.sample(curTick() - currState->startTime);
179310037SARM gem5 Developers            DPRINTF(TLBVerbose, "calling translateTiming again\n");
179410037SARM gem5 Developers            currState->fault = tlb->translateTiming(currState->req,
179510037SARM gem5 Developers                currState->tc, currState->transState, currState->mode);
179610621SCurtis.Dunham@arm.com            statWalksShortTerminatedAtLevel[1]++;
179710037SARM gem5 Developers        }
17987437Sdam.sunwoo@arm.com    }
17997437Sdam.sunwoo@arm.com
18007728SAli.Saidi@ARM.com
180110037SARM gem5 Developers    stateQueues[L2].pop_front();
18027728SAli.Saidi@ARM.com    pending = false;
18037728SAli.Saidi@ARM.com    nextWalk(currState->tc);
18047728SAli.Saidi@ARM.com
18057439Sdam.sunwoo@arm.com    currState->req = NULL;
18067439Sdam.sunwoo@arm.com    currState->tc = NULL;
18077439Sdam.sunwoo@arm.com    currState->delayed = false;
18087439Sdam.sunwoo@arm.com
18097653Sgene.wu@arm.com    delete currState;
18107439Sdam.sunwoo@arm.com    currState = NULL;
18117404SAli.Saidi@ARM.com}
18127404SAli.Saidi@ARM.com
18137728SAli.Saidi@ARM.comvoid
181410037SARM gem5 DevelopersTableWalker::doL0LongDescriptorWrapper()
181510037SARM gem5 Developers{
181610037SARM gem5 Developers    doLongDescriptorWrapper(L0);
181710037SARM gem5 Developers}
181810037SARM gem5 Developers
181910037SARM gem5 Developersvoid
182010037SARM gem5 DevelopersTableWalker::doL1LongDescriptorWrapper()
182110037SARM gem5 Developers{
182210037SARM gem5 Developers    doLongDescriptorWrapper(L1);
182310037SARM gem5 Developers}
182410037SARM gem5 Developers
182510037SARM gem5 Developersvoid
182610037SARM gem5 DevelopersTableWalker::doL2LongDescriptorWrapper()
182710037SARM gem5 Developers{
182810037SARM gem5 Developers    doLongDescriptorWrapper(L2);
182910037SARM gem5 Developers}
183010037SARM gem5 Developers
183110037SARM gem5 Developersvoid
183210037SARM gem5 DevelopersTableWalker::doL3LongDescriptorWrapper()
183310037SARM gem5 Developers{
183410037SARM gem5 Developers    doLongDescriptorWrapper(L3);
183510037SARM gem5 Developers}
183610037SARM gem5 Developers
183710037SARM gem5 Developersvoid
183810037SARM gem5 DevelopersTableWalker::doLongDescriptorWrapper(LookupLevel curr_lookup_level)
183910037SARM gem5 Developers{
184010037SARM gem5 Developers    currState = stateQueues[curr_lookup_level].front();
184110037SARM gem5 Developers    assert(curr_lookup_level == currState->longDesc.lookupLevel);
184210037SARM gem5 Developers    currState->delayed = false;
184310037SARM gem5 Developers
184410037SARM gem5 Developers    // if there's a stage2 translation object we don't need it any more
184510037SARM gem5 Developers    if (currState->stage2Tran) {
184610037SARM gem5 Developers        delete currState->stage2Tran;
184710037SARM gem5 Developers        currState->stage2Tran = NULL;
184810037SARM gem5 Developers    }
184910037SARM gem5 Developers
185010037SARM gem5 Developers    DPRINTF(TLBVerbose, "calling doLongDescriptor for vaddr:%#x\n",
185110037SARM gem5 Developers            currState->vaddr_tainted);
185210037SARM gem5 Developers    doLongDescriptor();
185310037SARM gem5 Developers
185410037SARM gem5 Developers    stateQueues[curr_lookup_level].pop_front();
185510037SARM gem5 Developers
185610037SARM gem5 Developers    if (currState->fault != NoFault) {
185710037SARM gem5 Developers        // A fault was generated
185810037SARM gem5 Developers        currState->transState->finish(currState->fault, currState->req,
185910037SARM gem5 Developers                                      currState->tc, currState->mode);
186010037SARM gem5 Developers
186110037SARM gem5 Developers        pending = false;
186210037SARM gem5 Developers        nextWalk(currState->tc);
186310037SARM gem5 Developers
186410037SARM gem5 Developers        currState->req = NULL;
186510037SARM gem5 Developers        currState->tc = NULL;
186610037SARM gem5 Developers        currState->delayed = false;
186710037SARM gem5 Developers        delete currState;
186810037SARM gem5 Developers    } else if (!currState->delayed) {
186910037SARM gem5 Developers        // No additional lookups required
187010037SARM gem5 Developers        // Don't finish the translation if a stage 2 look up is underway
187110037SARM gem5 Developers        if (!currState->doingStage2) {
187210037SARM gem5 Developers            DPRINTF(TLBVerbose, "calling translateTiming again\n");
187310621SCurtis.Dunham@arm.com            statWalkServiceTime.sample(curTick() - currState->startTime);
187410037SARM gem5 Developers            currState->fault = tlb->translateTiming(currState->req, currState->tc,
187510037SARM gem5 Developers                                                    currState->transState,
187610037SARM gem5 Developers                                                    currState->mode);
187710621SCurtis.Dunham@arm.com            statWalksLongTerminatedAtLevel[(unsigned) curr_lookup_level]++;
187810037SARM gem5 Developers        }
187910037SARM gem5 Developers
188010037SARM gem5 Developers        pending = false;
188110037SARM gem5 Developers        nextWalk(currState->tc);
188210037SARM gem5 Developers
188310037SARM gem5 Developers        currState->req = NULL;
188410037SARM gem5 Developers        currState->tc = NULL;
188510037SARM gem5 Developers        currState->delayed = false;
188610037SARM gem5 Developers        delete currState;
188710037SARM gem5 Developers    } else {
188810037SARM gem5 Developers        if (curr_lookup_level >= MAX_LOOKUP_LEVELS - 1)
188910037SARM gem5 Developers            panic("Max. number of lookups already reached in table walk\n");
189010037SARM gem5 Developers        // Need to perform additional lookups
189110037SARM gem5 Developers        stateQueues[currState->longDesc.lookupLevel].push_back(currState);
189210037SARM gem5 Developers    }
189310037SARM gem5 Developers    currState = NULL;
189410037SARM gem5 Developers}
189510037SARM gem5 Developers
189610037SARM gem5 Developers
189710037SARM gem5 Developersvoid
18987728SAli.Saidi@ARM.comTableWalker::nextWalk(ThreadContext *tc)
18997728SAli.Saidi@ARM.com{
19007728SAli.Saidi@ARM.com    if (pendingQueue.size())
19019309Sandreas.hansson@arm.com        schedule(doProcessEvent, clockEdge(Cycles(1)));
190210509SAli.Saidi@ARM.com    else
190310509SAli.Saidi@ARM.com        completeDrain();
19047728SAli.Saidi@ARM.com}
19057728SAli.Saidi@ARM.com
190610037SARM gem5 Developersbool
190710037SARM gem5 DevelopersTableWalker::fetchDescriptor(Addr descAddr, uint8_t *data, int numBytes,
190810037SARM gem5 Developers    Request::Flags flags, int queueIndex, Event *event,
190910037SARM gem5 Developers    void (TableWalker::*doDescriptor)())
191010037SARM gem5 Developers{
191110037SARM gem5 Developers    bool isTiming = currState->timing;
19127728SAli.Saidi@ARM.com
191310037SARM gem5 Developers    // do the requests for the page table descriptors have to go through the
191410037SARM gem5 Developers    // second stage MMU
191510037SARM gem5 Developers    if (currState->stage2Req) {
191610037SARM gem5 Developers        Fault fault;
191710037SARM gem5 Developers        flags = flags | TLB::MustBeOne;
191810037SARM gem5 Developers
191910037SARM gem5 Developers        if (isTiming) {
192010037SARM gem5 Developers            Stage2MMU::Stage2Translation *tran = new
192110037SARM gem5 Developers                Stage2MMU::Stage2Translation(*stage2Mmu, data, event,
192210037SARM gem5 Developers                                             currState->vaddr);
192310037SARM gem5 Developers            currState->stage2Tran = tran;
192410037SARM gem5 Developers            stage2Mmu->readDataTimed(currState->tc, descAddr, tran, numBytes,
192510717Sandreas.hansson@arm.com                                     flags);
192610037SARM gem5 Developers            fault = tran->fault;
192710037SARM gem5 Developers        } else {
192810037SARM gem5 Developers            fault = stage2Mmu->readDataUntimed(currState->tc,
192910717Sandreas.hansson@arm.com                currState->vaddr, descAddr, data, numBytes, flags,
193010037SARM gem5 Developers                currState->functional);
193110037SARM gem5 Developers        }
193210037SARM gem5 Developers
193310037SARM gem5 Developers        if (fault != NoFault) {
193410037SARM gem5 Developers            currState->fault = fault;
193510037SARM gem5 Developers        }
193610037SARM gem5 Developers        if (isTiming) {
193710037SARM gem5 Developers            if (queueIndex >= 0) {
193810037SARM gem5 Developers                DPRINTF(TLBVerbose, "Adding to walker fifo: queue size before adding: %d\n",
193910037SARM gem5 Developers                        stateQueues[queueIndex].size());
194010037SARM gem5 Developers                stateQueues[queueIndex].push_back(currState);
194110037SARM gem5 Developers                currState = NULL;
194210037SARM gem5 Developers            }
194310037SARM gem5 Developers        } else {
194410037SARM gem5 Developers            (this->*doDescriptor)();
194510037SARM gem5 Developers        }
194610037SARM gem5 Developers    } else {
194710037SARM gem5 Developers        if (isTiming) {
194810717Sandreas.hansson@arm.com            port->dmaAction(MemCmd::ReadReq, descAddr, numBytes, event, data,
194910621SCurtis.Dunham@arm.com                           currState->tc->getCpuPtr()->clockPeriod(),flags);
195010037SARM gem5 Developers            if (queueIndex >= 0) {
195110037SARM gem5 Developers                DPRINTF(TLBVerbose, "Adding to walker fifo: queue size before adding: %d\n",
195210037SARM gem5 Developers                        stateQueues[queueIndex].size());
195310037SARM gem5 Developers                stateQueues[queueIndex].push_back(currState);
195410037SARM gem5 Developers                currState = NULL;
195510037SARM gem5 Developers            }
195610037SARM gem5 Developers        } else if (!currState->functional) {
195710717Sandreas.hansson@arm.com            port->dmaAction(MemCmd::ReadReq, descAddr, numBytes, NULL, data,
195810037SARM gem5 Developers                           currState->tc->getCpuPtr()->clockPeriod(), flags);
195910037SARM gem5 Developers            (this->*doDescriptor)();
196010037SARM gem5 Developers        } else {
196110037SARM gem5 Developers            RequestPtr req = new Request(descAddr, numBytes, flags, masterId);
196210037SARM gem5 Developers            req->taskId(ContextSwitchTaskId::DMA);
196310037SARM gem5 Developers            PacketPtr  pkt = new Packet(req, MemCmd::ReadReq);
196410037SARM gem5 Developers            pkt->dataStatic(data);
196510717Sandreas.hansson@arm.com            port->sendFunctional(pkt);
196610037SARM gem5 Developers            (this->*doDescriptor)();
196710037SARM gem5 Developers            delete req;
196810037SARM gem5 Developers            delete pkt;
196910037SARM gem5 Developers        }
197010037SARM gem5 Developers    }
197110037SARM gem5 Developers    return (isTiming);
197210037SARM gem5 Developers}
197310037SARM gem5 Developers
197410037SARM gem5 Developersvoid
197510037SARM gem5 DevelopersTableWalker::insertTableEntry(DescriptorBase &descriptor, bool longDescriptor)
197610037SARM gem5 Developers{
197710037SARM gem5 Developers    TlbEntry te;
197810037SARM gem5 Developers
197910037SARM gem5 Developers    // Create and fill a new page table entry
198010037SARM gem5 Developers    te.valid          = true;
198110037SARM gem5 Developers    te.longDescFormat = longDescriptor;
198210037SARM gem5 Developers    te.isHyp          = currState->isHyp;
198310037SARM gem5 Developers    te.asid           = currState->asid;
198410037SARM gem5 Developers    te.vmid           = currState->vmid;
198510037SARM gem5 Developers    te.N              = descriptor.offsetBits();
198610037SARM gem5 Developers    te.vpn            = currState->vaddr >> te.N;
198710037SARM gem5 Developers    te.size           = (1<<te.N) - 1;
198810037SARM gem5 Developers    te.pfn            = descriptor.pfn();
198910037SARM gem5 Developers    te.domain         = descriptor.domain();
199010037SARM gem5 Developers    te.lookupLevel    = descriptor.lookupLevel;
199110037SARM gem5 Developers    te.ns             = !descriptor.secure(haveSecurity, currState) || isStage2;
199210037SARM gem5 Developers    te.nstid          = !currState->isSecure;
199310037SARM gem5 Developers    te.xn             = descriptor.xn();
199410037SARM gem5 Developers    if (currState->aarch64)
199510037SARM gem5 Developers        te.el         = currState->el;
199610037SARM gem5 Developers    else
199710037SARM gem5 Developers        te.el         = 1;
199810037SARM gem5 Developers
199910621SCurtis.Dunham@arm.com    statPageSizes[pageSizeNtoStatBin(te.N)]++;
200010621SCurtis.Dunham@arm.com    statRequestOrigin[COMPLETED][currState->isFetch]++;
200110621SCurtis.Dunham@arm.com
200210037SARM gem5 Developers    // ASID has no meaning for stage 2 TLB entries, so mark all stage 2 entries
200310037SARM gem5 Developers    // as global
200410037SARM gem5 Developers    te.global         = descriptor.global(currState) || isStage2;
200510037SARM gem5 Developers    if (longDescriptor) {
200610037SARM gem5 Developers        LongDescriptor lDescriptor =
200710037SARM gem5 Developers            dynamic_cast<LongDescriptor &>(descriptor);
200810037SARM gem5 Developers
200910037SARM gem5 Developers        te.xn |= currState->xnTable;
201010037SARM gem5 Developers        te.pxn = currState->pxnTable || lDescriptor.pxn();
201110037SARM gem5 Developers        if (isStage2) {
201210037SARM gem5 Developers            // this is actually the HAP field, but its stored in the same bit
201310037SARM gem5 Developers            // possitions as the AP field in a stage 1 translation.
201410037SARM gem5 Developers            te.hap = lDescriptor.ap();
201510037SARM gem5 Developers        } else {
201610037SARM gem5 Developers           te.ap = ((!currState->rwTable || descriptor.ap() >> 1) << 1) |
201710037SARM gem5 Developers               (currState->userTable && (descriptor.ap() & 0x1));
201810037SARM gem5 Developers        }
201910037SARM gem5 Developers        if (currState->aarch64)
202010037SARM gem5 Developers            memAttrsAArch64(currState->tc, te, currState->longDesc.attrIndx(),
202110037SARM gem5 Developers                            currState->longDesc.sh());
202210037SARM gem5 Developers        else
202310037SARM gem5 Developers            memAttrsLPAE(currState->tc, te, lDescriptor);
202410037SARM gem5 Developers    } else {
202510037SARM gem5 Developers        te.ap = descriptor.ap();
202610037SARM gem5 Developers        memAttrs(currState->tc, te, currState->sctlr, descriptor.texcb(),
202710037SARM gem5 Developers                 descriptor.shareable());
202810037SARM gem5 Developers    }
202910037SARM gem5 Developers
203010037SARM gem5 Developers    // Debug output
203110037SARM gem5 Developers    DPRINTF(TLB, descriptor.dbgHeader().c_str());
203210037SARM gem5 Developers    DPRINTF(TLB, " - N:%d pfn:%#x size:%#x global:%d valid:%d\n",
203310037SARM gem5 Developers            te.N, te.pfn, te.size, te.global, te.valid);
203410037SARM gem5 Developers    DPRINTF(TLB, " - vpn:%#x xn:%d pxn:%d ap:%d domain:%d asid:%d "
203510037SARM gem5 Developers            "vmid:%d hyp:%d nc:%d ns:%d\n", te.vpn, te.xn, te.pxn,
203610037SARM gem5 Developers            te.ap, static_cast<uint8_t>(te.domain), te.asid, te.vmid, te.isHyp,
203710037SARM gem5 Developers            te.nonCacheable, te.ns);
203810037SARM gem5 Developers    DPRINTF(TLB, " - domain from L%d desc:%d data:%#x\n",
203910037SARM gem5 Developers            descriptor.lookupLevel, static_cast<uint8_t>(descriptor.domain()),
204010037SARM gem5 Developers            descriptor.getRawData());
204110037SARM gem5 Developers
204210037SARM gem5 Developers    // Insert the entry into the TLB
204310037SARM gem5 Developers    tlb->insert(currState->vaddr, te);
204410037SARM gem5 Developers    if (!currState->timing) {
204510037SARM gem5 Developers        currState->tc  = NULL;
204610037SARM gem5 Developers        currState->req = NULL;
204710037SARM gem5 Developers    }
204810037SARM gem5 Developers}
20497728SAli.Saidi@ARM.com
20507404SAli.Saidi@ARM.comArmISA::TableWalker *
20517404SAli.Saidi@ARM.comArmTableWalkerParams::create()
20527404SAli.Saidi@ARM.com{
20537404SAli.Saidi@ARM.com    return new ArmISA::TableWalker(this);
20547404SAli.Saidi@ARM.com}
20557404SAli.Saidi@ARM.com
205610037SARM gem5 DevelopersLookupLevel
205710037SARM gem5 DevelopersTableWalker::toLookupLevel(uint8_t lookup_level_as_int)
205810037SARM gem5 Developers{
205910037SARM gem5 Developers    switch (lookup_level_as_int) {
206010037SARM gem5 Developers      case L1:
206110037SARM gem5 Developers        return L1;
206210037SARM gem5 Developers      case L2:
206310037SARM gem5 Developers        return L2;
206410037SARM gem5 Developers      case L3:
206510037SARM gem5 Developers        return L3;
206610037SARM gem5 Developers      default:
206710037SARM gem5 Developers        panic("Invalid lookup level conversion");
206810037SARM gem5 Developers    }
206910037SARM gem5 Developers}
207010621SCurtis.Dunham@arm.com
207110621SCurtis.Dunham@arm.com/* this method keeps track of the table walker queue's residency, so
207210621SCurtis.Dunham@arm.com * needs to be called whenever requests start and complete. */
207310621SCurtis.Dunham@arm.comvoid
207410621SCurtis.Dunham@arm.comTableWalker::pendingChange()
207510621SCurtis.Dunham@arm.com{
207610621SCurtis.Dunham@arm.com    unsigned n = pendingQueue.size();
207710621SCurtis.Dunham@arm.com    if ((currState != NULL) && (currState != pendingQueue.front())) {
207810621SCurtis.Dunham@arm.com        ++n;
207910621SCurtis.Dunham@arm.com    }
208010621SCurtis.Dunham@arm.com
208110621SCurtis.Dunham@arm.com    if (n != pendingReqs) {
208210621SCurtis.Dunham@arm.com        Tick now = curTick();
208310621SCurtis.Dunham@arm.com        statPendingWalks.sample(pendingReqs, now - pendingChangeTick);
208410621SCurtis.Dunham@arm.com        pendingReqs = n;
208510621SCurtis.Dunham@arm.com        pendingChangeTick = now;
208610621SCurtis.Dunham@arm.com    }
208710621SCurtis.Dunham@arm.com}
208810621SCurtis.Dunham@arm.com
208911395Sandreas.sandberg@arm.comFault
209011395Sandreas.sandberg@arm.comTableWalker::testWalk(Addr pa, Addr size, TlbEntry::DomainType domain,
209111395Sandreas.sandberg@arm.com                      LookupLevel lookup_level)
209211395Sandreas.sandberg@arm.com{
209311395Sandreas.sandberg@arm.com    return tlb->testWalk(pa, size, currState->vaddr, currState->isSecure,
209411395Sandreas.sandberg@arm.com                         currState->mode, domain, lookup_level);
209511395Sandreas.sandberg@arm.com}
209611395Sandreas.sandberg@arm.com
209711395Sandreas.sandberg@arm.com
209810621SCurtis.Dunham@arm.comuint8_t
209910621SCurtis.Dunham@arm.comTableWalker::pageSizeNtoStatBin(uint8_t N)
210010621SCurtis.Dunham@arm.com{
210110621SCurtis.Dunham@arm.com    /* for statPageSizes */
210210621SCurtis.Dunham@arm.com    switch(N) {
210310621SCurtis.Dunham@arm.com        case 12: return 0; // 4K
210410621SCurtis.Dunham@arm.com        case 14: return 1; // 16K (using 16K granule in v8-64)
210510621SCurtis.Dunham@arm.com        case 16: return 2; // 64K
210610621SCurtis.Dunham@arm.com        case 20: return 3; // 1M
210710621SCurtis.Dunham@arm.com        case 21: return 4; // 2M-LPAE
210810621SCurtis.Dunham@arm.com        case 24: return 5; // 16M
210910621SCurtis.Dunham@arm.com        case 25: return 6; // 32M (using 16K granule in v8-64)
211010621SCurtis.Dunham@arm.com        case 29: return 7; // 512M (using 64K granule in v8-64)
211110621SCurtis.Dunham@arm.com        case 30: return 8; // 1G-LPAE
211210621SCurtis.Dunham@arm.com        default:
211310621SCurtis.Dunham@arm.com            panic("unknown page size");
211410621SCurtis.Dunham@arm.com            return 255;
211510621SCurtis.Dunham@arm.com    }
211610621SCurtis.Dunham@arm.com}
211710621SCurtis.Dunham@arm.com
211810621SCurtis.Dunham@arm.comvoid
211910621SCurtis.Dunham@arm.comTableWalker::regStats()
212010621SCurtis.Dunham@arm.com{
212110621SCurtis.Dunham@arm.com    statWalks
212210621SCurtis.Dunham@arm.com        .name(name() + ".walks")
212310621SCurtis.Dunham@arm.com        .desc("Table walker walks requested")
212410621SCurtis.Dunham@arm.com        ;
212510621SCurtis.Dunham@arm.com
212610621SCurtis.Dunham@arm.com    statWalksShortDescriptor
212710621SCurtis.Dunham@arm.com        .name(name() + ".walksShort")
212810621SCurtis.Dunham@arm.com        .desc("Table walker walks initiated with short descriptors")
212910621SCurtis.Dunham@arm.com        .flags(Stats::nozero)
213010621SCurtis.Dunham@arm.com        ;
213110621SCurtis.Dunham@arm.com
213210621SCurtis.Dunham@arm.com    statWalksLongDescriptor
213310621SCurtis.Dunham@arm.com        .name(name() + ".walksLong")
213410621SCurtis.Dunham@arm.com        .desc("Table walker walks initiated with long descriptors")
213510621SCurtis.Dunham@arm.com        .flags(Stats::nozero)
213610621SCurtis.Dunham@arm.com        ;
213710621SCurtis.Dunham@arm.com
213810621SCurtis.Dunham@arm.com    statWalksShortTerminatedAtLevel
213910621SCurtis.Dunham@arm.com        .init(2)
214010621SCurtis.Dunham@arm.com        .name(name() + ".walksShortTerminationLevel")
214110621SCurtis.Dunham@arm.com        .desc("Level at which table walker walks "
214210621SCurtis.Dunham@arm.com              "with short descriptors terminate")
214310621SCurtis.Dunham@arm.com        .flags(Stats::nozero)
214410621SCurtis.Dunham@arm.com        ;
214510621SCurtis.Dunham@arm.com    statWalksShortTerminatedAtLevel.subname(0, "Level1");
214610621SCurtis.Dunham@arm.com    statWalksShortTerminatedAtLevel.subname(1, "Level2");
214710621SCurtis.Dunham@arm.com
214810621SCurtis.Dunham@arm.com    statWalksLongTerminatedAtLevel
214910621SCurtis.Dunham@arm.com        .init(4)
215010621SCurtis.Dunham@arm.com        .name(name() + ".walksLongTerminationLevel")
215110621SCurtis.Dunham@arm.com        .desc("Level at which table walker walks "
215210621SCurtis.Dunham@arm.com              "with long descriptors terminate")
215310621SCurtis.Dunham@arm.com        .flags(Stats::nozero)
215410621SCurtis.Dunham@arm.com        ;
215510621SCurtis.Dunham@arm.com    statWalksLongTerminatedAtLevel.subname(0, "Level0");
215610621SCurtis.Dunham@arm.com    statWalksLongTerminatedAtLevel.subname(1, "Level1");
215710621SCurtis.Dunham@arm.com    statWalksLongTerminatedAtLevel.subname(2, "Level2");
215810621SCurtis.Dunham@arm.com    statWalksLongTerminatedAtLevel.subname(3, "Level3");
215910621SCurtis.Dunham@arm.com
216010621SCurtis.Dunham@arm.com    statSquashedBefore
216110621SCurtis.Dunham@arm.com        .name(name() + ".walksSquashedBefore")
216210621SCurtis.Dunham@arm.com        .desc("Table walks squashed before starting")
216310621SCurtis.Dunham@arm.com        .flags(Stats::nozero)
216410621SCurtis.Dunham@arm.com        ;
216510621SCurtis.Dunham@arm.com
216610621SCurtis.Dunham@arm.com    statSquashedAfter
216710621SCurtis.Dunham@arm.com        .name(name() + ".walksSquashedAfter")
216810621SCurtis.Dunham@arm.com        .desc("Table walks squashed after completion")
216910621SCurtis.Dunham@arm.com        .flags(Stats::nozero)
217010621SCurtis.Dunham@arm.com        ;
217110621SCurtis.Dunham@arm.com
217210621SCurtis.Dunham@arm.com    statWalkWaitTime
217310621SCurtis.Dunham@arm.com        .init(16)
217410621SCurtis.Dunham@arm.com        .name(name() + ".walkWaitTime")
217510621SCurtis.Dunham@arm.com        .desc("Table walker wait (enqueue to first request) latency")
217610621SCurtis.Dunham@arm.com        .flags(Stats::pdf | Stats::nozero | Stats::nonan)
217710621SCurtis.Dunham@arm.com        ;
217810621SCurtis.Dunham@arm.com
217910621SCurtis.Dunham@arm.com    statWalkServiceTime
218010621SCurtis.Dunham@arm.com        .init(16)
218110621SCurtis.Dunham@arm.com        .name(name() + ".walkCompletionTime")
218210621SCurtis.Dunham@arm.com        .desc("Table walker service (enqueue to completion) latency")
218310621SCurtis.Dunham@arm.com        .flags(Stats::pdf | Stats::nozero | Stats::nonan)
218410621SCurtis.Dunham@arm.com        ;
218510621SCurtis.Dunham@arm.com
218610621SCurtis.Dunham@arm.com    statPendingWalks
218710621SCurtis.Dunham@arm.com        .init(16)
218810621SCurtis.Dunham@arm.com        .name(name() + ".walksPending")
218910621SCurtis.Dunham@arm.com        .desc("Table walker pending requests distribution")
219010621SCurtis.Dunham@arm.com        .flags(Stats::pdf | Stats::dist | Stats::nozero | Stats::nonan)
219110621SCurtis.Dunham@arm.com        ;
219210621SCurtis.Dunham@arm.com
219310621SCurtis.Dunham@arm.com    statPageSizes // see DDI 0487A D4-1661
219410621SCurtis.Dunham@arm.com        .init(9)
219510621SCurtis.Dunham@arm.com        .name(name() + ".walkPageSizes")
219610621SCurtis.Dunham@arm.com        .desc("Table walker page sizes translated")
219710621SCurtis.Dunham@arm.com        .flags(Stats::total | Stats::pdf | Stats::dist | Stats::nozero)
219810621SCurtis.Dunham@arm.com        ;
219910621SCurtis.Dunham@arm.com    statPageSizes.subname(0, "4K");
220010621SCurtis.Dunham@arm.com    statPageSizes.subname(1, "16K");
220110621SCurtis.Dunham@arm.com    statPageSizes.subname(2, "64K");
220210621SCurtis.Dunham@arm.com    statPageSizes.subname(3, "1M");
220310621SCurtis.Dunham@arm.com    statPageSizes.subname(4, "2M");
220410621SCurtis.Dunham@arm.com    statPageSizes.subname(5, "16M");
220510621SCurtis.Dunham@arm.com    statPageSizes.subname(6, "32M");
220610621SCurtis.Dunham@arm.com    statPageSizes.subname(7, "512M");
220710621SCurtis.Dunham@arm.com    statPageSizes.subname(8, "1G");
220810621SCurtis.Dunham@arm.com
220910621SCurtis.Dunham@arm.com    statRequestOrigin
221010621SCurtis.Dunham@arm.com        .init(2,2) // Instruction/Data, requests/completed
221110621SCurtis.Dunham@arm.com        .name(name() + ".walkRequestOrigin")
221210621SCurtis.Dunham@arm.com        .desc("Table walker requests started/completed, data/inst")
221310621SCurtis.Dunham@arm.com        .flags(Stats::total)
221410621SCurtis.Dunham@arm.com        ;
221510621SCurtis.Dunham@arm.com    statRequestOrigin.subname(0,"Requested");
221610621SCurtis.Dunham@arm.com    statRequestOrigin.subname(1,"Completed");
221710621SCurtis.Dunham@arm.com    statRequestOrigin.ysubname(0,"Data");
221810621SCurtis.Dunham@arm.com    statRequestOrigin.ysubname(1,"Inst");
221910621SCurtis.Dunham@arm.com}
2220