17404SAli.Saidi@ARM.com/*
214095Sgiacomo.travaglini@arm.com * Copyright (c) 2010, 2012-2019 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)
6013892Sgabeblack@google.com    : ClockedObject(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()),
6712086Sspwilson2@wisc.edu      doL1DescEvent([this]{ doL1DescriptorWrapper(); }, name()),
6812086Sspwilson2@wisc.edu      doL2DescEvent([this]{ doL2DescriptorWrapper(); }, name()),
6912086Sspwilson2@wisc.edu      doL0LongDescEvent([this]{ doL0LongDescriptorWrapper(); }, name()),
7012086Sspwilson2@wisc.edu      doL1LongDescEvent([this]{ doL1LongDescriptorWrapper(); }, name()),
7112086Sspwilson2@wisc.edu      doL2LongDescEvent([this]{ doL2LongDescriptorWrapper(); }, name()),
7212086Sspwilson2@wisc.edu      doL3LongDescEvent([this]{ doL3LongDescriptorWrapper(); }, name()),
7311588SCurtis.Dunham@arm.com      LongDescEventByLevel { &doL0LongDescEvent, &doL1LongDescEvent,
7411588SCurtis.Dunham@arm.com                             &doL2LongDescEvent, &doL3LongDescEvent },
7512086Sspwilson2@wisc.edu      doProcessEvent([this]{ processWalkWrapper(); }, name())
767439Sdam.sunwoo@arm.com{
777576SAli.Saidi@ARM.com    sctlr = 0;
7810037SARM gem5 Developers
7910037SARM gem5 Developers    // Cache system-level properties
8010037SARM gem5 Developers    if (FullSystem) {
8110717Sandreas.hansson@arm.com        ArmSystem *armSys = dynamic_cast<ArmSystem *>(p->sys);
8210037SARM gem5 Developers        assert(armSys);
8310037SARM gem5 Developers        haveSecurity = armSys->haveSecurity();
8410037SARM gem5 Developers        _haveLPAE = armSys->haveLPAE();
8510037SARM gem5 Developers        _haveVirtualization = armSys->haveVirtualization();
8610037SARM gem5 Developers        physAddrRange = armSys->physAddrRange();
8710037SARM gem5 Developers        _haveLargeAsid64 = armSys->haveLargeAsid64();
8810037SARM gem5 Developers    } else {
8910037SARM gem5 Developers        haveSecurity = _haveLPAE = _haveVirtualization = false;
9010037SARM gem5 Developers        _haveLargeAsid64 = false;
9110037SARM gem5 Developers        physAddrRange = 32;
9210037SARM gem5 Developers    }
9310037SARM gem5 Developers
947439Sdam.sunwoo@arm.com}
957404SAli.Saidi@ARM.com
967404SAli.Saidi@ARM.comTableWalker::~TableWalker()
977404SAli.Saidi@ARM.com{
987404SAli.Saidi@ARM.com    ;
997404SAli.Saidi@ARM.com}
1007404SAli.Saidi@ARM.com
10110717Sandreas.hansson@arm.comvoid
10210717Sandreas.hansson@arm.comTableWalker::setMMU(Stage2MMU *m, MasterID master_id)
10310717Sandreas.hansson@arm.com{
10410717Sandreas.hansson@arm.com    stage2Mmu = m;
10513795SAndrea.Mondelli@ucf.edu    port = &m->getDMAPort();
10610717Sandreas.hansson@arm.com    masterId = master_id;
10710717Sandreas.hansson@arm.com}
10810717Sandreas.hansson@arm.com
10910717Sandreas.hansson@arm.comvoid
11010717Sandreas.hansson@arm.comTableWalker::init()
11110717Sandreas.hansson@arm.com{
11210717Sandreas.hansson@arm.com    fatal_if(!stage2Mmu, "Table walker must have a valid stage-2 MMU\n");
11310717Sandreas.hansson@arm.com    fatal_if(!port, "Table walker must have a valid port\n");
11410717Sandreas.hansson@arm.com    fatal_if(!tlb, "Table walker must have a valid TLB\n");
11510717Sandreas.hansson@arm.com}
11610717Sandreas.hansson@arm.com
11713784Sgabeblack@google.comPort &
11813784Sgabeblack@google.comTableWalker::getPort(const std::string &if_name, PortID idx)
11910717Sandreas.hansson@arm.com{
12010717Sandreas.hansson@arm.com    if (if_name == "port") {
12110717Sandreas.hansson@arm.com        if (!isStage2) {
12210717Sandreas.hansson@arm.com            return *port;
12310717Sandreas.hansson@arm.com        } else {
12410717Sandreas.hansson@arm.com            fatal("Cannot access table walker port through stage-two walker\n");
12510717Sandreas.hansson@arm.com        }
12610717Sandreas.hansson@arm.com    }
12713892Sgabeblack@google.com    return ClockedObject::getPort(if_name, idx);
12810717Sandreas.hansson@arm.com}
12910717Sandreas.hansson@arm.com
13010537Sandreas.hansson@arm.comTableWalker::WalkerState::WalkerState() :
13110537Sandreas.hansson@arm.com    tc(nullptr), aarch64(false), el(EL0), physAddrRange(0), req(nullptr),
13210537Sandreas.hansson@arm.com    asid(0), vmid(0), isHyp(false), transState(nullptr),
13314040Sgiacomo.travaglini@arm.com    vaddr(0), vaddr_tainted(0),
13414040Sgiacomo.travaglini@arm.com    sctlr(0), scr(0), cpsr(0), tcr(0),
13514040Sgiacomo.travaglini@arm.com    htcr(0), hcr(0), vtcr(0),
13614040Sgiacomo.travaglini@arm.com    isWrite(false), isFetch(false), isSecure(false),
13710537Sandreas.hansson@arm.com    secureLookup(false), rwTable(false), userTable(false), xnTable(false),
13814095Sgiacomo.travaglini@arm.com    pxnTable(false), hpd(false), stage2Req(false),
13910537Sandreas.hansson@arm.com    stage2Tran(nullptr), timing(false), functional(false),
14010537Sandreas.hansson@arm.com    mode(BaseTLB::Read), tranType(TLB::NormalTran), l2Desc(l1Desc),
14110537Sandreas.hansson@arm.com    delayed(false), tableWalker(nullptr)
14210037SARM gem5 Developers{
14310037SARM gem5 Developers}
14410037SARM gem5 Developers
1459152Satgutier@umich.eduvoid
1469152Satgutier@umich.eduTableWalker::completeDrain()
1479152Satgutier@umich.edu{
14810913Sandreas.sandberg@arm.com    if (drainState() == DrainState::Draining &&
14911588SCurtis.Dunham@arm.com        stateQueues[L0].empty() && stateQueues[L1].empty() &&
15011588SCurtis.Dunham@arm.com        stateQueues[L2].empty() && stateQueues[L3].empty() &&
1519152Satgutier@umich.edu        pendingQueue.empty()) {
15210913Sandreas.sandberg@arm.com
1539152Satgutier@umich.edu        DPRINTF(Drain, "TableWalker done draining, processing drain event\n");
15410913Sandreas.sandberg@arm.com        signalDrainDone();
1559152Satgutier@umich.edu    }
1569152Satgutier@umich.edu}
1579152Satgutier@umich.edu
15810913Sandreas.sandberg@arm.comDrainState
15910913Sandreas.sandberg@arm.comTableWalker::drain()
1607404SAli.Saidi@ARM.com{
16110037SARM gem5 Developers    bool state_queues_not_empty = false;
1629152Satgutier@umich.edu
16310037SARM gem5 Developers    for (int i = 0; i < MAX_LOOKUP_LEVELS; ++i) {
16410037SARM gem5 Developers        if (!stateQueues[i].empty()) {
16510037SARM gem5 Developers            state_queues_not_empty = true;
16610037SARM gem5 Developers            break;
16710037SARM gem5 Developers        }
16810037SARM gem5 Developers    }
16910037SARM gem5 Developers
17010037SARM gem5 Developers    if (state_queues_not_empty || pendingQueue.size()) {
1719152Satgutier@umich.edu        DPRINTF(Drain, "TableWalker not drained\n");
17210913Sandreas.sandberg@arm.com        return DrainState::Draining;
17310037SARM gem5 Developers    } else {
17410037SARM gem5 Developers        DPRINTF(Drain, "TableWalker free, no need to drain\n");
17510913Sandreas.sandberg@arm.com        return DrainState::Drained;
1767733SAli.Saidi@ARM.com    }
1777404SAli.Saidi@ARM.com}
1787404SAli.Saidi@ARM.com
1797748SAli.Saidi@ARM.comvoid
1809342SAndreas.Sandberg@arm.comTableWalker::drainResume()
1817748SAli.Saidi@ARM.com{
1829524SAndreas.Sandberg@ARM.com    if (params()->sys->isTimingMode() && currState) {
1839152Satgutier@umich.edu        delete currState;
1849152Satgutier@umich.edu        currState = NULL;
18510621SCurtis.Dunham@arm.com        pendingChange();
1867748SAli.Saidi@ARM.com    }
1877748SAli.Saidi@ARM.com}
1887748SAli.Saidi@ARM.com
1897404SAli.Saidi@ARM.comFault
19012749Sgiacomo.travaglini@arm.comTableWalker::walk(const RequestPtr &_req, ThreadContext *_tc, uint16_t _asid,
19110037SARM gem5 Developers                  uint8_t _vmid, bool _isHyp, TLB::Mode _mode,
19210037SARM gem5 Developers                  TLB::Translation *_trans, bool _timing, bool _functional,
19311580SDylan.Johnson@ARM.com                  bool secure, TLB::ArmTranslationType tranType,
19411580SDylan.Johnson@ARM.com                  bool _stage2Req)
1957404SAli.Saidi@ARM.com{
1968733Sgeoffrey.blake@arm.com    assert(!(_functional && _timing));
19710621SCurtis.Dunham@arm.com    ++statWalks;
19810621SCurtis.Dunham@arm.com
19910109SGeoffrey.Blake@arm.com    WalkerState *savedCurrState = NULL;
20010037SARM gem5 Developers
20110109SGeoffrey.Blake@arm.com    if (!currState && !_functional) {
2027439Sdam.sunwoo@arm.com        // For atomic mode, a new WalkerState instance should be only created
2037439Sdam.sunwoo@arm.com        // once per TLB. For timing mode, a new instance is generated for every
2047439Sdam.sunwoo@arm.com        // TLB miss.
2057439Sdam.sunwoo@arm.com        DPRINTF(TLBVerbose, "creating new instance of WalkerState\n");
2067404SAli.Saidi@ARM.com
2077439Sdam.sunwoo@arm.com        currState = new WalkerState();
2087439Sdam.sunwoo@arm.com        currState->tableWalker = this;
20910109SGeoffrey.Blake@arm.com    } else if (_functional) {
21010109SGeoffrey.Blake@arm.com        // If we are mixing functional mode with timing (or even
21110109SGeoffrey.Blake@arm.com        // atomic), we need to to be careful and clean up after
21210109SGeoffrey.Blake@arm.com        // ourselves to not risk getting into an inconsistent state.
21310109SGeoffrey.Blake@arm.com        DPRINTF(TLBVerbose, "creating functional instance of WalkerState\n");
21410109SGeoffrey.Blake@arm.com        savedCurrState = currState;
21510109SGeoffrey.Blake@arm.com        currState = new WalkerState();
21610109SGeoffrey.Blake@arm.com        currState->tableWalker = this;
2178202SAli.Saidi@ARM.com    } else if (_timing) {
2188202SAli.Saidi@ARM.com        // This is a translation that was completed and then faulted again
2198202SAli.Saidi@ARM.com        // because some underlying parameters that affect the translation
2208202SAli.Saidi@ARM.com        // changed out from under us (e.g. asid). It will either be a
2218202SAli.Saidi@ARM.com        // misprediction, in which case nothing will happen or we'll use
2228202SAli.Saidi@ARM.com        // this fault to re-execute the faulting instruction which should clean
2238202SAli.Saidi@ARM.com        // up everything.
22410037SARM gem5 Developers        if (currState->vaddr_tainted == _req->getVaddr()) {
22510621SCurtis.Dunham@arm.com            ++statSquashedBefore;
22610474Sandreas.hansson@arm.com            return std::make_shared<ReExec>();
2278202SAli.Saidi@ARM.com        }
2287439Sdam.sunwoo@arm.com    }
22910621SCurtis.Dunham@arm.com    pendingChange();
2307439Sdam.sunwoo@arm.com
23110621SCurtis.Dunham@arm.com    currState->startTime = curTick();
2327439Sdam.sunwoo@arm.com    currState->tc = _tc;
23311517SCurtis.Dunham@arm.com    // ARM DDI 0487A.f (ARMv8 ARM) pg J8-5672
23411517SCurtis.Dunham@arm.com    // aarch32/translation/translation/AArch32.TranslateAddress dictates
23511517SCurtis.Dunham@arm.com    // even AArch32 EL0 will use AArch64 translation if EL1 is in AArch64.
23612735Sandreas.sandberg@arm.com    if (isStage2) {
23712735Sandreas.sandberg@arm.com        currState->el = EL1;
23812735Sandreas.sandberg@arm.com        currState->aarch64 = ELIs64(_tc, EL2);
23912735Sandreas.sandberg@arm.com    } else {
24012735Sandreas.sandberg@arm.com        currState->el =
24112735Sandreas.sandberg@arm.com            TLB::tranTypeEL(_tc->readMiscReg(MISCREG_CPSR), tranType);
24212735Sandreas.sandberg@arm.com        currState->aarch64 =
24312735Sandreas.sandberg@arm.com            ELIs64(_tc, currState->el == EL0 ? EL1 : currState->el);
24412735Sandreas.sandberg@arm.com    }
2457439Sdam.sunwoo@arm.com    currState->transState = _trans;
2467439Sdam.sunwoo@arm.com    currState->req = _req;
2477439Sdam.sunwoo@arm.com    currState->fault = NoFault;
24810037SARM gem5 Developers    currState->asid = _asid;
24910037SARM gem5 Developers    currState->vmid = _vmid;
25010037SARM gem5 Developers    currState->isHyp = _isHyp;
2517439Sdam.sunwoo@arm.com    currState->timing = _timing;
2528733Sgeoffrey.blake@arm.com    currState->functional = _functional;
2537439Sdam.sunwoo@arm.com    currState->mode = _mode;
25410037SARM gem5 Developers    currState->tranType = tranType;
25510037SARM gem5 Developers    currState->isSecure = secure;
25610037SARM gem5 Developers    currState->physAddrRange = physAddrRange;
2577404SAli.Saidi@ARM.com
2587436Sdam.sunwoo@arm.com    /** @todo These should be cached or grabbed from cached copies in
2597436Sdam.sunwoo@arm.com     the TLB, all these miscreg reads are expensive */
26010037SARM gem5 Developers    currState->vaddr_tainted = currState->req->getVaddr();
26110037SARM gem5 Developers    if (currState->aarch64)
26210037SARM gem5 Developers        currState->vaddr = purifyTaggedAddr(currState->vaddr_tainted,
26310037SARM gem5 Developers                                            currState->tc, currState->el);
26410037SARM gem5 Developers    else
26510037SARM gem5 Developers        currState->vaddr = currState->vaddr_tainted;
26610037SARM gem5 Developers
26710037SARM gem5 Developers    if (currState->aarch64) {
26811575SDylan.Johnson@ARM.com        if (isStage2) {
26911575SDylan.Johnson@ARM.com            currState->sctlr = currState->tc->readMiscReg(MISCREG_SCTLR_EL1);
27011575SDylan.Johnson@ARM.com            currState->vtcr = currState->tc->readMiscReg(MISCREG_VTCR_EL2);
27111575SDylan.Johnson@ARM.com        } else switch (currState->el) {
27210037SARM gem5 Developers          case EL0:
27310037SARM gem5 Developers          case EL1:
27410037SARM gem5 Developers            currState->sctlr = currState->tc->readMiscReg(MISCREG_SCTLR_EL1);
27510324SCurtis.Dunham@arm.com            currState->tcr = currState->tc->readMiscReg(MISCREG_TCR_EL1);
27610037SARM gem5 Developers            break;
27711574SCurtis.Dunham@arm.com          case EL2:
27811574SCurtis.Dunham@arm.com            assert(_haveVirtualization);
27911574SCurtis.Dunham@arm.com            currState->sctlr = currState->tc->readMiscReg(MISCREG_SCTLR_EL2);
28011574SCurtis.Dunham@arm.com            currState->tcr = currState->tc->readMiscReg(MISCREG_TCR_EL2);
28111574SCurtis.Dunham@arm.com            break;
28210037SARM gem5 Developers          case EL3:
28310037SARM gem5 Developers            assert(haveSecurity);
28410037SARM gem5 Developers            currState->sctlr = currState->tc->readMiscReg(MISCREG_SCTLR_EL3);
28510324SCurtis.Dunham@arm.com            currState->tcr = currState->tc->readMiscReg(MISCREG_TCR_EL3);
28610037SARM gem5 Developers            break;
28710037SARM gem5 Developers          default:
28810037SARM gem5 Developers            panic("Invalid exception level");
28910037SARM gem5 Developers            break;
29010037SARM gem5 Developers        }
29111575SDylan.Johnson@ARM.com        currState->hcr = currState->tc->readMiscReg(MISCREG_HCR_EL2);
29210037SARM gem5 Developers    } else {
29312499Sgiacomo.travaglini@arm.com        currState->sctlr = currState->tc->readMiscReg(snsBankedIndex(
29410037SARM gem5 Developers            MISCREG_SCTLR, currState->tc, !currState->isSecure));
29512499Sgiacomo.travaglini@arm.com        currState->ttbcr = currState->tc->readMiscReg(snsBankedIndex(
29610037SARM gem5 Developers            MISCREG_TTBCR, currState->tc, !currState->isSecure));
29710037SARM gem5 Developers        currState->htcr  = currState->tc->readMiscReg(MISCREG_HTCR);
29810037SARM gem5 Developers        currState->hcr   = currState->tc->readMiscReg(MISCREG_HCR);
29910037SARM gem5 Developers        currState->vtcr  = currState->tc->readMiscReg(MISCREG_VTCR);
30010037SARM gem5 Developers    }
3017439Sdam.sunwoo@arm.com    sctlr = currState->sctlr;
3027439Sdam.sunwoo@arm.com
3037439Sdam.sunwoo@arm.com    currState->isFetch = (currState->mode == TLB::Execute);
3047439Sdam.sunwoo@arm.com    currState->isWrite = (currState->mode == TLB::Write);
3057439Sdam.sunwoo@arm.com
30610621SCurtis.Dunham@arm.com    statRequestOrigin[REQUESTED][currState->isFetch]++;
30710621SCurtis.Dunham@arm.com
30811580SDylan.Johnson@ARM.com    currState->stage2Req = _stage2Req && !isStage2;
3097728SAli.Saidi@ARM.com
31011517SCurtis.Dunham@arm.com    bool long_desc_format = currState->aarch64 || _isHyp || isStage2 ||
31111517SCurtis.Dunham@arm.com                            longDescFormatInUse(currState->tc);
31210037SARM gem5 Developers
31310037SARM gem5 Developers    if (long_desc_format) {
31410037SARM gem5 Developers        // Helper variables used for hierarchical permissions
31510037SARM gem5 Developers        currState->secureLookup = currState->isSecure;
31610037SARM gem5 Developers        currState->rwTable = true;
31710037SARM gem5 Developers        currState->userTable = true;
31810037SARM gem5 Developers        currState->xnTable = false;
31910037SARM gem5 Developers        currState->pxnTable = false;
32010621SCurtis.Dunham@arm.com
32110621SCurtis.Dunham@arm.com        ++statWalksLongDescriptor;
32210621SCurtis.Dunham@arm.com    } else {
32310621SCurtis.Dunham@arm.com        ++statWalksShortDescriptor;
32410037SARM gem5 Developers    }
32510037SARM gem5 Developers
32610037SARM gem5 Developers    if (!currState->timing) {
32710109SGeoffrey.Blake@arm.com        Fault fault = NoFault;
32810037SARM gem5 Developers        if (currState->aarch64)
32910109SGeoffrey.Blake@arm.com            fault = processWalkAArch64();
33010037SARM gem5 Developers        else if (long_desc_format)
33110109SGeoffrey.Blake@arm.com            fault = processWalkLPAE();
33210037SARM gem5 Developers        else
33310109SGeoffrey.Blake@arm.com            fault = processWalk();
33410109SGeoffrey.Blake@arm.com
33510109SGeoffrey.Blake@arm.com        // If this was a functional non-timing access restore state to
33610109SGeoffrey.Blake@arm.com        // how we found it.
33710109SGeoffrey.Blake@arm.com        if (currState->functional) {
33810109SGeoffrey.Blake@arm.com            delete currState;
33910109SGeoffrey.Blake@arm.com            currState = savedCurrState;
34010109SGeoffrey.Blake@arm.com        }
34110109SGeoffrey.Blake@arm.com        return fault;
34210037SARM gem5 Developers    }
3437728SAli.Saidi@ARM.com
3448067SAli.Saidi@ARM.com    if (pending || pendingQueue.size()) {
3457728SAli.Saidi@ARM.com        pendingQueue.push_back(currState);
3467728SAli.Saidi@ARM.com        currState = NULL;
34710621SCurtis.Dunham@arm.com        pendingChange();
3487728SAli.Saidi@ARM.com    } else {
3497728SAli.Saidi@ARM.com        pending = true;
35010621SCurtis.Dunham@arm.com        pendingChange();
35110037SARM gem5 Developers        if (currState->aarch64)
35210037SARM gem5 Developers            return processWalkAArch64();
35310037SARM gem5 Developers        else if (long_desc_format)
35410037SARM gem5 Developers            return processWalkLPAE();
35510037SARM gem5 Developers        else
35610037SARM gem5 Developers            return processWalk();
3577728SAli.Saidi@ARM.com    }
3587728SAli.Saidi@ARM.com
3597728SAli.Saidi@ARM.com    return NoFault;
3607728SAli.Saidi@ARM.com}
3617728SAli.Saidi@ARM.com
3627728SAli.Saidi@ARM.comvoid
3637728SAli.Saidi@ARM.comTableWalker::processWalkWrapper()
3647728SAli.Saidi@ARM.com{
3657728SAli.Saidi@ARM.com    assert(!currState);
3667728SAli.Saidi@ARM.com    assert(pendingQueue.size());
36710621SCurtis.Dunham@arm.com    pendingChange();
3687728SAli.Saidi@ARM.com    currState = pendingQueue.front();
3699258SAli.Saidi@ARM.com
3709535Smrinmoy.ghosh@arm.com    // Check if a previous walk filled this request already
37110037SARM gem5 Developers    // @TODO Should this always be the TLB or should we look in the stage2 TLB?
37210037SARM gem5 Developers    TlbEntry* te = tlb->lookup(currState->vaddr, currState->asid,
37310037SARM gem5 Developers            currState->vmid, currState->isHyp, currState->isSecure, true, false,
37412735Sandreas.sandberg@arm.com            currState->el);
3759258SAli.Saidi@ARM.com
3769535Smrinmoy.ghosh@arm.com    // Check if we still need to have a walk for this request. If the requesting
3779535Smrinmoy.ghosh@arm.com    // instruction has been squashed, or a previous walk has filled the TLB with
3789535Smrinmoy.ghosh@arm.com    // a match, we just want to get rid of the walk. The latter could happen
3799535Smrinmoy.ghosh@arm.com    // when there are multiple outstanding misses to a single page and a
3809535Smrinmoy.ghosh@arm.com    // previous request has been successfully translated.
3819535Smrinmoy.ghosh@arm.com    if (!currState->transState->squashed() && !te) {
3829258SAli.Saidi@ARM.com        // We've got a valid request, lets process it
3839258SAli.Saidi@ARM.com        pending = true;
3849258SAli.Saidi@ARM.com        pendingQueue.pop_front();
38510579SAndrew.Bardsley@arm.com        // Keep currState in case one of the processWalk... calls NULLs it
38610579SAndrew.Bardsley@arm.com        WalkerState *curr_state_copy = currState;
38710579SAndrew.Bardsley@arm.com        Fault f;
38810037SARM gem5 Developers        if (currState->aarch64)
38910579SAndrew.Bardsley@arm.com            f = processWalkAArch64();
39011517SCurtis.Dunham@arm.com        else if (longDescFormatInUse(currState->tc) ||
39111517SCurtis.Dunham@arm.com                 currState->isHyp || isStage2)
39210579SAndrew.Bardsley@arm.com            f = processWalkLPAE();
39310037SARM gem5 Developers        else
39410579SAndrew.Bardsley@arm.com            f = processWalk();
39510579SAndrew.Bardsley@arm.com
39610579SAndrew.Bardsley@arm.com        if (f != NoFault) {
39710579SAndrew.Bardsley@arm.com            curr_state_copy->transState->finish(f, curr_state_copy->req,
39810579SAndrew.Bardsley@arm.com                    curr_state_copy->tc, curr_state_copy->mode);
39910579SAndrew.Bardsley@arm.com
40010579SAndrew.Bardsley@arm.com            delete curr_state_copy;
40110579SAndrew.Bardsley@arm.com        }
4029258SAli.Saidi@ARM.com        return;
4039258SAli.Saidi@ARM.com    }
4049258SAli.Saidi@ARM.com
4059258SAli.Saidi@ARM.com
4069258SAli.Saidi@ARM.com    // If the instruction that we were translating for has been
4079258SAli.Saidi@ARM.com    // squashed we shouldn't bother.
4089258SAli.Saidi@ARM.com    unsigned num_squashed = 0;
4099258SAli.Saidi@ARM.com    ThreadContext *tc = currState->tc;
4109258SAli.Saidi@ARM.com    while ((num_squashed < numSquashable) && currState &&
4119535Smrinmoy.ghosh@arm.com           (currState->transState->squashed() || te)) {
4129258SAli.Saidi@ARM.com        pendingQueue.pop_front();
4139258SAli.Saidi@ARM.com        num_squashed++;
41410621SCurtis.Dunham@arm.com        statSquashedBefore++;
4159258SAli.Saidi@ARM.com
41610037SARM gem5 Developers        DPRINTF(TLB, "Squashing table walk for address %#x\n",
41710037SARM gem5 Developers                      currState->vaddr_tainted);
4189258SAli.Saidi@ARM.com
4199535Smrinmoy.ghosh@arm.com        if (currState->transState->squashed()) {
4209535Smrinmoy.ghosh@arm.com            // finish the translation which will delete the translation object
42110474Sandreas.hansson@arm.com            currState->transState->finish(
42210474Sandreas.hansson@arm.com                std::make_shared<UnimpFault>("Squashed Inst"),
42310474Sandreas.hansson@arm.com                currState->req, currState->tc, currState->mode);
4249535Smrinmoy.ghosh@arm.com        } else {
4259535Smrinmoy.ghosh@arm.com            // translate the request now that we know it will work
42610621SCurtis.Dunham@arm.com            statWalkServiceTime.sample(curTick() - currState->startTime);
42710037SARM gem5 Developers            tlb->translateTiming(currState->req, currState->tc,
42810037SARM gem5 Developers                        currState->transState, currState->mode);
42910037SARM gem5 Developers
4309535Smrinmoy.ghosh@arm.com        }
4319258SAli.Saidi@ARM.com
4329258SAli.Saidi@ARM.com        // delete the current request
4339258SAli.Saidi@ARM.com        delete currState;
4349258SAli.Saidi@ARM.com
4359258SAli.Saidi@ARM.com        // peak at the next one
4369535Smrinmoy.ghosh@arm.com        if (pendingQueue.size()) {
4379258SAli.Saidi@ARM.com            currState = pendingQueue.front();
43810037SARM gem5 Developers            te = tlb->lookup(currState->vaddr, currState->asid,
43910037SARM gem5 Developers                currState->vmid, currState->isHyp, currState->isSecure, true,
44012735Sandreas.sandberg@arm.com                false, currState->el);
4419535Smrinmoy.ghosh@arm.com        } else {
4429535Smrinmoy.ghosh@arm.com            // Terminate the loop, nothing more to do
4439258SAli.Saidi@ARM.com            currState = NULL;
4449535Smrinmoy.ghosh@arm.com        }
4459258SAli.Saidi@ARM.com    }
44610621SCurtis.Dunham@arm.com    pendingChange();
4479258SAli.Saidi@ARM.com
44810621SCurtis.Dunham@arm.com    // if we still have pending translations, schedule more work
4499258SAli.Saidi@ARM.com    nextWalk(tc);
4509258SAli.Saidi@ARM.com    currState = NULL;
4517728SAli.Saidi@ARM.com}
4527728SAli.Saidi@ARM.com
4537728SAli.Saidi@ARM.comFault
4547728SAli.Saidi@ARM.comTableWalker::processWalk()
4557728SAli.Saidi@ARM.com{
4567404SAli.Saidi@ARM.com    Addr ttbr = 0;
4577404SAli.Saidi@ARM.com
4587404SAli.Saidi@ARM.com    // If translation isn't enabled, we shouldn't be here
45910037SARM gem5 Developers    assert(currState->sctlr.m || isStage2);
46014280Sgiacomo.travaglini@arm.com    const bool is_atomic = currState->req->isAtomic();
4617404SAli.Saidi@ARM.com
46210037SARM gem5 Developers    DPRINTF(TLB, "Beginning table walk for address %#x, TTBCR: %#x, bits:%#x\n",
46310037SARM gem5 Developers            currState->vaddr_tainted, currState->ttbcr, mbits(currState->vaddr, 31,
46410037SARM gem5 Developers                                                      32 - currState->ttbcr.n));
4657406SAli.Saidi@ARM.com
46610621SCurtis.Dunham@arm.com    statWalkWaitTime.sample(curTick() - currState->startTime);
46710621SCurtis.Dunham@arm.com
46810037SARM gem5 Developers    if (currState->ttbcr.n == 0 || !mbits(currState->vaddr, 31,
46910037SARM gem5 Developers                                          32 - currState->ttbcr.n)) {
4707406SAli.Saidi@ARM.com        DPRINTF(TLB, " - Selecting TTBR0\n");
47110037SARM gem5 Developers        // Check if table walk is allowed when Security Extensions are enabled
47210037SARM gem5 Developers        if (haveSecurity && currState->ttbcr.pd0) {
47310037SARM gem5 Developers            if (currState->isFetch)
47410474Sandreas.hansson@arm.com                return std::make_shared<PrefetchAbort>(
47510474Sandreas.hansson@arm.com                    currState->vaddr_tainted,
47610474Sandreas.hansson@arm.com                    ArmFault::TranslationLL + L1,
47710474Sandreas.hansson@arm.com                    isStage2,
47810474Sandreas.hansson@arm.com                    ArmFault::VmsaTran);
47910037SARM gem5 Developers            else
48010474Sandreas.hansson@arm.com                return std::make_shared<DataAbort>(
48110474Sandreas.hansson@arm.com                    currState->vaddr_tainted,
48214280Sgiacomo.travaglini@arm.com                    TlbEntry::DomainType::NoAccess,
48314280Sgiacomo.travaglini@arm.com                    is_atomic ? false : currState->isWrite,
48410474Sandreas.hansson@arm.com                    ArmFault::TranslationLL + L1, isStage2,
48510474Sandreas.hansson@arm.com                    ArmFault::VmsaTran);
48610037SARM gem5 Developers        }
48712499Sgiacomo.travaglini@arm.com        ttbr = currState->tc->readMiscReg(snsBankedIndex(
48810037SARM gem5 Developers            MISCREG_TTBR0, currState->tc, !currState->isSecure));
4897404SAli.Saidi@ARM.com    } else {
4907406SAli.Saidi@ARM.com        DPRINTF(TLB, " - Selecting TTBR1\n");
49110037SARM gem5 Developers        // Check if table walk is allowed when Security Extensions are enabled
49210037SARM gem5 Developers        if (haveSecurity && currState->ttbcr.pd1) {
49310037SARM gem5 Developers            if (currState->isFetch)
49410474Sandreas.hansson@arm.com                return std::make_shared<PrefetchAbort>(
49510474Sandreas.hansson@arm.com                    currState->vaddr_tainted,
49610474Sandreas.hansson@arm.com                    ArmFault::TranslationLL + L1,
49710474Sandreas.hansson@arm.com                    isStage2,
49810474Sandreas.hansson@arm.com                    ArmFault::VmsaTran);
49910037SARM gem5 Developers            else
50010474Sandreas.hansson@arm.com                return std::make_shared<DataAbort>(
50110474Sandreas.hansson@arm.com                    currState->vaddr_tainted,
50214280Sgiacomo.travaglini@arm.com                    TlbEntry::DomainType::NoAccess,
50314280Sgiacomo.travaglini@arm.com                    is_atomic ? false : currState->isWrite,
50410474Sandreas.hansson@arm.com                    ArmFault::TranslationLL + L1, isStage2,
50510474Sandreas.hansson@arm.com                    ArmFault::VmsaTran);
50610037SARM gem5 Developers        }
50712499Sgiacomo.travaglini@arm.com        ttbr = currState->tc->readMiscReg(snsBankedIndex(
50810037SARM gem5 Developers            MISCREG_TTBR1, currState->tc, !currState->isSecure));
50910037SARM gem5 Developers        currState->ttbcr.n = 0;
5107404SAli.Saidi@ARM.com    }
5117404SAli.Saidi@ARM.com
51210037SARM gem5 Developers    Addr l1desc_addr = mbits(ttbr, 31, 14 - currState->ttbcr.n) |
51310037SARM gem5 Developers        (bits(currState->vaddr, 31 - currState->ttbcr.n, 20) << 2);
51410037SARM gem5 Developers    DPRINTF(TLB, " - Descriptor at address %#x (%s)\n", l1desc_addr,
51510037SARM gem5 Developers            currState->isSecure ? "s" : "ns");
5167404SAli.Saidi@ARM.com
5177404SAli.Saidi@ARM.com    // Trickbox address check
5187439Sdam.sunwoo@arm.com    Fault f;
51911395Sandreas.sandberg@arm.com    f = testWalk(l1desc_addr, sizeof(uint32_t),
52011395Sandreas.sandberg@arm.com                 TlbEntry::DomainType::NoAccess, L1);
5217439Sdam.sunwoo@arm.com    if (f) {
52210037SARM gem5 Developers        DPRINTF(TLB, "Trickbox check caused fault on %#x\n", currState->vaddr_tainted);
5237579Sminkyu.jeong@arm.com        if (currState->timing) {
5247728SAli.Saidi@ARM.com            pending = false;
5257728SAli.Saidi@ARM.com            nextWalk(currState->tc);
5267579Sminkyu.jeong@arm.com            currState = NULL;
5277579Sminkyu.jeong@arm.com        } else {
5287579Sminkyu.jeong@arm.com            currState->tc = NULL;
5297579Sminkyu.jeong@arm.com            currState->req = NULL;
5307579Sminkyu.jeong@arm.com        }
5317579Sminkyu.jeong@arm.com        return f;
5327404SAli.Saidi@ARM.com    }
5337404SAli.Saidi@ARM.com
53410836Sandreas.hansson@arm.com    Request::Flags flag = Request::PT_WALK;
5357946SGiacomo.Gabrielli@arm.com    if (currState->sctlr.c == 0) {
53610836Sandreas.hansson@arm.com        flag.set(Request::UNCACHEABLE);
5377946SGiacomo.Gabrielli@arm.com    }
5387946SGiacomo.Gabrielli@arm.com
53911181Snathananel.premillieu@arm.com    if (currState->isSecure) {
54011181Snathananel.premillieu@arm.com        flag.set(Request::SECURE);
54111181Snathananel.premillieu@arm.com    }
54211181Snathananel.premillieu@arm.com
54310037SARM gem5 Developers    bool delayed;
54410037SARM gem5 Developers    delayed = fetchDescriptor(l1desc_addr, (uint8_t*)&currState->l1Desc.data,
54510037SARM gem5 Developers                              sizeof(uint32_t), flag, L1, &doL1DescEvent,
54610037SARM gem5 Developers                              &TableWalker::doL1Descriptor);
54710037SARM gem5 Developers    if (!delayed) {
54810037SARM gem5 Developers       f = currState->fault;
54910037SARM gem5 Developers    }
55010037SARM gem5 Developers
55110037SARM gem5 Developers    return f;
55210037SARM gem5 Developers}
55310037SARM gem5 Developers
55410037SARM gem5 DevelopersFault
55510037SARM gem5 DevelopersTableWalker::processWalkLPAE()
55610037SARM gem5 Developers{
55710037SARM gem5 Developers    Addr ttbr, ttbr0_max, ttbr1_min, desc_addr;
55810037SARM gem5 Developers    int tsz, n;
55910037SARM gem5 Developers    LookupLevel start_lookup_level = L1;
56010037SARM gem5 Developers
56110037SARM gem5 Developers    DPRINTF(TLB, "Beginning table walk for address %#x, TTBCR: %#x\n",
56210037SARM gem5 Developers            currState->vaddr_tainted, currState->ttbcr);
56310037SARM gem5 Developers
56410621SCurtis.Dunham@arm.com    statWalkWaitTime.sample(curTick() - currState->startTime);
56510621SCurtis.Dunham@arm.com
56610836Sandreas.hansson@arm.com    Request::Flags flag = Request::PT_WALK;
56710037SARM gem5 Developers    if (currState->isSecure)
56810037SARM gem5 Developers        flag.set(Request::SECURE);
56910037SARM gem5 Developers
57010037SARM gem5 Developers    // work out which base address register to use, if in hyp mode we always
57110037SARM gem5 Developers    // use HTTBR
57210037SARM gem5 Developers    if (isStage2) {
57310037SARM gem5 Developers        DPRINTF(TLB, " - Selecting VTTBR (long-desc.)\n");
57410037SARM gem5 Developers        ttbr = currState->tc->readMiscReg(MISCREG_VTTBR);
57510037SARM gem5 Developers        tsz  = sext<4>(currState->vtcr.t0sz);
57610037SARM gem5 Developers        start_lookup_level = currState->vtcr.sl0 ? L1 : L2;
57710037SARM gem5 Developers    } else if (currState->isHyp) {
57810037SARM gem5 Developers        DPRINTF(TLB, " - Selecting HTTBR (long-desc.)\n");
57910037SARM gem5 Developers        ttbr = currState->tc->readMiscReg(MISCREG_HTTBR);
58010037SARM gem5 Developers        tsz  = currState->htcr.t0sz;
58110037SARM gem5 Developers    } else {
58211517SCurtis.Dunham@arm.com        assert(longDescFormatInUse(currState->tc));
58310037SARM gem5 Developers
58410037SARM gem5 Developers        // Determine boundaries of TTBR0/1 regions
58510037SARM gem5 Developers        if (currState->ttbcr.t0sz)
58610037SARM gem5 Developers            ttbr0_max = (1ULL << (32 - currState->ttbcr.t0sz)) - 1;
58710037SARM gem5 Developers        else if (currState->ttbcr.t1sz)
58810037SARM gem5 Developers            ttbr0_max = (1ULL << 32) -
58910037SARM gem5 Developers                (1ULL << (32 - currState->ttbcr.t1sz)) - 1;
59010037SARM gem5 Developers        else
59110037SARM gem5 Developers            ttbr0_max = (1ULL << 32) - 1;
59210037SARM gem5 Developers        if (currState->ttbcr.t1sz)
59310037SARM gem5 Developers            ttbr1_min = (1ULL << 32) - (1ULL << (32 - currState->ttbcr.t1sz));
59410037SARM gem5 Developers        else
59510037SARM gem5 Developers            ttbr1_min = (1ULL << (32 - currState->ttbcr.t0sz));
59610037SARM gem5 Developers
59714280Sgiacomo.travaglini@arm.com        const bool is_atomic = currState->req->isAtomic();
59814280Sgiacomo.travaglini@arm.com
59910037SARM gem5 Developers        // The following code snippet selects the appropriate translation table base
60010037SARM gem5 Developers        // address (TTBR0 or TTBR1) and the appropriate starting lookup level
60110037SARM gem5 Developers        // depending on the address range supported by the translation table (ARM
60210037SARM gem5 Developers        // ARM issue C B3.6.4)
60310037SARM gem5 Developers        if (currState->vaddr <= ttbr0_max) {
60410037SARM gem5 Developers            DPRINTF(TLB, " - Selecting TTBR0 (long-desc.)\n");
60510037SARM gem5 Developers            // Check if table walk is allowed
60610037SARM gem5 Developers            if (currState->ttbcr.epd0) {
60710037SARM gem5 Developers                if (currState->isFetch)
60810474Sandreas.hansson@arm.com                    return std::make_shared<PrefetchAbort>(
60910474Sandreas.hansson@arm.com                        currState->vaddr_tainted,
61010474Sandreas.hansson@arm.com                        ArmFault::TranslationLL + L1,
61110474Sandreas.hansson@arm.com                        isStage2,
61210474Sandreas.hansson@arm.com                        ArmFault::LpaeTran);
61310037SARM gem5 Developers                else
61410474Sandreas.hansson@arm.com                    return std::make_shared<DataAbort>(
61510474Sandreas.hansson@arm.com                        currState->vaddr_tainted,
61610474Sandreas.hansson@arm.com                        TlbEntry::DomainType::NoAccess,
61714280Sgiacomo.travaglini@arm.com                        is_atomic ? false : currState->isWrite,
61810474Sandreas.hansson@arm.com                        ArmFault::TranslationLL + L1,
61910474Sandreas.hansson@arm.com                        isStage2,
62010474Sandreas.hansson@arm.com                        ArmFault::LpaeTran);
62110037SARM gem5 Developers            }
62212499Sgiacomo.travaglini@arm.com            ttbr = currState->tc->readMiscReg(snsBankedIndex(
62310037SARM gem5 Developers                MISCREG_TTBR0, currState->tc, !currState->isSecure));
62410037SARM gem5 Developers            tsz = currState->ttbcr.t0sz;
62510037SARM gem5 Developers            if (ttbr0_max < (1ULL << 30))  // Upper limit < 1 GB
62610037SARM gem5 Developers                start_lookup_level = L2;
62710037SARM gem5 Developers        } else if (currState->vaddr >= ttbr1_min) {
62810037SARM gem5 Developers            DPRINTF(TLB, " - Selecting TTBR1 (long-desc.)\n");
62910037SARM gem5 Developers            // Check if table walk is allowed
63010037SARM gem5 Developers            if (currState->ttbcr.epd1) {
63110037SARM gem5 Developers                if (currState->isFetch)
63210474Sandreas.hansson@arm.com                    return std::make_shared<PrefetchAbort>(
63310474Sandreas.hansson@arm.com                        currState->vaddr_tainted,
63410474Sandreas.hansson@arm.com                        ArmFault::TranslationLL + L1,
63510474Sandreas.hansson@arm.com                        isStage2,
63610474Sandreas.hansson@arm.com                        ArmFault::LpaeTran);
63710037SARM gem5 Developers                else
63810474Sandreas.hansson@arm.com                    return std::make_shared<DataAbort>(
63910474Sandreas.hansson@arm.com                        currState->vaddr_tainted,
64010474Sandreas.hansson@arm.com                        TlbEntry::DomainType::NoAccess,
64114280Sgiacomo.travaglini@arm.com                        is_atomic ? false : currState->isWrite,
64210474Sandreas.hansson@arm.com                        ArmFault::TranslationLL + L1,
64310474Sandreas.hansson@arm.com                        isStage2,
64410474Sandreas.hansson@arm.com                        ArmFault::LpaeTran);
64510037SARM gem5 Developers            }
64612499Sgiacomo.travaglini@arm.com            ttbr = currState->tc->readMiscReg(snsBankedIndex(
64710037SARM gem5 Developers                MISCREG_TTBR1, currState->tc, !currState->isSecure));
64810037SARM gem5 Developers            tsz = currState->ttbcr.t1sz;
64910037SARM gem5 Developers            if (ttbr1_min >= (1ULL << 31) + (1ULL << 30))  // Lower limit >= 3 GB
65010037SARM gem5 Developers                start_lookup_level = L2;
65110037SARM gem5 Developers        } else {
65210037SARM gem5 Developers            // Out of boundaries -> translation fault
65310037SARM gem5 Developers            if (currState->isFetch)
65410474Sandreas.hansson@arm.com                return std::make_shared<PrefetchAbort>(
65510474Sandreas.hansson@arm.com                    currState->vaddr_tainted,
65610474Sandreas.hansson@arm.com                    ArmFault::TranslationLL + L1,
65710474Sandreas.hansson@arm.com                    isStage2,
65810474Sandreas.hansson@arm.com                    ArmFault::LpaeTran);
65910037SARM gem5 Developers            else
66010474Sandreas.hansson@arm.com                return std::make_shared<DataAbort>(
66110474Sandreas.hansson@arm.com                    currState->vaddr_tainted,
66210474Sandreas.hansson@arm.com                    TlbEntry::DomainType::NoAccess,
66314280Sgiacomo.travaglini@arm.com                    is_atomic ? false : currState->isWrite,
66414280Sgiacomo.travaglini@arm.com                    ArmFault::TranslationLL + L1,
66510474Sandreas.hansson@arm.com                    isStage2, ArmFault::LpaeTran);
66610037SARM gem5 Developers        }
66710037SARM gem5 Developers
66810037SARM gem5 Developers    }
66910037SARM gem5 Developers
67010037SARM gem5 Developers    // Perform lookup (ARM ARM issue C B3.6.6)
67110037SARM gem5 Developers    if (start_lookup_level == L1) {
67210037SARM gem5 Developers        n = 5 - tsz;
67310037SARM gem5 Developers        desc_addr = mbits(ttbr, 39, n) |
67410037SARM gem5 Developers            (bits(currState->vaddr, n + 26, 30) << 3);
67510037SARM gem5 Developers        DPRINTF(TLB, " - Descriptor at address %#x (%s) (long-desc.)\n",
67610037SARM gem5 Developers                desc_addr, currState->isSecure ? "s" : "ns");
67710037SARM gem5 Developers    } else {
67810037SARM gem5 Developers        // Skip first-level lookup
67910037SARM gem5 Developers        n = (tsz >= 2 ? 14 - tsz : 12);
68010037SARM gem5 Developers        desc_addr = mbits(ttbr, 39, n) |
68110037SARM gem5 Developers            (bits(currState->vaddr, n + 17, 21) << 3);
68210037SARM gem5 Developers        DPRINTF(TLB, " - Descriptor at address %#x (%s) (long-desc.)\n",
68310037SARM gem5 Developers                desc_addr, currState->isSecure ? "s" : "ns");
68410037SARM gem5 Developers    }
68510037SARM gem5 Developers
68610037SARM gem5 Developers    // Trickbox address check
68711395Sandreas.sandberg@arm.com    Fault f = testWalk(desc_addr, sizeof(uint64_t),
68811395Sandreas.sandberg@arm.com                       TlbEntry::DomainType::NoAccess, start_lookup_level);
68910037SARM gem5 Developers    if (f) {
69010037SARM gem5 Developers        DPRINTF(TLB, "Trickbox check caused fault on %#x\n", currState->vaddr_tainted);
69110037SARM gem5 Developers        if (currState->timing) {
69210037SARM gem5 Developers            pending = false;
69310037SARM gem5 Developers            nextWalk(currState->tc);
69410037SARM gem5 Developers            currState = NULL;
69510037SARM gem5 Developers        } else {
69610037SARM gem5 Developers            currState->tc = NULL;
69710037SARM gem5 Developers            currState->req = NULL;
69810037SARM gem5 Developers        }
69910037SARM gem5 Developers        return f;
70010037SARM gem5 Developers    }
70110037SARM gem5 Developers
70210037SARM gem5 Developers    if (currState->sctlr.c == 0) {
70310836Sandreas.hansson@arm.com        flag.set(Request::UNCACHEABLE);
70410037SARM gem5 Developers    }
70510037SARM gem5 Developers
70610037SARM gem5 Developers    currState->longDesc.lookupLevel = start_lookup_level;
70710037SARM gem5 Developers    currState->longDesc.aarch64 = false;
70810324SCurtis.Dunham@arm.com    currState->longDesc.grainSize = Grain4KB;
70910037SARM gem5 Developers
71010037SARM gem5 Developers    bool delayed = fetchDescriptor(desc_addr, (uint8_t*)&currState->longDesc.data,
71110037SARM gem5 Developers                                   sizeof(uint64_t), flag, start_lookup_level,
71211588SCurtis.Dunham@arm.com                                   LongDescEventByLevel[start_lookup_level],
71311588SCurtis.Dunham@arm.com                                   &TableWalker::doLongDescriptor);
71410037SARM gem5 Developers    if (!delayed) {
71510037SARM gem5 Developers        f = currState->fault;
71610037SARM gem5 Developers    }
71710037SARM gem5 Developers
71810037SARM gem5 Developers    return f;
71910037SARM gem5 Developers}
72010037SARM gem5 Developers
72110037SARM gem5 Developersunsigned
72210037SARM gem5 DevelopersTableWalker::adjustTableSizeAArch64(unsigned tsz)
72310037SARM gem5 Developers{
72410037SARM gem5 Developers    if (tsz < 25)
72510037SARM gem5 Developers        return 25;
72610037SARM gem5 Developers    if (tsz > 48)
72710037SARM gem5 Developers        return 48;
72810037SARM gem5 Developers    return tsz;
72910037SARM gem5 Developers}
73010037SARM gem5 Developers
73110037SARM gem5 Developersbool
73210037SARM gem5 DevelopersTableWalker::checkAddrSizeFaultAArch64(Addr addr, int currPhysAddrRange)
73310037SARM gem5 Developers{
73410037SARM gem5 Developers    return (currPhysAddrRange != MaxPhysAddrRange &&
73510037SARM gem5 Developers            bits(addr, MaxPhysAddrRange - 1, currPhysAddrRange));
73610037SARM gem5 Developers}
73710037SARM gem5 Developers
73810037SARM gem5 DevelopersFault
73910037SARM gem5 DevelopersTableWalker::processWalkAArch64()
74010037SARM gem5 Developers{
74110037SARM gem5 Developers    assert(currState->aarch64);
74210037SARM gem5 Developers
74310324SCurtis.Dunham@arm.com    DPRINTF(TLB, "Beginning table walk for address %#llx, TCR: %#llx\n",
74410324SCurtis.Dunham@arm.com            currState->vaddr_tainted, currState->tcr);
74510324SCurtis.Dunham@arm.com
74612709Sgiacomo.travaglini@arm.com    static const GrainSize GrainMap_tg0[] =
74710324SCurtis.Dunham@arm.com      { Grain4KB, Grain64KB, Grain16KB, ReservedGrain };
74812709Sgiacomo.travaglini@arm.com    static const GrainSize GrainMap_tg1[] =
74910324SCurtis.Dunham@arm.com      { ReservedGrain, Grain16KB, Grain4KB, Grain64KB };
75010037SARM gem5 Developers
75110621SCurtis.Dunham@arm.com    statWalkWaitTime.sample(curTick() - currState->startTime);
75210621SCurtis.Dunham@arm.com
75310037SARM gem5 Developers    // Determine TTBR, table size, granule size and phys. address range
75410037SARM gem5 Developers    Addr ttbr = 0;
75510037SARM gem5 Developers    int tsz = 0, ps = 0;
75610324SCurtis.Dunham@arm.com    GrainSize tg = Grain4KB; // grain size computed from tg* field
75710037SARM gem5 Developers    bool fault = false;
75811575SDylan.Johnson@ARM.com
75911575SDylan.Johnson@ARM.com    LookupLevel start_lookup_level = MAX_LOOKUP_LEVELS;
76011575SDylan.Johnson@ARM.com
76110037SARM gem5 Developers    switch (currState->el) {
76210037SARM gem5 Developers      case EL0:
76310037SARM gem5 Developers      case EL1:
76411575SDylan.Johnson@ARM.com        if (isStage2) {
76511575SDylan.Johnson@ARM.com            DPRINTF(TLB, " - Selecting VTTBR0 (AArch64 stage 2)\n");
76611575SDylan.Johnson@ARM.com            ttbr = currState->tc->readMiscReg(MISCREG_VTTBR_EL2);
76711575SDylan.Johnson@ARM.com            tsz = 64 - currState->vtcr.t0sz64;
76812709Sgiacomo.travaglini@arm.com            tg = GrainMap_tg0[currState->vtcr.tg0];
76911575SDylan.Johnson@ARM.com            // ARM DDI 0487A.f D7-2148
77011575SDylan.Johnson@ARM.com            // The starting level of stage 2 translation depends on
77111575SDylan.Johnson@ARM.com            // VTCR_EL2.SL0 and VTCR_EL2.TG0
77211575SDylan.Johnson@ARM.com            LookupLevel __ = MAX_LOOKUP_LEVELS; // invalid level
77311575SDylan.Johnson@ARM.com            uint8_t sl_tg = (currState->vtcr.sl0 << 2) | currState->vtcr.tg0;
77411575SDylan.Johnson@ARM.com            static const LookupLevel SLL[] = {
77511575SDylan.Johnson@ARM.com                L2, L3, L3, __, // sl0 == 0
77611575SDylan.Johnson@ARM.com                L1, L2, L2, __, // sl0 == 1, etc.
77711575SDylan.Johnson@ARM.com                L0, L1, L1, __,
77811575SDylan.Johnson@ARM.com                __, __, __, __
77911575SDylan.Johnson@ARM.com            };
78011575SDylan.Johnson@ARM.com            start_lookup_level = SLL[sl_tg];
78111575SDylan.Johnson@ARM.com            panic_if(start_lookup_level == MAX_LOOKUP_LEVELS,
78211575SDylan.Johnson@ARM.com                     "Cannot discern lookup level from vtcr.{sl0,tg0}");
78313019Sanouk.vanlaer@arm.com            ps = currState->vtcr.ps;
78413019Sanouk.vanlaer@arm.com        } else {
78513019Sanouk.vanlaer@arm.com            switch (bits(currState->vaddr, 63,48)) {
78613019Sanouk.vanlaer@arm.com              case 0:
78713019Sanouk.vanlaer@arm.com                DPRINTF(TLB, " - Selecting TTBR0 (AArch64)\n");
78813019Sanouk.vanlaer@arm.com                ttbr = currState->tc->readMiscReg(MISCREG_TTBR0_EL1);
78913019Sanouk.vanlaer@arm.com                tsz = adjustTableSizeAArch64(64 - currState->tcr.t0sz);
79013019Sanouk.vanlaer@arm.com                tg = GrainMap_tg0[currState->tcr.tg0];
79114095Sgiacomo.travaglini@arm.com                currState->hpd = currState->tcr.hpd0;
79213019Sanouk.vanlaer@arm.com                if (bits(currState->vaddr, 63, tsz) != 0x0 ||
79313019Sanouk.vanlaer@arm.com                    currState->tcr.epd0)
79413019Sanouk.vanlaer@arm.com                  fault = true;
79513019Sanouk.vanlaer@arm.com                break;
79613019Sanouk.vanlaer@arm.com              case 0xffff:
79713019Sanouk.vanlaer@arm.com                DPRINTF(TLB, " - Selecting TTBR1 (AArch64)\n");
79813019Sanouk.vanlaer@arm.com                ttbr = currState->tc->readMiscReg(MISCREG_TTBR1_EL1);
79913019Sanouk.vanlaer@arm.com                tsz = adjustTableSizeAArch64(64 - currState->tcr.t1sz);
80013019Sanouk.vanlaer@arm.com                tg = GrainMap_tg1[currState->tcr.tg1];
80114095Sgiacomo.travaglini@arm.com                currState->hpd = currState->tcr.hpd1;
80213019Sanouk.vanlaer@arm.com                if (bits(currState->vaddr, 63, tsz) != mask(64-tsz) ||
80313019Sanouk.vanlaer@arm.com                    currState->tcr.epd1)
80413019Sanouk.vanlaer@arm.com                  fault = true;
80513019Sanouk.vanlaer@arm.com                break;
80613019Sanouk.vanlaer@arm.com              default:
80713019Sanouk.vanlaer@arm.com                // top two bytes must be all 0s or all 1s, else invalid addr
80813019Sanouk.vanlaer@arm.com                fault = true;
80913019Sanouk.vanlaer@arm.com            }
81013019Sanouk.vanlaer@arm.com            ps = currState->tcr.ips;
81110037SARM gem5 Developers        }
81210037SARM gem5 Developers        break;
81310037SARM gem5 Developers      case EL2:
81412709Sgiacomo.travaglini@arm.com        switch(bits(currState->vaddr, 63,48)) {
81512709Sgiacomo.travaglini@arm.com          case 0:
81612709Sgiacomo.travaglini@arm.com            DPRINTF(TLB, " - Selecting TTBR0 (AArch64)\n");
81712709Sgiacomo.travaglini@arm.com            ttbr = currState->tc->readMiscReg(MISCREG_TTBR0_EL2);
81812709Sgiacomo.travaglini@arm.com            tsz = adjustTableSizeAArch64(64 - currState->tcr.t0sz);
81912709Sgiacomo.travaglini@arm.com            tg = GrainMap_tg0[currState->tcr.tg0];
82014095Sgiacomo.travaglini@arm.com            currState->hpd = currState->hcr.e2h ?
82114095Sgiacomo.travaglini@arm.com                currState->tcr.hpd0 : currState->tcr.hpd;
82212709Sgiacomo.travaglini@arm.com            break;
82312709Sgiacomo.travaglini@arm.com
82412709Sgiacomo.travaglini@arm.com          case 0xffff:
82512709Sgiacomo.travaglini@arm.com            DPRINTF(TLB, " - Selecting TTBR1 (AArch64)\n");
82612709Sgiacomo.travaglini@arm.com            ttbr = currState->tc->readMiscReg(MISCREG_TTBR1_EL2);
82712709Sgiacomo.travaglini@arm.com            tsz = adjustTableSizeAArch64(64 - currState->tcr.t1sz);
82812709Sgiacomo.travaglini@arm.com            tg = GrainMap_tg1[currState->tcr.tg1];
82914095Sgiacomo.travaglini@arm.com            currState->hpd = currState->tcr.hpd1;
83012709Sgiacomo.travaglini@arm.com            if (bits(currState->vaddr, 63, tsz) != mask(64-tsz) ||
83112709Sgiacomo.travaglini@arm.com                currState->tcr.epd1 || !currState->hcr.e2h)
83212709Sgiacomo.travaglini@arm.com              fault = true;
83312709Sgiacomo.travaglini@arm.com            break;
83412709Sgiacomo.travaglini@arm.com
83512709Sgiacomo.travaglini@arm.com           default:
83612709Sgiacomo.travaglini@arm.com              // invalid addr if top two bytes are not all 0s
83712709Sgiacomo.travaglini@arm.com              fault = true;
83812709Sgiacomo.travaglini@arm.com        }
83913018Sanouk.vanlaer@arm.com        ps = currState->tcr.ps;
84012709Sgiacomo.travaglini@arm.com        break;
84110037SARM gem5 Developers      case EL3:
84210037SARM gem5 Developers        switch(bits(currState->vaddr, 63,48)) {
84310037SARM gem5 Developers            case 0:
84410324SCurtis.Dunham@arm.com                DPRINTF(TLB, " - Selecting TTBR0 (AArch64)\n");
84512709Sgiacomo.travaglini@arm.com                ttbr = currState->tc->readMiscReg(MISCREG_TTBR0_EL3);
84610324SCurtis.Dunham@arm.com                tsz = adjustTableSizeAArch64(64 - currState->tcr.t0sz);
84712709Sgiacomo.travaglini@arm.com                tg = GrainMap_tg0[currState->tcr.tg0];
84814095Sgiacomo.travaglini@arm.com                currState->hpd = currState->tcr.hpd;
84910037SARM gem5 Developers                break;
85010037SARM gem5 Developers            default:
85110037SARM gem5 Developers                // invalid addr if top two bytes are not all 0s
85210324SCurtis.Dunham@arm.com                fault = true;
85310037SARM gem5 Developers        }
85413018Sanouk.vanlaer@arm.com        ps = currState->tcr.ps;
85510037SARM gem5 Developers        break;
85610037SARM gem5 Developers    }
85710037SARM gem5 Developers
85814280Sgiacomo.travaglini@arm.com    const bool is_atomic = currState->req->isAtomic();
85914280Sgiacomo.travaglini@arm.com
86010037SARM gem5 Developers    if (fault) {
86110037SARM gem5 Developers        Fault f;
86210037SARM gem5 Developers        if (currState->isFetch)
86310474Sandreas.hansson@arm.com            f =  std::make_shared<PrefetchAbort>(
86410474Sandreas.hansson@arm.com                currState->vaddr_tainted,
86510474Sandreas.hansson@arm.com                ArmFault::TranslationLL + L0, isStage2,
86610474Sandreas.hansson@arm.com                ArmFault::LpaeTran);
86710037SARM gem5 Developers        else
86810474Sandreas.hansson@arm.com            f = std::make_shared<DataAbort>(
86910474Sandreas.hansson@arm.com                currState->vaddr_tainted,
87010474Sandreas.hansson@arm.com                TlbEntry::DomainType::NoAccess,
87114280Sgiacomo.travaglini@arm.com                is_atomic ? false : currState->isWrite,
87210474Sandreas.hansson@arm.com                ArmFault::TranslationLL + L0,
87310474Sandreas.hansson@arm.com                isStage2, ArmFault::LpaeTran);
87410037SARM gem5 Developers
87510037SARM gem5 Developers        if (currState->timing) {
87610037SARM gem5 Developers            pending = false;
87710037SARM gem5 Developers            nextWalk(currState->tc);
87810037SARM gem5 Developers            currState = NULL;
87910037SARM gem5 Developers        } else {
88010037SARM gem5 Developers            currState->tc = NULL;
88110037SARM gem5 Developers            currState->req = NULL;
88210037SARM gem5 Developers        }
88310037SARM gem5 Developers        return f;
88410037SARM gem5 Developers
88510037SARM gem5 Developers    }
88610037SARM gem5 Developers
88710324SCurtis.Dunham@arm.com    if (tg == ReservedGrain) {
88810324SCurtis.Dunham@arm.com        warn_once("Reserved granule size requested; gem5's IMPLEMENTATION "
88910324SCurtis.Dunham@arm.com                  "DEFINED behavior takes this to mean 4KB granules\n");
89010324SCurtis.Dunham@arm.com        tg = Grain4KB;
89110324SCurtis.Dunham@arm.com    }
89210324SCurtis.Dunham@arm.com
89310037SARM gem5 Developers    // Determine starting lookup level
89410324SCurtis.Dunham@arm.com    // See aarch64/translation/walk in Appendix G: ARMv8 Pseudocode Library
89510324SCurtis.Dunham@arm.com    // in ARM DDI 0487A.  These table values correspond to the cascading tests
89610324SCurtis.Dunham@arm.com    // to compute the lookup level and are of the form
89710324SCurtis.Dunham@arm.com    // (grain_size + N*stride), for N = {1, 2, 3}.
89810324SCurtis.Dunham@arm.com    // A value of 64 will never succeed and a value of 0 will always succeed.
89911575SDylan.Johnson@ARM.com    if (start_lookup_level == MAX_LOOKUP_LEVELS) {
90010324SCurtis.Dunham@arm.com        struct GrainMap {
90110324SCurtis.Dunham@arm.com            GrainSize grain_size;
90210324SCurtis.Dunham@arm.com            unsigned lookup_level_cutoff[MAX_LOOKUP_LEVELS];
90310324SCurtis.Dunham@arm.com        };
90410324SCurtis.Dunham@arm.com        static const GrainMap GM[] = {
90510324SCurtis.Dunham@arm.com            { Grain4KB,  { 39, 30,  0, 0 } },
90610324SCurtis.Dunham@arm.com            { Grain16KB, { 47, 36, 25, 0 } },
90710324SCurtis.Dunham@arm.com            { Grain64KB, { 64, 42, 29, 0 } }
90810324SCurtis.Dunham@arm.com        };
90910324SCurtis.Dunham@arm.com
91010324SCurtis.Dunham@arm.com        const unsigned *lookup = NULL; // points to a lookup_level_cutoff
91110324SCurtis.Dunham@arm.com
91210324SCurtis.Dunham@arm.com        for (unsigned i = 0; i < 3; ++i) { // choose entry of GM[]
91310324SCurtis.Dunham@arm.com            if (tg == GM[i].grain_size) {
91410324SCurtis.Dunham@arm.com                lookup = GM[i].lookup_level_cutoff;
91510324SCurtis.Dunham@arm.com                break;
91610324SCurtis.Dunham@arm.com            }
91710324SCurtis.Dunham@arm.com        }
91810324SCurtis.Dunham@arm.com        assert(lookup);
91910324SCurtis.Dunham@arm.com
92010324SCurtis.Dunham@arm.com        for (int L = L0; L != MAX_LOOKUP_LEVELS; ++L) {
92110324SCurtis.Dunham@arm.com            if (tsz > lookup[L]) {
92210324SCurtis.Dunham@arm.com                start_lookup_level = (LookupLevel) L;
92310324SCurtis.Dunham@arm.com                break;
92410324SCurtis.Dunham@arm.com            }
92510324SCurtis.Dunham@arm.com        }
92610324SCurtis.Dunham@arm.com        panic_if(start_lookup_level == MAX_LOOKUP_LEVELS,
92710324SCurtis.Dunham@arm.com                 "Table walker couldn't find lookup level\n");
92810037SARM gem5 Developers    }
92910037SARM gem5 Developers
93011575SDylan.Johnson@ARM.com    int stride = tg - 3;
93111575SDylan.Johnson@ARM.com
93210037SARM gem5 Developers    // Determine table base address
93310324SCurtis.Dunham@arm.com    int base_addr_lo = 3 + tsz - stride * (3 - start_lookup_level) - tg;
93410037SARM gem5 Developers    Addr base_addr = mbits(ttbr, 47, base_addr_lo);
93510037SARM gem5 Developers
93610037SARM gem5 Developers    // Determine physical address size and raise an Address Size Fault if
93710037SARM gem5 Developers    // necessary
93810037SARM gem5 Developers    int pa_range = decodePhysAddrRange64(ps);
93910037SARM gem5 Developers    // Clamp to lower limit
94010037SARM gem5 Developers    if (pa_range > physAddrRange)
94110037SARM gem5 Developers        currState->physAddrRange = physAddrRange;
94210037SARM gem5 Developers    else
94310037SARM gem5 Developers        currState->physAddrRange = pa_range;
94410037SARM gem5 Developers    if (checkAddrSizeFaultAArch64(base_addr, currState->physAddrRange)) {
94510037SARM gem5 Developers        DPRINTF(TLB, "Address size fault before any lookup\n");
94610037SARM gem5 Developers        Fault f;
94710037SARM gem5 Developers        if (currState->isFetch)
94810474Sandreas.hansson@arm.com            f = std::make_shared<PrefetchAbort>(
94910474Sandreas.hansson@arm.com                currState->vaddr_tainted,
95010474Sandreas.hansson@arm.com                ArmFault::AddressSizeLL + start_lookup_level,
95110474Sandreas.hansson@arm.com                isStage2,
95210474Sandreas.hansson@arm.com                ArmFault::LpaeTran);
95310037SARM gem5 Developers        else
95410474Sandreas.hansson@arm.com            f = std::make_shared<DataAbort>(
95510474Sandreas.hansson@arm.com                currState->vaddr_tainted,
95610474Sandreas.hansson@arm.com                TlbEntry::DomainType::NoAccess,
95714280Sgiacomo.travaglini@arm.com                is_atomic ? false : currState->isWrite,
95810474Sandreas.hansson@arm.com                ArmFault::AddressSizeLL + start_lookup_level,
95910474Sandreas.hansson@arm.com                isStage2,
96010474Sandreas.hansson@arm.com                ArmFault::LpaeTran);
96110037SARM gem5 Developers
96210037SARM gem5 Developers
96310037SARM gem5 Developers        if (currState->timing) {
96410037SARM gem5 Developers            pending = false;
96510037SARM gem5 Developers            nextWalk(currState->tc);
96610037SARM gem5 Developers            currState = NULL;
96710037SARM gem5 Developers        } else {
96810037SARM gem5 Developers            currState->tc = NULL;
96910037SARM gem5 Developers            currState->req = NULL;
97010037SARM gem5 Developers        }
97110037SARM gem5 Developers        return f;
97210037SARM gem5 Developers
97310037SARM gem5 Developers   }
97410037SARM gem5 Developers
97510037SARM gem5 Developers    // Determine descriptor address
97610037SARM gem5 Developers    Addr desc_addr = base_addr |
97710037SARM gem5 Developers        (bits(currState->vaddr, tsz - 1,
97810324SCurtis.Dunham@arm.com              stride * (3 - start_lookup_level) + tg) << 3);
97910037SARM gem5 Developers
98010037SARM gem5 Developers    // Trickbox address check
98111395Sandreas.sandberg@arm.com    Fault f = testWalk(desc_addr, sizeof(uint64_t),
98211395Sandreas.sandberg@arm.com                       TlbEntry::DomainType::NoAccess, start_lookup_level);
98310037SARM gem5 Developers    if (f) {
98410037SARM gem5 Developers        DPRINTF(TLB, "Trickbox check caused fault on %#x\n", currState->vaddr_tainted);
98510037SARM gem5 Developers        if (currState->timing) {
98610037SARM gem5 Developers            pending = false;
98710037SARM gem5 Developers            nextWalk(currState->tc);
98810037SARM gem5 Developers            currState = NULL;
98910037SARM gem5 Developers        } else {
99010037SARM gem5 Developers            currState->tc = NULL;
99110037SARM gem5 Developers            currState->req = NULL;
99210037SARM gem5 Developers        }
99310037SARM gem5 Developers        return f;
99410037SARM gem5 Developers    }
99510037SARM gem5 Developers
99610836Sandreas.hansson@arm.com    Request::Flags flag = Request::PT_WALK;
99710037SARM gem5 Developers    if (currState->sctlr.c == 0) {
99810836Sandreas.hansson@arm.com        flag.set(Request::UNCACHEABLE);
99910037SARM gem5 Developers    }
100010037SARM gem5 Developers
100111181Snathananel.premillieu@arm.com    if (currState->isSecure) {
100211181Snathananel.premillieu@arm.com        flag.set(Request::SECURE);
100311181Snathananel.premillieu@arm.com    }
100411181Snathananel.premillieu@arm.com
100510037SARM gem5 Developers    currState->longDesc.lookupLevel = start_lookup_level;
100610037SARM gem5 Developers    currState->longDesc.aarch64 = true;
100710324SCurtis.Dunham@arm.com    currState->longDesc.grainSize = tg;
100810037SARM gem5 Developers
10097439Sdam.sunwoo@arm.com    if (currState->timing) {
101011588SCurtis.Dunham@arm.com        fetchDescriptor(desc_addr, (uint8_t*) &currState->longDesc.data,
101111588SCurtis.Dunham@arm.com                        sizeof(uint64_t), flag, start_lookup_level,
101211588SCurtis.Dunham@arm.com                        LongDescEventByLevel[start_lookup_level], NULL);
101311579SDylan.Johnson@ARM.com    } else {
101411575SDylan.Johnson@ARM.com        fetchDescriptor(desc_addr, (uint8_t*)&currState->longDesc.data,
101511575SDylan.Johnson@ARM.com                        sizeof(uint64_t), flag, -1, NULL,
101611575SDylan.Johnson@ARM.com                        &TableWalker::doLongDescriptor);
10177439Sdam.sunwoo@arm.com        f = currState->fault;
10187404SAli.Saidi@ARM.com    }
10197404SAli.Saidi@ARM.com
10207439Sdam.sunwoo@arm.com    return f;
10217404SAli.Saidi@ARM.com}
10227404SAli.Saidi@ARM.com
10237404SAli.Saidi@ARM.comvoid
10247439Sdam.sunwoo@arm.comTableWalker::memAttrs(ThreadContext *tc, TlbEntry &te, SCTLR sctlr,
10257439Sdam.sunwoo@arm.com                      uint8_t texcb, bool s)
10267404SAli.Saidi@ARM.com{
10277439Sdam.sunwoo@arm.com    // Note: tc and sctlr local variables are hiding tc and sctrl class
10287439Sdam.sunwoo@arm.com    // variables
10297436Sdam.sunwoo@arm.com    DPRINTF(TLBVerbose, "memAttrs texcb:%d s:%d\n", texcb, s);
10307436Sdam.sunwoo@arm.com    te.shareable = false; // default value
10317582SAli.Saidi@arm.com    te.nonCacheable = false;
103210037SARM gem5 Developers    te.outerShareable = false;
10337439Sdam.sunwoo@arm.com    if (sctlr.tre == 0 || ((sctlr.tre == 1) && (sctlr.m == 0))) {
10347404SAli.Saidi@ARM.com        switch(texcb) {
10357436Sdam.sunwoo@arm.com          case 0: // Stongly-ordered
10367404SAli.Saidi@ARM.com            te.nonCacheable = true;
103710037SARM gem5 Developers            te.mtype = TlbEntry::MemoryType::StronglyOrdered;
10387436Sdam.sunwoo@arm.com            te.shareable = true;
10397436Sdam.sunwoo@arm.com            te.innerAttrs = 1;
10407436Sdam.sunwoo@arm.com            te.outerAttrs = 0;
10417404SAli.Saidi@ARM.com            break;
10427436Sdam.sunwoo@arm.com          case 1: // Shareable Device
10437436Sdam.sunwoo@arm.com            te.nonCacheable = true;
104410037SARM gem5 Developers            te.mtype = TlbEntry::MemoryType::Device;
10457436Sdam.sunwoo@arm.com            te.shareable = true;
10467436Sdam.sunwoo@arm.com            te.innerAttrs = 3;
10477436Sdam.sunwoo@arm.com            te.outerAttrs = 0;
10487436Sdam.sunwoo@arm.com            break;
10497436Sdam.sunwoo@arm.com          case 2: // Outer and Inner Write-Through, no Write-Allocate
105010037SARM gem5 Developers            te.mtype = TlbEntry::MemoryType::Normal;
10517436Sdam.sunwoo@arm.com            te.shareable = s;
10527436Sdam.sunwoo@arm.com            te.innerAttrs = 6;
10537436Sdam.sunwoo@arm.com            te.outerAttrs = bits(texcb, 1, 0);
10547436Sdam.sunwoo@arm.com            break;
10557436Sdam.sunwoo@arm.com          case 3: // Outer and Inner Write-Back, no Write-Allocate
105610037SARM gem5 Developers            te.mtype = TlbEntry::MemoryType::Normal;
10577436Sdam.sunwoo@arm.com            te.shareable = s;
10587436Sdam.sunwoo@arm.com            te.innerAttrs = 7;
10597436Sdam.sunwoo@arm.com            te.outerAttrs = bits(texcb, 1, 0);
10607436Sdam.sunwoo@arm.com            break;
10617436Sdam.sunwoo@arm.com          case 4: // Outer and Inner Non-cacheable
10627436Sdam.sunwoo@arm.com            te.nonCacheable = true;
106310037SARM gem5 Developers            te.mtype = TlbEntry::MemoryType::Normal;
10647436Sdam.sunwoo@arm.com            te.shareable = s;
10657436Sdam.sunwoo@arm.com            te.innerAttrs = 0;
10667436Sdam.sunwoo@arm.com            te.outerAttrs = bits(texcb, 1, 0);
10677436Sdam.sunwoo@arm.com            break;
10687436Sdam.sunwoo@arm.com          case 5: // Reserved
10697439Sdam.sunwoo@arm.com            panic("Reserved texcb value!\n");
10707436Sdam.sunwoo@arm.com            break;
10717436Sdam.sunwoo@arm.com          case 6: // Implementation Defined
10727439Sdam.sunwoo@arm.com            panic("Implementation-defined texcb value!\n");
10737436Sdam.sunwoo@arm.com            break;
10747436Sdam.sunwoo@arm.com          case 7: // Outer and Inner Write-Back, Write-Allocate
107510037SARM gem5 Developers            te.mtype = TlbEntry::MemoryType::Normal;
10767436Sdam.sunwoo@arm.com            te.shareable = s;
10777436Sdam.sunwoo@arm.com            te.innerAttrs = 5;
10787436Sdam.sunwoo@arm.com            te.outerAttrs = 1;
10797436Sdam.sunwoo@arm.com            break;
10807436Sdam.sunwoo@arm.com          case 8: // Non-shareable Device
10817436Sdam.sunwoo@arm.com            te.nonCacheable = true;
108210037SARM gem5 Developers            te.mtype = TlbEntry::MemoryType::Device;
10837436Sdam.sunwoo@arm.com            te.shareable = false;
10847436Sdam.sunwoo@arm.com            te.innerAttrs = 3;
10857436Sdam.sunwoo@arm.com            te.outerAttrs = 0;
10867436Sdam.sunwoo@arm.com            break;
10877436Sdam.sunwoo@arm.com          case 9 ... 15:  // Reserved
10887439Sdam.sunwoo@arm.com            panic("Reserved texcb value!\n");
10897436Sdam.sunwoo@arm.com            break;
10907436Sdam.sunwoo@arm.com          case 16 ... 31: // Cacheable Memory
109110037SARM gem5 Developers            te.mtype = TlbEntry::MemoryType::Normal;
10927436Sdam.sunwoo@arm.com            te.shareable = s;
10937404SAli.Saidi@ARM.com            if (bits(texcb, 1,0) == 0 || bits(texcb, 3,2) == 0)
10947404SAli.Saidi@ARM.com                te.nonCacheable = true;
10957436Sdam.sunwoo@arm.com            te.innerAttrs = bits(texcb, 1, 0);
10967436Sdam.sunwoo@arm.com            te.outerAttrs = bits(texcb, 3, 2);
10977404SAli.Saidi@ARM.com            break;
10987436Sdam.sunwoo@arm.com          default:
10997436Sdam.sunwoo@arm.com            panic("More than 32 states for 5 bits?\n");
11007404SAli.Saidi@ARM.com        }
11017404SAli.Saidi@ARM.com    } else {
11027438SAli.Saidi@ARM.com        assert(tc);
110312499Sgiacomo.travaglini@arm.com        PRRR prrr = tc->readMiscReg(snsBankedIndex(MISCREG_PRRR,
110410037SARM gem5 Developers                                    currState->tc, !currState->isSecure));
110512499Sgiacomo.travaglini@arm.com        NMRR nmrr = tc->readMiscReg(snsBankedIndex(MISCREG_NMRR,
110610037SARM gem5 Developers                                    currState->tc, !currState->isSecure));
11077436Sdam.sunwoo@arm.com        DPRINTF(TLBVerbose, "memAttrs PRRR:%08x NMRR:%08x\n", prrr, nmrr);
11087582SAli.Saidi@arm.com        uint8_t curr_tr = 0, curr_ir = 0, curr_or = 0;
11097404SAli.Saidi@ARM.com        switch(bits(texcb, 2,0)) {
11107404SAli.Saidi@ARM.com          case 0:
11117436Sdam.sunwoo@arm.com            curr_tr = prrr.tr0;
11127436Sdam.sunwoo@arm.com            curr_ir = nmrr.ir0;
11137436Sdam.sunwoo@arm.com            curr_or = nmrr.or0;
111410037SARM gem5 Developers            te.outerShareable = (prrr.nos0 == 0);
11157404SAli.Saidi@ARM.com            break;
11167404SAli.Saidi@ARM.com          case 1:
11177436Sdam.sunwoo@arm.com            curr_tr = prrr.tr1;
11187436Sdam.sunwoo@arm.com            curr_ir = nmrr.ir1;
11197436Sdam.sunwoo@arm.com            curr_or = nmrr.or1;
112010037SARM gem5 Developers            te.outerShareable = (prrr.nos1 == 0);
11217404SAli.Saidi@ARM.com            break;
11227404SAli.Saidi@ARM.com          case 2:
11237436Sdam.sunwoo@arm.com            curr_tr = prrr.tr2;
11247436Sdam.sunwoo@arm.com            curr_ir = nmrr.ir2;
11257436Sdam.sunwoo@arm.com            curr_or = nmrr.or2;
112610037SARM gem5 Developers            te.outerShareable = (prrr.nos2 == 0);
11277404SAli.Saidi@ARM.com            break;
11287404SAli.Saidi@ARM.com          case 3:
11297436Sdam.sunwoo@arm.com            curr_tr = prrr.tr3;
11307436Sdam.sunwoo@arm.com            curr_ir = nmrr.ir3;
11317436Sdam.sunwoo@arm.com            curr_or = nmrr.or3;
113210037SARM gem5 Developers            te.outerShareable = (prrr.nos3 == 0);
11337404SAli.Saidi@ARM.com            break;
11347404SAli.Saidi@ARM.com          case 4:
11357436Sdam.sunwoo@arm.com            curr_tr = prrr.tr4;
11367436Sdam.sunwoo@arm.com            curr_ir = nmrr.ir4;
11377436Sdam.sunwoo@arm.com            curr_or = nmrr.or4;
113810037SARM gem5 Developers            te.outerShareable = (prrr.nos4 == 0);
11397404SAli.Saidi@ARM.com            break;
11407404SAli.Saidi@ARM.com          case 5:
11417436Sdam.sunwoo@arm.com            curr_tr = prrr.tr5;
11427436Sdam.sunwoo@arm.com            curr_ir = nmrr.ir5;
11437436Sdam.sunwoo@arm.com            curr_or = nmrr.or5;
114410037SARM gem5 Developers            te.outerShareable = (prrr.nos5 == 0);
11457404SAli.Saidi@ARM.com            break;
11467404SAli.Saidi@ARM.com          case 6:
11477404SAli.Saidi@ARM.com            panic("Imp defined type\n");
11487404SAli.Saidi@ARM.com          case 7:
11497436Sdam.sunwoo@arm.com            curr_tr = prrr.tr7;
11507436Sdam.sunwoo@arm.com            curr_ir = nmrr.ir7;
11517436Sdam.sunwoo@arm.com            curr_or = nmrr.or7;
115210037SARM gem5 Developers            te.outerShareable = (prrr.nos7 == 0);
11537404SAli.Saidi@ARM.com            break;
11547404SAli.Saidi@ARM.com        }
11557436Sdam.sunwoo@arm.com
11567436Sdam.sunwoo@arm.com        switch(curr_tr) {
11577436Sdam.sunwoo@arm.com          case 0:
11587436Sdam.sunwoo@arm.com            DPRINTF(TLBVerbose, "StronglyOrdered\n");
115910037SARM gem5 Developers            te.mtype = TlbEntry::MemoryType::StronglyOrdered;
11607436Sdam.sunwoo@arm.com            te.nonCacheable = true;
11617436Sdam.sunwoo@arm.com            te.innerAttrs = 1;
11627436Sdam.sunwoo@arm.com            te.outerAttrs = 0;
11637436Sdam.sunwoo@arm.com            te.shareable = true;
11647436Sdam.sunwoo@arm.com            break;
11657436Sdam.sunwoo@arm.com          case 1:
11667436Sdam.sunwoo@arm.com            DPRINTF(TLBVerbose, "Device ds1:%d ds0:%d s:%d\n",
11677436Sdam.sunwoo@arm.com                    prrr.ds1, prrr.ds0, s);
116810037SARM gem5 Developers            te.mtype = TlbEntry::MemoryType::Device;
11697436Sdam.sunwoo@arm.com            te.nonCacheable = true;
11707436Sdam.sunwoo@arm.com            te.innerAttrs = 3;
11717436Sdam.sunwoo@arm.com            te.outerAttrs = 0;
11727436Sdam.sunwoo@arm.com            if (prrr.ds1 && s)
11737436Sdam.sunwoo@arm.com                te.shareable = true;
11747436Sdam.sunwoo@arm.com            if (prrr.ds0 && !s)
11757436Sdam.sunwoo@arm.com                te.shareable = true;
11767436Sdam.sunwoo@arm.com            break;
11777436Sdam.sunwoo@arm.com          case 2:
11787436Sdam.sunwoo@arm.com            DPRINTF(TLBVerbose, "Normal ns1:%d ns0:%d s:%d\n",
11797436Sdam.sunwoo@arm.com                    prrr.ns1, prrr.ns0, s);
118010037SARM gem5 Developers            te.mtype = TlbEntry::MemoryType::Normal;
11817436Sdam.sunwoo@arm.com            if (prrr.ns1 && s)
11827436Sdam.sunwoo@arm.com                te.shareable = true;
11837436Sdam.sunwoo@arm.com            if (prrr.ns0 && !s)
11847436Sdam.sunwoo@arm.com                te.shareable = true;
11857436Sdam.sunwoo@arm.com            break;
11867436Sdam.sunwoo@arm.com          case 3:
11877436Sdam.sunwoo@arm.com            panic("Reserved type");
11887436Sdam.sunwoo@arm.com        }
11897436Sdam.sunwoo@arm.com
119010037SARM gem5 Developers        if (te.mtype == TlbEntry::MemoryType::Normal){
11917436Sdam.sunwoo@arm.com            switch(curr_ir) {
11927436Sdam.sunwoo@arm.com              case 0:
11937436Sdam.sunwoo@arm.com                te.nonCacheable = true;
11947436Sdam.sunwoo@arm.com                te.innerAttrs = 0;
11957436Sdam.sunwoo@arm.com                break;
11967436Sdam.sunwoo@arm.com              case 1:
11977436Sdam.sunwoo@arm.com                te.innerAttrs = 5;
11987436Sdam.sunwoo@arm.com                break;
11997436Sdam.sunwoo@arm.com              case 2:
12007436Sdam.sunwoo@arm.com                te.innerAttrs = 6;
12017436Sdam.sunwoo@arm.com                break;
12027436Sdam.sunwoo@arm.com              case 3:
12037436Sdam.sunwoo@arm.com                te.innerAttrs = 7;
12047436Sdam.sunwoo@arm.com                break;
12057436Sdam.sunwoo@arm.com            }
12067436Sdam.sunwoo@arm.com
12077436Sdam.sunwoo@arm.com            switch(curr_or) {
12087436Sdam.sunwoo@arm.com              case 0:
12097436Sdam.sunwoo@arm.com                te.nonCacheable = true;
12107436Sdam.sunwoo@arm.com                te.outerAttrs = 0;
12117436Sdam.sunwoo@arm.com                break;
12127436Sdam.sunwoo@arm.com              case 1:
12137436Sdam.sunwoo@arm.com                te.outerAttrs = 1;
12147436Sdam.sunwoo@arm.com                break;
12157436Sdam.sunwoo@arm.com              case 2:
12167436Sdam.sunwoo@arm.com                te.outerAttrs = 2;
12177436Sdam.sunwoo@arm.com                break;
12187436Sdam.sunwoo@arm.com              case 3:
12197436Sdam.sunwoo@arm.com                te.outerAttrs = 3;
12207436Sdam.sunwoo@arm.com                break;
12217436Sdam.sunwoo@arm.com            }
12227436Sdam.sunwoo@arm.com        }
12237404SAli.Saidi@ARM.com    }
122410367SAndrew.Bardsley@arm.com    DPRINTF(TLBVerbose, "memAttrs: shareable: %d, innerAttrs: %d, "
122510367SAndrew.Bardsley@arm.com            "outerAttrs: %d\n",
12267439Sdam.sunwoo@arm.com            te.shareable, te.innerAttrs, te.outerAttrs);
122710037SARM gem5 Developers    te.setAttributes(false);
122810037SARM gem5 Developers}
12297436Sdam.sunwoo@arm.com
123010037SARM gem5 Developersvoid
123110037SARM gem5 DevelopersTableWalker::memAttrsLPAE(ThreadContext *tc, TlbEntry &te,
123210037SARM gem5 Developers    LongDescriptor &lDescriptor)
123310037SARM gem5 Developers{
123410037SARM gem5 Developers    assert(_haveLPAE);
12357436Sdam.sunwoo@arm.com
123610037SARM gem5 Developers    uint8_t attr;
123710037SARM gem5 Developers    uint8_t sh = lDescriptor.sh();
123810037SARM gem5 Developers    // Different format and source of attributes if this is a stage 2
123910037SARM gem5 Developers    // translation
124010037SARM gem5 Developers    if (isStage2) {
124110037SARM gem5 Developers        attr = lDescriptor.memAttr();
124210037SARM gem5 Developers        uint8_t attr_3_2 = (attr >> 2) & 0x3;
124310037SARM gem5 Developers        uint8_t attr_1_0 =  attr       & 0x3;
12447436Sdam.sunwoo@arm.com
124510037SARM gem5 Developers        DPRINTF(TLBVerbose, "memAttrsLPAE MemAttr:%#x sh:%#x\n", attr, sh);
124610037SARM gem5 Developers
124710037SARM gem5 Developers        if (attr_3_2 == 0) {
124810037SARM gem5 Developers            te.mtype        = attr_1_0 == 0 ? TlbEntry::MemoryType::StronglyOrdered
124910037SARM gem5 Developers                                            : TlbEntry::MemoryType::Device;
125010037SARM gem5 Developers            te.outerAttrs   = 0;
125110037SARM gem5 Developers            te.innerAttrs   = attr_1_0 == 0 ? 1 : 3;
125210037SARM gem5 Developers            te.nonCacheable = true;
125310037SARM gem5 Developers        } else {
125410037SARM gem5 Developers            te.mtype        = TlbEntry::MemoryType::Normal;
125510037SARM gem5 Developers            te.outerAttrs   = attr_3_2 == 1 ? 0 :
125610037SARM gem5 Developers                              attr_3_2 == 2 ? 2 : 1;
125710037SARM gem5 Developers            te.innerAttrs   = attr_1_0 == 1 ? 0 :
125810037SARM gem5 Developers                              attr_1_0 == 2 ? 6 : 5;
125910037SARM gem5 Developers            te.nonCacheable = (attr_3_2 == 1) || (attr_1_0 == 1);
126010037SARM gem5 Developers        }
126110037SARM gem5 Developers    } else {
126210037SARM gem5 Developers        uint8_t attrIndx = lDescriptor.attrIndx();
126310037SARM gem5 Developers
126410037SARM gem5 Developers        // LPAE always uses remapping of memory attributes, irrespective of the
126510037SARM gem5 Developers        // value of SCTLR.TRE
126610421Sandreas.hansson@arm.com        MiscRegIndex reg = attrIndx & 0x4 ? MISCREG_MAIR1 : MISCREG_MAIR0;
126712499Sgiacomo.travaglini@arm.com        int reg_as_int = snsBankedIndex(reg, currState->tc,
126812499Sgiacomo.travaglini@arm.com                                        !currState->isSecure);
126910421Sandreas.hansson@arm.com        uint32_t mair = currState->tc->readMiscReg(reg_as_int);
127010037SARM gem5 Developers        attr = (mair >> (8 * (attrIndx % 4))) & 0xff;
127110037SARM gem5 Developers        uint8_t attr_7_4 = bits(attr, 7, 4);
127210037SARM gem5 Developers        uint8_t attr_3_0 = bits(attr, 3, 0);
127310037SARM gem5 Developers        DPRINTF(TLBVerbose, "memAttrsLPAE AttrIndx:%#x sh:%#x, attr %#x\n", attrIndx, sh, attr);
127410037SARM gem5 Developers
127510037SARM gem5 Developers        // Note: the memory subsystem only cares about the 'cacheable' memory
127610037SARM gem5 Developers        // attribute. The other attributes are only used to fill the PAR register
127710037SARM gem5 Developers        // accordingly to provide the illusion of full support
127810037SARM gem5 Developers        te.nonCacheable = false;
127910037SARM gem5 Developers
128010037SARM gem5 Developers        switch (attr_7_4) {
128110037SARM gem5 Developers          case 0x0:
128210037SARM gem5 Developers            // Strongly-ordered or Device memory
128310037SARM gem5 Developers            if (attr_3_0 == 0x0)
128410037SARM gem5 Developers                te.mtype = TlbEntry::MemoryType::StronglyOrdered;
128510037SARM gem5 Developers            else if (attr_3_0 == 0x4)
128610037SARM gem5 Developers                te.mtype = TlbEntry::MemoryType::Device;
128710037SARM gem5 Developers            else
128810037SARM gem5 Developers                panic("Unpredictable behavior\n");
128910037SARM gem5 Developers            te.nonCacheable = true;
129010037SARM gem5 Developers            te.outerAttrs   = 0;
129110037SARM gem5 Developers            break;
129210037SARM gem5 Developers          case 0x4:
129310037SARM gem5 Developers            // Normal memory, Outer Non-cacheable
129410037SARM gem5 Developers            te.mtype = TlbEntry::MemoryType::Normal;
129510037SARM gem5 Developers            te.outerAttrs = 0;
129610037SARM gem5 Developers            if (attr_3_0 == 0x4)
129710037SARM gem5 Developers                // Inner Non-cacheable
129810037SARM gem5 Developers                te.nonCacheable = true;
129910037SARM gem5 Developers            else if (attr_3_0 < 0x8)
130010037SARM gem5 Developers                panic("Unpredictable behavior\n");
130110037SARM gem5 Developers            break;
130210037SARM gem5 Developers          case 0x8:
130310037SARM gem5 Developers          case 0x9:
130410037SARM gem5 Developers          case 0xa:
130510037SARM gem5 Developers          case 0xb:
130610037SARM gem5 Developers          case 0xc:
130710037SARM gem5 Developers          case 0xd:
130810037SARM gem5 Developers          case 0xe:
130910037SARM gem5 Developers          case 0xf:
131010037SARM gem5 Developers            if (attr_7_4 & 0x4) {
131110037SARM gem5 Developers                te.outerAttrs = (attr_7_4 & 1) ? 1 : 3;
131210037SARM gem5 Developers            } else {
131310037SARM gem5 Developers                te.outerAttrs = 0x2;
131410037SARM gem5 Developers            }
131510037SARM gem5 Developers            // Normal memory, Outer Cacheable
131610037SARM gem5 Developers            te.mtype = TlbEntry::MemoryType::Normal;
131710037SARM gem5 Developers            if (attr_3_0 != 0x4 && attr_3_0 < 0x8)
131810037SARM gem5 Developers                panic("Unpredictable behavior\n");
131910037SARM gem5 Developers            break;
132010037SARM gem5 Developers          default:
132110037SARM gem5 Developers            panic("Unpredictable behavior\n");
132210037SARM gem5 Developers            break;
132310037SARM gem5 Developers        }
132410037SARM gem5 Developers
132510037SARM gem5 Developers        switch (attr_3_0) {
132610037SARM gem5 Developers          case 0x0:
132710037SARM gem5 Developers            te.innerAttrs = 0x1;
132810037SARM gem5 Developers            break;
132910037SARM gem5 Developers          case 0x4:
133010037SARM gem5 Developers            te.innerAttrs = attr_7_4 == 0 ? 0x3 : 0;
133110037SARM gem5 Developers            break;
133210037SARM gem5 Developers          case 0x8:
133310037SARM gem5 Developers          case 0x9:
133410037SARM gem5 Developers          case 0xA:
133510037SARM gem5 Developers          case 0xB:
133610037SARM gem5 Developers            te.innerAttrs = 6;
133710037SARM gem5 Developers            break;
133810037SARM gem5 Developers          case 0xC:
133910037SARM gem5 Developers          case 0xD:
134010037SARM gem5 Developers          case 0xE:
134110037SARM gem5 Developers          case 0xF:
134210037SARM gem5 Developers            te.innerAttrs = attr_3_0 & 1 ? 0x5 : 0x7;
134310037SARM gem5 Developers            break;
134410037SARM gem5 Developers          default:
134510037SARM gem5 Developers            panic("Unpredictable behavior\n");
134610037SARM gem5 Developers            break;
134710037SARM gem5 Developers        }
134810037SARM gem5 Developers    }
134910037SARM gem5 Developers
135010037SARM gem5 Developers    te.outerShareable = sh == 2;
135110037SARM gem5 Developers    te.shareable       = (sh & 0x2) ? true : false;
135210037SARM gem5 Developers    te.setAttributes(true);
135310037SARM gem5 Developers    te.attributes |= (uint64_t) attr << 56;
135410037SARM gem5 Developers}
135510037SARM gem5 Developers
135610037SARM gem5 Developersvoid
135711583SDylan.Johnson@ARM.comTableWalker::memAttrsAArch64(ThreadContext *tc, TlbEntry &te,
135811583SDylan.Johnson@ARM.com                             LongDescriptor &lDescriptor)
135910037SARM gem5 Developers{
136011583SDylan.Johnson@ARM.com    uint8_t attr;
136111583SDylan.Johnson@ARM.com    uint8_t attr_hi;
136211583SDylan.Johnson@ARM.com    uint8_t attr_lo;
136311583SDylan.Johnson@ARM.com    uint8_t sh = lDescriptor.sh();
136410037SARM gem5 Developers
136511583SDylan.Johnson@ARM.com    if (isStage2) {
136611583SDylan.Johnson@ARM.com        attr = lDescriptor.memAttr();
136711583SDylan.Johnson@ARM.com        uint8_t attr_hi = (attr >> 2) & 0x3;
136811583SDylan.Johnson@ARM.com        uint8_t attr_lo =  attr       & 0x3;
136911583SDylan.Johnson@ARM.com
137011583SDylan.Johnson@ARM.com        DPRINTF(TLBVerbose, "memAttrsAArch64 MemAttr:%#x sh:%#x\n", attr, sh);
137111583SDylan.Johnson@ARM.com
137211583SDylan.Johnson@ARM.com        if (attr_hi == 0) {
137311583SDylan.Johnson@ARM.com            te.mtype        = attr_lo == 0 ? TlbEntry::MemoryType::StronglyOrdered
137411583SDylan.Johnson@ARM.com                                            : TlbEntry::MemoryType::Device;
137511583SDylan.Johnson@ARM.com            te.outerAttrs   = 0;
137611583SDylan.Johnson@ARM.com            te.innerAttrs   = attr_lo == 0 ? 1 : 3;
137711583SDylan.Johnson@ARM.com            te.nonCacheable = true;
137811583SDylan.Johnson@ARM.com        } else {
137911583SDylan.Johnson@ARM.com            te.mtype        = TlbEntry::MemoryType::Normal;
138011583SDylan.Johnson@ARM.com            te.outerAttrs   = attr_hi == 1 ? 0 :
138111583SDylan.Johnson@ARM.com                              attr_hi == 2 ? 2 : 1;
138211583SDylan.Johnson@ARM.com            te.innerAttrs   = attr_lo == 1 ? 0 :
138311583SDylan.Johnson@ARM.com                              attr_lo == 2 ? 6 : 5;
138411938Snikos.nikoleris@arm.com            // Treat write-through memory as uncacheable, this is safe
138511938Snikos.nikoleris@arm.com            // but for performance reasons not optimal.
138611938Snikos.nikoleris@arm.com            te.nonCacheable = (attr_hi == 1) || (attr_hi == 2) ||
138711938Snikos.nikoleris@arm.com                (attr_lo == 1) || (attr_lo == 2);
138811583SDylan.Johnson@ARM.com        }
138911583SDylan.Johnson@ARM.com    } else {
139011583SDylan.Johnson@ARM.com        uint8_t attrIndx = lDescriptor.attrIndx();
139111583SDylan.Johnson@ARM.com
139211583SDylan.Johnson@ARM.com        DPRINTF(TLBVerbose, "memAttrsAArch64 AttrIndx:%#x sh:%#x\n", attrIndx, sh);
139311583SDylan.Johnson@ARM.com
139411583SDylan.Johnson@ARM.com        // Select MAIR
139511583SDylan.Johnson@ARM.com        uint64_t mair;
139611583SDylan.Johnson@ARM.com        switch (currState->el) {
139711583SDylan.Johnson@ARM.com          case EL0:
139811583SDylan.Johnson@ARM.com          case EL1:
139911583SDylan.Johnson@ARM.com            mair = tc->readMiscReg(MISCREG_MAIR_EL1);
140011583SDylan.Johnson@ARM.com            break;
140111583SDylan.Johnson@ARM.com          case EL2:
140211583SDylan.Johnson@ARM.com            mair = tc->readMiscReg(MISCREG_MAIR_EL2);
140311583SDylan.Johnson@ARM.com            break;
140411583SDylan.Johnson@ARM.com          case EL3:
140511583SDylan.Johnson@ARM.com            mair = tc->readMiscReg(MISCREG_MAIR_EL3);
140611583SDylan.Johnson@ARM.com            break;
140711583SDylan.Johnson@ARM.com          default:
140811583SDylan.Johnson@ARM.com            panic("Invalid exception level");
140911583SDylan.Johnson@ARM.com            break;
141011583SDylan.Johnson@ARM.com        }
141111583SDylan.Johnson@ARM.com
141211583SDylan.Johnson@ARM.com        // Select attributes
141311583SDylan.Johnson@ARM.com        attr = bits(mair, 8 * attrIndx + 7, 8 * attrIndx);
141411583SDylan.Johnson@ARM.com        attr_lo = bits(attr, 3, 0);
141511583SDylan.Johnson@ARM.com        attr_hi = bits(attr, 7, 4);
141611583SDylan.Johnson@ARM.com
141711583SDylan.Johnson@ARM.com        // Memory type
141811583SDylan.Johnson@ARM.com        te.mtype = attr_hi == 0 ? TlbEntry::MemoryType::Device : TlbEntry::MemoryType::Normal;
141911583SDylan.Johnson@ARM.com
142011583SDylan.Johnson@ARM.com        // Cacheability
142111583SDylan.Johnson@ARM.com        te.nonCacheable = false;
142211938Snikos.nikoleris@arm.com        if (te.mtype == TlbEntry::MemoryType::Device) {  // Device memory
142311938Snikos.nikoleris@arm.com            te.nonCacheable = true;
142411938Snikos.nikoleris@arm.com        }
142511938Snikos.nikoleris@arm.com        // Treat write-through memory as uncacheable, this is safe
142611938Snikos.nikoleris@arm.com        // but for performance reasons not optimal.
142711938Snikos.nikoleris@arm.com        switch (attr_hi) {
142811938Snikos.nikoleris@arm.com          case 0x1 ... 0x3: // Normal Memory, Outer Write-through transient
142911938Snikos.nikoleris@arm.com          case 0x4:         // Normal memory, Outer Non-cacheable
143011938Snikos.nikoleris@arm.com          case 0x8 ... 0xb: // Normal Memory, Outer Write-through non-transient
143111938Snikos.nikoleris@arm.com            te.nonCacheable = true;
143211938Snikos.nikoleris@arm.com        }
143311938Snikos.nikoleris@arm.com        switch (attr_lo) {
143411938Snikos.nikoleris@arm.com          case 0x1 ... 0x3: // Normal Memory, Inner Write-through transient
143511938Snikos.nikoleris@arm.com          case 0x9 ... 0xb: // Normal Memory, Inner Write-through non-transient
143611938Snikos.nikoleris@arm.com            warn_if(!attr_hi, "Unpredictable behavior");
143712392Sjason@lowepower.com            M5_FALLTHROUGH;
143811938Snikos.nikoleris@arm.com          case 0x4:         // Device-nGnRE memory or
143911938Snikos.nikoleris@arm.com                            // Normal memory, Inner Non-cacheable
144011938Snikos.nikoleris@arm.com          case 0x8:         // Device-nGRE memory or
144111938Snikos.nikoleris@arm.com                            // Normal memory, Inner Write-through non-transient
144211583SDylan.Johnson@ARM.com            te.nonCacheable = true;
144311583SDylan.Johnson@ARM.com        }
144411583SDylan.Johnson@ARM.com
144511583SDylan.Johnson@ARM.com        te.shareable       = sh == 2;
144611583SDylan.Johnson@ARM.com        te.outerShareable = (sh & 0x2) ? true : false;
144711583SDylan.Johnson@ARM.com        // Attributes formatted according to the 64-bit PAR
144811583SDylan.Johnson@ARM.com        te.attributes = ((uint64_t) attr << 56) |
144911583SDylan.Johnson@ARM.com            (1 << 11) |     // LPAE bit
145011583SDylan.Johnson@ARM.com            (te.ns << 9) |  // NS bit
145111583SDylan.Johnson@ARM.com            (sh << 7);
145210037SARM gem5 Developers    }
14537404SAli.Saidi@ARM.com}
14547404SAli.Saidi@ARM.com
14557404SAli.Saidi@ARM.comvoid
14567404SAli.Saidi@ARM.comTableWalker::doL1Descriptor()
14577404SAli.Saidi@ARM.com{
145810037SARM gem5 Developers    if (currState->fault != NoFault) {
145910037SARM gem5 Developers        return;
146010037SARM gem5 Developers    }
146110037SARM gem5 Developers
146212526Schuan.zhu@arm.com    currState->l1Desc.data = htog(currState->l1Desc.data,
146312526Schuan.zhu@arm.com                                  byteOrder(currState->tc));
146412526Schuan.zhu@arm.com
14657439Sdam.sunwoo@arm.com    DPRINTF(TLB, "L1 descriptor for %#x is %#x\n",
146610037SARM gem5 Developers            currState->vaddr_tainted, currState->l1Desc.data);
14677404SAli.Saidi@ARM.com    TlbEntry te;
14687404SAli.Saidi@ARM.com
146914280Sgiacomo.travaglini@arm.com    const bool is_atomic = currState->req->isAtomic();
147014280Sgiacomo.travaglini@arm.com
14717439Sdam.sunwoo@arm.com    switch (currState->l1Desc.type()) {
14727404SAli.Saidi@ARM.com      case L1Descriptor::Ignore:
14737404SAli.Saidi@ARM.com      case L1Descriptor::Reserved:
14747946SGiacomo.Gabrielli@arm.com        if (!currState->timing) {
14757439Sdam.sunwoo@arm.com            currState->tc = NULL;
14767439Sdam.sunwoo@arm.com            currState->req = NULL;
14777437Sdam.sunwoo@arm.com        }
14787406SAli.Saidi@ARM.com        DPRINTF(TLB, "L1 Descriptor Reserved/Ignore, causing fault\n");
14797439Sdam.sunwoo@arm.com        if (currState->isFetch)
14807439Sdam.sunwoo@arm.com            currState->fault =
148110474Sandreas.hansson@arm.com                std::make_shared<PrefetchAbort>(
148210474Sandreas.hansson@arm.com                    currState->vaddr_tainted,
148310474Sandreas.hansson@arm.com                    ArmFault::TranslationLL + L1,
148410474Sandreas.hansson@arm.com                    isStage2,
148510474Sandreas.hansson@arm.com                    ArmFault::VmsaTran);
14867406SAli.Saidi@ARM.com        else
14877439Sdam.sunwoo@arm.com            currState->fault =
148810474Sandreas.hansson@arm.com                std::make_shared<DataAbort>(
148910474Sandreas.hansson@arm.com                    currState->vaddr_tainted,
149010474Sandreas.hansson@arm.com                    TlbEntry::DomainType::NoAccess,
149114280Sgiacomo.travaglini@arm.com                    is_atomic ? false : currState->isWrite,
149210474Sandreas.hansson@arm.com                    ArmFault::TranslationLL + L1, isStage2,
149310474Sandreas.hansson@arm.com                    ArmFault::VmsaTran);
14947404SAli.Saidi@ARM.com        return;
14957404SAli.Saidi@ARM.com      case L1Descriptor::Section:
14967439Sdam.sunwoo@arm.com        if (currState->sctlr.afe && bits(currState->l1Desc.ap(), 0) == 0) {
14977436Sdam.sunwoo@arm.com            /** @todo: check sctlr.ha (bit[17]) if Hardware Access Flag is
14987436Sdam.sunwoo@arm.com              * enabled if set, do l1.Desc.setAp0() instead of generating
14997436Sdam.sunwoo@arm.com              * AccessFlag0
15007436Sdam.sunwoo@arm.com              */
15017436Sdam.sunwoo@arm.com
150210474Sandreas.hansson@arm.com            currState->fault = std::make_shared<DataAbort>(
150310474Sandreas.hansson@arm.com                currState->vaddr_tainted,
150410474Sandreas.hansson@arm.com                currState->l1Desc.domain(),
150514280Sgiacomo.travaglini@arm.com                is_atomic ? false : currState->isWrite,
150610474Sandreas.hansson@arm.com                ArmFault::AccessFlagLL + L1,
150710474Sandreas.hansson@arm.com                isStage2,
150810474Sandreas.hansson@arm.com                ArmFault::VmsaTran);
15097436Sdam.sunwoo@arm.com        }
15107439Sdam.sunwoo@arm.com        if (currState->l1Desc.supersection()) {
15117404SAli.Saidi@ARM.com            panic("Haven't implemented supersections\n");
15127404SAli.Saidi@ARM.com        }
151310037SARM gem5 Developers        insertTableEntry(currState->l1Desc, false);
151410037SARM gem5 Developers        return;
151510037SARM gem5 Developers      case L1Descriptor::PageTable:
151610037SARM gem5 Developers        {
151710037SARM gem5 Developers            Addr l2desc_addr;
151810037SARM gem5 Developers            l2desc_addr = currState->l1Desc.l2Addr() |
151910037SARM gem5 Developers                (bits(currState->vaddr, 19, 12) << 2);
152010037SARM gem5 Developers            DPRINTF(TLB, "L1 descriptor points to page table at: %#x (%s)\n",
152110037SARM gem5 Developers                    l2desc_addr, currState->isSecure ? "s" : "ns");
15227404SAli.Saidi@ARM.com
152310037SARM gem5 Developers            // Trickbox address check
152411395Sandreas.sandberg@arm.com            currState->fault = testWalk(l2desc_addr, sizeof(uint32_t),
152511395Sandreas.sandberg@arm.com                                        currState->l1Desc.domain(), L2);
15267404SAli.Saidi@ARM.com
152710037SARM gem5 Developers            if (currState->fault) {
152810037SARM gem5 Developers                if (!currState->timing) {
152910037SARM gem5 Developers                    currState->tc = NULL;
153010037SARM gem5 Developers                    currState->req = NULL;
153110037SARM gem5 Developers                }
153210037SARM gem5 Developers                return;
153310037SARM gem5 Developers            }
153410037SARM gem5 Developers
153510836Sandreas.hansson@arm.com            Request::Flags flag = Request::PT_WALK;
153610037SARM gem5 Developers            if (currState->isSecure)
153710037SARM gem5 Developers                flag.set(Request::SECURE);
153810037SARM gem5 Developers
153910037SARM gem5 Developers            bool delayed;
154010037SARM gem5 Developers            delayed = fetchDescriptor(l2desc_addr,
154110037SARM gem5 Developers                                      (uint8_t*)&currState->l2Desc.data,
154210037SARM gem5 Developers                                      sizeof(uint32_t), flag, -1, &doL2DescEvent,
154310037SARM gem5 Developers                                      &TableWalker::doL2Descriptor);
154410037SARM gem5 Developers            if (delayed) {
154510037SARM gem5 Developers                currState->delayed = true;
154610037SARM gem5 Developers            }
154710037SARM gem5 Developers
154810037SARM gem5 Developers            return;
154910037SARM gem5 Developers        }
155010037SARM gem5 Developers      default:
155110037SARM gem5 Developers        panic("A new type in a 2 bit field?\n");
155210037SARM gem5 Developers    }
155310037SARM gem5 Developers}
155410037SARM gem5 Developers
155514093Sgiacomo.travaglini@arm.comFault
155614093Sgiacomo.travaglini@arm.comTableWalker::generateLongDescFault(ArmFault::FaultSource src)
155714093Sgiacomo.travaglini@arm.com{
155814093Sgiacomo.travaglini@arm.com    if (currState->isFetch) {
155914093Sgiacomo.travaglini@arm.com        return std::make_shared<PrefetchAbort>(
156014093Sgiacomo.travaglini@arm.com            currState->vaddr_tainted,
156114093Sgiacomo.travaglini@arm.com            src + currState->longDesc.lookupLevel,
156214093Sgiacomo.travaglini@arm.com            isStage2,
156314093Sgiacomo.travaglini@arm.com            ArmFault::LpaeTran);
156414093Sgiacomo.travaglini@arm.com    } else {
156514093Sgiacomo.travaglini@arm.com        return std::make_shared<DataAbort>(
156614093Sgiacomo.travaglini@arm.com            currState->vaddr_tainted,
156714093Sgiacomo.travaglini@arm.com            TlbEntry::DomainType::NoAccess,
156814280Sgiacomo.travaglini@arm.com            currState->req->isAtomic() ? false : currState->isWrite,
156914093Sgiacomo.travaglini@arm.com            src + currState->longDesc.lookupLevel,
157014093Sgiacomo.travaglini@arm.com            isStage2,
157114093Sgiacomo.travaglini@arm.com            ArmFault::LpaeTran);
157214093Sgiacomo.travaglini@arm.com    }
157314093Sgiacomo.travaglini@arm.com}
157414093Sgiacomo.travaglini@arm.com
157510037SARM gem5 Developersvoid
157610037SARM gem5 DevelopersTableWalker::doLongDescriptor()
157710037SARM gem5 Developers{
157810037SARM gem5 Developers    if (currState->fault != NoFault) {
157910037SARM gem5 Developers        return;
158010037SARM gem5 Developers    }
158110037SARM gem5 Developers
158212526Schuan.zhu@arm.com    currState->longDesc.data = htog(currState->longDesc.data,
158312526Schuan.zhu@arm.com                                    byteOrder(currState->tc));
158412526Schuan.zhu@arm.com
158510037SARM gem5 Developers    DPRINTF(TLB, "L%d descriptor for %#llx is %#llx (%s)\n",
158610037SARM gem5 Developers            currState->longDesc.lookupLevel, currState->vaddr_tainted,
158710037SARM gem5 Developers            currState->longDesc.data,
158810037SARM gem5 Developers            currState->aarch64 ? "AArch64" : "long-desc.");
158910037SARM gem5 Developers
159010037SARM gem5 Developers    if ((currState->longDesc.type() == LongDescriptor::Block) ||
159110037SARM gem5 Developers        (currState->longDesc.type() == LongDescriptor::Page)) {
159210037SARM gem5 Developers        DPRINTF(TLBVerbose, "Analyzing L%d descriptor: %#llx, pxn: %d, "
159310037SARM gem5 Developers                "xn: %d, ap: %d, af: %d, type: %d\n",
159410037SARM gem5 Developers                currState->longDesc.lookupLevel,
159510037SARM gem5 Developers                currState->longDesc.data,
159610037SARM gem5 Developers                currState->longDesc.pxn(),
159710037SARM gem5 Developers                currState->longDesc.xn(),
159810037SARM gem5 Developers                currState->longDesc.ap(),
159910037SARM gem5 Developers                currState->longDesc.af(),
160010037SARM gem5 Developers                currState->longDesc.type());
160110037SARM gem5 Developers    } else {
160210037SARM gem5 Developers        DPRINTF(TLBVerbose, "Analyzing L%d descriptor: %#llx, type: %d\n",
160310037SARM gem5 Developers                currState->longDesc.lookupLevel,
160410037SARM gem5 Developers                currState->longDesc.data,
160510037SARM gem5 Developers                currState->longDesc.type());
160610037SARM gem5 Developers    }
160710037SARM gem5 Developers
160810037SARM gem5 Developers    TlbEntry te;
160910037SARM gem5 Developers
161010037SARM gem5 Developers    switch (currState->longDesc.type()) {
161110037SARM gem5 Developers      case LongDescriptor::Invalid:
161210037SARM gem5 Developers        DPRINTF(TLB, "L%d descriptor Invalid, causing fault type %d\n",
161310037SARM gem5 Developers                currState->longDesc.lookupLevel,
161410037SARM gem5 Developers                ArmFault::TranslationLL + currState->longDesc.lookupLevel);
161514093Sgiacomo.travaglini@arm.com
161614093Sgiacomo.travaglini@arm.com        currState->fault = generateLongDescFault(ArmFault::TranslationLL);
161714280Sgiacomo.travaglini@arm.com        if (!currState->timing) {
161814280Sgiacomo.travaglini@arm.com            currState->tc = NULL;
161914280Sgiacomo.travaglini@arm.com            currState->req = NULL;
162014280Sgiacomo.travaglini@arm.com        }
16217404SAli.Saidi@ARM.com        return;
162214093Sgiacomo.travaglini@arm.com
162310037SARM gem5 Developers      case LongDescriptor::Block:
162410037SARM gem5 Developers      case LongDescriptor::Page:
162510037SARM gem5 Developers        {
162614093Sgiacomo.travaglini@arm.com            auto fault_source = ArmFault::FaultSourceInvalid;
162710037SARM gem5 Developers            // Check for address size fault
162810037SARM gem5 Developers            if (checkAddrSizeFaultAArch64(
162910037SARM gem5 Developers                    mbits(currState->longDesc.data, MaxPhysAddrRange - 1,
163010037SARM gem5 Developers                          currState->longDesc.offsetBits()),
163110037SARM gem5 Developers                    currState->physAddrRange)) {
163214093Sgiacomo.travaglini@arm.com
163310037SARM gem5 Developers                DPRINTF(TLB, "L%d descriptor causing Address Size Fault\n",
163410037SARM gem5 Developers                        currState->longDesc.lookupLevel);
163514093Sgiacomo.travaglini@arm.com                fault_source = ArmFault::AddressSizeLL;
163614093Sgiacomo.travaglini@arm.com
163710037SARM gem5 Developers            // Check for access fault
163810037SARM gem5 Developers            } else if (currState->longDesc.af() == 0) {
163914093Sgiacomo.travaglini@arm.com
164010037SARM gem5 Developers                DPRINTF(TLB, "L%d descriptor causing Access Fault\n",
164110037SARM gem5 Developers                        currState->longDesc.lookupLevel);
164214093Sgiacomo.travaglini@arm.com                fault_source = ArmFault::AccessFlagLL;
164310037SARM gem5 Developers            }
164414093Sgiacomo.travaglini@arm.com
164514093Sgiacomo.travaglini@arm.com            if (fault_source != ArmFault::FaultSourceInvalid) {
164614093Sgiacomo.travaglini@arm.com                currState->fault = generateLongDescFault(fault_source);
164710037SARM gem5 Developers            } else {
164810037SARM gem5 Developers                insertTableEntry(currState->longDesc, true);
164910037SARM gem5 Developers            }
165010037SARM gem5 Developers        }
165110037SARM gem5 Developers        return;
165210037SARM gem5 Developers      case LongDescriptor::Table:
165310037SARM gem5 Developers        {
165410037SARM gem5 Developers            // Set hierarchical permission flags
165510037SARM gem5 Developers            currState->secureLookup = currState->secureLookup &&
165610037SARM gem5 Developers                currState->longDesc.secureTable();
165710037SARM gem5 Developers            currState->rwTable = currState->rwTable &&
165814095Sgiacomo.travaglini@arm.com                (currState->longDesc.rwTable() || currState->hpd);
165910037SARM gem5 Developers            currState->userTable = currState->userTable &&
166014095Sgiacomo.travaglini@arm.com                (currState->longDesc.userTable() || currState->hpd);
166110037SARM gem5 Developers            currState->xnTable = currState->xnTable ||
166214095Sgiacomo.travaglini@arm.com                (currState->longDesc.xnTable() && !currState->hpd);
166310037SARM gem5 Developers            currState->pxnTable = currState->pxnTable ||
166414095Sgiacomo.travaglini@arm.com                (currState->longDesc.pxnTable() && !currState->hpd);
16657404SAli.Saidi@ARM.com
166610037SARM gem5 Developers            // Set up next level lookup
166710037SARM gem5 Developers            Addr next_desc_addr = currState->longDesc.nextDescAddr(
166810037SARM gem5 Developers                currState->vaddr);
16697439Sdam.sunwoo@arm.com
167010037SARM gem5 Developers            DPRINTF(TLB, "L%d descriptor points to L%d descriptor at: %#x (%s)\n",
167110037SARM gem5 Developers                    currState->longDesc.lookupLevel,
167210037SARM gem5 Developers                    currState->longDesc.lookupLevel + 1,
167310037SARM gem5 Developers                    next_desc_addr,
167410037SARM gem5 Developers                    currState->secureLookup ? "s" : "ns");
167510037SARM gem5 Developers
167610037SARM gem5 Developers            // Check for address size fault
167710037SARM gem5 Developers            if (currState->aarch64 && checkAddrSizeFaultAArch64(
167810037SARM gem5 Developers                    next_desc_addr, currState->physAddrRange)) {
167910037SARM gem5 Developers                DPRINTF(TLB, "L%d descriptor causing Address Size Fault\n",
168010037SARM gem5 Developers                        currState->longDesc.lookupLevel);
168114093Sgiacomo.travaglini@arm.com
168214093Sgiacomo.travaglini@arm.com                currState->fault = generateLongDescFault(
168314093Sgiacomo.travaglini@arm.com                    ArmFault::AddressSizeLL);
168410037SARM gem5 Developers                return;
16857437Sdam.sunwoo@arm.com            }
16867404SAli.Saidi@ARM.com
168710037SARM gem5 Developers            // Trickbox address check
168811395Sandreas.sandberg@arm.com            currState->fault = testWalk(
168911395Sandreas.sandberg@arm.com                next_desc_addr, sizeof(uint64_t), TlbEntry::DomainType::Client,
169011395Sandreas.sandberg@arm.com                toLookupLevel(currState->longDesc.lookupLevel +1));
16917404SAli.Saidi@ARM.com
169210037SARM gem5 Developers            if (currState->fault) {
169310037SARM gem5 Developers                if (!currState->timing) {
169410037SARM gem5 Developers                    currState->tc = NULL;
169510037SARM gem5 Developers                    currState->req = NULL;
169610037SARM gem5 Developers                }
169710037SARM gem5 Developers                return;
169810037SARM gem5 Developers            }
169910037SARM gem5 Developers
170010836Sandreas.hansson@arm.com            Request::Flags flag = Request::PT_WALK;
170110037SARM gem5 Developers            if (currState->secureLookup)
170210037SARM gem5 Developers                flag.set(Request::SECURE);
170310037SARM gem5 Developers
170411588SCurtis.Dunham@arm.com            LookupLevel L = currState->longDesc.lookupLevel =
170510037SARM gem5 Developers                (LookupLevel) (currState->longDesc.lookupLevel + 1);
170610037SARM gem5 Developers            Event *event = NULL;
170711588SCurtis.Dunham@arm.com            switch (L) {
170810037SARM gem5 Developers              case L1:
170910037SARM gem5 Developers                assert(currState->aarch64);
171010037SARM gem5 Developers              case L2:
171110037SARM gem5 Developers              case L3:
171211588SCurtis.Dunham@arm.com                event = LongDescEventByLevel[L];
171310037SARM gem5 Developers                break;
171410037SARM gem5 Developers              default:
171510037SARM gem5 Developers                panic("Wrong lookup level in table walk\n");
171610037SARM gem5 Developers                break;
171710037SARM gem5 Developers            }
171810037SARM gem5 Developers
171910037SARM gem5 Developers            bool delayed;
172010037SARM gem5 Developers            delayed = fetchDescriptor(next_desc_addr, (uint8_t*)&currState->longDesc.data,
172110037SARM gem5 Developers                                      sizeof(uint64_t), flag, -1, event,
172210037SARM gem5 Developers                                      &TableWalker::doLongDescriptor);
172310037SARM gem5 Developers            if (delayed) {
172410037SARM gem5 Developers                 currState->delayed = true;
172510037SARM gem5 Developers            }
17267404SAli.Saidi@ARM.com        }
17277404SAli.Saidi@ARM.com        return;
17287404SAli.Saidi@ARM.com      default:
17297404SAli.Saidi@ARM.com        panic("A new type in a 2 bit field?\n");
17307404SAli.Saidi@ARM.com    }
17317404SAli.Saidi@ARM.com}
17327404SAli.Saidi@ARM.com
17337404SAli.Saidi@ARM.comvoid
17347404SAli.Saidi@ARM.comTableWalker::doL2Descriptor()
17357404SAli.Saidi@ARM.com{
173610037SARM gem5 Developers    if (currState->fault != NoFault) {
173710037SARM gem5 Developers        return;
173810037SARM gem5 Developers    }
173910037SARM gem5 Developers
174012526Schuan.zhu@arm.com    currState->l2Desc.data = htog(currState->l2Desc.data,
174112526Schuan.zhu@arm.com                                  byteOrder(currState->tc));
174212526Schuan.zhu@arm.com
17437439Sdam.sunwoo@arm.com    DPRINTF(TLB, "L2 descriptor for %#x is %#x\n",
174410037SARM gem5 Developers            currState->vaddr_tainted, currState->l2Desc.data);
17457404SAli.Saidi@ARM.com    TlbEntry te;
17467404SAli.Saidi@ARM.com
174714280Sgiacomo.travaglini@arm.com    const bool is_atomic = currState->req->isAtomic();
174814280Sgiacomo.travaglini@arm.com
17497439Sdam.sunwoo@arm.com    if (currState->l2Desc.invalid()) {
17507404SAli.Saidi@ARM.com        DPRINTF(TLB, "L2 descriptor invalid, causing fault\n");
17517946SGiacomo.Gabrielli@arm.com        if (!currState->timing) {
17527439Sdam.sunwoo@arm.com            currState->tc = NULL;
17537439Sdam.sunwoo@arm.com            currState->req = NULL;
17547437Sdam.sunwoo@arm.com        }
17557439Sdam.sunwoo@arm.com        if (currState->isFetch)
175610474Sandreas.hansson@arm.com            currState->fault = std::make_shared<PrefetchAbort>(
175710474Sandreas.hansson@arm.com                    currState->vaddr_tainted,
175810474Sandreas.hansson@arm.com                    ArmFault::TranslationLL + L2,
175910474Sandreas.hansson@arm.com                    isStage2,
176010474Sandreas.hansson@arm.com                    ArmFault::VmsaTran);
17617406SAli.Saidi@ARM.com        else
176210474Sandreas.hansson@arm.com            currState->fault = std::make_shared<DataAbort>(
176310474Sandreas.hansson@arm.com                currState->vaddr_tainted, currState->l1Desc.domain(),
176414280Sgiacomo.travaglini@arm.com                is_atomic ? false : currState->isWrite,
176514280Sgiacomo.travaglini@arm.com                ArmFault::TranslationLL + L2,
176610474Sandreas.hansson@arm.com                isStage2,
176710474Sandreas.hansson@arm.com                ArmFault::VmsaTran);
17687404SAli.Saidi@ARM.com        return;
17697404SAli.Saidi@ARM.com    }
17707404SAli.Saidi@ARM.com
17717439Sdam.sunwoo@arm.com    if (currState->sctlr.afe && bits(currState->l2Desc.ap(), 0) == 0) {
17727436Sdam.sunwoo@arm.com        /** @todo: check sctlr.ha (bit[17]) if Hardware Access Flag is enabled
17737436Sdam.sunwoo@arm.com          * if set, do l2.Desc.setAp0() instead of generating AccessFlag0
17747436Sdam.sunwoo@arm.com          */
177510037SARM gem5 Developers         DPRINTF(TLB, "Generating access fault at L2, afe: %d, ap: %d\n",
177610037SARM gem5 Developers                 currState->sctlr.afe, currState->l2Desc.ap());
17777436Sdam.sunwoo@arm.com
177810474Sandreas.hansson@arm.com        currState->fault = std::make_shared<DataAbort>(
177910474Sandreas.hansson@arm.com            currState->vaddr_tainted,
178014280Sgiacomo.travaglini@arm.com            TlbEntry::DomainType::NoAccess,
178114280Sgiacomo.travaglini@arm.com            is_atomic ? false : currState->isWrite,
178210474Sandreas.hansson@arm.com            ArmFault::AccessFlagLL + L2, isStage2,
178310474Sandreas.hansson@arm.com            ArmFault::VmsaTran);
17847436Sdam.sunwoo@arm.com    }
17857436Sdam.sunwoo@arm.com
178610037SARM gem5 Developers    insertTableEntry(currState->l2Desc, false);
17877437Sdam.sunwoo@arm.com}
17887437Sdam.sunwoo@arm.com
17897437Sdam.sunwoo@arm.comvoid
17907437Sdam.sunwoo@arm.comTableWalker::doL1DescriptorWrapper()
17917437Sdam.sunwoo@arm.com{
179210037SARM gem5 Developers    currState = stateQueues[L1].front();
17937439Sdam.sunwoo@arm.com    currState->delayed = false;
179410037SARM gem5 Developers    // if there's a stage2 translation object we don't need it any more
179510037SARM gem5 Developers    if (currState->stage2Tran) {
179610037SARM gem5 Developers        delete currState->stage2Tran;
179710037SARM gem5 Developers        currState->stage2Tran = NULL;
179810037SARM gem5 Developers    }
179910037SARM gem5 Developers
18007437Sdam.sunwoo@arm.com
18017578Sdam.sunwoo@arm.com    DPRINTF(TLBVerbose, "L1 Desc object host addr: %p\n",&currState->l1Desc.data);
18027578Sdam.sunwoo@arm.com    DPRINTF(TLBVerbose, "L1 Desc object      data: %08x\n",currState->l1Desc.data);
18037578Sdam.sunwoo@arm.com
180410037SARM gem5 Developers    DPRINTF(TLBVerbose, "calling doL1Descriptor for vaddr:%#x\n", currState->vaddr_tainted);
18057437Sdam.sunwoo@arm.com    doL1Descriptor();
18067437Sdam.sunwoo@arm.com
180710037SARM gem5 Developers    stateQueues[L1].pop_front();
18087437Sdam.sunwoo@arm.com    // Check if fault was generated
18097439Sdam.sunwoo@arm.com    if (currState->fault != NoFault) {
18107439Sdam.sunwoo@arm.com        currState->transState->finish(currState->fault, currState->req,
18117439Sdam.sunwoo@arm.com                                      currState->tc, currState->mode);
181210621SCurtis.Dunham@arm.com        statWalksShortTerminatedAtLevel[0]++;
18137437Sdam.sunwoo@arm.com
18147728SAli.Saidi@ARM.com        pending = false;
18157728SAli.Saidi@ARM.com        nextWalk(currState->tc);
18167728SAli.Saidi@ARM.com
18177439Sdam.sunwoo@arm.com        currState->req = NULL;
18187439Sdam.sunwoo@arm.com        currState->tc = NULL;
18197439Sdam.sunwoo@arm.com        currState->delayed = false;
18208510SAli.Saidi@ARM.com        delete currState;
18217437Sdam.sunwoo@arm.com    }
18227439Sdam.sunwoo@arm.com    else if (!currState->delayed) {
18237653Sgene.wu@arm.com        // delay is not set so there is no L2 to do
182410037SARM gem5 Developers        // Don't finish the translation if a stage 2 look up is underway
182512738Sandreas.sandberg@arm.com        statWalkServiceTime.sample(curTick() - currState->startTime);
182612738Sandreas.sandberg@arm.com        DPRINTF(TLBVerbose, "calling translateTiming again\n");
182712738Sandreas.sandberg@arm.com        tlb->translateTiming(currState->req, currState->tc,
182812738Sandreas.sandberg@arm.com                             currState->transState, currState->mode);
182912738Sandreas.sandberg@arm.com        statWalksShortTerminatedAtLevel[0]++;
18307437Sdam.sunwoo@arm.com
18317728SAli.Saidi@ARM.com        pending = false;
18327728SAli.Saidi@ARM.com        nextWalk(currState->tc);
18337728SAli.Saidi@ARM.com
18347439Sdam.sunwoo@arm.com        currState->req = NULL;
18357439Sdam.sunwoo@arm.com        currState->tc = NULL;
18367439Sdam.sunwoo@arm.com        currState->delayed = false;
18377653Sgene.wu@arm.com        delete currState;
18387653Sgene.wu@arm.com    } else {
18397653Sgene.wu@arm.com        // need to do L2 descriptor
184010037SARM gem5 Developers        stateQueues[L2].push_back(currState);
18417437Sdam.sunwoo@arm.com    }
18427439Sdam.sunwoo@arm.com    currState = NULL;
18437437Sdam.sunwoo@arm.com}
18447437Sdam.sunwoo@arm.com
18457437Sdam.sunwoo@arm.comvoid
18467437Sdam.sunwoo@arm.comTableWalker::doL2DescriptorWrapper()
18477437Sdam.sunwoo@arm.com{
184810037SARM gem5 Developers    currState = stateQueues[L2].front();
18497439Sdam.sunwoo@arm.com    assert(currState->delayed);
185010037SARM gem5 Developers    // if there's a stage2 translation object we don't need it any more
185110037SARM gem5 Developers    if (currState->stage2Tran) {
185210037SARM gem5 Developers        delete currState->stage2Tran;
185310037SARM gem5 Developers        currState->stage2Tran = NULL;
185410037SARM gem5 Developers    }
18557437Sdam.sunwoo@arm.com
18567439Sdam.sunwoo@arm.com    DPRINTF(TLBVerbose, "calling doL2Descriptor for vaddr:%#x\n",
185710037SARM gem5 Developers            currState->vaddr_tainted);
18587437Sdam.sunwoo@arm.com    doL2Descriptor();
18597437Sdam.sunwoo@arm.com
18607437Sdam.sunwoo@arm.com    // Check if fault was generated
18617439Sdam.sunwoo@arm.com    if (currState->fault != NoFault) {
18627439Sdam.sunwoo@arm.com        currState->transState->finish(currState->fault, currState->req,
18637439Sdam.sunwoo@arm.com                                      currState->tc, currState->mode);
186410621SCurtis.Dunham@arm.com        statWalksShortTerminatedAtLevel[1]++;
186512738Sandreas.sandberg@arm.com    } else {
186612738Sandreas.sandberg@arm.com        statWalkServiceTime.sample(curTick() - currState->startTime);
186712738Sandreas.sandberg@arm.com        DPRINTF(TLBVerbose, "calling translateTiming again\n");
186812738Sandreas.sandberg@arm.com        tlb->translateTiming(currState->req, currState->tc,
186912738Sandreas.sandberg@arm.com                             currState->transState, currState->mode);
187012738Sandreas.sandberg@arm.com        statWalksShortTerminatedAtLevel[1]++;
18717437Sdam.sunwoo@arm.com    }
18727437Sdam.sunwoo@arm.com
18737728SAli.Saidi@ARM.com
187410037SARM gem5 Developers    stateQueues[L2].pop_front();
18757728SAli.Saidi@ARM.com    pending = false;
18767728SAli.Saidi@ARM.com    nextWalk(currState->tc);
18777728SAli.Saidi@ARM.com
18787439Sdam.sunwoo@arm.com    currState->req = NULL;
18797439Sdam.sunwoo@arm.com    currState->tc = NULL;
18807439Sdam.sunwoo@arm.com    currState->delayed = false;
18817439Sdam.sunwoo@arm.com
18827653Sgene.wu@arm.com    delete currState;
18837439Sdam.sunwoo@arm.com    currState = NULL;
18847404SAli.Saidi@ARM.com}
18857404SAli.Saidi@ARM.com
18867728SAli.Saidi@ARM.comvoid
188710037SARM gem5 DevelopersTableWalker::doL0LongDescriptorWrapper()
188810037SARM gem5 Developers{
188910037SARM gem5 Developers    doLongDescriptorWrapper(L0);
189010037SARM gem5 Developers}
189110037SARM gem5 Developers
189210037SARM gem5 Developersvoid
189310037SARM gem5 DevelopersTableWalker::doL1LongDescriptorWrapper()
189410037SARM gem5 Developers{
189510037SARM gem5 Developers    doLongDescriptorWrapper(L1);
189610037SARM gem5 Developers}
189710037SARM gem5 Developers
189810037SARM gem5 Developersvoid
189910037SARM gem5 DevelopersTableWalker::doL2LongDescriptorWrapper()
190010037SARM gem5 Developers{
190110037SARM gem5 Developers    doLongDescriptorWrapper(L2);
190210037SARM gem5 Developers}
190310037SARM gem5 Developers
190410037SARM gem5 Developersvoid
190510037SARM gem5 DevelopersTableWalker::doL3LongDescriptorWrapper()
190610037SARM gem5 Developers{
190710037SARM gem5 Developers    doLongDescriptorWrapper(L3);
190810037SARM gem5 Developers}
190910037SARM gem5 Developers
191010037SARM gem5 Developersvoid
191110037SARM gem5 DevelopersTableWalker::doLongDescriptorWrapper(LookupLevel curr_lookup_level)
191210037SARM gem5 Developers{
191310037SARM gem5 Developers    currState = stateQueues[curr_lookup_level].front();
191410037SARM gem5 Developers    assert(curr_lookup_level == currState->longDesc.lookupLevel);
191510037SARM gem5 Developers    currState->delayed = false;
191610037SARM gem5 Developers
191710037SARM gem5 Developers    // if there's a stage2 translation object we don't need it any more
191810037SARM gem5 Developers    if (currState->stage2Tran) {
191910037SARM gem5 Developers        delete currState->stage2Tran;
192010037SARM gem5 Developers        currState->stage2Tran = NULL;
192110037SARM gem5 Developers    }
192210037SARM gem5 Developers
192310037SARM gem5 Developers    DPRINTF(TLBVerbose, "calling doLongDescriptor for vaddr:%#x\n",
192410037SARM gem5 Developers            currState->vaddr_tainted);
192510037SARM gem5 Developers    doLongDescriptor();
192610037SARM gem5 Developers
192710037SARM gem5 Developers    stateQueues[curr_lookup_level].pop_front();
192810037SARM gem5 Developers
192910037SARM gem5 Developers    if (currState->fault != NoFault) {
193010037SARM gem5 Developers        // A fault was generated
193110037SARM gem5 Developers        currState->transState->finish(currState->fault, currState->req,
193210037SARM gem5 Developers                                      currState->tc, currState->mode);
193310037SARM gem5 Developers
193410037SARM gem5 Developers        pending = false;
193510037SARM gem5 Developers        nextWalk(currState->tc);
193610037SARM gem5 Developers
193710037SARM gem5 Developers        currState->req = NULL;
193810037SARM gem5 Developers        currState->tc = NULL;
193910037SARM gem5 Developers        currState->delayed = false;
194010037SARM gem5 Developers        delete currState;
194110037SARM gem5 Developers    } else if (!currState->delayed) {
194210037SARM gem5 Developers        // No additional lookups required
194312738Sandreas.sandberg@arm.com        DPRINTF(TLBVerbose, "calling translateTiming again\n");
194412738Sandreas.sandberg@arm.com        statWalkServiceTime.sample(curTick() - currState->startTime);
194512738Sandreas.sandberg@arm.com        tlb->translateTiming(currState->req, currState->tc,
194612738Sandreas.sandberg@arm.com                             currState->transState, currState->mode);
194712738Sandreas.sandberg@arm.com        statWalksLongTerminatedAtLevel[(unsigned) curr_lookup_level]++;
194810037SARM gem5 Developers
194910037SARM gem5 Developers        pending = false;
195010037SARM gem5 Developers        nextWalk(currState->tc);
195110037SARM gem5 Developers
195210037SARM gem5 Developers        currState->req = NULL;
195310037SARM gem5 Developers        currState->tc = NULL;
195410037SARM gem5 Developers        currState->delayed = false;
195510037SARM gem5 Developers        delete currState;
195610037SARM gem5 Developers    } else {
195710037SARM gem5 Developers        if (curr_lookup_level >= MAX_LOOKUP_LEVELS - 1)
195810037SARM gem5 Developers            panic("Max. number of lookups already reached in table walk\n");
195910037SARM gem5 Developers        // Need to perform additional lookups
196010037SARM gem5 Developers        stateQueues[currState->longDesc.lookupLevel].push_back(currState);
196110037SARM gem5 Developers    }
196210037SARM gem5 Developers    currState = NULL;
196310037SARM gem5 Developers}
196410037SARM gem5 Developers
196510037SARM gem5 Developers
196610037SARM gem5 Developersvoid
19677728SAli.Saidi@ARM.comTableWalker::nextWalk(ThreadContext *tc)
19687728SAli.Saidi@ARM.com{
19697728SAli.Saidi@ARM.com    if (pendingQueue.size())
19709309Sandreas.hansson@arm.com        schedule(doProcessEvent, clockEdge(Cycles(1)));
197110509SAli.Saidi@ARM.com    else
197210509SAli.Saidi@ARM.com        completeDrain();
19737728SAli.Saidi@ARM.com}
19747728SAli.Saidi@ARM.com
197510037SARM gem5 Developersbool
197610037SARM gem5 DevelopersTableWalker::fetchDescriptor(Addr descAddr, uint8_t *data, int numBytes,
197710037SARM gem5 Developers    Request::Flags flags, int queueIndex, Event *event,
197810037SARM gem5 Developers    void (TableWalker::*doDescriptor)())
197910037SARM gem5 Developers{
198010037SARM gem5 Developers    bool isTiming = currState->timing;
19817728SAli.Saidi@ARM.com
198211575SDylan.Johnson@ARM.com    DPRINTF(TLBVerbose, "Fetching descriptor at address: 0x%x stage2Req: %d\n",
198311575SDylan.Johnson@ARM.com            descAddr, currState->stage2Req);
198411575SDylan.Johnson@ARM.com
198511575SDylan.Johnson@ARM.com    // If this translation has a stage 2 then we know descAddr is an IPA and
198611575SDylan.Johnson@ARM.com    // needs to be translated before we can access the page table. Do that
198711575SDylan.Johnson@ARM.com    // check here.
198810037SARM gem5 Developers    if (currState->stage2Req) {
198910037SARM gem5 Developers        Fault fault;
199010037SARM gem5 Developers        flags = flags | TLB::MustBeOne;
199110037SARM gem5 Developers
199210037SARM gem5 Developers        if (isTiming) {
199310037SARM gem5 Developers            Stage2MMU::Stage2Translation *tran = new
199410037SARM gem5 Developers                Stage2MMU::Stage2Translation(*stage2Mmu, data, event,
199510037SARM gem5 Developers                                             currState->vaddr);
199610037SARM gem5 Developers            currState->stage2Tran = tran;
199710037SARM gem5 Developers            stage2Mmu->readDataTimed(currState->tc, descAddr, tran, numBytes,
199810717Sandreas.hansson@arm.com                                     flags);
199910037SARM gem5 Developers            fault = tran->fault;
200010037SARM gem5 Developers        } else {
200110037SARM gem5 Developers            fault = stage2Mmu->readDataUntimed(currState->tc,
200210717Sandreas.hansson@arm.com                currState->vaddr, descAddr, data, numBytes, flags,
200310037SARM gem5 Developers                currState->functional);
200410037SARM gem5 Developers        }
200510037SARM gem5 Developers
200610037SARM gem5 Developers        if (fault != NoFault) {
200710037SARM gem5 Developers            currState->fault = fault;
200810037SARM gem5 Developers        }
200910037SARM gem5 Developers        if (isTiming) {
201010037SARM gem5 Developers            if (queueIndex >= 0) {
201110037SARM gem5 Developers                DPRINTF(TLBVerbose, "Adding to walker fifo: queue size before adding: %d\n",
201210037SARM gem5 Developers                        stateQueues[queueIndex].size());
201310037SARM gem5 Developers                stateQueues[queueIndex].push_back(currState);
201410037SARM gem5 Developers                currState = NULL;
201510037SARM gem5 Developers            }
201610037SARM gem5 Developers        } else {
201710037SARM gem5 Developers            (this->*doDescriptor)();
201810037SARM gem5 Developers        }
201910037SARM gem5 Developers    } else {
202010037SARM gem5 Developers        if (isTiming) {
202110717Sandreas.hansson@arm.com            port->dmaAction(MemCmd::ReadReq, descAddr, numBytes, event, data,
202210621SCurtis.Dunham@arm.com                           currState->tc->getCpuPtr()->clockPeriod(),flags);
202310037SARM gem5 Developers            if (queueIndex >= 0) {
202410037SARM gem5 Developers                DPRINTF(TLBVerbose, "Adding to walker fifo: queue size before adding: %d\n",
202510037SARM gem5 Developers                        stateQueues[queueIndex].size());
202610037SARM gem5 Developers                stateQueues[queueIndex].push_back(currState);
202710037SARM gem5 Developers                currState = NULL;
202810037SARM gem5 Developers            }
202910037SARM gem5 Developers        } else if (!currState->functional) {
203010717Sandreas.hansson@arm.com            port->dmaAction(MemCmd::ReadReq, descAddr, numBytes, NULL, data,
203110037SARM gem5 Developers                           currState->tc->getCpuPtr()->clockPeriod(), flags);
203210037SARM gem5 Developers            (this->*doDescriptor)();
203310037SARM gem5 Developers        } else {
203412749Sgiacomo.travaglini@arm.com            RequestPtr req = std::make_shared<Request>(
203512749Sgiacomo.travaglini@arm.com                descAddr, numBytes, flags, masterId);
203612749Sgiacomo.travaglini@arm.com
203710037SARM gem5 Developers            req->taskId(ContextSwitchTaskId::DMA);
203810037SARM gem5 Developers            PacketPtr  pkt = new Packet(req, MemCmd::ReadReq);
203910037SARM gem5 Developers            pkt->dataStatic(data);
204010717Sandreas.hansson@arm.com            port->sendFunctional(pkt);
204110037SARM gem5 Developers            (this->*doDescriptor)();
204210037SARM gem5 Developers            delete pkt;
204310037SARM gem5 Developers        }
204410037SARM gem5 Developers    }
204510037SARM gem5 Developers    return (isTiming);
204610037SARM gem5 Developers}
204710037SARM gem5 Developers
204810037SARM gem5 Developersvoid
204910037SARM gem5 DevelopersTableWalker::insertTableEntry(DescriptorBase &descriptor, bool longDescriptor)
205010037SARM gem5 Developers{
205110037SARM gem5 Developers    TlbEntry te;
205210037SARM gem5 Developers
205310037SARM gem5 Developers    // Create and fill a new page table entry
205410037SARM gem5 Developers    te.valid          = true;
205510037SARM gem5 Developers    te.longDescFormat = longDescriptor;
205610037SARM gem5 Developers    te.isHyp          = currState->isHyp;
205710037SARM gem5 Developers    te.asid           = currState->asid;
205810037SARM gem5 Developers    te.vmid           = currState->vmid;
205910037SARM gem5 Developers    te.N              = descriptor.offsetBits();
206010037SARM gem5 Developers    te.vpn            = currState->vaddr >> te.N;
206110037SARM gem5 Developers    te.size           = (1<<te.N) - 1;
206210037SARM gem5 Developers    te.pfn            = descriptor.pfn();
206310037SARM gem5 Developers    te.domain         = descriptor.domain();
206410037SARM gem5 Developers    te.lookupLevel    = descriptor.lookupLevel;
206510037SARM gem5 Developers    te.ns             = !descriptor.secure(haveSecurity, currState) || isStage2;
206610037SARM gem5 Developers    te.nstid          = !currState->isSecure;
206710037SARM gem5 Developers    te.xn             = descriptor.xn();
206810037SARM gem5 Developers    if (currState->aarch64)
206910037SARM gem5 Developers        te.el         = currState->el;
207010037SARM gem5 Developers    else
207114088Sgiacomo.travaglini@arm.com        te.el         = EL1;
207210037SARM gem5 Developers
207310621SCurtis.Dunham@arm.com    statPageSizes[pageSizeNtoStatBin(te.N)]++;
207410621SCurtis.Dunham@arm.com    statRequestOrigin[COMPLETED][currState->isFetch]++;
207510621SCurtis.Dunham@arm.com
207610037SARM gem5 Developers    // ASID has no meaning for stage 2 TLB entries, so mark all stage 2 entries
207710037SARM gem5 Developers    // as global
207810037SARM gem5 Developers    te.global         = descriptor.global(currState) || isStage2;
207910037SARM gem5 Developers    if (longDescriptor) {
208010037SARM gem5 Developers        LongDescriptor lDescriptor =
208110037SARM gem5 Developers            dynamic_cast<LongDescriptor &>(descriptor);
208210037SARM gem5 Developers
208310037SARM gem5 Developers        te.xn |= currState->xnTable;
208410037SARM gem5 Developers        te.pxn = currState->pxnTable || lDescriptor.pxn();
208510037SARM gem5 Developers        if (isStage2) {
208610037SARM gem5 Developers            // this is actually the HAP field, but its stored in the same bit
208710037SARM gem5 Developers            // possitions as the AP field in a stage 1 translation.
208810037SARM gem5 Developers            te.hap = lDescriptor.ap();
208910037SARM gem5 Developers        } else {
209010037SARM gem5 Developers           te.ap = ((!currState->rwTable || descriptor.ap() >> 1) << 1) |
209110037SARM gem5 Developers               (currState->userTable && (descriptor.ap() & 0x1));
209210037SARM gem5 Developers        }
209310037SARM gem5 Developers        if (currState->aarch64)
209411583SDylan.Johnson@ARM.com            memAttrsAArch64(currState->tc, te, lDescriptor);
209510037SARM gem5 Developers        else
209610037SARM gem5 Developers            memAttrsLPAE(currState->tc, te, lDescriptor);
209710037SARM gem5 Developers    } else {
209810037SARM gem5 Developers        te.ap = descriptor.ap();
209910037SARM gem5 Developers        memAttrs(currState->tc, te, currState->sctlr, descriptor.texcb(),
210010037SARM gem5 Developers                 descriptor.shareable());
210110037SARM gem5 Developers    }
210210037SARM gem5 Developers
210310037SARM gem5 Developers    // Debug output
210410037SARM gem5 Developers    DPRINTF(TLB, descriptor.dbgHeader().c_str());
210510037SARM gem5 Developers    DPRINTF(TLB, " - N:%d pfn:%#x size:%#x global:%d valid:%d\n",
210610037SARM gem5 Developers            te.N, te.pfn, te.size, te.global, te.valid);
210710037SARM gem5 Developers    DPRINTF(TLB, " - vpn:%#x xn:%d pxn:%d ap:%d domain:%d asid:%d "
210810037SARM gem5 Developers            "vmid:%d hyp:%d nc:%d ns:%d\n", te.vpn, te.xn, te.pxn,
210910037SARM gem5 Developers            te.ap, static_cast<uint8_t>(te.domain), te.asid, te.vmid, te.isHyp,
211010037SARM gem5 Developers            te.nonCacheable, te.ns);
211110037SARM gem5 Developers    DPRINTF(TLB, " - domain from L%d desc:%d data:%#x\n",
211210037SARM gem5 Developers            descriptor.lookupLevel, static_cast<uint8_t>(descriptor.domain()),
211310037SARM gem5 Developers            descriptor.getRawData());
211410037SARM gem5 Developers
211510037SARM gem5 Developers    // Insert the entry into the TLB
211610037SARM gem5 Developers    tlb->insert(currState->vaddr, te);
211710037SARM gem5 Developers    if (!currState->timing) {
211810037SARM gem5 Developers        currState->tc  = NULL;
211910037SARM gem5 Developers        currState->req = NULL;
212010037SARM gem5 Developers    }
212110037SARM gem5 Developers}
21227728SAli.Saidi@ARM.com
21237404SAli.Saidi@ARM.comArmISA::TableWalker *
21247404SAli.Saidi@ARM.comArmTableWalkerParams::create()
21257404SAli.Saidi@ARM.com{
21267404SAli.Saidi@ARM.com    return new ArmISA::TableWalker(this);
21277404SAli.Saidi@ARM.com}
21287404SAli.Saidi@ARM.com
212910037SARM gem5 DevelopersLookupLevel
213010037SARM gem5 DevelopersTableWalker::toLookupLevel(uint8_t lookup_level_as_int)
213110037SARM gem5 Developers{
213210037SARM gem5 Developers    switch (lookup_level_as_int) {
213310037SARM gem5 Developers      case L1:
213410037SARM gem5 Developers        return L1;
213510037SARM gem5 Developers      case L2:
213610037SARM gem5 Developers        return L2;
213710037SARM gem5 Developers      case L3:
213810037SARM gem5 Developers        return L3;
213910037SARM gem5 Developers      default:
214010037SARM gem5 Developers        panic("Invalid lookup level conversion");
214110037SARM gem5 Developers    }
214210037SARM gem5 Developers}
214310621SCurtis.Dunham@arm.com
214410621SCurtis.Dunham@arm.com/* this method keeps track of the table walker queue's residency, so
214510621SCurtis.Dunham@arm.com * needs to be called whenever requests start and complete. */
214610621SCurtis.Dunham@arm.comvoid
214710621SCurtis.Dunham@arm.comTableWalker::pendingChange()
214810621SCurtis.Dunham@arm.com{
214910621SCurtis.Dunham@arm.com    unsigned n = pendingQueue.size();
215010621SCurtis.Dunham@arm.com    if ((currState != NULL) && (currState != pendingQueue.front())) {
215110621SCurtis.Dunham@arm.com        ++n;
215210621SCurtis.Dunham@arm.com    }
215310621SCurtis.Dunham@arm.com
215410621SCurtis.Dunham@arm.com    if (n != pendingReqs) {
215510621SCurtis.Dunham@arm.com        Tick now = curTick();
215610621SCurtis.Dunham@arm.com        statPendingWalks.sample(pendingReqs, now - pendingChangeTick);
215710621SCurtis.Dunham@arm.com        pendingReqs = n;
215810621SCurtis.Dunham@arm.com        pendingChangeTick = now;
215910621SCurtis.Dunham@arm.com    }
216010621SCurtis.Dunham@arm.com}
216110621SCurtis.Dunham@arm.com
216211395Sandreas.sandberg@arm.comFault
216311395Sandreas.sandberg@arm.comTableWalker::testWalk(Addr pa, Addr size, TlbEntry::DomainType domain,
216411395Sandreas.sandberg@arm.com                      LookupLevel lookup_level)
216511395Sandreas.sandberg@arm.com{
216611395Sandreas.sandberg@arm.com    return tlb->testWalk(pa, size, currState->vaddr, currState->isSecure,
216711395Sandreas.sandberg@arm.com                         currState->mode, domain, lookup_level);
216811395Sandreas.sandberg@arm.com}
216911395Sandreas.sandberg@arm.com
217011395Sandreas.sandberg@arm.com
217110621SCurtis.Dunham@arm.comuint8_t
217210621SCurtis.Dunham@arm.comTableWalker::pageSizeNtoStatBin(uint8_t N)
217310621SCurtis.Dunham@arm.com{
217410621SCurtis.Dunham@arm.com    /* for statPageSizes */
217510621SCurtis.Dunham@arm.com    switch(N) {
217610621SCurtis.Dunham@arm.com        case 12: return 0; // 4K
217710621SCurtis.Dunham@arm.com        case 14: return 1; // 16K (using 16K granule in v8-64)
217810621SCurtis.Dunham@arm.com        case 16: return 2; // 64K
217910621SCurtis.Dunham@arm.com        case 20: return 3; // 1M
218010621SCurtis.Dunham@arm.com        case 21: return 4; // 2M-LPAE
218110621SCurtis.Dunham@arm.com        case 24: return 5; // 16M
218210621SCurtis.Dunham@arm.com        case 25: return 6; // 32M (using 16K granule in v8-64)
218310621SCurtis.Dunham@arm.com        case 29: return 7; // 512M (using 64K granule in v8-64)
218410621SCurtis.Dunham@arm.com        case 30: return 8; // 1G-LPAE
218510621SCurtis.Dunham@arm.com        default:
218610621SCurtis.Dunham@arm.com            panic("unknown page size");
218710621SCurtis.Dunham@arm.com            return 255;
218810621SCurtis.Dunham@arm.com    }
218910621SCurtis.Dunham@arm.com}
219010621SCurtis.Dunham@arm.com
219110621SCurtis.Dunham@arm.comvoid
219210621SCurtis.Dunham@arm.comTableWalker::regStats()
219310621SCurtis.Dunham@arm.com{
219411522Sstephan.diestelhorst@arm.com    ClockedObject::regStats();
219511522Sstephan.diestelhorst@arm.com
219610621SCurtis.Dunham@arm.com    statWalks
219710621SCurtis.Dunham@arm.com        .name(name() + ".walks")
219810621SCurtis.Dunham@arm.com        .desc("Table walker walks requested")
219910621SCurtis.Dunham@arm.com        ;
220010621SCurtis.Dunham@arm.com
220110621SCurtis.Dunham@arm.com    statWalksShortDescriptor
220210621SCurtis.Dunham@arm.com        .name(name() + ".walksShort")
220310621SCurtis.Dunham@arm.com        .desc("Table walker walks initiated with short descriptors")
220410621SCurtis.Dunham@arm.com        .flags(Stats::nozero)
220510621SCurtis.Dunham@arm.com        ;
220610621SCurtis.Dunham@arm.com
220710621SCurtis.Dunham@arm.com    statWalksLongDescriptor
220810621SCurtis.Dunham@arm.com        .name(name() + ".walksLong")
220910621SCurtis.Dunham@arm.com        .desc("Table walker walks initiated with long descriptors")
221010621SCurtis.Dunham@arm.com        .flags(Stats::nozero)
221110621SCurtis.Dunham@arm.com        ;
221210621SCurtis.Dunham@arm.com
221310621SCurtis.Dunham@arm.com    statWalksShortTerminatedAtLevel
221410621SCurtis.Dunham@arm.com        .init(2)
221510621SCurtis.Dunham@arm.com        .name(name() + ".walksShortTerminationLevel")
221610621SCurtis.Dunham@arm.com        .desc("Level at which table walker walks "
221710621SCurtis.Dunham@arm.com              "with short descriptors terminate")
221810621SCurtis.Dunham@arm.com        .flags(Stats::nozero)
221910621SCurtis.Dunham@arm.com        ;
222010621SCurtis.Dunham@arm.com    statWalksShortTerminatedAtLevel.subname(0, "Level1");
222110621SCurtis.Dunham@arm.com    statWalksShortTerminatedAtLevel.subname(1, "Level2");
222210621SCurtis.Dunham@arm.com
222310621SCurtis.Dunham@arm.com    statWalksLongTerminatedAtLevel
222410621SCurtis.Dunham@arm.com        .init(4)
222510621SCurtis.Dunham@arm.com        .name(name() + ".walksLongTerminationLevel")
222610621SCurtis.Dunham@arm.com        .desc("Level at which table walker walks "
222710621SCurtis.Dunham@arm.com              "with long descriptors terminate")
222810621SCurtis.Dunham@arm.com        .flags(Stats::nozero)
222910621SCurtis.Dunham@arm.com        ;
223010621SCurtis.Dunham@arm.com    statWalksLongTerminatedAtLevel.subname(0, "Level0");
223110621SCurtis.Dunham@arm.com    statWalksLongTerminatedAtLevel.subname(1, "Level1");
223210621SCurtis.Dunham@arm.com    statWalksLongTerminatedAtLevel.subname(2, "Level2");
223310621SCurtis.Dunham@arm.com    statWalksLongTerminatedAtLevel.subname(3, "Level3");
223410621SCurtis.Dunham@arm.com
223510621SCurtis.Dunham@arm.com    statSquashedBefore
223610621SCurtis.Dunham@arm.com        .name(name() + ".walksSquashedBefore")
223710621SCurtis.Dunham@arm.com        .desc("Table walks squashed before starting")
223810621SCurtis.Dunham@arm.com        .flags(Stats::nozero)
223910621SCurtis.Dunham@arm.com        ;
224010621SCurtis.Dunham@arm.com
224110621SCurtis.Dunham@arm.com    statSquashedAfter
224210621SCurtis.Dunham@arm.com        .name(name() + ".walksSquashedAfter")
224310621SCurtis.Dunham@arm.com        .desc("Table walks squashed after completion")
224410621SCurtis.Dunham@arm.com        .flags(Stats::nozero)
224510621SCurtis.Dunham@arm.com        ;
224610621SCurtis.Dunham@arm.com
224710621SCurtis.Dunham@arm.com    statWalkWaitTime
224810621SCurtis.Dunham@arm.com        .init(16)
224910621SCurtis.Dunham@arm.com        .name(name() + ".walkWaitTime")
225010621SCurtis.Dunham@arm.com        .desc("Table walker wait (enqueue to first request) latency")
225110621SCurtis.Dunham@arm.com        .flags(Stats::pdf | Stats::nozero | Stats::nonan)
225210621SCurtis.Dunham@arm.com        ;
225310621SCurtis.Dunham@arm.com
225410621SCurtis.Dunham@arm.com    statWalkServiceTime
225510621SCurtis.Dunham@arm.com        .init(16)
225610621SCurtis.Dunham@arm.com        .name(name() + ".walkCompletionTime")
225710621SCurtis.Dunham@arm.com        .desc("Table walker service (enqueue to completion) latency")
225810621SCurtis.Dunham@arm.com        .flags(Stats::pdf | Stats::nozero | Stats::nonan)
225910621SCurtis.Dunham@arm.com        ;
226010621SCurtis.Dunham@arm.com
226110621SCurtis.Dunham@arm.com    statPendingWalks
226210621SCurtis.Dunham@arm.com        .init(16)
226310621SCurtis.Dunham@arm.com        .name(name() + ".walksPending")
226410621SCurtis.Dunham@arm.com        .desc("Table walker pending requests distribution")
226510621SCurtis.Dunham@arm.com        .flags(Stats::pdf | Stats::dist | Stats::nozero | Stats::nonan)
226610621SCurtis.Dunham@arm.com        ;
226710621SCurtis.Dunham@arm.com
226810621SCurtis.Dunham@arm.com    statPageSizes // see DDI 0487A D4-1661
226910621SCurtis.Dunham@arm.com        .init(9)
227010621SCurtis.Dunham@arm.com        .name(name() + ".walkPageSizes")
227110621SCurtis.Dunham@arm.com        .desc("Table walker page sizes translated")
227210621SCurtis.Dunham@arm.com        .flags(Stats::total | Stats::pdf | Stats::dist | Stats::nozero)
227310621SCurtis.Dunham@arm.com        ;
227410621SCurtis.Dunham@arm.com    statPageSizes.subname(0, "4K");
227510621SCurtis.Dunham@arm.com    statPageSizes.subname(1, "16K");
227610621SCurtis.Dunham@arm.com    statPageSizes.subname(2, "64K");
227710621SCurtis.Dunham@arm.com    statPageSizes.subname(3, "1M");
227810621SCurtis.Dunham@arm.com    statPageSizes.subname(4, "2M");
227910621SCurtis.Dunham@arm.com    statPageSizes.subname(5, "16M");
228010621SCurtis.Dunham@arm.com    statPageSizes.subname(6, "32M");
228110621SCurtis.Dunham@arm.com    statPageSizes.subname(7, "512M");
228210621SCurtis.Dunham@arm.com    statPageSizes.subname(8, "1G");
228310621SCurtis.Dunham@arm.com
228410621SCurtis.Dunham@arm.com    statRequestOrigin
228510621SCurtis.Dunham@arm.com        .init(2,2) // Instruction/Data, requests/completed
228610621SCurtis.Dunham@arm.com        .name(name() + ".walkRequestOrigin")
228710621SCurtis.Dunham@arm.com        .desc("Table walker requests started/completed, data/inst")
228810621SCurtis.Dunham@arm.com        .flags(Stats::total)
228910621SCurtis.Dunham@arm.com        ;
229010621SCurtis.Dunham@arm.com    statRequestOrigin.subname(0,"Requested");
229110621SCurtis.Dunham@arm.com    statRequestOrigin.subname(1,"Completed");
229210621SCurtis.Dunham@arm.com    statRequestOrigin.ysubname(0,"Data");
229310621SCurtis.Dunham@arm.com    statRequestOrigin.ysubname(1,"Inst");
229410621SCurtis.Dunham@arm.com}
2295