table_walker.cc revision 10509
17404SAli.Saidi@ARM.com/*
210324SCurtis.Dunham@arm.com * Copyright (c) 2010, 2012-2014 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 */
407404SAli.Saidi@ARM.com
4110474Sandreas.hansson@arm.com#include <memory>
4210474Sandreas.hansson@arm.com
437404SAli.Saidi@ARM.com#include "arch/arm/faults.hh"
4410037SARM gem5 Developers#include "arch/arm/stage2_mmu.hh"
4510037SARM gem5 Developers#include "arch/arm/system.hh"
467404SAli.Saidi@ARM.com#include "arch/arm/table_walker.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"
547748SAli.Saidi@ARM.com#include "sim/system.hh"
557404SAli.Saidi@ARM.com
567404SAli.Saidi@ARM.comusing namespace ArmISA;
577404SAli.Saidi@ARM.com
587404SAli.Saidi@ARM.comTableWalker::TableWalker(const Params *p)
5910037SARM gem5 Developers    : MemObject(p), port(this, p->sys), drainManager(NULL),
6010037SARM gem5 Developers      stage2Mmu(NULL), isStage2(p->is_stage2), tlb(NULL),
6110037SARM gem5 Developers      currState(NULL), pending(false), masterId(p->sys->getMasterId(name())),
629258SAli.Saidi@ARM.com      numSquashable(p->num_squash_per_cycle),
6310037SARM gem5 Developers      doL1DescEvent(this), doL2DescEvent(this),
6410037SARM gem5 Developers      doL0LongDescEvent(this), doL1LongDescEvent(this), doL2LongDescEvent(this),
6510037SARM gem5 Developers      doL3LongDescEvent(this),
6610037SARM gem5 Developers      doProcessEvent(this)
677439Sdam.sunwoo@arm.com{
687576SAli.Saidi@ARM.com    sctlr = 0;
6910037SARM gem5 Developers
7010037SARM gem5 Developers    // Cache system-level properties
7110037SARM gem5 Developers    if (FullSystem) {
7210037SARM gem5 Developers        armSys = dynamic_cast<ArmSystem *>(p->sys);
7310037SARM gem5 Developers        assert(armSys);
7410037SARM gem5 Developers        haveSecurity = armSys->haveSecurity();
7510037SARM gem5 Developers        _haveLPAE = armSys->haveLPAE();
7610037SARM gem5 Developers        _haveVirtualization = armSys->haveVirtualization();
7710037SARM gem5 Developers        physAddrRange = armSys->physAddrRange();
7810037SARM gem5 Developers        _haveLargeAsid64 = armSys->haveLargeAsid64();
7910037SARM gem5 Developers    } else {
8010037SARM gem5 Developers        armSys = NULL;
8110037SARM gem5 Developers        haveSecurity = _haveLPAE = _haveVirtualization = false;
8210037SARM gem5 Developers        _haveLargeAsid64 = false;
8310037SARM gem5 Developers        physAddrRange = 32;
8410037SARM gem5 Developers    }
8510037SARM gem5 Developers
867439Sdam.sunwoo@arm.com}
877404SAli.Saidi@ARM.com
887404SAli.Saidi@ARM.comTableWalker::~TableWalker()
897404SAli.Saidi@ARM.com{
907404SAli.Saidi@ARM.com    ;
917404SAli.Saidi@ARM.com}
927404SAli.Saidi@ARM.com
9310037SARM gem5 DevelopersTableWalker::WalkerState::WalkerState() : stage2Tran(NULL), l2Desc(l1Desc)
9410037SARM gem5 Developers{
9510037SARM gem5 Developers}
9610037SARM gem5 Developers
979152Satgutier@umich.eduvoid
989152Satgutier@umich.eduTableWalker::completeDrain()
999152Satgutier@umich.edu{
10010037SARM gem5 Developers    if (drainManager && stateQueues[L1].empty() && stateQueues[L2].empty() &&
1019152Satgutier@umich.edu        pendingQueue.empty()) {
1029342SAndreas.Sandberg@arm.com        setDrainState(Drainable::Drained);
1039152Satgutier@umich.edu        DPRINTF(Drain, "TableWalker done draining, processing drain event\n");
1049342SAndreas.Sandberg@arm.com        drainManager->signalDrainDone();
1059342SAndreas.Sandberg@arm.com        drainManager = NULL;
1069152Satgutier@umich.edu    }
1079152Satgutier@umich.edu}
1089152Satgutier@umich.edu
1097748SAli.Saidi@ARM.comunsigned int
1109342SAndreas.Sandberg@arm.comTableWalker::drain(DrainManager *dm)
1117404SAli.Saidi@ARM.com{
1129342SAndreas.Sandberg@arm.com    unsigned int count = port.drain(dm);
1139152Satgutier@umich.edu
11410037SARM gem5 Developers    bool state_queues_not_empty = false;
1159152Satgutier@umich.edu
11610037SARM gem5 Developers    for (int i = 0; i < MAX_LOOKUP_LEVELS; ++i) {
11710037SARM gem5 Developers        if (!stateQueues[i].empty()) {
11810037SARM gem5 Developers            state_queues_not_empty = true;
11910037SARM gem5 Developers            break;
12010037SARM gem5 Developers        }
12110037SARM gem5 Developers    }
12210037SARM gem5 Developers
12310037SARM gem5 Developers    if (state_queues_not_empty || pendingQueue.size()) {
1249342SAndreas.Sandberg@arm.com        drainManager = dm;
1259342SAndreas.Sandberg@arm.com        setDrainState(Drainable::Draining);
1269152Satgutier@umich.edu        DPRINTF(Drain, "TableWalker not drained\n");
1279152Satgutier@umich.edu
1289152Satgutier@umich.edu        // return port drain count plus the table walker itself needs to drain
1299152Satgutier@umich.edu        return count + 1;
13010037SARM gem5 Developers    } else {
13110037SARM gem5 Developers        setDrainState(Drainable::Drained);
13210037SARM gem5 Developers        DPRINTF(Drain, "TableWalker free, no need to drain\n");
1339152Satgutier@umich.edu
13410037SARM gem5 Developers        // table walker is drained, but its ports may still need to be drained
13510037SARM gem5 Developers        return count;
1367733SAli.Saidi@ARM.com    }
1377404SAli.Saidi@ARM.com}
1387404SAli.Saidi@ARM.com
1397748SAli.Saidi@ARM.comvoid
1409342SAndreas.Sandberg@arm.comTableWalker::drainResume()
1417748SAli.Saidi@ARM.com{
1429342SAndreas.Sandberg@arm.com    Drainable::drainResume();
1439524SAndreas.Sandberg@ARM.com    if (params()->sys->isTimingMode() && currState) {
1449152Satgutier@umich.edu        delete currState;
1459152Satgutier@umich.edu        currState = NULL;
1467748SAli.Saidi@ARM.com    }
1477748SAli.Saidi@ARM.com}
1487748SAli.Saidi@ARM.com
1499294Sandreas.hansson@arm.comBaseMasterPort&
1509294Sandreas.hansson@arm.comTableWalker::getMasterPort(const std::string &if_name, PortID idx)
1517404SAli.Saidi@ARM.com{
1527404SAli.Saidi@ARM.com    if (if_name == "port") {
1538922Swilliam.wang@arm.com        return port;
1547404SAli.Saidi@ARM.com    }
1558922Swilliam.wang@arm.com    return MemObject::getMasterPort(if_name, idx);
1567404SAli.Saidi@ARM.com}
1577404SAli.Saidi@ARM.com
1587404SAli.Saidi@ARM.comFault
15910037SARM gem5 DevelopersTableWalker::walk(RequestPtr _req, ThreadContext *_tc, uint16_t _asid,
16010037SARM gem5 Developers                  uint8_t _vmid, bool _isHyp, TLB::Mode _mode,
16110037SARM gem5 Developers                  TLB::Translation *_trans, bool _timing, bool _functional,
16210037SARM gem5 Developers                  bool secure, TLB::ArmTranslationType tranType)
1637404SAli.Saidi@ARM.com{
1648733Sgeoffrey.blake@arm.com    assert(!(_functional && _timing));
16510109SGeoffrey.Blake@arm.com    WalkerState *savedCurrState = NULL;
16610037SARM gem5 Developers
16710109SGeoffrey.Blake@arm.com    if (!currState && !_functional) {
1687439Sdam.sunwoo@arm.com        // For atomic mode, a new WalkerState instance should be only created
1697439Sdam.sunwoo@arm.com        // once per TLB. For timing mode, a new instance is generated for every
1707439Sdam.sunwoo@arm.com        // TLB miss.
1717439Sdam.sunwoo@arm.com        DPRINTF(TLBVerbose, "creating new instance of WalkerState\n");
1727404SAli.Saidi@ARM.com
1737439Sdam.sunwoo@arm.com        currState = new WalkerState();
1747439Sdam.sunwoo@arm.com        currState->tableWalker = this;
17510109SGeoffrey.Blake@arm.com    } else if (_functional) {
17610109SGeoffrey.Blake@arm.com        // If we are mixing functional mode with timing (or even
17710109SGeoffrey.Blake@arm.com        // atomic), we need to to be careful and clean up after
17810109SGeoffrey.Blake@arm.com        // ourselves to not risk getting into an inconsistent state.
17910109SGeoffrey.Blake@arm.com        DPRINTF(TLBVerbose, "creating functional instance of WalkerState\n");
18010109SGeoffrey.Blake@arm.com        savedCurrState = currState;
18110109SGeoffrey.Blake@arm.com        currState = new WalkerState();
18210109SGeoffrey.Blake@arm.com        currState->tableWalker = this;
1838202SAli.Saidi@ARM.com    } else if (_timing) {
1848202SAli.Saidi@ARM.com        // This is a translation that was completed and then faulted again
1858202SAli.Saidi@ARM.com        // because some underlying parameters that affect the translation
1868202SAli.Saidi@ARM.com        // changed out from under us (e.g. asid). It will either be a
1878202SAli.Saidi@ARM.com        // misprediction, in which case nothing will happen or we'll use
1888202SAli.Saidi@ARM.com        // this fault to re-execute the faulting instruction which should clean
1898202SAli.Saidi@ARM.com        // up everything.
19010037SARM gem5 Developers        if (currState->vaddr_tainted == _req->getVaddr()) {
19110474Sandreas.hansson@arm.com            return std::make_shared<ReExec>();
1928202SAli.Saidi@ARM.com        }
1937439Sdam.sunwoo@arm.com    }
1947439Sdam.sunwoo@arm.com
1957439Sdam.sunwoo@arm.com    currState->tc = _tc;
19610037SARM gem5 Developers    currState->aarch64 = opModeIs64(currOpMode(_tc));
19710037SARM gem5 Developers    currState->el = currEL(_tc);
1987439Sdam.sunwoo@arm.com    currState->transState = _trans;
1997439Sdam.sunwoo@arm.com    currState->req = _req;
2007439Sdam.sunwoo@arm.com    currState->fault = NoFault;
20110037SARM gem5 Developers    currState->asid = _asid;
20210037SARM gem5 Developers    currState->vmid = _vmid;
20310037SARM gem5 Developers    currState->isHyp = _isHyp;
2047439Sdam.sunwoo@arm.com    currState->timing = _timing;
2058733Sgeoffrey.blake@arm.com    currState->functional = _functional;
2067439Sdam.sunwoo@arm.com    currState->mode = _mode;
20710037SARM gem5 Developers    currState->tranType = tranType;
20810037SARM gem5 Developers    currState->isSecure = secure;
20910037SARM gem5 Developers    currState->physAddrRange = physAddrRange;
2107404SAli.Saidi@ARM.com
2117436Sdam.sunwoo@arm.com    /** @todo These should be cached or grabbed from cached copies in
2127436Sdam.sunwoo@arm.com     the TLB, all these miscreg reads are expensive */
21310037SARM gem5 Developers    currState->vaddr_tainted = currState->req->getVaddr();
21410037SARM gem5 Developers    if (currState->aarch64)
21510037SARM gem5 Developers        currState->vaddr = purifyTaggedAddr(currState->vaddr_tainted,
21610037SARM gem5 Developers                                            currState->tc, currState->el);
21710037SARM gem5 Developers    else
21810037SARM gem5 Developers        currState->vaddr = currState->vaddr_tainted;
21910037SARM gem5 Developers
22010037SARM gem5 Developers    if (currState->aarch64) {
22110037SARM gem5 Developers        switch (currState->el) {
22210037SARM gem5 Developers          case EL0:
22310037SARM gem5 Developers          case EL1:
22410037SARM gem5 Developers            currState->sctlr = currState->tc->readMiscReg(MISCREG_SCTLR_EL1);
22510324SCurtis.Dunham@arm.com            currState->tcr = currState->tc->readMiscReg(MISCREG_TCR_EL1);
22610037SARM gem5 Developers            break;
22710037SARM gem5 Developers          // @todo: uncomment this to enable Virtualization
22810037SARM gem5 Developers          // case EL2:
22910037SARM gem5 Developers          //   assert(haveVirtualization);
23010037SARM gem5 Developers          //   currState->sctlr = currState->tc->readMiscReg(MISCREG_SCTLR_EL2);
23110324SCurtis.Dunham@arm.com          //   currState->tcr = currState->tc->readMiscReg(MISCREG_TCR_EL2);
23210037SARM gem5 Developers          //   break;
23310037SARM gem5 Developers          case EL3:
23410037SARM gem5 Developers            assert(haveSecurity);
23510037SARM gem5 Developers            currState->sctlr = currState->tc->readMiscReg(MISCREG_SCTLR_EL3);
23610324SCurtis.Dunham@arm.com            currState->tcr = currState->tc->readMiscReg(MISCREG_TCR_EL3);
23710037SARM gem5 Developers            break;
23810037SARM gem5 Developers          default:
23910037SARM gem5 Developers            panic("Invalid exception level");
24010037SARM gem5 Developers            break;
24110037SARM gem5 Developers        }
24210037SARM gem5 Developers    } else {
24310037SARM gem5 Developers        currState->sctlr = currState->tc->readMiscReg(flattenMiscRegNsBanked(
24410037SARM gem5 Developers            MISCREG_SCTLR, currState->tc, !currState->isSecure));
24510037SARM gem5 Developers        currState->ttbcr = currState->tc->readMiscReg(flattenMiscRegNsBanked(
24610037SARM gem5 Developers            MISCREG_TTBCR, currState->tc, !currState->isSecure));
24710037SARM gem5 Developers        currState->htcr  = currState->tc->readMiscReg(MISCREG_HTCR);
24810037SARM gem5 Developers        currState->hcr   = currState->tc->readMiscReg(MISCREG_HCR);
24910037SARM gem5 Developers        currState->vtcr  = currState->tc->readMiscReg(MISCREG_VTCR);
25010037SARM gem5 Developers    }
2517439Sdam.sunwoo@arm.com    sctlr = currState->sctlr;
2527439Sdam.sunwoo@arm.com
2537439Sdam.sunwoo@arm.com    currState->isFetch = (currState->mode == TLB::Execute);
2547439Sdam.sunwoo@arm.com    currState->isWrite = (currState->mode == TLB::Write);
2557439Sdam.sunwoo@arm.com
25610037SARM gem5 Developers    // We only do a second stage of translation if we're not secure, or in
25710037SARM gem5 Developers    // hyp mode, the second stage MMU is enabled, and this table walker
25810037SARM gem5 Developers    // instance is the first stage.
25910037SARM gem5 Developers    currState->doingStage2 = false;
26010037SARM gem5 Developers    // @todo: for now disable this in AArch64 (HCR is not set)
26110037SARM gem5 Developers    currState->stage2Req = !currState->aarch64 && currState->hcr.vm &&
26210037SARM gem5 Developers                           !isStage2 && !currState->isSecure && !currState->isHyp;
2637728SAli.Saidi@ARM.com
26410037SARM gem5 Developers    bool long_desc_format = currState->aarch64 ||
26510037SARM gem5 Developers                            (_haveLPAE && currState->ttbcr.eae) ||
26610037SARM gem5 Developers                            _isHyp || isStage2;
26710037SARM gem5 Developers
26810037SARM gem5 Developers    if (long_desc_format) {
26910037SARM gem5 Developers        // Helper variables used for hierarchical permissions
27010037SARM gem5 Developers        currState->secureLookup = currState->isSecure;
27110037SARM gem5 Developers        currState->rwTable = true;
27210037SARM gem5 Developers        currState->userTable = true;
27310037SARM gem5 Developers        currState->xnTable = false;
27410037SARM gem5 Developers        currState->pxnTable = false;
27510037SARM gem5 Developers    }
27610037SARM gem5 Developers
27710037SARM gem5 Developers    if (!currState->timing) {
27810109SGeoffrey.Blake@arm.com        Fault fault = NoFault;
27910037SARM gem5 Developers        if (currState->aarch64)
28010109SGeoffrey.Blake@arm.com            fault = processWalkAArch64();
28110037SARM gem5 Developers        else if (long_desc_format)
28210109SGeoffrey.Blake@arm.com            fault = processWalkLPAE();
28310037SARM gem5 Developers        else
28410109SGeoffrey.Blake@arm.com            fault = processWalk();
28510109SGeoffrey.Blake@arm.com
28610109SGeoffrey.Blake@arm.com        // If this was a functional non-timing access restore state to
28710109SGeoffrey.Blake@arm.com        // how we found it.
28810109SGeoffrey.Blake@arm.com        if (currState->functional) {
28910109SGeoffrey.Blake@arm.com            delete currState;
29010109SGeoffrey.Blake@arm.com            currState = savedCurrState;
29110109SGeoffrey.Blake@arm.com        }
29210109SGeoffrey.Blake@arm.com        return fault;
29310037SARM gem5 Developers    }
2947728SAli.Saidi@ARM.com
2958067SAli.Saidi@ARM.com    if (pending || pendingQueue.size()) {
2967728SAli.Saidi@ARM.com        pendingQueue.push_back(currState);
2977728SAli.Saidi@ARM.com        currState = NULL;
2987728SAli.Saidi@ARM.com    } else {
2997728SAli.Saidi@ARM.com        pending = true;
30010037SARM gem5 Developers        if (currState->aarch64)
30110037SARM gem5 Developers            return processWalkAArch64();
30210037SARM gem5 Developers        else if (long_desc_format)
30310037SARM gem5 Developers            return processWalkLPAE();
30410037SARM gem5 Developers        else
30510037SARM gem5 Developers            return processWalk();
3067728SAli.Saidi@ARM.com    }
3077728SAli.Saidi@ARM.com
3087728SAli.Saidi@ARM.com    return NoFault;
3097728SAli.Saidi@ARM.com}
3107728SAli.Saidi@ARM.com
3117728SAli.Saidi@ARM.comvoid
3127728SAli.Saidi@ARM.comTableWalker::processWalkWrapper()
3137728SAli.Saidi@ARM.com{
3147728SAli.Saidi@ARM.com    assert(!currState);
3157728SAli.Saidi@ARM.com    assert(pendingQueue.size());
3167728SAli.Saidi@ARM.com    currState = pendingQueue.front();
3179258SAli.Saidi@ARM.com
31810037SARM gem5 Developers    ExceptionLevel target_el = EL0;
31910037SARM gem5 Developers    if (currState->aarch64)
32010037SARM gem5 Developers        target_el = currEL(currState->tc);
32110037SARM gem5 Developers    else
32210037SARM gem5 Developers        target_el = EL1;
32310037SARM gem5 Developers
3249535Smrinmoy.ghosh@arm.com    // Check if a previous walk filled this request already
32510037SARM gem5 Developers    // @TODO Should this always be the TLB or should we look in the stage2 TLB?
32610037SARM gem5 Developers    TlbEntry* te = tlb->lookup(currState->vaddr, currState->asid,
32710037SARM gem5 Developers            currState->vmid, currState->isHyp, currState->isSecure, true, false,
32810037SARM gem5 Developers            target_el);
3299258SAli.Saidi@ARM.com
3309535Smrinmoy.ghosh@arm.com    // Check if we still need to have a walk for this request. If the requesting
3319535Smrinmoy.ghosh@arm.com    // instruction has been squashed, or a previous walk has filled the TLB with
3329535Smrinmoy.ghosh@arm.com    // a match, we just want to get rid of the walk. The latter could happen
3339535Smrinmoy.ghosh@arm.com    // when there are multiple outstanding misses to a single page and a
3349535Smrinmoy.ghosh@arm.com    // previous request has been successfully translated.
3359535Smrinmoy.ghosh@arm.com    if (!currState->transState->squashed() && !te) {
3369258SAli.Saidi@ARM.com        // We've got a valid request, lets process it
3379258SAli.Saidi@ARM.com        pending = true;
3389258SAli.Saidi@ARM.com        pendingQueue.pop_front();
33910037SARM gem5 Developers        if (currState->aarch64)
34010037SARM gem5 Developers            processWalkAArch64();
34110037SARM gem5 Developers        else if ((_haveLPAE && currState->ttbcr.eae) || currState->isHyp || isStage2)
34210037SARM gem5 Developers            processWalkLPAE();
34310037SARM gem5 Developers        else
34410037SARM gem5 Developers            processWalk();
3459258SAli.Saidi@ARM.com        return;
3469258SAli.Saidi@ARM.com    }
3479258SAli.Saidi@ARM.com
3489258SAli.Saidi@ARM.com
3499258SAli.Saidi@ARM.com    // If the instruction that we were translating for has been
3509258SAli.Saidi@ARM.com    // squashed we shouldn't bother.
3519258SAli.Saidi@ARM.com    unsigned num_squashed = 0;
3529258SAli.Saidi@ARM.com    ThreadContext *tc = currState->tc;
3539258SAli.Saidi@ARM.com    while ((num_squashed < numSquashable) && currState &&
3549535Smrinmoy.ghosh@arm.com           (currState->transState->squashed() || te)) {
3559258SAli.Saidi@ARM.com        pendingQueue.pop_front();
3569258SAli.Saidi@ARM.com        num_squashed++;
3579258SAli.Saidi@ARM.com
35810037SARM gem5 Developers        DPRINTF(TLB, "Squashing table walk for address %#x\n",
35910037SARM gem5 Developers                      currState->vaddr_tainted);
3609258SAli.Saidi@ARM.com
3619535Smrinmoy.ghosh@arm.com        if (currState->transState->squashed()) {
3629535Smrinmoy.ghosh@arm.com            // finish the translation which will delete the translation object
36310474Sandreas.hansson@arm.com            currState->transState->finish(
36410474Sandreas.hansson@arm.com                std::make_shared<UnimpFault>("Squashed Inst"),
36510474Sandreas.hansson@arm.com                currState->req, currState->tc, currState->mode);
3669535Smrinmoy.ghosh@arm.com        } else {
3679535Smrinmoy.ghosh@arm.com            // translate the request now that we know it will work
36810037SARM gem5 Developers            tlb->translateTiming(currState->req, currState->tc,
36910037SARM gem5 Developers                        currState->transState, currState->mode);
37010037SARM gem5 Developers
3719535Smrinmoy.ghosh@arm.com        }
3729258SAli.Saidi@ARM.com
3739258SAli.Saidi@ARM.com        // delete the current request
3749258SAli.Saidi@ARM.com        delete currState;
3759258SAli.Saidi@ARM.com
3769258SAli.Saidi@ARM.com        // peak at the next one
3779535Smrinmoy.ghosh@arm.com        if (pendingQueue.size()) {
3789258SAli.Saidi@ARM.com            currState = pendingQueue.front();
37910037SARM gem5 Developers            te = tlb->lookup(currState->vaddr, currState->asid,
38010037SARM gem5 Developers                currState->vmid, currState->isHyp, currState->isSecure, true,
38110037SARM gem5 Developers                false, target_el);
3829535Smrinmoy.ghosh@arm.com        } else {
3839535Smrinmoy.ghosh@arm.com            // Terminate the loop, nothing more to do
3849258SAli.Saidi@ARM.com            currState = NULL;
3859535Smrinmoy.ghosh@arm.com        }
3869258SAli.Saidi@ARM.com    }
3879258SAli.Saidi@ARM.com
3889258SAli.Saidi@ARM.com    // if we've still got pending translations schedule more work
3899258SAli.Saidi@ARM.com    nextWalk(tc);
3909258SAli.Saidi@ARM.com    currState = NULL;
3917728SAli.Saidi@ARM.com}
3927728SAli.Saidi@ARM.com
3937728SAli.Saidi@ARM.comFault
3947728SAli.Saidi@ARM.comTableWalker::processWalk()
3957728SAli.Saidi@ARM.com{
3967404SAli.Saidi@ARM.com    Addr ttbr = 0;
3977404SAli.Saidi@ARM.com
3987404SAli.Saidi@ARM.com    // If translation isn't enabled, we shouldn't be here
39910037SARM gem5 Developers    assert(currState->sctlr.m || isStage2);
4007404SAli.Saidi@ARM.com
40110037SARM gem5 Developers    DPRINTF(TLB, "Beginning table walk for address %#x, TTBCR: %#x, bits:%#x\n",
40210037SARM gem5 Developers            currState->vaddr_tainted, currState->ttbcr, mbits(currState->vaddr, 31,
40310037SARM gem5 Developers                                                      32 - currState->ttbcr.n));
4047406SAli.Saidi@ARM.com
40510037SARM gem5 Developers    if (currState->ttbcr.n == 0 || !mbits(currState->vaddr, 31,
40610037SARM gem5 Developers                                          32 - currState->ttbcr.n)) {
4077406SAli.Saidi@ARM.com        DPRINTF(TLB, " - Selecting TTBR0\n");
40810037SARM gem5 Developers        // Check if table walk is allowed when Security Extensions are enabled
40910037SARM gem5 Developers        if (haveSecurity && currState->ttbcr.pd0) {
41010037SARM gem5 Developers            if (currState->isFetch)
41110474Sandreas.hansson@arm.com                return std::make_shared<PrefetchAbort>(
41210474Sandreas.hansson@arm.com                    currState->vaddr_tainted,
41310474Sandreas.hansson@arm.com                    ArmFault::TranslationLL + L1,
41410474Sandreas.hansson@arm.com                    isStage2,
41510474Sandreas.hansson@arm.com                    ArmFault::VmsaTran);
41610037SARM gem5 Developers            else
41710474Sandreas.hansson@arm.com                return std::make_shared<DataAbort>(
41810474Sandreas.hansson@arm.com                    currState->vaddr_tainted,
41910474Sandreas.hansson@arm.com                    TlbEntry::DomainType::NoAccess, currState->isWrite,
42010474Sandreas.hansson@arm.com                    ArmFault::TranslationLL + L1, isStage2,
42110474Sandreas.hansson@arm.com                    ArmFault::VmsaTran);
42210037SARM gem5 Developers        }
42310037SARM gem5 Developers        ttbr = currState->tc->readMiscReg(flattenMiscRegNsBanked(
42410037SARM gem5 Developers            MISCREG_TTBR0, currState->tc, !currState->isSecure));
4257404SAli.Saidi@ARM.com    } else {
4267406SAli.Saidi@ARM.com        DPRINTF(TLB, " - Selecting TTBR1\n");
42710037SARM gem5 Developers        // Check if table walk is allowed when Security Extensions are enabled
42810037SARM gem5 Developers        if (haveSecurity && currState->ttbcr.pd1) {
42910037SARM gem5 Developers            if (currState->isFetch)
43010474Sandreas.hansson@arm.com                return std::make_shared<PrefetchAbort>(
43110474Sandreas.hansson@arm.com                    currState->vaddr_tainted,
43210474Sandreas.hansson@arm.com                    ArmFault::TranslationLL + L1,
43310474Sandreas.hansson@arm.com                    isStage2,
43410474Sandreas.hansson@arm.com                    ArmFault::VmsaTran);
43510037SARM gem5 Developers            else
43610474Sandreas.hansson@arm.com                return std::make_shared<DataAbort>(
43710474Sandreas.hansson@arm.com                    currState->vaddr_tainted,
43810474Sandreas.hansson@arm.com                    TlbEntry::DomainType::NoAccess, currState->isWrite,
43910474Sandreas.hansson@arm.com                    ArmFault::TranslationLL + L1, isStage2,
44010474Sandreas.hansson@arm.com                    ArmFault::VmsaTran);
44110037SARM gem5 Developers        }
44210037SARM gem5 Developers        ttbr = currState->tc->readMiscReg(flattenMiscRegNsBanked(
44310037SARM gem5 Developers            MISCREG_TTBR1, currState->tc, !currState->isSecure));
44410037SARM gem5 Developers        currState->ttbcr.n = 0;
4457404SAli.Saidi@ARM.com    }
4467404SAli.Saidi@ARM.com
44710037SARM gem5 Developers    Addr l1desc_addr = mbits(ttbr, 31, 14 - currState->ttbcr.n) |
44810037SARM gem5 Developers        (bits(currState->vaddr, 31 - currState->ttbcr.n, 20) << 2);
44910037SARM gem5 Developers    DPRINTF(TLB, " - Descriptor at address %#x (%s)\n", l1desc_addr,
45010037SARM gem5 Developers            currState->isSecure ? "s" : "ns");
4517404SAli.Saidi@ARM.com
4527404SAli.Saidi@ARM.com    // Trickbox address check
4537439Sdam.sunwoo@arm.com    Fault f;
45410037SARM gem5 Developers    f = tlb->walkTrickBoxCheck(l1desc_addr, currState->isSecure,
45510037SARM gem5 Developers            currState->vaddr, sizeof(uint32_t), currState->isFetch,
45610037SARM gem5 Developers            currState->isWrite, TlbEntry::DomainType::NoAccess, L1);
4577439Sdam.sunwoo@arm.com    if (f) {
45810037SARM gem5 Developers        DPRINTF(TLB, "Trickbox check caused fault on %#x\n", currState->vaddr_tainted);
4597579Sminkyu.jeong@arm.com        if (currState->timing) {
4607728SAli.Saidi@ARM.com            pending = false;
4617728SAli.Saidi@ARM.com            nextWalk(currState->tc);
4627579Sminkyu.jeong@arm.com            currState = NULL;
4637579Sminkyu.jeong@arm.com        } else {
4647579Sminkyu.jeong@arm.com            currState->tc = NULL;
4657579Sminkyu.jeong@arm.com            currState->req = NULL;
4667579Sminkyu.jeong@arm.com        }
4677579Sminkyu.jeong@arm.com        return f;
4687404SAli.Saidi@ARM.com    }
4697404SAli.Saidi@ARM.com
4707946SGiacomo.Gabrielli@arm.com    Request::Flags flag = 0;
4717946SGiacomo.Gabrielli@arm.com    if (currState->sctlr.c == 0) {
4727946SGiacomo.Gabrielli@arm.com        flag = Request::UNCACHEABLE;
4737946SGiacomo.Gabrielli@arm.com    }
4747946SGiacomo.Gabrielli@arm.com
47510037SARM gem5 Developers    bool delayed;
47610037SARM gem5 Developers    delayed = fetchDescriptor(l1desc_addr, (uint8_t*)&currState->l1Desc.data,
47710037SARM gem5 Developers                              sizeof(uint32_t), flag, L1, &doL1DescEvent,
47810037SARM gem5 Developers                              &TableWalker::doL1Descriptor);
47910037SARM gem5 Developers    if (!delayed) {
48010037SARM gem5 Developers       f = currState->fault;
48110037SARM gem5 Developers    }
48210037SARM gem5 Developers
48310037SARM gem5 Developers    return f;
48410037SARM gem5 Developers}
48510037SARM gem5 Developers
48610037SARM gem5 DevelopersFault
48710037SARM gem5 DevelopersTableWalker::processWalkLPAE()
48810037SARM gem5 Developers{
48910037SARM gem5 Developers    Addr ttbr, ttbr0_max, ttbr1_min, desc_addr;
49010037SARM gem5 Developers    int tsz, n;
49110037SARM gem5 Developers    LookupLevel start_lookup_level = L1;
49210037SARM gem5 Developers
49310037SARM gem5 Developers    DPRINTF(TLB, "Beginning table walk for address %#x, TTBCR: %#x\n",
49410037SARM gem5 Developers            currState->vaddr_tainted, currState->ttbcr);
49510037SARM gem5 Developers
49610037SARM gem5 Developers    Request::Flags flag = 0;
49710037SARM gem5 Developers    if (currState->isSecure)
49810037SARM gem5 Developers        flag.set(Request::SECURE);
49910037SARM gem5 Developers
50010037SARM gem5 Developers    // work out which base address register to use, if in hyp mode we always
50110037SARM gem5 Developers    // use HTTBR
50210037SARM gem5 Developers    if (isStage2) {
50310037SARM gem5 Developers        DPRINTF(TLB, " - Selecting VTTBR (long-desc.)\n");
50410037SARM gem5 Developers        ttbr = currState->tc->readMiscReg(MISCREG_VTTBR);
50510037SARM gem5 Developers        tsz  = sext<4>(currState->vtcr.t0sz);
50610037SARM gem5 Developers        start_lookup_level = currState->vtcr.sl0 ? L1 : L2;
50710037SARM gem5 Developers    } else if (currState->isHyp) {
50810037SARM gem5 Developers        DPRINTF(TLB, " - Selecting HTTBR (long-desc.)\n");
50910037SARM gem5 Developers        ttbr = currState->tc->readMiscReg(MISCREG_HTTBR);
51010037SARM gem5 Developers        tsz  = currState->htcr.t0sz;
51110037SARM gem5 Developers    } else {
51210037SARM gem5 Developers        assert(_haveLPAE && currState->ttbcr.eae);
51310037SARM gem5 Developers
51410037SARM gem5 Developers        // Determine boundaries of TTBR0/1 regions
51510037SARM gem5 Developers        if (currState->ttbcr.t0sz)
51610037SARM gem5 Developers            ttbr0_max = (1ULL << (32 - currState->ttbcr.t0sz)) - 1;
51710037SARM gem5 Developers        else if (currState->ttbcr.t1sz)
51810037SARM gem5 Developers            ttbr0_max = (1ULL << 32) -
51910037SARM gem5 Developers                (1ULL << (32 - currState->ttbcr.t1sz)) - 1;
52010037SARM gem5 Developers        else
52110037SARM gem5 Developers            ttbr0_max = (1ULL << 32) - 1;
52210037SARM gem5 Developers        if (currState->ttbcr.t1sz)
52310037SARM gem5 Developers            ttbr1_min = (1ULL << 32) - (1ULL << (32 - currState->ttbcr.t1sz));
52410037SARM gem5 Developers        else
52510037SARM gem5 Developers            ttbr1_min = (1ULL << (32 - currState->ttbcr.t0sz));
52610037SARM gem5 Developers
52710037SARM gem5 Developers        // The following code snippet selects the appropriate translation table base
52810037SARM gem5 Developers        // address (TTBR0 or TTBR1) and the appropriate starting lookup level
52910037SARM gem5 Developers        // depending on the address range supported by the translation table (ARM
53010037SARM gem5 Developers        // ARM issue C B3.6.4)
53110037SARM gem5 Developers        if (currState->vaddr <= ttbr0_max) {
53210037SARM gem5 Developers            DPRINTF(TLB, " - Selecting TTBR0 (long-desc.)\n");
53310037SARM gem5 Developers            // Check if table walk is allowed
53410037SARM gem5 Developers            if (currState->ttbcr.epd0) {
53510037SARM gem5 Developers                if (currState->isFetch)
53610474Sandreas.hansson@arm.com                    return std::make_shared<PrefetchAbort>(
53710474Sandreas.hansson@arm.com                        currState->vaddr_tainted,
53810474Sandreas.hansson@arm.com                        ArmFault::TranslationLL + L1,
53910474Sandreas.hansson@arm.com                        isStage2,
54010474Sandreas.hansson@arm.com                        ArmFault::LpaeTran);
54110037SARM gem5 Developers                else
54210474Sandreas.hansson@arm.com                    return std::make_shared<DataAbort>(
54310474Sandreas.hansson@arm.com                        currState->vaddr_tainted,
54410474Sandreas.hansson@arm.com                        TlbEntry::DomainType::NoAccess,
54510474Sandreas.hansson@arm.com                        currState->isWrite,
54610474Sandreas.hansson@arm.com                        ArmFault::TranslationLL + L1,
54710474Sandreas.hansson@arm.com                        isStage2,
54810474Sandreas.hansson@arm.com                        ArmFault::LpaeTran);
54910037SARM gem5 Developers            }
55010037SARM gem5 Developers            ttbr = currState->tc->readMiscReg(flattenMiscRegNsBanked(
55110037SARM gem5 Developers                MISCREG_TTBR0, currState->tc, !currState->isSecure));
55210037SARM gem5 Developers            tsz = currState->ttbcr.t0sz;
55310037SARM gem5 Developers            if (ttbr0_max < (1ULL << 30))  // Upper limit < 1 GB
55410037SARM gem5 Developers                start_lookup_level = L2;
55510037SARM gem5 Developers        } else if (currState->vaddr >= ttbr1_min) {
55610037SARM gem5 Developers            DPRINTF(TLB, " - Selecting TTBR1 (long-desc.)\n");
55710037SARM gem5 Developers            // Check if table walk is allowed
55810037SARM gem5 Developers            if (currState->ttbcr.epd1) {
55910037SARM gem5 Developers                if (currState->isFetch)
56010474Sandreas.hansson@arm.com                    return std::make_shared<PrefetchAbort>(
56110474Sandreas.hansson@arm.com                        currState->vaddr_tainted,
56210474Sandreas.hansson@arm.com                        ArmFault::TranslationLL + L1,
56310474Sandreas.hansson@arm.com                        isStage2,
56410474Sandreas.hansson@arm.com                        ArmFault::LpaeTran);
56510037SARM gem5 Developers                else
56610474Sandreas.hansson@arm.com                    return std::make_shared<DataAbort>(
56710474Sandreas.hansson@arm.com                        currState->vaddr_tainted,
56810474Sandreas.hansson@arm.com                        TlbEntry::DomainType::NoAccess,
56910474Sandreas.hansson@arm.com                        currState->isWrite,
57010474Sandreas.hansson@arm.com                        ArmFault::TranslationLL + L1,
57110474Sandreas.hansson@arm.com                        isStage2,
57210474Sandreas.hansson@arm.com                        ArmFault::LpaeTran);
57310037SARM gem5 Developers            }
57410037SARM gem5 Developers            ttbr = currState->tc->readMiscReg(flattenMiscRegNsBanked(
57510037SARM gem5 Developers                MISCREG_TTBR1, currState->tc, !currState->isSecure));
57610037SARM gem5 Developers            tsz = currState->ttbcr.t1sz;
57710037SARM gem5 Developers            if (ttbr1_min >= (1ULL << 31) + (1ULL << 30))  // Lower limit >= 3 GB
57810037SARM gem5 Developers                start_lookup_level = L2;
57910037SARM gem5 Developers        } else {
58010037SARM gem5 Developers            // Out of boundaries -> translation fault
58110037SARM gem5 Developers            if (currState->isFetch)
58210474Sandreas.hansson@arm.com                return std::make_shared<PrefetchAbort>(
58310474Sandreas.hansson@arm.com                    currState->vaddr_tainted,
58410474Sandreas.hansson@arm.com                    ArmFault::TranslationLL + L1,
58510474Sandreas.hansson@arm.com                    isStage2,
58610474Sandreas.hansson@arm.com                    ArmFault::LpaeTran);
58710037SARM gem5 Developers            else
58810474Sandreas.hansson@arm.com                return std::make_shared<DataAbort>(
58910474Sandreas.hansson@arm.com                    currState->vaddr_tainted,
59010474Sandreas.hansson@arm.com                    TlbEntry::DomainType::NoAccess,
59110474Sandreas.hansson@arm.com                    currState->isWrite, ArmFault::TranslationLL + L1,
59210474Sandreas.hansson@arm.com                    isStage2, ArmFault::LpaeTran);
59310037SARM gem5 Developers        }
59410037SARM gem5 Developers
59510037SARM gem5 Developers    }
59610037SARM gem5 Developers
59710037SARM gem5 Developers    // Perform lookup (ARM ARM issue C B3.6.6)
59810037SARM gem5 Developers    if (start_lookup_level == L1) {
59910037SARM gem5 Developers        n = 5 - tsz;
60010037SARM gem5 Developers        desc_addr = mbits(ttbr, 39, n) |
60110037SARM gem5 Developers            (bits(currState->vaddr, n + 26, 30) << 3);
60210037SARM gem5 Developers        DPRINTF(TLB, " - Descriptor at address %#x (%s) (long-desc.)\n",
60310037SARM gem5 Developers                desc_addr, currState->isSecure ? "s" : "ns");
60410037SARM gem5 Developers    } else {
60510037SARM gem5 Developers        // Skip first-level lookup
60610037SARM gem5 Developers        n = (tsz >= 2 ? 14 - tsz : 12);
60710037SARM gem5 Developers        desc_addr = mbits(ttbr, 39, n) |
60810037SARM gem5 Developers            (bits(currState->vaddr, n + 17, 21) << 3);
60910037SARM gem5 Developers        DPRINTF(TLB, " - Descriptor at address %#x (%s) (long-desc.)\n",
61010037SARM gem5 Developers                desc_addr, currState->isSecure ? "s" : "ns");
61110037SARM gem5 Developers    }
61210037SARM gem5 Developers
61310037SARM gem5 Developers    // Trickbox address check
61410037SARM gem5 Developers    Fault f = tlb->walkTrickBoxCheck(desc_addr, currState->isSecure,
61510037SARM gem5 Developers                        currState->vaddr, sizeof(uint64_t), currState->isFetch,
61610037SARM gem5 Developers                        currState->isWrite, TlbEntry::DomainType::NoAccess,
61710037SARM gem5 Developers                        start_lookup_level);
61810037SARM gem5 Developers    if (f) {
61910037SARM gem5 Developers        DPRINTF(TLB, "Trickbox check caused fault on %#x\n", currState->vaddr_tainted);
62010037SARM gem5 Developers        if (currState->timing) {
62110037SARM gem5 Developers            pending = false;
62210037SARM gem5 Developers            nextWalk(currState->tc);
62310037SARM gem5 Developers            currState = NULL;
62410037SARM gem5 Developers        } else {
62510037SARM gem5 Developers            currState->tc = NULL;
62610037SARM gem5 Developers            currState->req = NULL;
62710037SARM gem5 Developers        }
62810037SARM gem5 Developers        return f;
62910037SARM gem5 Developers    }
63010037SARM gem5 Developers
63110037SARM gem5 Developers    if (currState->sctlr.c == 0) {
63210037SARM gem5 Developers        flag = Request::UNCACHEABLE;
63310037SARM gem5 Developers    }
63410037SARM gem5 Developers
63510037SARM gem5 Developers    if (currState->isSecure)
63610037SARM gem5 Developers        flag.set(Request::SECURE);
63710037SARM gem5 Developers
63810037SARM gem5 Developers    currState->longDesc.lookupLevel = start_lookup_level;
63910037SARM gem5 Developers    currState->longDesc.aarch64 = false;
64010324SCurtis.Dunham@arm.com    currState->longDesc.grainSize = Grain4KB;
64110037SARM gem5 Developers
64210037SARM gem5 Developers    Event *event = start_lookup_level == L1 ? (Event *) &doL1LongDescEvent
64310037SARM gem5 Developers                                            : (Event *) &doL2LongDescEvent;
64410037SARM gem5 Developers
64510037SARM gem5 Developers    bool delayed = fetchDescriptor(desc_addr, (uint8_t*)&currState->longDesc.data,
64610037SARM gem5 Developers                                   sizeof(uint64_t), flag, start_lookup_level,
64710037SARM gem5 Developers                                   event, &TableWalker::doLongDescriptor);
64810037SARM gem5 Developers    if (!delayed) {
64910037SARM gem5 Developers        f = currState->fault;
65010037SARM gem5 Developers    }
65110037SARM gem5 Developers
65210037SARM gem5 Developers    return f;
65310037SARM gem5 Developers}
65410037SARM gem5 Developers
65510037SARM gem5 Developersunsigned
65610037SARM gem5 DevelopersTableWalker::adjustTableSizeAArch64(unsigned tsz)
65710037SARM gem5 Developers{
65810037SARM gem5 Developers    if (tsz < 25)
65910037SARM gem5 Developers        return 25;
66010037SARM gem5 Developers    if (tsz > 48)
66110037SARM gem5 Developers        return 48;
66210037SARM gem5 Developers    return tsz;
66310037SARM gem5 Developers}
66410037SARM gem5 Developers
66510037SARM gem5 Developersbool
66610037SARM gem5 DevelopersTableWalker::checkAddrSizeFaultAArch64(Addr addr, int currPhysAddrRange)
66710037SARM gem5 Developers{
66810037SARM gem5 Developers    return (currPhysAddrRange != MaxPhysAddrRange &&
66910037SARM gem5 Developers            bits(addr, MaxPhysAddrRange - 1, currPhysAddrRange));
67010037SARM gem5 Developers}
67110037SARM gem5 Developers
67210037SARM gem5 DevelopersFault
67310037SARM gem5 DevelopersTableWalker::processWalkAArch64()
67410037SARM gem5 Developers{
67510037SARM gem5 Developers    assert(currState->aarch64);
67610037SARM gem5 Developers
67710324SCurtis.Dunham@arm.com    DPRINTF(TLB, "Beginning table walk for address %#llx, TCR: %#llx\n",
67810324SCurtis.Dunham@arm.com            currState->vaddr_tainted, currState->tcr);
67910324SCurtis.Dunham@arm.com
68010324SCurtis.Dunham@arm.com    static const GrainSize GrainMapDefault[] =
68110324SCurtis.Dunham@arm.com      { Grain4KB, Grain64KB, Grain16KB, ReservedGrain };
68210324SCurtis.Dunham@arm.com    static const GrainSize GrainMap_EL1_tg1[] =
68310324SCurtis.Dunham@arm.com      { ReservedGrain, Grain16KB, Grain4KB, Grain64KB };
68410037SARM gem5 Developers
68510037SARM gem5 Developers    // Determine TTBR, table size, granule size and phys. address range
68610037SARM gem5 Developers    Addr ttbr = 0;
68710037SARM gem5 Developers    int tsz = 0, ps = 0;
68810324SCurtis.Dunham@arm.com    GrainSize tg = Grain4KB; // grain size computed from tg* field
68910037SARM gem5 Developers    bool fault = false;
69010037SARM gem5 Developers    switch (currState->el) {
69110037SARM gem5 Developers      case EL0:
69210037SARM gem5 Developers      case EL1:
69310037SARM gem5 Developers        switch (bits(currState->vaddr, 63,48)) {
69410037SARM gem5 Developers          case 0:
69510037SARM gem5 Developers            DPRINTF(TLB, " - Selecting TTBR0 (AArch64)\n");
69610037SARM gem5 Developers            ttbr = currState->tc->readMiscReg(MISCREG_TTBR0_EL1);
69710324SCurtis.Dunham@arm.com            tsz = adjustTableSizeAArch64(64 - currState->tcr.t0sz);
69810324SCurtis.Dunham@arm.com            tg = GrainMapDefault[currState->tcr.tg0];
69910037SARM gem5 Developers            if (bits(currState->vaddr, 63, tsz) != 0x0 ||
70010324SCurtis.Dunham@arm.com                currState->tcr.epd0)
70110037SARM gem5 Developers              fault = true;
70210037SARM gem5 Developers            break;
70310037SARM gem5 Developers          case 0xffff:
70410037SARM gem5 Developers            DPRINTF(TLB, " - Selecting TTBR1 (AArch64)\n");
70510037SARM gem5 Developers            ttbr = currState->tc->readMiscReg(MISCREG_TTBR1_EL1);
70610324SCurtis.Dunham@arm.com            tsz = adjustTableSizeAArch64(64 - currState->tcr.t1sz);
70710324SCurtis.Dunham@arm.com            tg = GrainMap_EL1_tg1[currState->tcr.tg1];
70810037SARM gem5 Developers            if (bits(currState->vaddr, 63, tsz) != mask(64-tsz) ||
70910324SCurtis.Dunham@arm.com                currState->tcr.epd1)
71010037SARM gem5 Developers              fault = true;
71110037SARM gem5 Developers            break;
71210037SARM gem5 Developers          default:
71310037SARM gem5 Developers            // top two bytes must be all 0s or all 1s, else invalid addr
71410037SARM gem5 Developers            fault = true;
71510037SARM gem5 Developers        }
71610324SCurtis.Dunham@arm.com        ps = currState->tcr.ips;
71710037SARM gem5 Developers        break;
71810037SARM gem5 Developers      case EL2:
71910037SARM gem5 Developers      case EL3:
72010037SARM gem5 Developers        switch(bits(currState->vaddr, 63,48)) {
72110037SARM gem5 Developers            case 0:
72210324SCurtis.Dunham@arm.com                DPRINTF(TLB, " - Selecting TTBR0 (AArch64)\n");
72310324SCurtis.Dunham@arm.com                if (currState->el == EL2)
72410324SCurtis.Dunham@arm.com                    ttbr = currState->tc->readMiscReg(MISCREG_TTBR0_EL2);
72510324SCurtis.Dunham@arm.com                else
72610324SCurtis.Dunham@arm.com                    ttbr = currState->tc->readMiscReg(MISCREG_TTBR0_EL3);
72710324SCurtis.Dunham@arm.com                tsz = adjustTableSizeAArch64(64 - currState->tcr.t0sz);
72810324SCurtis.Dunham@arm.com                tg = GrainMapDefault[currState->tcr.tg0];
72910037SARM gem5 Developers                break;
73010037SARM gem5 Developers            default:
73110037SARM gem5 Developers                // invalid addr if top two bytes are not all 0s
73210324SCurtis.Dunham@arm.com                fault = true;
73310037SARM gem5 Developers        }
73410324SCurtis.Dunham@arm.com        ps = currState->tcr.ips;
73510037SARM gem5 Developers        break;
73610037SARM gem5 Developers    }
73710037SARM gem5 Developers
73810037SARM gem5 Developers    if (fault) {
73910037SARM gem5 Developers        Fault f;
74010037SARM gem5 Developers        if (currState->isFetch)
74110474Sandreas.hansson@arm.com            f =  std::make_shared<PrefetchAbort>(
74210474Sandreas.hansson@arm.com                currState->vaddr_tainted,
74310474Sandreas.hansson@arm.com                ArmFault::TranslationLL + L0, isStage2,
74410474Sandreas.hansson@arm.com                ArmFault::LpaeTran);
74510037SARM gem5 Developers        else
74610474Sandreas.hansson@arm.com            f = std::make_shared<DataAbort>(
74710474Sandreas.hansson@arm.com                currState->vaddr_tainted,
74810474Sandreas.hansson@arm.com                TlbEntry::DomainType::NoAccess,
74910474Sandreas.hansson@arm.com                currState->isWrite,
75010474Sandreas.hansson@arm.com                ArmFault::TranslationLL + L0,
75110474Sandreas.hansson@arm.com                isStage2, ArmFault::LpaeTran);
75210037SARM gem5 Developers
75310037SARM gem5 Developers        if (currState->timing) {
75410037SARM gem5 Developers            pending = false;
75510037SARM gem5 Developers            nextWalk(currState->tc);
75610037SARM gem5 Developers            currState = NULL;
75710037SARM gem5 Developers        } else {
75810037SARM gem5 Developers            currState->tc = NULL;
75910037SARM gem5 Developers            currState->req = NULL;
76010037SARM gem5 Developers        }
76110037SARM gem5 Developers        return f;
76210037SARM gem5 Developers
76310037SARM gem5 Developers    }
76410037SARM gem5 Developers
76510324SCurtis.Dunham@arm.com    if (tg == ReservedGrain) {
76610324SCurtis.Dunham@arm.com        warn_once("Reserved granule size requested; gem5's IMPLEMENTATION "
76710324SCurtis.Dunham@arm.com                  "DEFINED behavior takes this to mean 4KB granules\n");
76810324SCurtis.Dunham@arm.com        tg = Grain4KB;
76910324SCurtis.Dunham@arm.com    }
77010324SCurtis.Dunham@arm.com
77110324SCurtis.Dunham@arm.com    int stride = tg - 3;
77210324SCurtis.Dunham@arm.com    LookupLevel start_lookup_level = MAX_LOOKUP_LEVELS;
77310324SCurtis.Dunham@arm.com
77410037SARM gem5 Developers    // Determine starting lookup level
77510324SCurtis.Dunham@arm.com    // See aarch64/translation/walk in Appendix G: ARMv8 Pseudocode Library
77610324SCurtis.Dunham@arm.com    // in ARM DDI 0487A.  These table values correspond to the cascading tests
77710324SCurtis.Dunham@arm.com    // to compute the lookup level and are of the form
77810324SCurtis.Dunham@arm.com    // (grain_size + N*stride), for N = {1, 2, 3}.
77910324SCurtis.Dunham@arm.com    // A value of 64 will never succeed and a value of 0 will always succeed.
78010324SCurtis.Dunham@arm.com    {
78110324SCurtis.Dunham@arm.com        struct GrainMap {
78210324SCurtis.Dunham@arm.com            GrainSize grain_size;
78310324SCurtis.Dunham@arm.com            unsigned lookup_level_cutoff[MAX_LOOKUP_LEVELS];
78410324SCurtis.Dunham@arm.com        };
78510324SCurtis.Dunham@arm.com        static const GrainMap GM[] = {
78610324SCurtis.Dunham@arm.com            { Grain4KB,  { 39, 30,  0, 0 } },
78710324SCurtis.Dunham@arm.com            { Grain16KB, { 47, 36, 25, 0 } },
78810324SCurtis.Dunham@arm.com            { Grain64KB, { 64, 42, 29, 0 } }
78910324SCurtis.Dunham@arm.com        };
79010324SCurtis.Dunham@arm.com
79110324SCurtis.Dunham@arm.com        const unsigned *lookup = NULL; // points to a lookup_level_cutoff
79210324SCurtis.Dunham@arm.com
79310324SCurtis.Dunham@arm.com        for (unsigned i = 0; i < 3; ++i) { // choose entry of GM[]
79410324SCurtis.Dunham@arm.com            if (tg == GM[i].grain_size) {
79510324SCurtis.Dunham@arm.com                lookup = GM[i].lookup_level_cutoff;
79610324SCurtis.Dunham@arm.com                break;
79710324SCurtis.Dunham@arm.com            }
79810324SCurtis.Dunham@arm.com        }
79910324SCurtis.Dunham@arm.com        assert(lookup);
80010324SCurtis.Dunham@arm.com
80110324SCurtis.Dunham@arm.com        for (int L = L0; L != MAX_LOOKUP_LEVELS; ++L) {
80210324SCurtis.Dunham@arm.com            if (tsz > lookup[L]) {
80310324SCurtis.Dunham@arm.com                start_lookup_level = (LookupLevel) L;
80410324SCurtis.Dunham@arm.com                break;
80510324SCurtis.Dunham@arm.com            }
80610324SCurtis.Dunham@arm.com        }
80710324SCurtis.Dunham@arm.com        panic_if(start_lookup_level == MAX_LOOKUP_LEVELS,
80810324SCurtis.Dunham@arm.com                 "Table walker couldn't find lookup level\n");
80910037SARM gem5 Developers    }
81010037SARM gem5 Developers
81110037SARM gem5 Developers    // Determine table base address
81210324SCurtis.Dunham@arm.com    int base_addr_lo = 3 + tsz - stride * (3 - start_lookup_level) - tg;
81310037SARM gem5 Developers    Addr base_addr = mbits(ttbr, 47, base_addr_lo);
81410037SARM gem5 Developers
81510037SARM gem5 Developers    // Determine physical address size and raise an Address Size Fault if
81610037SARM gem5 Developers    // necessary
81710037SARM gem5 Developers    int pa_range = decodePhysAddrRange64(ps);
81810037SARM gem5 Developers    // Clamp to lower limit
81910037SARM gem5 Developers    if (pa_range > physAddrRange)
82010037SARM gem5 Developers        currState->physAddrRange = physAddrRange;
82110037SARM gem5 Developers    else
82210037SARM gem5 Developers        currState->physAddrRange = pa_range;
82310037SARM gem5 Developers    if (checkAddrSizeFaultAArch64(base_addr, currState->physAddrRange)) {
82410037SARM gem5 Developers        DPRINTF(TLB, "Address size fault before any lookup\n");
82510037SARM gem5 Developers        Fault f;
82610037SARM gem5 Developers        if (currState->isFetch)
82710474Sandreas.hansson@arm.com            f = std::make_shared<PrefetchAbort>(
82810474Sandreas.hansson@arm.com                currState->vaddr_tainted,
82910474Sandreas.hansson@arm.com                ArmFault::AddressSizeLL + start_lookup_level,
83010474Sandreas.hansson@arm.com                isStage2,
83110474Sandreas.hansson@arm.com                ArmFault::LpaeTran);
83210037SARM gem5 Developers        else
83310474Sandreas.hansson@arm.com            f = std::make_shared<DataAbort>(
83410474Sandreas.hansson@arm.com                currState->vaddr_tainted,
83510474Sandreas.hansson@arm.com                TlbEntry::DomainType::NoAccess,
83610474Sandreas.hansson@arm.com                currState->isWrite,
83710474Sandreas.hansson@arm.com                ArmFault::AddressSizeLL + start_lookup_level,
83810474Sandreas.hansson@arm.com                isStage2,
83910474Sandreas.hansson@arm.com                ArmFault::LpaeTran);
84010037SARM gem5 Developers
84110037SARM gem5 Developers
84210037SARM gem5 Developers        if (currState->timing) {
84310037SARM gem5 Developers            pending = false;
84410037SARM gem5 Developers            nextWalk(currState->tc);
84510037SARM gem5 Developers            currState = NULL;
84610037SARM gem5 Developers        } else {
84710037SARM gem5 Developers            currState->tc = NULL;
84810037SARM gem5 Developers            currState->req = NULL;
84910037SARM gem5 Developers        }
85010037SARM gem5 Developers        return f;
85110037SARM gem5 Developers
85210037SARM gem5 Developers   }
85310037SARM gem5 Developers
85410037SARM gem5 Developers    // Determine descriptor address
85510037SARM gem5 Developers    Addr desc_addr = base_addr |
85610037SARM gem5 Developers        (bits(currState->vaddr, tsz - 1,
85710324SCurtis.Dunham@arm.com              stride * (3 - start_lookup_level) + tg) << 3);
85810037SARM gem5 Developers
85910037SARM gem5 Developers    // Trickbox address check
86010037SARM gem5 Developers    Fault f = tlb->walkTrickBoxCheck(desc_addr, currState->isSecure,
86110037SARM gem5 Developers                        currState->vaddr, sizeof(uint64_t), currState->isFetch,
86210037SARM gem5 Developers                        currState->isWrite, TlbEntry::DomainType::NoAccess,
86310037SARM gem5 Developers                        start_lookup_level);
86410037SARM gem5 Developers    if (f) {
86510037SARM gem5 Developers        DPRINTF(TLB, "Trickbox check caused fault on %#x\n", currState->vaddr_tainted);
86610037SARM gem5 Developers        if (currState->timing) {
86710037SARM gem5 Developers            pending = false;
86810037SARM gem5 Developers            nextWalk(currState->tc);
86910037SARM gem5 Developers            currState = NULL;
87010037SARM gem5 Developers        } else {
87110037SARM gem5 Developers            currState->tc = NULL;
87210037SARM gem5 Developers            currState->req = NULL;
87310037SARM gem5 Developers        }
87410037SARM gem5 Developers        return f;
87510037SARM gem5 Developers    }
87610037SARM gem5 Developers
87710037SARM gem5 Developers    Request::Flags flag = 0;
87810037SARM gem5 Developers    if (currState->sctlr.c == 0) {
87910037SARM gem5 Developers        flag = Request::UNCACHEABLE;
88010037SARM gem5 Developers    }
88110037SARM gem5 Developers
88210037SARM gem5 Developers    currState->longDesc.lookupLevel = start_lookup_level;
88310037SARM gem5 Developers    currState->longDesc.aarch64 = true;
88410324SCurtis.Dunham@arm.com    currState->longDesc.grainSize = tg;
88510037SARM gem5 Developers
8867439Sdam.sunwoo@arm.com    if (currState->timing) {
88710037SARM gem5 Developers        Event *event;
88810037SARM gem5 Developers        switch (start_lookup_level) {
88910037SARM gem5 Developers          case L0:
89010037SARM gem5 Developers            event = (Event *) &doL0LongDescEvent;
89110037SARM gem5 Developers            break;
89210037SARM gem5 Developers          case L1:
89310037SARM gem5 Developers            event = (Event *) &doL1LongDescEvent;
89410037SARM gem5 Developers            break;
89510037SARM gem5 Developers          case L2:
89610037SARM gem5 Developers            event = (Event *) &doL2LongDescEvent;
89710037SARM gem5 Developers            break;
89810037SARM gem5 Developers          case L3:
89910037SARM gem5 Developers            event = (Event *) &doL3LongDescEvent;
90010037SARM gem5 Developers            break;
90110037SARM gem5 Developers          default:
90210037SARM gem5 Developers            panic("Invalid table lookup level");
90310037SARM gem5 Developers            break;
90410037SARM gem5 Developers        }
90510037SARM gem5 Developers        port.dmaAction(MemCmd::ReadReq, desc_addr, sizeof(uint64_t), event,
90610037SARM gem5 Developers                       (uint8_t*) &currState->longDesc.data,
9079180Sandreas.hansson@arm.com                       currState->tc->getCpuPtr()->clockPeriod(), flag);
90810037SARM gem5 Developers        DPRINTF(TLBVerbose,
90910037SARM gem5 Developers                "Adding to walker fifo: queue size before adding: %d\n",
91010037SARM gem5 Developers                stateQueues[start_lookup_level].size());
91110037SARM gem5 Developers        stateQueues[start_lookup_level].push_back(currState);
9127439Sdam.sunwoo@arm.com        currState = NULL;
9138733Sgeoffrey.blake@arm.com    } else if (!currState->functional) {
91410037SARM gem5 Developers        port.dmaAction(MemCmd::ReadReq, desc_addr, sizeof(uint64_t),
91510037SARM gem5 Developers                       NULL, (uint8_t*) &currState->longDesc.data,
9169180Sandreas.hansson@arm.com                       currState->tc->getCpuPtr()->clockPeriod(), flag);
91710037SARM gem5 Developers        doLongDescriptor();
9187439Sdam.sunwoo@arm.com        f = currState->fault;
9198733Sgeoffrey.blake@arm.com    } else {
92010037SARM gem5 Developers        RequestPtr req = new Request(desc_addr, sizeof(uint64_t), flag,
92110037SARM gem5 Developers                                     masterId);
9228949Sandreas.hansson@arm.com        PacketPtr pkt = new Packet(req, MemCmd::ReadReq);
92310037SARM gem5 Developers        pkt->dataStatic((uint8_t*) &currState->longDesc.data);
9248851Sandreas.hansson@arm.com        port.sendFunctional(pkt);
92510037SARM gem5 Developers        doLongDescriptor();
9268733Sgeoffrey.blake@arm.com        delete req;
9278733Sgeoffrey.blake@arm.com        delete pkt;
9288733Sgeoffrey.blake@arm.com        f = currState->fault;
9297404SAli.Saidi@ARM.com    }
9307404SAli.Saidi@ARM.com
9317439Sdam.sunwoo@arm.com    return f;
9327404SAli.Saidi@ARM.com}
9337404SAli.Saidi@ARM.com
9347404SAli.Saidi@ARM.comvoid
9357439Sdam.sunwoo@arm.comTableWalker::memAttrs(ThreadContext *tc, TlbEntry &te, SCTLR sctlr,
9367439Sdam.sunwoo@arm.com                      uint8_t texcb, bool s)
9377404SAli.Saidi@ARM.com{
9387439Sdam.sunwoo@arm.com    // Note: tc and sctlr local variables are hiding tc and sctrl class
9397439Sdam.sunwoo@arm.com    // variables
9407436Sdam.sunwoo@arm.com    DPRINTF(TLBVerbose, "memAttrs texcb:%d s:%d\n", texcb, s);
9417436Sdam.sunwoo@arm.com    te.shareable = false; // default value
9427582SAli.Saidi@arm.com    te.nonCacheable = false;
94310037SARM gem5 Developers    te.outerShareable = false;
9447439Sdam.sunwoo@arm.com    if (sctlr.tre == 0 || ((sctlr.tre == 1) && (sctlr.m == 0))) {
9457404SAli.Saidi@ARM.com        switch(texcb) {
9467436Sdam.sunwoo@arm.com          case 0: // Stongly-ordered
9477404SAli.Saidi@ARM.com            te.nonCacheable = true;
94810037SARM gem5 Developers            te.mtype = TlbEntry::MemoryType::StronglyOrdered;
9497436Sdam.sunwoo@arm.com            te.shareable = true;
9507436Sdam.sunwoo@arm.com            te.innerAttrs = 1;
9517436Sdam.sunwoo@arm.com            te.outerAttrs = 0;
9527404SAli.Saidi@ARM.com            break;
9537436Sdam.sunwoo@arm.com          case 1: // Shareable Device
9547436Sdam.sunwoo@arm.com            te.nonCacheable = true;
95510037SARM gem5 Developers            te.mtype = TlbEntry::MemoryType::Device;
9567436Sdam.sunwoo@arm.com            te.shareable = true;
9577436Sdam.sunwoo@arm.com            te.innerAttrs = 3;
9587436Sdam.sunwoo@arm.com            te.outerAttrs = 0;
9597436Sdam.sunwoo@arm.com            break;
9607436Sdam.sunwoo@arm.com          case 2: // Outer and Inner Write-Through, no Write-Allocate
96110037SARM gem5 Developers            te.mtype = TlbEntry::MemoryType::Normal;
9627436Sdam.sunwoo@arm.com            te.shareable = s;
9637436Sdam.sunwoo@arm.com            te.innerAttrs = 6;
9647436Sdam.sunwoo@arm.com            te.outerAttrs = bits(texcb, 1, 0);
9657436Sdam.sunwoo@arm.com            break;
9667436Sdam.sunwoo@arm.com          case 3: // Outer and Inner Write-Back, no Write-Allocate
96710037SARM gem5 Developers            te.mtype = TlbEntry::MemoryType::Normal;
9687436Sdam.sunwoo@arm.com            te.shareable = s;
9697436Sdam.sunwoo@arm.com            te.innerAttrs = 7;
9707436Sdam.sunwoo@arm.com            te.outerAttrs = bits(texcb, 1, 0);
9717436Sdam.sunwoo@arm.com            break;
9727436Sdam.sunwoo@arm.com          case 4: // Outer and Inner Non-cacheable
9737436Sdam.sunwoo@arm.com            te.nonCacheable = true;
97410037SARM gem5 Developers            te.mtype = TlbEntry::MemoryType::Normal;
9757436Sdam.sunwoo@arm.com            te.shareable = s;
9767436Sdam.sunwoo@arm.com            te.innerAttrs = 0;
9777436Sdam.sunwoo@arm.com            te.outerAttrs = bits(texcb, 1, 0);
9787436Sdam.sunwoo@arm.com            break;
9797436Sdam.sunwoo@arm.com          case 5: // Reserved
9807439Sdam.sunwoo@arm.com            panic("Reserved texcb value!\n");
9817436Sdam.sunwoo@arm.com            break;
9827436Sdam.sunwoo@arm.com          case 6: // Implementation Defined
9837439Sdam.sunwoo@arm.com            panic("Implementation-defined texcb value!\n");
9847436Sdam.sunwoo@arm.com            break;
9857436Sdam.sunwoo@arm.com          case 7: // Outer and Inner Write-Back, Write-Allocate
98610037SARM gem5 Developers            te.mtype = TlbEntry::MemoryType::Normal;
9877436Sdam.sunwoo@arm.com            te.shareable = s;
9887436Sdam.sunwoo@arm.com            te.innerAttrs = 5;
9897436Sdam.sunwoo@arm.com            te.outerAttrs = 1;
9907436Sdam.sunwoo@arm.com            break;
9917436Sdam.sunwoo@arm.com          case 8: // Non-shareable Device
9927436Sdam.sunwoo@arm.com            te.nonCacheable = true;
99310037SARM gem5 Developers            te.mtype = TlbEntry::MemoryType::Device;
9947436Sdam.sunwoo@arm.com            te.shareable = false;
9957436Sdam.sunwoo@arm.com            te.innerAttrs = 3;
9967436Sdam.sunwoo@arm.com            te.outerAttrs = 0;
9977436Sdam.sunwoo@arm.com            break;
9987436Sdam.sunwoo@arm.com          case 9 ... 15:  // Reserved
9997439Sdam.sunwoo@arm.com            panic("Reserved texcb value!\n");
10007436Sdam.sunwoo@arm.com            break;
10017436Sdam.sunwoo@arm.com          case 16 ... 31: // Cacheable Memory
100210037SARM gem5 Developers            te.mtype = TlbEntry::MemoryType::Normal;
10037436Sdam.sunwoo@arm.com            te.shareable = s;
10047404SAli.Saidi@ARM.com            if (bits(texcb, 1,0) == 0 || bits(texcb, 3,2) == 0)
10057404SAli.Saidi@ARM.com                te.nonCacheable = true;
10067436Sdam.sunwoo@arm.com            te.innerAttrs = bits(texcb, 1, 0);
10077436Sdam.sunwoo@arm.com            te.outerAttrs = bits(texcb, 3, 2);
10087404SAli.Saidi@ARM.com            break;
10097436Sdam.sunwoo@arm.com          default:
10107436Sdam.sunwoo@arm.com            panic("More than 32 states for 5 bits?\n");
10117404SAli.Saidi@ARM.com        }
10127404SAli.Saidi@ARM.com    } else {
10137438SAli.Saidi@ARM.com        assert(tc);
101410037SARM gem5 Developers        PRRR prrr = tc->readMiscReg(flattenMiscRegNsBanked(MISCREG_PRRR,
101510037SARM gem5 Developers                                    currState->tc, !currState->isSecure));
101610037SARM gem5 Developers        NMRR nmrr = tc->readMiscReg(flattenMiscRegNsBanked(MISCREG_NMRR,
101710037SARM gem5 Developers                                    currState->tc, !currState->isSecure));
10187436Sdam.sunwoo@arm.com        DPRINTF(TLBVerbose, "memAttrs PRRR:%08x NMRR:%08x\n", prrr, nmrr);
10197582SAli.Saidi@arm.com        uint8_t curr_tr = 0, curr_ir = 0, curr_or = 0;
10207404SAli.Saidi@ARM.com        switch(bits(texcb, 2,0)) {
10217404SAli.Saidi@ARM.com          case 0:
10227436Sdam.sunwoo@arm.com            curr_tr = prrr.tr0;
10237436Sdam.sunwoo@arm.com            curr_ir = nmrr.ir0;
10247436Sdam.sunwoo@arm.com            curr_or = nmrr.or0;
102510037SARM gem5 Developers            te.outerShareable = (prrr.nos0 == 0);
10267404SAli.Saidi@ARM.com            break;
10277404SAli.Saidi@ARM.com          case 1:
10287436Sdam.sunwoo@arm.com            curr_tr = prrr.tr1;
10297436Sdam.sunwoo@arm.com            curr_ir = nmrr.ir1;
10307436Sdam.sunwoo@arm.com            curr_or = nmrr.or1;
103110037SARM gem5 Developers            te.outerShareable = (prrr.nos1 == 0);
10327404SAli.Saidi@ARM.com            break;
10337404SAli.Saidi@ARM.com          case 2:
10347436Sdam.sunwoo@arm.com            curr_tr = prrr.tr2;
10357436Sdam.sunwoo@arm.com            curr_ir = nmrr.ir2;
10367436Sdam.sunwoo@arm.com            curr_or = nmrr.or2;
103710037SARM gem5 Developers            te.outerShareable = (prrr.nos2 == 0);
10387404SAli.Saidi@ARM.com            break;
10397404SAli.Saidi@ARM.com          case 3:
10407436Sdam.sunwoo@arm.com            curr_tr = prrr.tr3;
10417436Sdam.sunwoo@arm.com            curr_ir = nmrr.ir3;
10427436Sdam.sunwoo@arm.com            curr_or = nmrr.or3;
104310037SARM gem5 Developers            te.outerShareable = (prrr.nos3 == 0);
10447404SAli.Saidi@ARM.com            break;
10457404SAli.Saidi@ARM.com          case 4:
10467436Sdam.sunwoo@arm.com            curr_tr = prrr.tr4;
10477436Sdam.sunwoo@arm.com            curr_ir = nmrr.ir4;
10487436Sdam.sunwoo@arm.com            curr_or = nmrr.or4;
104910037SARM gem5 Developers            te.outerShareable = (prrr.nos4 == 0);
10507404SAli.Saidi@ARM.com            break;
10517404SAli.Saidi@ARM.com          case 5:
10527436Sdam.sunwoo@arm.com            curr_tr = prrr.tr5;
10537436Sdam.sunwoo@arm.com            curr_ir = nmrr.ir5;
10547436Sdam.sunwoo@arm.com            curr_or = nmrr.or5;
105510037SARM gem5 Developers            te.outerShareable = (prrr.nos5 == 0);
10567404SAli.Saidi@ARM.com            break;
10577404SAli.Saidi@ARM.com          case 6:
10587404SAli.Saidi@ARM.com            panic("Imp defined type\n");
10597404SAli.Saidi@ARM.com          case 7:
10607436Sdam.sunwoo@arm.com            curr_tr = prrr.tr7;
10617436Sdam.sunwoo@arm.com            curr_ir = nmrr.ir7;
10627436Sdam.sunwoo@arm.com            curr_or = nmrr.or7;
106310037SARM gem5 Developers            te.outerShareable = (prrr.nos7 == 0);
10647404SAli.Saidi@ARM.com            break;
10657404SAli.Saidi@ARM.com        }
10667436Sdam.sunwoo@arm.com
10677436Sdam.sunwoo@arm.com        switch(curr_tr) {
10687436Sdam.sunwoo@arm.com          case 0:
10697436Sdam.sunwoo@arm.com            DPRINTF(TLBVerbose, "StronglyOrdered\n");
107010037SARM gem5 Developers            te.mtype = TlbEntry::MemoryType::StronglyOrdered;
10717436Sdam.sunwoo@arm.com            te.nonCacheable = true;
10727436Sdam.sunwoo@arm.com            te.innerAttrs = 1;
10737436Sdam.sunwoo@arm.com            te.outerAttrs = 0;
10747436Sdam.sunwoo@arm.com            te.shareable = true;
10757436Sdam.sunwoo@arm.com            break;
10767436Sdam.sunwoo@arm.com          case 1:
10777436Sdam.sunwoo@arm.com            DPRINTF(TLBVerbose, "Device ds1:%d ds0:%d s:%d\n",
10787436Sdam.sunwoo@arm.com                    prrr.ds1, prrr.ds0, s);
107910037SARM gem5 Developers            te.mtype = TlbEntry::MemoryType::Device;
10807436Sdam.sunwoo@arm.com            te.nonCacheable = true;
10817436Sdam.sunwoo@arm.com            te.innerAttrs = 3;
10827436Sdam.sunwoo@arm.com            te.outerAttrs = 0;
10837436Sdam.sunwoo@arm.com            if (prrr.ds1 && s)
10847436Sdam.sunwoo@arm.com                te.shareable = true;
10857436Sdam.sunwoo@arm.com            if (prrr.ds0 && !s)
10867436Sdam.sunwoo@arm.com                te.shareable = true;
10877436Sdam.sunwoo@arm.com            break;
10887436Sdam.sunwoo@arm.com          case 2:
10897436Sdam.sunwoo@arm.com            DPRINTF(TLBVerbose, "Normal ns1:%d ns0:%d s:%d\n",
10907436Sdam.sunwoo@arm.com                    prrr.ns1, prrr.ns0, s);
109110037SARM gem5 Developers            te.mtype = TlbEntry::MemoryType::Normal;
10927436Sdam.sunwoo@arm.com            if (prrr.ns1 && s)
10937436Sdam.sunwoo@arm.com                te.shareable = true;
10947436Sdam.sunwoo@arm.com            if (prrr.ns0 && !s)
10957436Sdam.sunwoo@arm.com                te.shareable = true;
10967436Sdam.sunwoo@arm.com            break;
10977436Sdam.sunwoo@arm.com          case 3:
10987436Sdam.sunwoo@arm.com            panic("Reserved type");
10997436Sdam.sunwoo@arm.com        }
11007436Sdam.sunwoo@arm.com
110110037SARM gem5 Developers        if (te.mtype == TlbEntry::MemoryType::Normal){
11027436Sdam.sunwoo@arm.com            switch(curr_ir) {
11037436Sdam.sunwoo@arm.com              case 0:
11047436Sdam.sunwoo@arm.com                te.nonCacheable = true;
11057436Sdam.sunwoo@arm.com                te.innerAttrs = 0;
11067436Sdam.sunwoo@arm.com                break;
11077436Sdam.sunwoo@arm.com              case 1:
11087436Sdam.sunwoo@arm.com                te.innerAttrs = 5;
11097436Sdam.sunwoo@arm.com                break;
11107436Sdam.sunwoo@arm.com              case 2:
11117436Sdam.sunwoo@arm.com                te.innerAttrs = 6;
11127436Sdam.sunwoo@arm.com                break;
11137436Sdam.sunwoo@arm.com              case 3:
11147436Sdam.sunwoo@arm.com                te.innerAttrs = 7;
11157436Sdam.sunwoo@arm.com                break;
11167436Sdam.sunwoo@arm.com            }
11177436Sdam.sunwoo@arm.com
11187436Sdam.sunwoo@arm.com            switch(curr_or) {
11197436Sdam.sunwoo@arm.com              case 0:
11207436Sdam.sunwoo@arm.com                te.nonCacheable = true;
11217436Sdam.sunwoo@arm.com                te.outerAttrs = 0;
11227436Sdam.sunwoo@arm.com                break;
11237436Sdam.sunwoo@arm.com              case 1:
11247436Sdam.sunwoo@arm.com                te.outerAttrs = 1;
11257436Sdam.sunwoo@arm.com                break;
11267436Sdam.sunwoo@arm.com              case 2:
11277436Sdam.sunwoo@arm.com                te.outerAttrs = 2;
11287436Sdam.sunwoo@arm.com                break;
11297436Sdam.sunwoo@arm.com              case 3:
11307436Sdam.sunwoo@arm.com                te.outerAttrs = 3;
11317436Sdam.sunwoo@arm.com                break;
11327436Sdam.sunwoo@arm.com            }
11337436Sdam.sunwoo@arm.com        }
11347404SAli.Saidi@ARM.com    }
113510367SAndrew.Bardsley@arm.com    DPRINTF(TLBVerbose, "memAttrs: shareable: %d, innerAttrs: %d, "
113610367SAndrew.Bardsley@arm.com            "outerAttrs: %d\n",
11377439Sdam.sunwoo@arm.com            te.shareable, te.innerAttrs, te.outerAttrs);
113810037SARM gem5 Developers    te.setAttributes(false);
113910037SARM gem5 Developers}
11407436Sdam.sunwoo@arm.com
114110037SARM gem5 Developersvoid
114210037SARM gem5 DevelopersTableWalker::memAttrsLPAE(ThreadContext *tc, TlbEntry &te,
114310037SARM gem5 Developers    LongDescriptor &lDescriptor)
114410037SARM gem5 Developers{
114510037SARM gem5 Developers    assert(_haveLPAE);
11467436Sdam.sunwoo@arm.com
114710037SARM gem5 Developers    uint8_t attr;
114810037SARM gem5 Developers    uint8_t sh = lDescriptor.sh();
114910037SARM gem5 Developers    // Different format and source of attributes if this is a stage 2
115010037SARM gem5 Developers    // translation
115110037SARM gem5 Developers    if (isStage2) {
115210037SARM gem5 Developers        attr = lDescriptor.memAttr();
115310037SARM gem5 Developers        uint8_t attr_3_2 = (attr >> 2) & 0x3;
115410037SARM gem5 Developers        uint8_t attr_1_0 =  attr       & 0x3;
11557436Sdam.sunwoo@arm.com
115610037SARM gem5 Developers        DPRINTF(TLBVerbose, "memAttrsLPAE MemAttr:%#x sh:%#x\n", attr, sh);
115710037SARM gem5 Developers
115810037SARM gem5 Developers        if (attr_3_2 == 0) {
115910037SARM gem5 Developers            te.mtype        = attr_1_0 == 0 ? TlbEntry::MemoryType::StronglyOrdered
116010037SARM gem5 Developers                                            : TlbEntry::MemoryType::Device;
116110037SARM gem5 Developers            te.outerAttrs   = 0;
116210037SARM gem5 Developers            te.innerAttrs   = attr_1_0 == 0 ? 1 : 3;
116310037SARM gem5 Developers            te.nonCacheable = true;
116410037SARM gem5 Developers        } else {
116510037SARM gem5 Developers            te.mtype        = TlbEntry::MemoryType::Normal;
116610037SARM gem5 Developers            te.outerAttrs   = attr_3_2 == 1 ? 0 :
116710037SARM gem5 Developers                              attr_3_2 == 2 ? 2 : 1;
116810037SARM gem5 Developers            te.innerAttrs   = attr_1_0 == 1 ? 0 :
116910037SARM gem5 Developers                              attr_1_0 == 2 ? 6 : 5;
117010037SARM gem5 Developers            te.nonCacheable = (attr_3_2 == 1) || (attr_1_0 == 1);
117110037SARM gem5 Developers        }
117210037SARM gem5 Developers    } else {
117310037SARM gem5 Developers        uint8_t attrIndx = lDescriptor.attrIndx();
117410037SARM gem5 Developers
117510037SARM gem5 Developers        // LPAE always uses remapping of memory attributes, irrespective of the
117610037SARM gem5 Developers        // value of SCTLR.TRE
117710421Sandreas.hansson@arm.com        MiscRegIndex reg = attrIndx & 0x4 ? MISCREG_MAIR1 : MISCREG_MAIR0;
117810421Sandreas.hansson@arm.com        int reg_as_int = flattenMiscRegNsBanked(reg, currState->tc,
117910421Sandreas.hansson@arm.com                                                !currState->isSecure);
118010421Sandreas.hansson@arm.com        uint32_t mair = currState->tc->readMiscReg(reg_as_int);
118110037SARM gem5 Developers        attr = (mair >> (8 * (attrIndx % 4))) & 0xff;
118210037SARM gem5 Developers        uint8_t attr_7_4 = bits(attr, 7, 4);
118310037SARM gem5 Developers        uint8_t attr_3_0 = bits(attr, 3, 0);
118410037SARM gem5 Developers        DPRINTF(TLBVerbose, "memAttrsLPAE AttrIndx:%#x sh:%#x, attr %#x\n", attrIndx, sh, attr);
118510037SARM gem5 Developers
118610037SARM gem5 Developers        // Note: the memory subsystem only cares about the 'cacheable' memory
118710037SARM gem5 Developers        // attribute. The other attributes are only used to fill the PAR register
118810037SARM gem5 Developers        // accordingly to provide the illusion of full support
118910037SARM gem5 Developers        te.nonCacheable = false;
119010037SARM gem5 Developers
119110037SARM gem5 Developers        switch (attr_7_4) {
119210037SARM gem5 Developers          case 0x0:
119310037SARM gem5 Developers            // Strongly-ordered or Device memory
119410037SARM gem5 Developers            if (attr_3_0 == 0x0)
119510037SARM gem5 Developers                te.mtype = TlbEntry::MemoryType::StronglyOrdered;
119610037SARM gem5 Developers            else if (attr_3_0 == 0x4)
119710037SARM gem5 Developers                te.mtype = TlbEntry::MemoryType::Device;
119810037SARM gem5 Developers            else
119910037SARM gem5 Developers                panic("Unpredictable behavior\n");
120010037SARM gem5 Developers            te.nonCacheable = true;
120110037SARM gem5 Developers            te.outerAttrs   = 0;
120210037SARM gem5 Developers            break;
120310037SARM gem5 Developers          case 0x4:
120410037SARM gem5 Developers            // Normal memory, Outer Non-cacheable
120510037SARM gem5 Developers            te.mtype = TlbEntry::MemoryType::Normal;
120610037SARM gem5 Developers            te.outerAttrs = 0;
120710037SARM gem5 Developers            if (attr_3_0 == 0x4)
120810037SARM gem5 Developers                // Inner Non-cacheable
120910037SARM gem5 Developers                te.nonCacheable = true;
121010037SARM gem5 Developers            else if (attr_3_0 < 0x8)
121110037SARM gem5 Developers                panic("Unpredictable behavior\n");
121210037SARM gem5 Developers            break;
121310037SARM gem5 Developers          case 0x8:
121410037SARM gem5 Developers          case 0x9:
121510037SARM gem5 Developers          case 0xa:
121610037SARM gem5 Developers          case 0xb:
121710037SARM gem5 Developers          case 0xc:
121810037SARM gem5 Developers          case 0xd:
121910037SARM gem5 Developers          case 0xe:
122010037SARM gem5 Developers          case 0xf:
122110037SARM gem5 Developers            if (attr_7_4 & 0x4) {
122210037SARM gem5 Developers                te.outerAttrs = (attr_7_4 & 1) ? 1 : 3;
122310037SARM gem5 Developers            } else {
122410037SARM gem5 Developers                te.outerAttrs = 0x2;
122510037SARM gem5 Developers            }
122610037SARM gem5 Developers            // Normal memory, Outer Cacheable
122710037SARM gem5 Developers            te.mtype = TlbEntry::MemoryType::Normal;
122810037SARM gem5 Developers            if (attr_3_0 != 0x4 && attr_3_0 < 0x8)
122910037SARM gem5 Developers                panic("Unpredictable behavior\n");
123010037SARM gem5 Developers            break;
123110037SARM gem5 Developers          default:
123210037SARM gem5 Developers            panic("Unpredictable behavior\n");
123310037SARM gem5 Developers            break;
123410037SARM gem5 Developers        }
123510037SARM gem5 Developers
123610037SARM gem5 Developers        switch (attr_3_0) {
123710037SARM gem5 Developers          case 0x0:
123810037SARM gem5 Developers            te.innerAttrs = 0x1;
123910037SARM gem5 Developers            break;
124010037SARM gem5 Developers          case 0x4:
124110037SARM gem5 Developers            te.innerAttrs = attr_7_4 == 0 ? 0x3 : 0;
124210037SARM gem5 Developers            break;
124310037SARM gem5 Developers          case 0x8:
124410037SARM gem5 Developers          case 0x9:
124510037SARM gem5 Developers          case 0xA:
124610037SARM gem5 Developers          case 0xB:
124710037SARM gem5 Developers            te.innerAttrs = 6;
124810037SARM gem5 Developers            break;
124910037SARM gem5 Developers          case 0xC:
125010037SARM gem5 Developers          case 0xD:
125110037SARM gem5 Developers          case 0xE:
125210037SARM gem5 Developers          case 0xF:
125310037SARM gem5 Developers            te.innerAttrs = attr_3_0 & 1 ? 0x5 : 0x7;
125410037SARM gem5 Developers            break;
125510037SARM gem5 Developers          default:
125610037SARM gem5 Developers            panic("Unpredictable behavior\n");
125710037SARM gem5 Developers            break;
125810037SARM gem5 Developers        }
125910037SARM gem5 Developers    }
126010037SARM gem5 Developers
126110037SARM gem5 Developers    te.outerShareable = sh == 2;
126210037SARM gem5 Developers    te.shareable       = (sh & 0x2) ? true : false;
126310037SARM gem5 Developers    te.setAttributes(true);
126410037SARM gem5 Developers    te.attributes |= (uint64_t) attr << 56;
126510037SARM gem5 Developers}
126610037SARM gem5 Developers
126710037SARM gem5 Developersvoid
126810037SARM gem5 DevelopersTableWalker::memAttrsAArch64(ThreadContext *tc, TlbEntry &te, uint8_t attrIndx,
126910037SARM gem5 Developers                             uint8_t sh)
127010037SARM gem5 Developers{
127110037SARM gem5 Developers    DPRINTF(TLBVerbose, "memAttrsAArch64 AttrIndx:%#x sh:%#x\n", attrIndx, sh);
127210037SARM gem5 Developers
127310037SARM gem5 Developers    // Select MAIR
127410037SARM gem5 Developers    uint64_t mair;
127510037SARM gem5 Developers    switch (currState->el) {
127610037SARM gem5 Developers      case EL0:
127710037SARM gem5 Developers      case EL1:
127810037SARM gem5 Developers        mair = tc->readMiscReg(MISCREG_MAIR_EL1);
127910037SARM gem5 Developers        break;
128010037SARM gem5 Developers      case EL2:
128110037SARM gem5 Developers        mair = tc->readMiscReg(MISCREG_MAIR_EL2);
128210037SARM gem5 Developers        break;
128310037SARM gem5 Developers      case EL3:
128410037SARM gem5 Developers        mair = tc->readMiscReg(MISCREG_MAIR_EL3);
128510037SARM gem5 Developers        break;
128610037SARM gem5 Developers      default:
128710037SARM gem5 Developers        panic("Invalid exception level");
128810037SARM gem5 Developers        break;
128910037SARM gem5 Developers    }
129010037SARM gem5 Developers
129110037SARM gem5 Developers    // Select attributes
129210037SARM gem5 Developers    uint8_t attr = bits(mair, 8 * attrIndx + 7, 8 * attrIndx);
129310037SARM gem5 Developers    uint8_t attr_lo = bits(attr, 3, 0);
129410037SARM gem5 Developers    uint8_t attr_hi = bits(attr, 7, 4);
129510037SARM gem5 Developers
129610037SARM gem5 Developers    // Memory type
129710037SARM gem5 Developers    te.mtype = attr_hi == 0 ? TlbEntry::MemoryType::Device : TlbEntry::MemoryType::Normal;
129810037SARM gem5 Developers
129910037SARM gem5 Developers    // Cacheability
130010037SARM gem5 Developers    te.nonCacheable = false;
130110037SARM gem5 Developers    if (te.mtype == TlbEntry::MemoryType::Device ||  // Device memory
130210037SARM gem5 Developers        attr_hi == 0x8 ||  // Normal memory, Outer Non-cacheable
130310037SARM gem5 Developers        attr_lo == 0x8) {  // Normal memory, Inner Non-cacheable
130410037SARM gem5 Developers        te.nonCacheable = true;
130510037SARM gem5 Developers    }
130610037SARM gem5 Developers
130710037SARM gem5 Developers    te.shareable       = sh == 2;
130810037SARM gem5 Developers    te.outerShareable = (sh & 0x2) ? true : false;
130910037SARM gem5 Developers    // Attributes formatted according to the 64-bit PAR
131010037SARM gem5 Developers    te.attributes = ((uint64_t) attr << 56) |
131110037SARM gem5 Developers        (1 << 11) |     // LPAE bit
131210037SARM gem5 Developers        (te.ns << 9) |  // NS bit
131310037SARM gem5 Developers        (sh << 7);
13147404SAli.Saidi@ARM.com}
13157404SAli.Saidi@ARM.com
13167404SAli.Saidi@ARM.comvoid
13177404SAli.Saidi@ARM.comTableWalker::doL1Descriptor()
13187404SAli.Saidi@ARM.com{
131910037SARM gem5 Developers    if (currState->fault != NoFault) {
132010037SARM gem5 Developers        return;
132110037SARM gem5 Developers    }
132210037SARM gem5 Developers
13237439Sdam.sunwoo@arm.com    DPRINTF(TLB, "L1 descriptor for %#x is %#x\n",
132410037SARM gem5 Developers            currState->vaddr_tainted, currState->l1Desc.data);
13257404SAli.Saidi@ARM.com    TlbEntry te;
13267404SAli.Saidi@ARM.com
13277439Sdam.sunwoo@arm.com    switch (currState->l1Desc.type()) {
13287404SAli.Saidi@ARM.com      case L1Descriptor::Ignore:
13297404SAli.Saidi@ARM.com      case L1Descriptor::Reserved:
13307946SGiacomo.Gabrielli@arm.com        if (!currState->timing) {
13317439Sdam.sunwoo@arm.com            currState->tc = NULL;
13327439Sdam.sunwoo@arm.com            currState->req = NULL;
13337437Sdam.sunwoo@arm.com        }
13347406SAli.Saidi@ARM.com        DPRINTF(TLB, "L1 Descriptor Reserved/Ignore, causing fault\n");
13357439Sdam.sunwoo@arm.com        if (currState->isFetch)
13367439Sdam.sunwoo@arm.com            currState->fault =
133710474Sandreas.hansson@arm.com                std::make_shared<PrefetchAbort>(
133810474Sandreas.hansson@arm.com                    currState->vaddr_tainted,
133910474Sandreas.hansson@arm.com                    ArmFault::TranslationLL + L1,
134010474Sandreas.hansson@arm.com                    isStage2,
134110474Sandreas.hansson@arm.com                    ArmFault::VmsaTran);
13427406SAli.Saidi@ARM.com        else
13437439Sdam.sunwoo@arm.com            currState->fault =
134410474Sandreas.hansson@arm.com                std::make_shared<DataAbort>(
134510474Sandreas.hansson@arm.com                    currState->vaddr_tainted,
134610474Sandreas.hansson@arm.com                    TlbEntry::DomainType::NoAccess,
134710474Sandreas.hansson@arm.com                    currState->isWrite,
134810474Sandreas.hansson@arm.com                    ArmFault::TranslationLL + L1, isStage2,
134910474Sandreas.hansson@arm.com                    ArmFault::VmsaTran);
13507404SAli.Saidi@ARM.com        return;
13517404SAli.Saidi@ARM.com      case L1Descriptor::Section:
13527439Sdam.sunwoo@arm.com        if (currState->sctlr.afe && bits(currState->l1Desc.ap(), 0) == 0) {
13537436Sdam.sunwoo@arm.com            /** @todo: check sctlr.ha (bit[17]) if Hardware Access Flag is
13547436Sdam.sunwoo@arm.com              * enabled if set, do l1.Desc.setAp0() instead of generating
13557436Sdam.sunwoo@arm.com              * AccessFlag0
13567436Sdam.sunwoo@arm.com              */
13577436Sdam.sunwoo@arm.com
135810474Sandreas.hansson@arm.com            currState->fault = std::make_shared<DataAbort>(
135910474Sandreas.hansson@arm.com                currState->vaddr_tainted,
136010474Sandreas.hansson@arm.com                currState->l1Desc.domain(),
136110474Sandreas.hansson@arm.com                currState->isWrite,
136210474Sandreas.hansson@arm.com                ArmFault::AccessFlagLL + L1,
136310474Sandreas.hansson@arm.com                isStage2,
136410474Sandreas.hansson@arm.com                ArmFault::VmsaTran);
13657436Sdam.sunwoo@arm.com        }
13667439Sdam.sunwoo@arm.com        if (currState->l1Desc.supersection()) {
13677404SAli.Saidi@ARM.com            panic("Haven't implemented supersections\n");
13687404SAli.Saidi@ARM.com        }
136910037SARM gem5 Developers        insertTableEntry(currState->l1Desc, false);
137010037SARM gem5 Developers        return;
137110037SARM gem5 Developers      case L1Descriptor::PageTable:
137210037SARM gem5 Developers        {
137310037SARM gem5 Developers            Addr l2desc_addr;
137410037SARM gem5 Developers            l2desc_addr = currState->l1Desc.l2Addr() |
137510037SARM gem5 Developers                (bits(currState->vaddr, 19, 12) << 2);
137610037SARM gem5 Developers            DPRINTF(TLB, "L1 descriptor points to page table at: %#x (%s)\n",
137710037SARM gem5 Developers                    l2desc_addr, currState->isSecure ? "s" : "ns");
13787404SAli.Saidi@ARM.com
137910037SARM gem5 Developers            // Trickbox address check
138010037SARM gem5 Developers            currState->fault = tlb->walkTrickBoxCheck(
138110037SARM gem5 Developers                l2desc_addr, currState->isSecure, currState->vaddr,
138210037SARM gem5 Developers                sizeof(uint32_t), currState->isFetch, currState->isWrite,
138310037SARM gem5 Developers                currState->l1Desc.domain(), L2);
13847404SAli.Saidi@ARM.com
138510037SARM gem5 Developers            if (currState->fault) {
138610037SARM gem5 Developers                if (!currState->timing) {
138710037SARM gem5 Developers                    currState->tc = NULL;
138810037SARM gem5 Developers                    currState->req = NULL;
138910037SARM gem5 Developers                }
139010037SARM gem5 Developers                return;
139110037SARM gem5 Developers            }
139210037SARM gem5 Developers
139310037SARM gem5 Developers            Request::Flags flag = 0;
139410037SARM gem5 Developers            if (currState->isSecure)
139510037SARM gem5 Developers                flag.set(Request::SECURE);
139610037SARM gem5 Developers
139710037SARM gem5 Developers            bool delayed;
139810037SARM gem5 Developers            delayed = fetchDescriptor(l2desc_addr,
139910037SARM gem5 Developers                                      (uint8_t*)&currState->l2Desc.data,
140010037SARM gem5 Developers                                      sizeof(uint32_t), flag, -1, &doL2DescEvent,
140110037SARM gem5 Developers                                      &TableWalker::doL2Descriptor);
140210037SARM gem5 Developers            if (delayed) {
140310037SARM gem5 Developers                currState->delayed = true;
140410037SARM gem5 Developers            }
140510037SARM gem5 Developers
140610037SARM gem5 Developers            return;
140710037SARM gem5 Developers        }
140810037SARM gem5 Developers      default:
140910037SARM gem5 Developers        panic("A new type in a 2 bit field?\n");
141010037SARM gem5 Developers    }
141110037SARM gem5 Developers}
141210037SARM gem5 Developers
141310037SARM gem5 Developersvoid
141410037SARM gem5 DevelopersTableWalker::doLongDescriptor()
141510037SARM gem5 Developers{
141610037SARM gem5 Developers    if (currState->fault != NoFault) {
141710037SARM gem5 Developers        return;
141810037SARM gem5 Developers    }
141910037SARM gem5 Developers
142010037SARM gem5 Developers    DPRINTF(TLB, "L%d descriptor for %#llx is %#llx (%s)\n",
142110037SARM gem5 Developers            currState->longDesc.lookupLevel, currState->vaddr_tainted,
142210037SARM gem5 Developers            currState->longDesc.data,
142310037SARM gem5 Developers            currState->aarch64 ? "AArch64" : "long-desc.");
142410037SARM gem5 Developers
142510037SARM gem5 Developers    if ((currState->longDesc.type() == LongDescriptor::Block) ||
142610037SARM gem5 Developers        (currState->longDesc.type() == LongDescriptor::Page)) {
142710037SARM gem5 Developers        DPRINTF(TLBVerbose, "Analyzing L%d descriptor: %#llx, pxn: %d, "
142810037SARM gem5 Developers                "xn: %d, ap: %d, af: %d, type: %d\n",
142910037SARM gem5 Developers                currState->longDesc.lookupLevel,
143010037SARM gem5 Developers                currState->longDesc.data,
143110037SARM gem5 Developers                currState->longDesc.pxn(),
143210037SARM gem5 Developers                currState->longDesc.xn(),
143310037SARM gem5 Developers                currState->longDesc.ap(),
143410037SARM gem5 Developers                currState->longDesc.af(),
143510037SARM gem5 Developers                currState->longDesc.type());
143610037SARM gem5 Developers    } else {
143710037SARM gem5 Developers        DPRINTF(TLBVerbose, "Analyzing L%d descriptor: %#llx, type: %d\n",
143810037SARM gem5 Developers                currState->longDesc.lookupLevel,
143910037SARM gem5 Developers                currState->longDesc.data,
144010037SARM gem5 Developers                currState->longDesc.type());
144110037SARM gem5 Developers    }
144210037SARM gem5 Developers
144310037SARM gem5 Developers    TlbEntry te;
144410037SARM gem5 Developers
144510037SARM gem5 Developers    switch (currState->longDesc.type()) {
144610037SARM gem5 Developers      case LongDescriptor::Invalid:
14477439Sdam.sunwoo@arm.com        if (!currState->timing) {
14487439Sdam.sunwoo@arm.com            currState->tc = NULL;
14497439Sdam.sunwoo@arm.com            currState->req = NULL;
14507437Sdam.sunwoo@arm.com        }
14517404SAli.Saidi@ARM.com
145210037SARM gem5 Developers        DPRINTF(TLB, "L%d descriptor Invalid, causing fault type %d\n",
145310037SARM gem5 Developers                currState->longDesc.lookupLevel,
145410037SARM gem5 Developers                ArmFault::TranslationLL + currState->longDesc.lookupLevel);
145510037SARM gem5 Developers        if (currState->isFetch)
145610474Sandreas.hansson@arm.com            currState->fault = std::make_shared<PrefetchAbort>(
145710037SARM gem5 Developers                currState->vaddr_tainted,
145810037SARM gem5 Developers                ArmFault::TranslationLL + currState->longDesc.lookupLevel,
145910037SARM gem5 Developers                isStage2,
146010037SARM gem5 Developers                ArmFault::LpaeTran);
146110037SARM gem5 Developers        else
146210474Sandreas.hansson@arm.com            currState->fault = std::make_shared<DataAbort>(
146310037SARM gem5 Developers                currState->vaddr_tainted,
146410037SARM gem5 Developers                TlbEntry::DomainType::NoAccess,
146510037SARM gem5 Developers                currState->isWrite,
146610037SARM gem5 Developers                ArmFault::TranslationLL + currState->longDesc.lookupLevel,
146710037SARM gem5 Developers                isStage2,
146810037SARM gem5 Developers                ArmFault::LpaeTran);
14697404SAli.Saidi@ARM.com        return;
147010037SARM gem5 Developers      case LongDescriptor::Block:
147110037SARM gem5 Developers      case LongDescriptor::Page:
147210037SARM gem5 Developers        {
147310037SARM gem5 Developers            bool fault = false;
147410037SARM gem5 Developers            bool aff = false;
147510037SARM gem5 Developers            // Check for address size fault
147610037SARM gem5 Developers            if (checkAddrSizeFaultAArch64(
147710037SARM gem5 Developers                    mbits(currState->longDesc.data, MaxPhysAddrRange - 1,
147810037SARM gem5 Developers                          currState->longDesc.offsetBits()),
147910037SARM gem5 Developers                    currState->physAddrRange)) {
148010037SARM gem5 Developers                fault = true;
148110037SARM gem5 Developers                DPRINTF(TLB, "L%d descriptor causing Address Size Fault\n",
148210037SARM gem5 Developers                        currState->longDesc.lookupLevel);
148310037SARM gem5 Developers            // Check for access fault
148410037SARM gem5 Developers            } else if (currState->longDesc.af() == 0) {
148510037SARM gem5 Developers                fault = true;
148610037SARM gem5 Developers                DPRINTF(TLB, "L%d descriptor causing Access Fault\n",
148710037SARM gem5 Developers                        currState->longDesc.lookupLevel);
148810037SARM gem5 Developers                aff = true;
148910037SARM gem5 Developers            }
149010037SARM gem5 Developers            if (fault) {
149110037SARM gem5 Developers                if (currState->isFetch)
149210474Sandreas.hansson@arm.com                    currState->fault = std::make_shared<PrefetchAbort>(
149310037SARM gem5 Developers                        currState->vaddr_tainted,
149410037SARM gem5 Developers                        (aff ? ArmFault::AccessFlagLL : ArmFault::AddressSizeLL) +
149510037SARM gem5 Developers                        currState->longDesc.lookupLevel,
149610037SARM gem5 Developers                        isStage2,
149710037SARM gem5 Developers                        ArmFault::LpaeTran);
149810037SARM gem5 Developers                else
149910474Sandreas.hansson@arm.com                    currState->fault = std::make_shared<DataAbort>(
150010037SARM gem5 Developers                        currState->vaddr_tainted,
150110037SARM gem5 Developers                        TlbEntry::DomainType::NoAccess, currState->isWrite,
150210037SARM gem5 Developers                        (aff ? ArmFault::AccessFlagLL : ArmFault::AddressSizeLL) +
150310037SARM gem5 Developers                        currState->longDesc.lookupLevel,
150410037SARM gem5 Developers                        isStage2,
150510037SARM gem5 Developers                        ArmFault::LpaeTran);
150610037SARM gem5 Developers            } else {
150710037SARM gem5 Developers                insertTableEntry(currState->longDesc, true);
150810037SARM gem5 Developers            }
150910037SARM gem5 Developers        }
151010037SARM gem5 Developers        return;
151110037SARM gem5 Developers      case LongDescriptor::Table:
151210037SARM gem5 Developers        {
151310037SARM gem5 Developers            // Set hierarchical permission flags
151410037SARM gem5 Developers            currState->secureLookup = currState->secureLookup &&
151510037SARM gem5 Developers                currState->longDesc.secureTable();
151610037SARM gem5 Developers            currState->rwTable = currState->rwTable &&
151710037SARM gem5 Developers                currState->longDesc.rwTable();
151810037SARM gem5 Developers            currState->userTable = currState->userTable &&
151910037SARM gem5 Developers                currState->longDesc.userTable();
152010037SARM gem5 Developers            currState->xnTable = currState->xnTable ||
152110037SARM gem5 Developers                currState->longDesc.xnTable();
152210037SARM gem5 Developers            currState->pxnTable = currState->pxnTable ||
152310037SARM gem5 Developers                currState->longDesc.pxnTable();
15247404SAli.Saidi@ARM.com
152510037SARM gem5 Developers            // Set up next level lookup
152610037SARM gem5 Developers            Addr next_desc_addr = currState->longDesc.nextDescAddr(
152710037SARM gem5 Developers                currState->vaddr);
15287439Sdam.sunwoo@arm.com
152910037SARM gem5 Developers            DPRINTF(TLB, "L%d descriptor points to L%d descriptor at: %#x (%s)\n",
153010037SARM gem5 Developers                    currState->longDesc.lookupLevel,
153110037SARM gem5 Developers                    currState->longDesc.lookupLevel + 1,
153210037SARM gem5 Developers                    next_desc_addr,
153310037SARM gem5 Developers                    currState->secureLookup ? "s" : "ns");
153410037SARM gem5 Developers
153510037SARM gem5 Developers            // Check for address size fault
153610037SARM gem5 Developers            if (currState->aarch64 && checkAddrSizeFaultAArch64(
153710037SARM gem5 Developers                    next_desc_addr, currState->physAddrRange)) {
153810037SARM gem5 Developers                DPRINTF(TLB, "L%d descriptor causing Address Size Fault\n",
153910037SARM gem5 Developers                        currState->longDesc.lookupLevel);
154010037SARM gem5 Developers                if (currState->isFetch)
154110474Sandreas.hansson@arm.com                    currState->fault = std::make_shared<PrefetchAbort>(
154210037SARM gem5 Developers                        currState->vaddr_tainted,
154310037SARM gem5 Developers                        ArmFault::AddressSizeLL
154410037SARM gem5 Developers                        + currState->longDesc.lookupLevel,
154510037SARM gem5 Developers                        isStage2,
154610037SARM gem5 Developers                        ArmFault::LpaeTran);
154710037SARM gem5 Developers                else
154810474Sandreas.hansson@arm.com                    currState->fault = std::make_shared<DataAbort>(
154910037SARM gem5 Developers                        currState->vaddr_tainted,
155010037SARM gem5 Developers                        TlbEntry::DomainType::NoAccess, currState->isWrite,
155110037SARM gem5 Developers                        ArmFault::AddressSizeLL
155210037SARM gem5 Developers                        + currState->longDesc.lookupLevel,
155310037SARM gem5 Developers                        isStage2,
155410037SARM gem5 Developers                        ArmFault::LpaeTran);
155510037SARM gem5 Developers                return;
15567437Sdam.sunwoo@arm.com            }
15577404SAli.Saidi@ARM.com
155810037SARM gem5 Developers            // Trickbox address check
155910037SARM gem5 Developers            currState->fault = tlb->walkTrickBoxCheck(
156010037SARM gem5 Developers                            next_desc_addr, currState->vaddr,
156110037SARM gem5 Developers                            currState->vaddr, sizeof(uint64_t),
156210037SARM gem5 Developers                            currState->isFetch, currState->isWrite,
156310037SARM gem5 Developers                            TlbEntry::DomainType::Client,
156410037SARM gem5 Developers                            toLookupLevel(currState->longDesc.lookupLevel +1));
15657404SAli.Saidi@ARM.com
156610037SARM gem5 Developers            if (currState->fault) {
156710037SARM gem5 Developers                if (!currState->timing) {
156810037SARM gem5 Developers                    currState->tc = NULL;
156910037SARM gem5 Developers                    currState->req = NULL;
157010037SARM gem5 Developers                }
157110037SARM gem5 Developers                return;
157210037SARM gem5 Developers            }
157310037SARM gem5 Developers
157410037SARM gem5 Developers            Request::Flags flag = 0;
157510037SARM gem5 Developers            if (currState->secureLookup)
157610037SARM gem5 Developers                flag.set(Request::SECURE);
157710037SARM gem5 Developers
157810037SARM gem5 Developers            currState->longDesc.lookupLevel =
157910037SARM gem5 Developers                (LookupLevel) (currState->longDesc.lookupLevel + 1);
158010037SARM gem5 Developers            Event *event = NULL;
158110037SARM gem5 Developers            switch (currState->longDesc.lookupLevel) {
158210037SARM gem5 Developers              case L1:
158310037SARM gem5 Developers                assert(currState->aarch64);
158410037SARM gem5 Developers                event = &doL1LongDescEvent;
158510037SARM gem5 Developers                break;
158610037SARM gem5 Developers              case L2:
158710037SARM gem5 Developers                event = &doL2LongDescEvent;
158810037SARM gem5 Developers                break;
158910037SARM gem5 Developers              case L3:
159010037SARM gem5 Developers                event = &doL3LongDescEvent;
159110037SARM gem5 Developers                break;
159210037SARM gem5 Developers              default:
159310037SARM gem5 Developers                panic("Wrong lookup level in table walk\n");
159410037SARM gem5 Developers                break;
159510037SARM gem5 Developers            }
159610037SARM gem5 Developers
159710037SARM gem5 Developers            bool delayed;
159810037SARM gem5 Developers            delayed = fetchDescriptor(next_desc_addr, (uint8_t*)&currState->longDesc.data,
159910037SARM gem5 Developers                                      sizeof(uint64_t), flag, -1, event,
160010037SARM gem5 Developers                                      &TableWalker::doLongDescriptor);
160110037SARM gem5 Developers            if (delayed) {
160210037SARM gem5 Developers                 currState->delayed = true;
160310037SARM gem5 Developers            }
16047404SAli.Saidi@ARM.com        }
16057404SAli.Saidi@ARM.com        return;
16067404SAli.Saidi@ARM.com      default:
16077404SAli.Saidi@ARM.com        panic("A new type in a 2 bit field?\n");
16087404SAli.Saidi@ARM.com    }
16097404SAli.Saidi@ARM.com}
16107404SAli.Saidi@ARM.com
16117404SAli.Saidi@ARM.comvoid
16127404SAli.Saidi@ARM.comTableWalker::doL2Descriptor()
16137404SAli.Saidi@ARM.com{
161410037SARM gem5 Developers    if (currState->fault != NoFault) {
161510037SARM gem5 Developers        return;
161610037SARM gem5 Developers    }
161710037SARM gem5 Developers
16187439Sdam.sunwoo@arm.com    DPRINTF(TLB, "L2 descriptor for %#x is %#x\n",
161910037SARM gem5 Developers            currState->vaddr_tainted, currState->l2Desc.data);
16207404SAli.Saidi@ARM.com    TlbEntry te;
16217404SAli.Saidi@ARM.com
16227439Sdam.sunwoo@arm.com    if (currState->l2Desc.invalid()) {
16237404SAli.Saidi@ARM.com        DPRINTF(TLB, "L2 descriptor invalid, causing fault\n");
16247946SGiacomo.Gabrielli@arm.com        if (!currState->timing) {
16257439Sdam.sunwoo@arm.com            currState->tc = NULL;
16267439Sdam.sunwoo@arm.com            currState->req = NULL;
16277437Sdam.sunwoo@arm.com        }
16287439Sdam.sunwoo@arm.com        if (currState->isFetch)
162910474Sandreas.hansson@arm.com            currState->fault = std::make_shared<PrefetchAbort>(
163010474Sandreas.hansson@arm.com                    currState->vaddr_tainted,
163110474Sandreas.hansson@arm.com                    ArmFault::TranslationLL + L2,
163210474Sandreas.hansson@arm.com                    isStage2,
163310474Sandreas.hansson@arm.com                    ArmFault::VmsaTran);
16347406SAli.Saidi@ARM.com        else
163510474Sandreas.hansson@arm.com            currState->fault = std::make_shared<DataAbort>(
163610474Sandreas.hansson@arm.com                currState->vaddr_tainted, currState->l1Desc.domain(),
163710474Sandreas.hansson@arm.com                currState->isWrite, ArmFault::TranslationLL + L2,
163810474Sandreas.hansson@arm.com                isStage2,
163910474Sandreas.hansson@arm.com                ArmFault::VmsaTran);
16407404SAli.Saidi@ARM.com        return;
16417404SAli.Saidi@ARM.com    }
16427404SAli.Saidi@ARM.com
16437439Sdam.sunwoo@arm.com    if (currState->sctlr.afe && bits(currState->l2Desc.ap(), 0) == 0) {
16447436Sdam.sunwoo@arm.com        /** @todo: check sctlr.ha (bit[17]) if Hardware Access Flag is enabled
16457436Sdam.sunwoo@arm.com          * if set, do l2.Desc.setAp0() instead of generating AccessFlag0
16467436Sdam.sunwoo@arm.com          */
164710037SARM gem5 Developers         DPRINTF(TLB, "Generating access fault at L2, afe: %d, ap: %d\n",
164810037SARM gem5 Developers                 currState->sctlr.afe, currState->l2Desc.ap());
16497436Sdam.sunwoo@arm.com
165010474Sandreas.hansson@arm.com        currState->fault = std::make_shared<DataAbort>(
165110474Sandreas.hansson@arm.com            currState->vaddr_tainted,
165210474Sandreas.hansson@arm.com            TlbEntry::DomainType::NoAccess, currState->isWrite,
165310474Sandreas.hansson@arm.com            ArmFault::AccessFlagLL + L2, isStage2,
165410474Sandreas.hansson@arm.com            ArmFault::VmsaTran);
16557436Sdam.sunwoo@arm.com    }
16567436Sdam.sunwoo@arm.com
165710037SARM gem5 Developers    insertTableEntry(currState->l2Desc, false);
16587437Sdam.sunwoo@arm.com}
16597437Sdam.sunwoo@arm.com
16607437Sdam.sunwoo@arm.comvoid
16617437Sdam.sunwoo@arm.comTableWalker::doL1DescriptorWrapper()
16627437Sdam.sunwoo@arm.com{
166310037SARM gem5 Developers    currState = stateQueues[L1].front();
16647439Sdam.sunwoo@arm.com    currState->delayed = false;
166510037SARM gem5 Developers    // if there's a stage2 translation object we don't need it any more
166610037SARM gem5 Developers    if (currState->stage2Tran) {
166710037SARM gem5 Developers        delete currState->stage2Tran;
166810037SARM gem5 Developers        currState->stage2Tran = NULL;
166910037SARM gem5 Developers    }
167010037SARM gem5 Developers
16717437Sdam.sunwoo@arm.com
16727578Sdam.sunwoo@arm.com    DPRINTF(TLBVerbose, "L1 Desc object host addr: %p\n",&currState->l1Desc.data);
16737578Sdam.sunwoo@arm.com    DPRINTF(TLBVerbose, "L1 Desc object      data: %08x\n",currState->l1Desc.data);
16747578Sdam.sunwoo@arm.com
167510037SARM gem5 Developers    DPRINTF(TLBVerbose, "calling doL1Descriptor for vaddr:%#x\n", currState->vaddr_tainted);
16767437Sdam.sunwoo@arm.com    doL1Descriptor();
16777437Sdam.sunwoo@arm.com
167810037SARM gem5 Developers    stateQueues[L1].pop_front();
16797437Sdam.sunwoo@arm.com    // Check if fault was generated
16807439Sdam.sunwoo@arm.com    if (currState->fault != NoFault) {
16817439Sdam.sunwoo@arm.com        currState->transState->finish(currState->fault, currState->req,
16827439Sdam.sunwoo@arm.com                                      currState->tc, currState->mode);
16837437Sdam.sunwoo@arm.com
16847728SAli.Saidi@ARM.com        pending = false;
16857728SAli.Saidi@ARM.com        nextWalk(currState->tc);
16867728SAli.Saidi@ARM.com
16877439Sdam.sunwoo@arm.com        currState->req = NULL;
16887439Sdam.sunwoo@arm.com        currState->tc = NULL;
16897439Sdam.sunwoo@arm.com        currState->delayed = false;
16908510SAli.Saidi@ARM.com        delete currState;
16917437Sdam.sunwoo@arm.com    }
16927439Sdam.sunwoo@arm.com    else if (!currState->delayed) {
16937653Sgene.wu@arm.com        // delay is not set so there is no L2 to do
169410037SARM gem5 Developers        // Don't finish the translation if a stage 2 look up is underway
169510037SARM gem5 Developers        if (!currState->doingStage2) {
169610037SARM gem5 Developers            DPRINTF(TLBVerbose, "calling translateTiming again\n");
169710037SARM gem5 Developers            currState->fault = tlb->translateTiming(currState->req, currState->tc,
169810037SARM gem5 Developers                currState->transState, currState->mode);
169910037SARM gem5 Developers        }
17007437Sdam.sunwoo@arm.com
17017728SAli.Saidi@ARM.com        pending = false;
17027728SAli.Saidi@ARM.com        nextWalk(currState->tc);
17037728SAli.Saidi@ARM.com
17047439Sdam.sunwoo@arm.com        currState->req = NULL;
17057439Sdam.sunwoo@arm.com        currState->tc = NULL;
17067439Sdam.sunwoo@arm.com        currState->delayed = false;
17077653Sgene.wu@arm.com        delete currState;
17087653Sgene.wu@arm.com    } else {
17097653Sgene.wu@arm.com        // need to do L2 descriptor
171010037SARM gem5 Developers        stateQueues[L2].push_back(currState);
17117437Sdam.sunwoo@arm.com    }
17127439Sdam.sunwoo@arm.com    currState = NULL;
17137437Sdam.sunwoo@arm.com}
17147437Sdam.sunwoo@arm.com
17157437Sdam.sunwoo@arm.comvoid
17167437Sdam.sunwoo@arm.comTableWalker::doL2DescriptorWrapper()
17177437Sdam.sunwoo@arm.com{
171810037SARM gem5 Developers    currState = stateQueues[L2].front();
17197439Sdam.sunwoo@arm.com    assert(currState->delayed);
172010037SARM gem5 Developers    // if there's a stage2 translation object we don't need it any more
172110037SARM gem5 Developers    if (currState->stage2Tran) {
172210037SARM gem5 Developers        delete currState->stage2Tran;
172310037SARM gem5 Developers        currState->stage2Tran = NULL;
172410037SARM gem5 Developers    }
17257437Sdam.sunwoo@arm.com
17267439Sdam.sunwoo@arm.com    DPRINTF(TLBVerbose, "calling doL2Descriptor for vaddr:%#x\n",
172710037SARM gem5 Developers            currState->vaddr_tainted);
17287437Sdam.sunwoo@arm.com    doL2Descriptor();
17297437Sdam.sunwoo@arm.com
17307437Sdam.sunwoo@arm.com    // Check if fault was generated
17317439Sdam.sunwoo@arm.com    if (currState->fault != NoFault) {
17327439Sdam.sunwoo@arm.com        currState->transState->finish(currState->fault, currState->req,
17337439Sdam.sunwoo@arm.com                                      currState->tc, currState->mode);
17347437Sdam.sunwoo@arm.com    }
17357437Sdam.sunwoo@arm.com    else {
173610037SARM gem5 Developers        // Don't finish the translation if a stage 2 look up is underway
173710037SARM gem5 Developers        if (!currState->doingStage2) {
173810037SARM gem5 Developers            DPRINTF(TLBVerbose, "calling translateTiming again\n");
173910037SARM gem5 Developers            currState->fault = tlb->translateTiming(currState->req,
174010037SARM gem5 Developers                currState->tc, currState->transState, currState->mode);
174110037SARM gem5 Developers        }
17427437Sdam.sunwoo@arm.com    }
17437437Sdam.sunwoo@arm.com
17447728SAli.Saidi@ARM.com
174510037SARM gem5 Developers    stateQueues[L2].pop_front();
17467728SAli.Saidi@ARM.com    pending = false;
17477728SAli.Saidi@ARM.com    nextWalk(currState->tc);
17487728SAli.Saidi@ARM.com
17497439Sdam.sunwoo@arm.com    currState->req = NULL;
17507439Sdam.sunwoo@arm.com    currState->tc = NULL;
17517439Sdam.sunwoo@arm.com    currState->delayed = false;
17527439Sdam.sunwoo@arm.com
17537653Sgene.wu@arm.com    delete currState;
17547439Sdam.sunwoo@arm.com    currState = NULL;
17557404SAli.Saidi@ARM.com}
17567404SAli.Saidi@ARM.com
17577728SAli.Saidi@ARM.comvoid
175810037SARM gem5 DevelopersTableWalker::doL0LongDescriptorWrapper()
175910037SARM gem5 Developers{
176010037SARM gem5 Developers    doLongDescriptorWrapper(L0);
176110037SARM gem5 Developers}
176210037SARM gem5 Developers
176310037SARM gem5 Developersvoid
176410037SARM gem5 DevelopersTableWalker::doL1LongDescriptorWrapper()
176510037SARM gem5 Developers{
176610037SARM gem5 Developers    doLongDescriptorWrapper(L1);
176710037SARM gem5 Developers}
176810037SARM gem5 Developers
176910037SARM gem5 Developersvoid
177010037SARM gem5 DevelopersTableWalker::doL2LongDescriptorWrapper()
177110037SARM gem5 Developers{
177210037SARM gem5 Developers    doLongDescriptorWrapper(L2);
177310037SARM gem5 Developers}
177410037SARM gem5 Developers
177510037SARM gem5 Developersvoid
177610037SARM gem5 DevelopersTableWalker::doL3LongDescriptorWrapper()
177710037SARM gem5 Developers{
177810037SARM gem5 Developers    doLongDescriptorWrapper(L3);
177910037SARM gem5 Developers}
178010037SARM gem5 Developers
178110037SARM gem5 Developersvoid
178210037SARM gem5 DevelopersTableWalker::doLongDescriptorWrapper(LookupLevel curr_lookup_level)
178310037SARM gem5 Developers{
178410037SARM gem5 Developers    currState = stateQueues[curr_lookup_level].front();
178510037SARM gem5 Developers    assert(curr_lookup_level == currState->longDesc.lookupLevel);
178610037SARM gem5 Developers    currState->delayed = false;
178710037SARM gem5 Developers
178810037SARM gem5 Developers    // if there's a stage2 translation object we don't need it any more
178910037SARM gem5 Developers    if (currState->stage2Tran) {
179010037SARM gem5 Developers        delete currState->stage2Tran;
179110037SARM gem5 Developers        currState->stage2Tran = NULL;
179210037SARM gem5 Developers    }
179310037SARM gem5 Developers
179410037SARM gem5 Developers    DPRINTF(TLBVerbose, "calling doLongDescriptor for vaddr:%#x\n",
179510037SARM gem5 Developers            currState->vaddr_tainted);
179610037SARM gem5 Developers    doLongDescriptor();
179710037SARM gem5 Developers
179810037SARM gem5 Developers    stateQueues[curr_lookup_level].pop_front();
179910037SARM gem5 Developers
180010037SARM gem5 Developers    if (currState->fault != NoFault) {
180110037SARM gem5 Developers        // A fault was generated
180210037SARM gem5 Developers        currState->transState->finish(currState->fault, currState->req,
180310037SARM gem5 Developers                                      currState->tc, currState->mode);
180410037SARM gem5 Developers
180510037SARM gem5 Developers        pending = false;
180610037SARM gem5 Developers        nextWalk(currState->tc);
180710037SARM gem5 Developers
180810037SARM gem5 Developers        currState->req = NULL;
180910037SARM gem5 Developers        currState->tc = NULL;
181010037SARM gem5 Developers        currState->delayed = false;
181110037SARM gem5 Developers        delete currState;
181210037SARM gem5 Developers    } else if (!currState->delayed) {
181310037SARM gem5 Developers        // No additional lookups required
181410037SARM gem5 Developers        // Don't finish the translation if a stage 2 look up is underway
181510037SARM gem5 Developers        if (!currState->doingStage2) {
181610037SARM gem5 Developers            DPRINTF(TLBVerbose, "calling translateTiming again\n");
181710037SARM gem5 Developers            currState->fault = tlb->translateTiming(currState->req, currState->tc,
181810037SARM gem5 Developers                                                    currState->transState,
181910037SARM gem5 Developers                                                    currState->mode);
182010037SARM gem5 Developers        }
182110037SARM gem5 Developers
182210037SARM gem5 Developers        pending = false;
182310037SARM gem5 Developers        nextWalk(currState->tc);
182410037SARM gem5 Developers
182510037SARM gem5 Developers        currState->req = NULL;
182610037SARM gem5 Developers        currState->tc = NULL;
182710037SARM gem5 Developers        currState->delayed = false;
182810037SARM gem5 Developers        delete currState;
182910037SARM gem5 Developers    } else {
183010037SARM gem5 Developers        if (curr_lookup_level >= MAX_LOOKUP_LEVELS - 1)
183110037SARM gem5 Developers            panic("Max. number of lookups already reached in table walk\n");
183210037SARM gem5 Developers        // Need to perform additional lookups
183310037SARM gem5 Developers        stateQueues[currState->longDesc.lookupLevel].push_back(currState);
183410037SARM gem5 Developers    }
183510037SARM gem5 Developers    currState = NULL;
183610037SARM gem5 Developers}
183710037SARM gem5 Developers
183810037SARM gem5 Developers
183910037SARM gem5 Developersvoid
18407728SAli.Saidi@ARM.comTableWalker::nextWalk(ThreadContext *tc)
18417728SAli.Saidi@ARM.com{
18427728SAli.Saidi@ARM.com    if (pendingQueue.size())
18439309Sandreas.hansson@arm.com        schedule(doProcessEvent, clockEdge(Cycles(1)));
184410509SAli.Saidi@ARM.com    else
184510509SAli.Saidi@ARM.com        completeDrain();
18467728SAli.Saidi@ARM.com}
18477728SAli.Saidi@ARM.com
184810037SARM gem5 Developersbool
184910037SARM gem5 DevelopersTableWalker::fetchDescriptor(Addr descAddr, uint8_t *data, int numBytes,
185010037SARM gem5 Developers    Request::Flags flags, int queueIndex, Event *event,
185110037SARM gem5 Developers    void (TableWalker::*doDescriptor)())
185210037SARM gem5 Developers{
185310037SARM gem5 Developers    bool isTiming = currState->timing;
18547728SAli.Saidi@ARM.com
185510037SARM gem5 Developers    // do the requests for the page table descriptors have to go through the
185610037SARM gem5 Developers    // second stage MMU
185710037SARM gem5 Developers    if (currState->stage2Req) {
185810037SARM gem5 Developers        Fault fault;
185910037SARM gem5 Developers        flags = flags | TLB::MustBeOne;
186010037SARM gem5 Developers
186110037SARM gem5 Developers        if (isTiming) {
186210037SARM gem5 Developers            Stage2MMU::Stage2Translation *tran = new
186310037SARM gem5 Developers                Stage2MMU::Stage2Translation(*stage2Mmu, data, event,
186410037SARM gem5 Developers                                             currState->vaddr);
186510037SARM gem5 Developers            currState->stage2Tran = tran;
186610037SARM gem5 Developers            stage2Mmu->readDataTimed(currState->tc, descAddr, tran, numBytes,
186710037SARM gem5 Developers                                     flags, masterId);
186810037SARM gem5 Developers            fault = tran->fault;
186910037SARM gem5 Developers        } else {
187010037SARM gem5 Developers            fault = stage2Mmu->readDataUntimed(currState->tc,
187110037SARM gem5 Developers                currState->vaddr, descAddr, data, numBytes, flags, masterId,
187210037SARM gem5 Developers                currState->functional);
187310037SARM gem5 Developers        }
187410037SARM gem5 Developers
187510037SARM gem5 Developers        if (fault != NoFault) {
187610037SARM gem5 Developers            currState->fault = fault;
187710037SARM gem5 Developers        }
187810037SARM gem5 Developers        if (isTiming) {
187910037SARM gem5 Developers            if (queueIndex >= 0) {
188010037SARM gem5 Developers                DPRINTF(TLBVerbose, "Adding to walker fifo: queue size before adding: %d\n",
188110037SARM gem5 Developers                        stateQueues[queueIndex].size());
188210037SARM gem5 Developers                stateQueues[queueIndex].push_back(currState);
188310037SARM gem5 Developers                currState = NULL;
188410037SARM gem5 Developers            }
188510037SARM gem5 Developers        } else {
188610037SARM gem5 Developers            (this->*doDescriptor)();
188710037SARM gem5 Developers        }
188810037SARM gem5 Developers    } else {
188910037SARM gem5 Developers        if (isTiming) {
189010037SARM gem5 Developers            port.dmaAction(MemCmd::ReadReq, descAddr, numBytes, event, data,
189110037SARM gem5 Developers                           currState->tc->getCpuPtr()->clockPeriod(), flags);
189210037SARM gem5 Developers            if (queueIndex >= 0) {
189310037SARM gem5 Developers                DPRINTF(TLBVerbose, "Adding to walker fifo: queue size before adding: %d\n",
189410037SARM gem5 Developers                        stateQueues[queueIndex].size());
189510037SARM gem5 Developers                stateQueues[queueIndex].push_back(currState);
189610037SARM gem5 Developers                currState = NULL;
189710037SARM gem5 Developers            }
189810037SARM gem5 Developers        } else if (!currState->functional) {
189910037SARM gem5 Developers            port.dmaAction(MemCmd::ReadReq, descAddr, numBytes, NULL, data,
190010037SARM gem5 Developers                           currState->tc->getCpuPtr()->clockPeriod(), flags);
190110037SARM gem5 Developers            (this->*doDescriptor)();
190210037SARM gem5 Developers        } else {
190310037SARM gem5 Developers            RequestPtr req = new Request(descAddr, numBytes, flags, masterId);
190410037SARM gem5 Developers            req->taskId(ContextSwitchTaskId::DMA);
190510037SARM gem5 Developers            PacketPtr  pkt = new Packet(req, MemCmd::ReadReq);
190610037SARM gem5 Developers            pkt->dataStatic(data);
190710037SARM gem5 Developers            port.sendFunctional(pkt);
190810037SARM gem5 Developers            (this->*doDescriptor)();
190910037SARM gem5 Developers            delete req;
191010037SARM gem5 Developers            delete pkt;
191110037SARM gem5 Developers        }
191210037SARM gem5 Developers    }
191310037SARM gem5 Developers    return (isTiming);
191410037SARM gem5 Developers}
191510037SARM gem5 Developers
191610037SARM gem5 Developersvoid
191710037SARM gem5 DevelopersTableWalker::insertTableEntry(DescriptorBase &descriptor, bool longDescriptor)
191810037SARM gem5 Developers{
191910037SARM gem5 Developers    TlbEntry te;
192010037SARM gem5 Developers
192110037SARM gem5 Developers    // Create and fill a new page table entry
192210037SARM gem5 Developers    te.valid          = true;
192310037SARM gem5 Developers    te.longDescFormat = longDescriptor;
192410037SARM gem5 Developers    te.isHyp          = currState->isHyp;
192510037SARM gem5 Developers    te.asid           = currState->asid;
192610037SARM gem5 Developers    te.vmid           = currState->vmid;
192710037SARM gem5 Developers    te.N              = descriptor.offsetBits();
192810037SARM gem5 Developers    te.vpn            = currState->vaddr >> te.N;
192910037SARM gem5 Developers    te.size           = (1<<te.N) - 1;
193010037SARM gem5 Developers    te.pfn            = descriptor.pfn();
193110037SARM gem5 Developers    te.domain         = descriptor.domain();
193210037SARM gem5 Developers    te.lookupLevel    = descriptor.lookupLevel;
193310037SARM gem5 Developers    te.ns             = !descriptor.secure(haveSecurity, currState) || isStage2;
193410037SARM gem5 Developers    te.nstid          = !currState->isSecure;
193510037SARM gem5 Developers    te.xn             = descriptor.xn();
193610037SARM gem5 Developers    if (currState->aarch64)
193710037SARM gem5 Developers        te.el         = currState->el;
193810037SARM gem5 Developers    else
193910037SARM gem5 Developers        te.el         = 1;
194010037SARM gem5 Developers
194110037SARM gem5 Developers    // ASID has no meaning for stage 2 TLB entries, so mark all stage 2 entries
194210037SARM gem5 Developers    // as global
194310037SARM gem5 Developers    te.global         = descriptor.global(currState) || isStage2;
194410037SARM gem5 Developers    if (longDescriptor) {
194510037SARM gem5 Developers        LongDescriptor lDescriptor =
194610037SARM gem5 Developers            dynamic_cast<LongDescriptor &>(descriptor);
194710037SARM gem5 Developers
194810037SARM gem5 Developers        te.xn |= currState->xnTable;
194910037SARM gem5 Developers        te.pxn = currState->pxnTable || lDescriptor.pxn();
195010037SARM gem5 Developers        if (isStage2) {
195110037SARM gem5 Developers            // this is actually the HAP field, but its stored in the same bit
195210037SARM gem5 Developers            // possitions as the AP field in a stage 1 translation.
195310037SARM gem5 Developers            te.hap = lDescriptor.ap();
195410037SARM gem5 Developers        } else {
195510037SARM gem5 Developers           te.ap = ((!currState->rwTable || descriptor.ap() >> 1) << 1) |
195610037SARM gem5 Developers               (currState->userTable && (descriptor.ap() & 0x1));
195710037SARM gem5 Developers        }
195810037SARM gem5 Developers        if (currState->aarch64)
195910037SARM gem5 Developers            memAttrsAArch64(currState->tc, te, currState->longDesc.attrIndx(),
196010037SARM gem5 Developers                            currState->longDesc.sh());
196110037SARM gem5 Developers        else
196210037SARM gem5 Developers            memAttrsLPAE(currState->tc, te, lDescriptor);
196310037SARM gem5 Developers    } else {
196410037SARM gem5 Developers        te.ap = descriptor.ap();
196510037SARM gem5 Developers        memAttrs(currState->tc, te, currState->sctlr, descriptor.texcb(),
196610037SARM gem5 Developers                 descriptor.shareable());
196710037SARM gem5 Developers    }
196810037SARM gem5 Developers
196910037SARM gem5 Developers    // Debug output
197010037SARM gem5 Developers    DPRINTF(TLB, descriptor.dbgHeader().c_str());
197110037SARM gem5 Developers    DPRINTF(TLB, " - N:%d pfn:%#x size:%#x global:%d valid:%d\n",
197210037SARM gem5 Developers            te.N, te.pfn, te.size, te.global, te.valid);
197310037SARM gem5 Developers    DPRINTF(TLB, " - vpn:%#x xn:%d pxn:%d ap:%d domain:%d asid:%d "
197410037SARM gem5 Developers            "vmid:%d hyp:%d nc:%d ns:%d\n", te.vpn, te.xn, te.pxn,
197510037SARM gem5 Developers            te.ap, static_cast<uint8_t>(te.domain), te.asid, te.vmid, te.isHyp,
197610037SARM gem5 Developers            te.nonCacheable, te.ns);
197710037SARM gem5 Developers    DPRINTF(TLB, " - domain from L%d desc:%d data:%#x\n",
197810037SARM gem5 Developers            descriptor.lookupLevel, static_cast<uint8_t>(descriptor.domain()),
197910037SARM gem5 Developers            descriptor.getRawData());
198010037SARM gem5 Developers
198110037SARM gem5 Developers    // Insert the entry into the TLB
198210037SARM gem5 Developers    tlb->insert(currState->vaddr, te);
198310037SARM gem5 Developers    if (!currState->timing) {
198410037SARM gem5 Developers        currState->tc  = NULL;
198510037SARM gem5 Developers        currState->req = NULL;
198610037SARM gem5 Developers    }
198710037SARM gem5 Developers}
19887728SAli.Saidi@ARM.com
19897404SAli.Saidi@ARM.comArmISA::TableWalker *
19907404SAli.Saidi@ARM.comArmTableWalkerParams::create()
19917404SAli.Saidi@ARM.com{
19927404SAli.Saidi@ARM.com    return new ArmISA::TableWalker(this);
19937404SAli.Saidi@ARM.com}
19947404SAli.Saidi@ARM.com
199510037SARM gem5 DevelopersLookupLevel
199610037SARM gem5 DevelopersTableWalker::toLookupLevel(uint8_t lookup_level_as_int)
199710037SARM gem5 Developers{
199810037SARM gem5 Developers    switch (lookup_level_as_int) {
199910037SARM gem5 Developers      case L1:
200010037SARM gem5 Developers        return L1;
200110037SARM gem5 Developers      case L2:
200210037SARM gem5 Developers        return L2;
200310037SARM gem5 Developers      case L3:
200410037SARM gem5 Developers        return L3;
200510037SARM gem5 Developers      default:
200610037SARM gem5 Developers        panic("Invalid lookup level conversion");
200710037SARM gem5 Developers    }
200810037SARM gem5 Developers}
2009