table_walker.cc revision 11517
17404SAli.Saidi@ARM.com/* 210717Sandreas.hansson@arm.com * Copyright (c) 2010, 2012-2015 ARM Limited 37404SAli.Saidi@ARM.com * All rights reserved 47404SAli.Saidi@ARM.com * 57404SAli.Saidi@ARM.com * The license below extends only to copyright in the software and shall 67404SAli.Saidi@ARM.com * not be construed as granting a license to any other intellectual 77404SAli.Saidi@ARM.com * property including but not limited to intellectual property relating 87404SAli.Saidi@ARM.com * to a hardware implementation of the functionality of the software 97404SAli.Saidi@ARM.com * licensed hereunder. You may use the software subject to the license 107404SAli.Saidi@ARM.com * terms below provided that you ensure that this notice is replicated 117404SAli.Saidi@ARM.com * unmodified and in its entirety in all distributions of the software, 127404SAli.Saidi@ARM.com * modified or unmodified, in source code or in binary form. 137404SAli.Saidi@ARM.com * 147404SAli.Saidi@ARM.com * Redistribution and use in source and binary forms, with or without 157404SAli.Saidi@ARM.com * modification, are permitted provided that the following conditions are 167404SAli.Saidi@ARM.com * met: redistributions of source code must retain the above copyright 177404SAli.Saidi@ARM.com * notice, this list of conditions and the following disclaimer; 187404SAli.Saidi@ARM.com * redistributions in binary form must reproduce the above copyright 197404SAli.Saidi@ARM.com * notice, this list of conditions and the following disclaimer in the 207404SAli.Saidi@ARM.com * documentation and/or other materials provided with the distribution; 217404SAli.Saidi@ARM.com * neither the name of the copyright holders nor the names of its 227404SAli.Saidi@ARM.com * contributors may be used to endorse or promote products derived from 237404SAli.Saidi@ARM.com * this software without specific prior written permission. 247404SAli.Saidi@ARM.com * 257404SAli.Saidi@ARM.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 267404SAli.Saidi@ARM.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 277404SAli.Saidi@ARM.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 287404SAli.Saidi@ARM.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 297404SAli.Saidi@ARM.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 307404SAli.Saidi@ARM.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 317404SAli.Saidi@ARM.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 327404SAli.Saidi@ARM.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 337404SAli.Saidi@ARM.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 347404SAli.Saidi@ARM.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 357404SAli.Saidi@ARM.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 367404SAli.Saidi@ARM.com * 377404SAli.Saidi@ARM.com * Authors: Ali Saidi 3810037SARM gem5 Developers * Giacomo Gabrielli 397404SAli.Saidi@ARM.com */ 4010873Sandreas.sandberg@arm.com#include "arch/arm/table_walker.hh" 417404SAli.Saidi@ARM.com 4210474Sandreas.hansson@arm.com#include <memory> 4310474Sandreas.hansson@arm.com 447404SAli.Saidi@ARM.com#include "arch/arm/faults.hh" 4510037SARM gem5 Developers#include "arch/arm/stage2_mmu.hh" 4610037SARM gem5 Developers#include "arch/arm/system.hh" 477404SAli.Saidi@ARM.com#include "arch/arm/tlb.hh" 487728SAli.Saidi@ARM.com#include "cpu/base.hh" 497404SAli.Saidi@ARM.com#include "cpu/thread_context.hh" 508245Snate@binkert.org#include "debug/Checkpoint.hh" 519152Satgutier@umich.edu#include "debug/Drain.hh" 528245Snate@binkert.org#include "debug/TLB.hh" 538245Snate@binkert.org#include "debug/TLBVerbose.hh" 5410873Sandreas.sandberg@arm.com#include "dev/dma_device.hh" 557748SAli.Saidi@ARM.com#include "sim/system.hh" 567404SAli.Saidi@ARM.com 577404SAli.Saidi@ARM.comusing namespace ArmISA; 587404SAli.Saidi@ARM.com 597404SAli.Saidi@ARM.comTableWalker::TableWalker(const Params *p) 6010913Sandreas.sandberg@arm.com : MemObject(p), 6110717Sandreas.hansson@arm.com stage2Mmu(NULL), port(NULL), masterId(Request::invldMasterId), 6210717Sandreas.hansson@arm.com isStage2(p->is_stage2), tlb(NULL), 6310717Sandreas.hansson@arm.com currState(NULL), pending(false), 649258SAli.Saidi@ARM.com numSquashable(p->num_squash_per_cycle), 6510621SCurtis.Dunham@arm.com pendingReqs(0), 6610621SCurtis.Dunham@arm.com pendingChangeTick(curTick()), 6710037SARM gem5 Developers doL1DescEvent(this), doL2DescEvent(this), 6810037SARM gem5 Developers doL0LongDescEvent(this), doL1LongDescEvent(this), doL2LongDescEvent(this), 6910037SARM gem5 Developers doL3LongDescEvent(this), 7010037SARM gem5 Developers doProcessEvent(this) 717439Sdam.sunwoo@arm.com{ 727576SAli.Saidi@ARM.com sctlr = 0; 7310037SARM gem5 Developers 7410037SARM gem5 Developers // Cache system-level properties 7510037SARM gem5 Developers if (FullSystem) { 7610717Sandreas.hansson@arm.com ArmSystem *armSys = dynamic_cast<ArmSystem *>(p->sys); 7710037SARM gem5 Developers assert(armSys); 7810037SARM gem5 Developers haveSecurity = armSys->haveSecurity(); 7910037SARM gem5 Developers _haveLPAE = armSys->haveLPAE(); 8010037SARM gem5 Developers _haveVirtualization = armSys->haveVirtualization(); 8110037SARM gem5 Developers physAddrRange = armSys->physAddrRange(); 8210037SARM gem5 Developers _haveLargeAsid64 = armSys->haveLargeAsid64(); 8310037SARM gem5 Developers } else { 8410037SARM gem5 Developers haveSecurity = _haveLPAE = _haveVirtualization = false; 8510037SARM gem5 Developers _haveLargeAsid64 = false; 8610037SARM gem5 Developers physAddrRange = 32; 8710037SARM gem5 Developers } 8810037SARM gem5 Developers 897439Sdam.sunwoo@arm.com} 907404SAli.Saidi@ARM.com 917404SAli.Saidi@ARM.comTableWalker::~TableWalker() 927404SAli.Saidi@ARM.com{ 937404SAli.Saidi@ARM.com ; 947404SAli.Saidi@ARM.com} 957404SAli.Saidi@ARM.com 9610717Sandreas.hansson@arm.comvoid 9710717Sandreas.hansson@arm.comTableWalker::setMMU(Stage2MMU *m, MasterID master_id) 9810717Sandreas.hansson@arm.com{ 9910717Sandreas.hansson@arm.com stage2Mmu = m; 10010717Sandreas.hansson@arm.com port = &m->getPort(); 10110717Sandreas.hansson@arm.com masterId = master_id; 10210717Sandreas.hansson@arm.com} 10310717Sandreas.hansson@arm.com 10410717Sandreas.hansson@arm.comvoid 10510717Sandreas.hansson@arm.comTableWalker::init() 10610717Sandreas.hansson@arm.com{ 10710717Sandreas.hansson@arm.com fatal_if(!stage2Mmu, "Table walker must have a valid stage-2 MMU\n"); 10810717Sandreas.hansson@arm.com fatal_if(!port, "Table walker must have a valid port\n"); 10910717Sandreas.hansson@arm.com fatal_if(!tlb, "Table walker must have a valid TLB\n"); 11010717Sandreas.hansson@arm.com} 11110717Sandreas.hansson@arm.com 11210717Sandreas.hansson@arm.comBaseMasterPort& 11310717Sandreas.hansson@arm.comTableWalker::getMasterPort(const std::string &if_name, PortID idx) 11410717Sandreas.hansson@arm.com{ 11510717Sandreas.hansson@arm.com if (if_name == "port") { 11610717Sandreas.hansson@arm.com if (!isStage2) { 11710717Sandreas.hansson@arm.com return *port; 11810717Sandreas.hansson@arm.com } else { 11910717Sandreas.hansson@arm.com fatal("Cannot access table walker port through stage-two walker\n"); 12010717Sandreas.hansson@arm.com } 12110717Sandreas.hansson@arm.com } 12210717Sandreas.hansson@arm.com return MemObject::getMasterPort(if_name, idx); 12310717Sandreas.hansson@arm.com} 12410717Sandreas.hansson@arm.com 12510537Sandreas.hansson@arm.comTableWalker::WalkerState::WalkerState() : 12610537Sandreas.hansson@arm.com tc(nullptr), aarch64(false), el(EL0), physAddrRange(0), req(nullptr), 12710537Sandreas.hansson@arm.com asid(0), vmid(0), isHyp(false), transState(nullptr), 12810537Sandreas.hansson@arm.com vaddr(0), vaddr_tainted(0), isWrite(false), isFetch(false), isSecure(false), 12910537Sandreas.hansson@arm.com secureLookup(false), rwTable(false), userTable(false), xnTable(false), 13010537Sandreas.hansson@arm.com pxnTable(false), stage2Req(false), doingStage2(false), 13110537Sandreas.hansson@arm.com stage2Tran(nullptr), timing(false), functional(false), 13210537Sandreas.hansson@arm.com mode(BaseTLB::Read), tranType(TLB::NormalTran), l2Desc(l1Desc), 13310537Sandreas.hansson@arm.com delayed(false), tableWalker(nullptr) 13410037SARM gem5 Developers{ 13510037SARM gem5 Developers} 13610037SARM gem5 Developers 1379152Satgutier@umich.eduvoid 1389152Satgutier@umich.eduTableWalker::completeDrain() 1399152Satgutier@umich.edu{ 14010913Sandreas.sandberg@arm.com if (drainState() == DrainState::Draining && 14110913Sandreas.sandberg@arm.com stateQueues[L1].empty() && stateQueues[L2].empty() && 1429152Satgutier@umich.edu pendingQueue.empty()) { 14310913Sandreas.sandberg@arm.com 1449152Satgutier@umich.edu DPRINTF(Drain, "TableWalker done draining, processing drain event\n"); 14510913Sandreas.sandberg@arm.com signalDrainDone(); 1469152Satgutier@umich.edu } 1479152Satgutier@umich.edu} 1489152Satgutier@umich.edu 14910913Sandreas.sandberg@arm.comDrainState 15010913Sandreas.sandberg@arm.comTableWalker::drain() 1517404SAli.Saidi@ARM.com{ 15210037SARM gem5 Developers bool state_queues_not_empty = false; 1539152Satgutier@umich.edu 15410037SARM gem5 Developers for (int i = 0; i < MAX_LOOKUP_LEVELS; ++i) { 15510037SARM gem5 Developers if (!stateQueues[i].empty()) { 15610037SARM gem5 Developers state_queues_not_empty = true; 15710037SARM gem5 Developers break; 15810037SARM gem5 Developers } 15910037SARM gem5 Developers } 16010037SARM gem5 Developers 16110037SARM gem5 Developers if (state_queues_not_empty || pendingQueue.size()) { 1629152Satgutier@umich.edu DPRINTF(Drain, "TableWalker not drained\n"); 16310913Sandreas.sandberg@arm.com return DrainState::Draining; 16410037SARM gem5 Developers } else { 16510037SARM gem5 Developers DPRINTF(Drain, "TableWalker free, no need to drain\n"); 16610913Sandreas.sandberg@arm.com return DrainState::Drained; 1677733SAli.Saidi@ARM.com } 1687404SAli.Saidi@ARM.com} 1697404SAli.Saidi@ARM.com 1707748SAli.Saidi@ARM.comvoid 1719342SAndreas.Sandberg@arm.comTableWalker::drainResume() 1727748SAli.Saidi@ARM.com{ 1739524SAndreas.Sandberg@ARM.com if (params()->sys->isTimingMode() && currState) { 1749152Satgutier@umich.edu delete currState; 1759152Satgutier@umich.edu currState = NULL; 17610621SCurtis.Dunham@arm.com pendingChange(); 1777748SAli.Saidi@ARM.com } 1787748SAli.Saidi@ARM.com} 1797748SAli.Saidi@ARM.com 1807404SAli.Saidi@ARM.comFault 18110037SARM gem5 DevelopersTableWalker::walk(RequestPtr _req, ThreadContext *_tc, uint16_t _asid, 18210037SARM gem5 Developers uint8_t _vmid, bool _isHyp, TLB::Mode _mode, 18310037SARM gem5 Developers TLB::Translation *_trans, bool _timing, bool _functional, 18410037SARM gem5 Developers bool secure, TLB::ArmTranslationType tranType) 1857404SAli.Saidi@ARM.com{ 1868733Sgeoffrey.blake@arm.com assert(!(_functional && _timing)); 18710621SCurtis.Dunham@arm.com ++statWalks; 18810621SCurtis.Dunham@arm.com 18910109SGeoffrey.Blake@arm.com WalkerState *savedCurrState = NULL; 19010037SARM gem5 Developers 19110109SGeoffrey.Blake@arm.com if (!currState && !_functional) { 1927439Sdam.sunwoo@arm.com // For atomic mode, a new WalkerState instance should be only created 1937439Sdam.sunwoo@arm.com // once per TLB. For timing mode, a new instance is generated for every 1947439Sdam.sunwoo@arm.com // TLB miss. 1957439Sdam.sunwoo@arm.com DPRINTF(TLBVerbose, "creating new instance of WalkerState\n"); 1967404SAli.Saidi@ARM.com 1977439Sdam.sunwoo@arm.com currState = new WalkerState(); 1987439Sdam.sunwoo@arm.com currState->tableWalker = this; 19910109SGeoffrey.Blake@arm.com } else if (_functional) { 20010109SGeoffrey.Blake@arm.com // If we are mixing functional mode with timing (or even 20110109SGeoffrey.Blake@arm.com // atomic), we need to to be careful and clean up after 20210109SGeoffrey.Blake@arm.com // ourselves to not risk getting into an inconsistent state. 20310109SGeoffrey.Blake@arm.com DPRINTF(TLBVerbose, "creating functional instance of WalkerState\n"); 20410109SGeoffrey.Blake@arm.com savedCurrState = currState; 20510109SGeoffrey.Blake@arm.com currState = new WalkerState(); 20610109SGeoffrey.Blake@arm.com currState->tableWalker = this; 2078202SAli.Saidi@ARM.com } else if (_timing) { 2088202SAli.Saidi@ARM.com // This is a translation that was completed and then faulted again 2098202SAli.Saidi@ARM.com // because some underlying parameters that affect the translation 2108202SAli.Saidi@ARM.com // changed out from under us (e.g. asid). It will either be a 2118202SAli.Saidi@ARM.com // misprediction, in which case nothing will happen or we'll use 2128202SAli.Saidi@ARM.com // this fault to re-execute the faulting instruction which should clean 2138202SAli.Saidi@ARM.com // up everything. 21410037SARM gem5 Developers if (currState->vaddr_tainted == _req->getVaddr()) { 21510621SCurtis.Dunham@arm.com ++statSquashedBefore; 21610474Sandreas.hansson@arm.com return std::make_shared<ReExec>(); 2178202SAli.Saidi@ARM.com } 2187439Sdam.sunwoo@arm.com } 21910621SCurtis.Dunham@arm.com pendingChange(); 2207439Sdam.sunwoo@arm.com 22110621SCurtis.Dunham@arm.com currState->startTime = curTick(); 2227439Sdam.sunwoo@arm.com currState->tc = _tc; 22311517SCurtis.Dunham@arm.com // ARM DDI 0487A.f (ARMv8 ARM) pg J8-5672 22411517SCurtis.Dunham@arm.com // aarch32/translation/translation/AArch32.TranslateAddress dictates 22511517SCurtis.Dunham@arm.com // even AArch32 EL0 will use AArch64 translation if EL1 is in AArch64. 22611517SCurtis.Dunham@arm.com currState->aarch64 = opModeIs64(currOpMode(_tc)) || 22711517SCurtis.Dunham@arm.com ((currEL(_tc) == EL0) && ELIs64(_tc, EL1)); 22810037SARM gem5 Developers currState->el = currEL(_tc); 2297439Sdam.sunwoo@arm.com currState->transState = _trans; 2307439Sdam.sunwoo@arm.com currState->req = _req; 2317439Sdam.sunwoo@arm.com currState->fault = NoFault; 23210037SARM gem5 Developers currState->asid = _asid; 23310037SARM gem5 Developers currState->vmid = _vmid; 23410037SARM gem5 Developers currState->isHyp = _isHyp; 2357439Sdam.sunwoo@arm.com currState->timing = _timing; 2368733Sgeoffrey.blake@arm.com currState->functional = _functional; 2377439Sdam.sunwoo@arm.com currState->mode = _mode; 23810037SARM gem5 Developers currState->tranType = tranType; 23910037SARM gem5 Developers currState->isSecure = secure; 24010037SARM gem5 Developers currState->physAddrRange = physAddrRange; 2417404SAli.Saidi@ARM.com 2427436Sdam.sunwoo@arm.com /** @todo These should be cached or grabbed from cached copies in 2437436Sdam.sunwoo@arm.com the TLB, all these miscreg reads are expensive */ 24410037SARM gem5 Developers currState->vaddr_tainted = currState->req->getVaddr(); 24510037SARM gem5 Developers if (currState->aarch64) 24610037SARM gem5 Developers currState->vaddr = purifyTaggedAddr(currState->vaddr_tainted, 24710037SARM gem5 Developers currState->tc, currState->el); 24810037SARM gem5 Developers else 24910037SARM gem5 Developers currState->vaddr = currState->vaddr_tainted; 25010037SARM gem5 Developers 25110037SARM gem5 Developers if (currState->aarch64) { 25210037SARM gem5 Developers switch (currState->el) { 25310037SARM gem5 Developers case EL0: 25410037SARM gem5 Developers case EL1: 25510037SARM gem5 Developers currState->sctlr = currState->tc->readMiscReg(MISCREG_SCTLR_EL1); 25610324SCurtis.Dunham@arm.com currState->tcr = currState->tc->readMiscReg(MISCREG_TCR_EL1); 25710037SARM gem5 Developers break; 25810037SARM gem5 Developers // @todo: uncomment this to enable Virtualization 25910037SARM gem5 Developers // case EL2: 26010037SARM gem5 Developers // assert(haveVirtualization); 26110037SARM gem5 Developers // currState->sctlr = currState->tc->readMiscReg(MISCREG_SCTLR_EL2); 26210324SCurtis.Dunham@arm.com // currState->tcr = currState->tc->readMiscReg(MISCREG_TCR_EL2); 26310037SARM gem5 Developers // break; 26410037SARM gem5 Developers case EL3: 26510037SARM gem5 Developers assert(haveSecurity); 26610037SARM gem5 Developers currState->sctlr = currState->tc->readMiscReg(MISCREG_SCTLR_EL3); 26710324SCurtis.Dunham@arm.com currState->tcr = currState->tc->readMiscReg(MISCREG_TCR_EL3); 26810037SARM gem5 Developers break; 26910037SARM gem5 Developers default: 27010037SARM gem5 Developers panic("Invalid exception level"); 27110037SARM gem5 Developers break; 27210037SARM gem5 Developers } 27310037SARM gem5 Developers } else { 27410037SARM gem5 Developers currState->sctlr = currState->tc->readMiscReg(flattenMiscRegNsBanked( 27510037SARM gem5 Developers MISCREG_SCTLR, currState->tc, !currState->isSecure)); 27610037SARM gem5 Developers currState->ttbcr = currState->tc->readMiscReg(flattenMiscRegNsBanked( 27710037SARM gem5 Developers MISCREG_TTBCR, currState->tc, !currState->isSecure)); 27810037SARM gem5 Developers currState->htcr = currState->tc->readMiscReg(MISCREG_HTCR); 27910037SARM gem5 Developers currState->hcr = currState->tc->readMiscReg(MISCREG_HCR); 28010037SARM gem5 Developers currState->vtcr = currState->tc->readMiscReg(MISCREG_VTCR); 28110037SARM gem5 Developers } 2827439Sdam.sunwoo@arm.com sctlr = currState->sctlr; 2837439Sdam.sunwoo@arm.com 2847439Sdam.sunwoo@arm.com currState->isFetch = (currState->mode == TLB::Execute); 2857439Sdam.sunwoo@arm.com currState->isWrite = (currState->mode == TLB::Write); 2867439Sdam.sunwoo@arm.com 28710621SCurtis.Dunham@arm.com statRequestOrigin[REQUESTED][currState->isFetch]++; 28810621SCurtis.Dunham@arm.com 28910037SARM gem5 Developers // We only do a second stage of translation if we're not secure, or in 29010037SARM gem5 Developers // hyp mode, the second stage MMU is enabled, and this table walker 29110037SARM gem5 Developers // instance is the first stage. 29210037SARM gem5 Developers currState->doingStage2 = false; 29310037SARM gem5 Developers // @todo: for now disable this in AArch64 (HCR is not set) 29410037SARM gem5 Developers currState->stage2Req = !currState->aarch64 && currState->hcr.vm && 29510037SARM gem5 Developers !isStage2 && !currState->isSecure && !currState->isHyp; 2967728SAli.Saidi@ARM.com 29711517SCurtis.Dunham@arm.com bool long_desc_format = currState->aarch64 || _isHyp || isStage2 || 29811517SCurtis.Dunham@arm.com longDescFormatInUse(currState->tc); 29910037SARM gem5 Developers 30010037SARM gem5 Developers if (long_desc_format) { 30110037SARM gem5 Developers // Helper variables used for hierarchical permissions 30210037SARM gem5 Developers currState->secureLookup = currState->isSecure; 30310037SARM gem5 Developers currState->rwTable = true; 30410037SARM gem5 Developers currState->userTable = true; 30510037SARM gem5 Developers currState->xnTable = false; 30610037SARM gem5 Developers currState->pxnTable = false; 30710621SCurtis.Dunham@arm.com 30810621SCurtis.Dunham@arm.com ++statWalksLongDescriptor; 30910621SCurtis.Dunham@arm.com } else { 31010621SCurtis.Dunham@arm.com ++statWalksShortDescriptor; 31110037SARM gem5 Developers } 31210037SARM gem5 Developers 31310037SARM gem5 Developers if (!currState->timing) { 31410109SGeoffrey.Blake@arm.com Fault fault = NoFault; 31510037SARM gem5 Developers if (currState->aarch64) 31610109SGeoffrey.Blake@arm.com fault = processWalkAArch64(); 31710037SARM gem5 Developers else if (long_desc_format) 31810109SGeoffrey.Blake@arm.com fault = processWalkLPAE(); 31910037SARM gem5 Developers else 32010109SGeoffrey.Blake@arm.com fault = processWalk(); 32110109SGeoffrey.Blake@arm.com 32210109SGeoffrey.Blake@arm.com // If this was a functional non-timing access restore state to 32310109SGeoffrey.Blake@arm.com // how we found it. 32410109SGeoffrey.Blake@arm.com if (currState->functional) { 32510109SGeoffrey.Blake@arm.com delete currState; 32610109SGeoffrey.Blake@arm.com currState = savedCurrState; 32710109SGeoffrey.Blake@arm.com } 32810109SGeoffrey.Blake@arm.com return fault; 32910037SARM gem5 Developers } 3307728SAli.Saidi@ARM.com 3318067SAli.Saidi@ARM.com if (pending || pendingQueue.size()) { 3327728SAli.Saidi@ARM.com pendingQueue.push_back(currState); 3337728SAli.Saidi@ARM.com currState = NULL; 33410621SCurtis.Dunham@arm.com pendingChange(); 3357728SAli.Saidi@ARM.com } else { 3367728SAli.Saidi@ARM.com pending = true; 33710621SCurtis.Dunham@arm.com pendingChange(); 33810037SARM gem5 Developers if (currState->aarch64) 33910037SARM gem5 Developers return processWalkAArch64(); 34010037SARM gem5 Developers else if (long_desc_format) 34110037SARM gem5 Developers return processWalkLPAE(); 34210037SARM gem5 Developers else 34310037SARM gem5 Developers return processWalk(); 3447728SAli.Saidi@ARM.com } 3457728SAli.Saidi@ARM.com 3467728SAli.Saidi@ARM.com return NoFault; 3477728SAli.Saidi@ARM.com} 3487728SAli.Saidi@ARM.com 3497728SAli.Saidi@ARM.comvoid 3507728SAli.Saidi@ARM.comTableWalker::processWalkWrapper() 3517728SAli.Saidi@ARM.com{ 3527728SAli.Saidi@ARM.com assert(!currState); 3537728SAli.Saidi@ARM.com assert(pendingQueue.size()); 35410621SCurtis.Dunham@arm.com pendingChange(); 3557728SAli.Saidi@ARM.com currState = pendingQueue.front(); 3569258SAli.Saidi@ARM.com 35710037SARM gem5 Developers ExceptionLevel target_el = EL0; 35810037SARM gem5 Developers if (currState->aarch64) 35910037SARM gem5 Developers target_el = currEL(currState->tc); 36010037SARM gem5 Developers else 36110037SARM gem5 Developers target_el = EL1; 36210037SARM gem5 Developers 3639535Smrinmoy.ghosh@arm.com // Check if a previous walk filled this request already 36410037SARM gem5 Developers // @TODO Should this always be the TLB or should we look in the stage2 TLB? 36510037SARM gem5 Developers TlbEntry* te = tlb->lookup(currState->vaddr, currState->asid, 36610037SARM gem5 Developers currState->vmid, currState->isHyp, currState->isSecure, true, false, 36710037SARM gem5 Developers target_el); 3689258SAli.Saidi@ARM.com 3699535Smrinmoy.ghosh@arm.com // Check if we still need to have a walk for this request. If the requesting 3709535Smrinmoy.ghosh@arm.com // instruction has been squashed, or a previous walk has filled the TLB with 3719535Smrinmoy.ghosh@arm.com // a match, we just want to get rid of the walk. The latter could happen 3729535Smrinmoy.ghosh@arm.com // when there are multiple outstanding misses to a single page and a 3739535Smrinmoy.ghosh@arm.com // previous request has been successfully translated. 3749535Smrinmoy.ghosh@arm.com if (!currState->transState->squashed() && !te) { 3759258SAli.Saidi@ARM.com // We've got a valid request, lets process it 3769258SAli.Saidi@ARM.com pending = true; 3779258SAli.Saidi@ARM.com pendingQueue.pop_front(); 37810579SAndrew.Bardsley@arm.com // Keep currState in case one of the processWalk... calls NULLs it 37910579SAndrew.Bardsley@arm.com WalkerState *curr_state_copy = currState; 38010579SAndrew.Bardsley@arm.com Fault f; 38110037SARM gem5 Developers if (currState->aarch64) 38210579SAndrew.Bardsley@arm.com f = processWalkAArch64(); 38311517SCurtis.Dunham@arm.com else if (longDescFormatInUse(currState->tc) || 38411517SCurtis.Dunham@arm.com currState->isHyp || isStage2) 38510579SAndrew.Bardsley@arm.com f = processWalkLPAE(); 38610037SARM gem5 Developers else 38710579SAndrew.Bardsley@arm.com f = processWalk(); 38810579SAndrew.Bardsley@arm.com 38910579SAndrew.Bardsley@arm.com if (f != NoFault) { 39010579SAndrew.Bardsley@arm.com curr_state_copy->transState->finish(f, curr_state_copy->req, 39110579SAndrew.Bardsley@arm.com curr_state_copy->tc, curr_state_copy->mode); 39210579SAndrew.Bardsley@arm.com 39310579SAndrew.Bardsley@arm.com delete curr_state_copy; 39410579SAndrew.Bardsley@arm.com } 3959258SAli.Saidi@ARM.com return; 3969258SAli.Saidi@ARM.com } 3979258SAli.Saidi@ARM.com 3989258SAli.Saidi@ARM.com 3999258SAli.Saidi@ARM.com // If the instruction that we were translating for has been 4009258SAli.Saidi@ARM.com // squashed we shouldn't bother. 4019258SAli.Saidi@ARM.com unsigned num_squashed = 0; 4029258SAli.Saidi@ARM.com ThreadContext *tc = currState->tc; 4039258SAli.Saidi@ARM.com while ((num_squashed < numSquashable) && currState && 4049535Smrinmoy.ghosh@arm.com (currState->transState->squashed() || te)) { 4059258SAli.Saidi@ARM.com pendingQueue.pop_front(); 4069258SAli.Saidi@ARM.com num_squashed++; 40710621SCurtis.Dunham@arm.com statSquashedBefore++; 4089258SAli.Saidi@ARM.com 40910037SARM gem5 Developers DPRINTF(TLB, "Squashing table walk for address %#x\n", 41010037SARM gem5 Developers currState->vaddr_tainted); 4119258SAli.Saidi@ARM.com 4129535Smrinmoy.ghosh@arm.com if (currState->transState->squashed()) { 4139535Smrinmoy.ghosh@arm.com // finish the translation which will delete the translation object 41410474Sandreas.hansson@arm.com currState->transState->finish( 41510474Sandreas.hansson@arm.com std::make_shared<UnimpFault>("Squashed Inst"), 41610474Sandreas.hansson@arm.com currState->req, currState->tc, currState->mode); 4179535Smrinmoy.ghosh@arm.com } else { 4189535Smrinmoy.ghosh@arm.com // translate the request now that we know it will work 41910621SCurtis.Dunham@arm.com statWalkServiceTime.sample(curTick() - currState->startTime); 42010037SARM gem5 Developers tlb->translateTiming(currState->req, currState->tc, 42110037SARM gem5 Developers currState->transState, currState->mode); 42210037SARM gem5 Developers 4239535Smrinmoy.ghosh@arm.com } 4249258SAli.Saidi@ARM.com 4259258SAli.Saidi@ARM.com // delete the current request 4269258SAli.Saidi@ARM.com delete currState; 4279258SAli.Saidi@ARM.com 4289258SAli.Saidi@ARM.com // peak at the next one 4299535Smrinmoy.ghosh@arm.com if (pendingQueue.size()) { 4309258SAli.Saidi@ARM.com currState = pendingQueue.front(); 43110037SARM gem5 Developers te = tlb->lookup(currState->vaddr, currState->asid, 43210037SARM gem5 Developers currState->vmid, currState->isHyp, currState->isSecure, true, 43310037SARM gem5 Developers false, target_el); 4349535Smrinmoy.ghosh@arm.com } else { 4359535Smrinmoy.ghosh@arm.com // Terminate the loop, nothing more to do 4369258SAli.Saidi@ARM.com currState = NULL; 4379535Smrinmoy.ghosh@arm.com } 4389258SAli.Saidi@ARM.com } 43910621SCurtis.Dunham@arm.com pendingChange(); 4409258SAli.Saidi@ARM.com 44110621SCurtis.Dunham@arm.com // if we still have pending translations, schedule more work 4429258SAli.Saidi@ARM.com nextWalk(tc); 4439258SAli.Saidi@ARM.com currState = NULL; 4447728SAli.Saidi@ARM.com} 4457728SAli.Saidi@ARM.com 4467728SAli.Saidi@ARM.comFault 4477728SAli.Saidi@ARM.comTableWalker::processWalk() 4487728SAli.Saidi@ARM.com{ 4497404SAli.Saidi@ARM.com Addr ttbr = 0; 4507404SAli.Saidi@ARM.com 4517404SAli.Saidi@ARM.com // If translation isn't enabled, we shouldn't be here 45210037SARM gem5 Developers assert(currState->sctlr.m || isStage2); 4537404SAli.Saidi@ARM.com 45410037SARM gem5 Developers DPRINTF(TLB, "Beginning table walk for address %#x, TTBCR: %#x, bits:%#x\n", 45510037SARM gem5 Developers currState->vaddr_tainted, currState->ttbcr, mbits(currState->vaddr, 31, 45610037SARM gem5 Developers 32 - currState->ttbcr.n)); 4577406SAli.Saidi@ARM.com 45810621SCurtis.Dunham@arm.com statWalkWaitTime.sample(curTick() - currState->startTime); 45910621SCurtis.Dunham@arm.com 46010037SARM gem5 Developers if (currState->ttbcr.n == 0 || !mbits(currState->vaddr, 31, 46110037SARM gem5 Developers 32 - currState->ttbcr.n)) { 4627406SAli.Saidi@ARM.com DPRINTF(TLB, " - Selecting TTBR0\n"); 46310037SARM gem5 Developers // Check if table walk is allowed when Security Extensions are enabled 46410037SARM gem5 Developers if (haveSecurity && currState->ttbcr.pd0) { 46510037SARM gem5 Developers if (currState->isFetch) 46610474Sandreas.hansson@arm.com return std::make_shared<PrefetchAbort>( 46710474Sandreas.hansson@arm.com currState->vaddr_tainted, 46810474Sandreas.hansson@arm.com ArmFault::TranslationLL + L1, 46910474Sandreas.hansson@arm.com isStage2, 47010474Sandreas.hansson@arm.com ArmFault::VmsaTran); 47110037SARM gem5 Developers else 47210474Sandreas.hansson@arm.com return std::make_shared<DataAbort>( 47310474Sandreas.hansson@arm.com currState->vaddr_tainted, 47410474Sandreas.hansson@arm.com TlbEntry::DomainType::NoAccess, currState->isWrite, 47510474Sandreas.hansson@arm.com ArmFault::TranslationLL + L1, isStage2, 47610474Sandreas.hansson@arm.com ArmFault::VmsaTran); 47710037SARM gem5 Developers } 47810037SARM gem5 Developers ttbr = currState->tc->readMiscReg(flattenMiscRegNsBanked( 47910037SARM gem5 Developers MISCREG_TTBR0, currState->tc, !currState->isSecure)); 4807404SAli.Saidi@ARM.com } else { 4817406SAli.Saidi@ARM.com DPRINTF(TLB, " - Selecting TTBR1\n"); 48210037SARM gem5 Developers // Check if table walk is allowed when Security Extensions are enabled 48310037SARM gem5 Developers if (haveSecurity && currState->ttbcr.pd1) { 48410037SARM gem5 Developers if (currState->isFetch) 48510474Sandreas.hansson@arm.com return std::make_shared<PrefetchAbort>( 48610474Sandreas.hansson@arm.com currState->vaddr_tainted, 48710474Sandreas.hansson@arm.com ArmFault::TranslationLL + L1, 48810474Sandreas.hansson@arm.com isStage2, 48910474Sandreas.hansson@arm.com ArmFault::VmsaTran); 49010037SARM gem5 Developers else 49110474Sandreas.hansson@arm.com return std::make_shared<DataAbort>( 49210474Sandreas.hansson@arm.com currState->vaddr_tainted, 49310474Sandreas.hansson@arm.com TlbEntry::DomainType::NoAccess, currState->isWrite, 49410474Sandreas.hansson@arm.com ArmFault::TranslationLL + L1, isStage2, 49510474Sandreas.hansson@arm.com ArmFault::VmsaTran); 49610037SARM gem5 Developers } 49710037SARM gem5 Developers ttbr = currState->tc->readMiscReg(flattenMiscRegNsBanked( 49810037SARM gem5 Developers MISCREG_TTBR1, currState->tc, !currState->isSecure)); 49910037SARM gem5 Developers currState->ttbcr.n = 0; 5007404SAli.Saidi@ARM.com } 5017404SAli.Saidi@ARM.com 50210037SARM gem5 Developers Addr l1desc_addr = mbits(ttbr, 31, 14 - currState->ttbcr.n) | 50310037SARM gem5 Developers (bits(currState->vaddr, 31 - currState->ttbcr.n, 20) << 2); 50410037SARM gem5 Developers DPRINTF(TLB, " - Descriptor at address %#x (%s)\n", l1desc_addr, 50510037SARM gem5 Developers currState->isSecure ? "s" : "ns"); 5067404SAli.Saidi@ARM.com 5077404SAli.Saidi@ARM.com // Trickbox address check 5087439Sdam.sunwoo@arm.com Fault f; 50911395Sandreas.sandberg@arm.com f = testWalk(l1desc_addr, sizeof(uint32_t), 51011395Sandreas.sandberg@arm.com TlbEntry::DomainType::NoAccess, L1); 5117439Sdam.sunwoo@arm.com if (f) { 51210037SARM gem5 Developers DPRINTF(TLB, "Trickbox check caused fault on %#x\n", currState->vaddr_tainted); 5137579Sminkyu.jeong@arm.com if (currState->timing) { 5147728SAli.Saidi@ARM.com pending = false; 5157728SAli.Saidi@ARM.com nextWalk(currState->tc); 5167579Sminkyu.jeong@arm.com currState = NULL; 5177579Sminkyu.jeong@arm.com } else { 5187579Sminkyu.jeong@arm.com currState->tc = NULL; 5197579Sminkyu.jeong@arm.com currState->req = NULL; 5207579Sminkyu.jeong@arm.com } 5217579Sminkyu.jeong@arm.com return f; 5227404SAli.Saidi@ARM.com } 5237404SAli.Saidi@ARM.com 52410836Sandreas.hansson@arm.com Request::Flags flag = Request::PT_WALK; 5257946SGiacomo.Gabrielli@arm.com if (currState->sctlr.c == 0) { 52610836Sandreas.hansson@arm.com flag.set(Request::UNCACHEABLE); 5277946SGiacomo.Gabrielli@arm.com } 5287946SGiacomo.Gabrielli@arm.com 52911181Snathananel.premillieu@arm.com if (currState->isSecure) { 53011181Snathananel.premillieu@arm.com flag.set(Request::SECURE); 53111181Snathananel.premillieu@arm.com } 53211181Snathananel.premillieu@arm.com 53310037SARM gem5 Developers bool delayed; 53410037SARM gem5 Developers delayed = fetchDescriptor(l1desc_addr, (uint8_t*)&currState->l1Desc.data, 53510037SARM gem5 Developers sizeof(uint32_t), flag, L1, &doL1DescEvent, 53610037SARM gem5 Developers &TableWalker::doL1Descriptor); 53710037SARM gem5 Developers if (!delayed) { 53810037SARM gem5 Developers f = currState->fault; 53910037SARM gem5 Developers } 54010037SARM gem5 Developers 54110037SARM gem5 Developers return f; 54210037SARM gem5 Developers} 54310037SARM gem5 Developers 54410037SARM gem5 DevelopersFault 54510037SARM gem5 DevelopersTableWalker::processWalkLPAE() 54610037SARM gem5 Developers{ 54710037SARM gem5 Developers Addr ttbr, ttbr0_max, ttbr1_min, desc_addr; 54810037SARM gem5 Developers int tsz, n; 54910037SARM gem5 Developers LookupLevel start_lookup_level = L1; 55010037SARM gem5 Developers 55110037SARM gem5 Developers DPRINTF(TLB, "Beginning table walk for address %#x, TTBCR: %#x\n", 55210037SARM gem5 Developers currState->vaddr_tainted, currState->ttbcr); 55310037SARM gem5 Developers 55410621SCurtis.Dunham@arm.com statWalkWaitTime.sample(curTick() - currState->startTime); 55510621SCurtis.Dunham@arm.com 55610836Sandreas.hansson@arm.com Request::Flags flag = Request::PT_WALK; 55710037SARM gem5 Developers if (currState->isSecure) 55810037SARM gem5 Developers flag.set(Request::SECURE); 55910037SARM gem5 Developers 56010037SARM gem5 Developers // work out which base address register to use, if in hyp mode we always 56110037SARM gem5 Developers // use HTTBR 56210037SARM gem5 Developers if (isStage2) { 56310037SARM gem5 Developers DPRINTF(TLB, " - Selecting VTTBR (long-desc.)\n"); 56410037SARM gem5 Developers ttbr = currState->tc->readMiscReg(MISCREG_VTTBR); 56510037SARM gem5 Developers tsz = sext<4>(currState->vtcr.t0sz); 56610037SARM gem5 Developers start_lookup_level = currState->vtcr.sl0 ? L1 : L2; 56710037SARM gem5 Developers } else if (currState->isHyp) { 56810037SARM gem5 Developers DPRINTF(TLB, " - Selecting HTTBR (long-desc.)\n"); 56910037SARM gem5 Developers ttbr = currState->tc->readMiscReg(MISCREG_HTTBR); 57010037SARM gem5 Developers tsz = currState->htcr.t0sz; 57110037SARM gem5 Developers } else { 57211517SCurtis.Dunham@arm.com assert(longDescFormatInUse(currState->tc)); 57310037SARM gem5 Developers 57410037SARM gem5 Developers // Determine boundaries of TTBR0/1 regions 57510037SARM gem5 Developers if (currState->ttbcr.t0sz) 57610037SARM gem5 Developers ttbr0_max = (1ULL << (32 - currState->ttbcr.t0sz)) - 1; 57710037SARM gem5 Developers else if (currState->ttbcr.t1sz) 57810037SARM gem5 Developers ttbr0_max = (1ULL << 32) - 57910037SARM gem5 Developers (1ULL << (32 - currState->ttbcr.t1sz)) - 1; 58010037SARM gem5 Developers else 58110037SARM gem5 Developers ttbr0_max = (1ULL << 32) - 1; 58210037SARM gem5 Developers if (currState->ttbcr.t1sz) 58310037SARM gem5 Developers ttbr1_min = (1ULL << 32) - (1ULL << (32 - currState->ttbcr.t1sz)); 58410037SARM gem5 Developers else 58510037SARM gem5 Developers ttbr1_min = (1ULL << (32 - currState->ttbcr.t0sz)); 58610037SARM gem5 Developers 58710037SARM gem5 Developers // The following code snippet selects the appropriate translation table base 58810037SARM gem5 Developers // address (TTBR0 or TTBR1) and the appropriate starting lookup level 58910037SARM gem5 Developers // depending on the address range supported by the translation table (ARM 59010037SARM gem5 Developers // ARM issue C B3.6.4) 59110037SARM gem5 Developers if (currState->vaddr <= ttbr0_max) { 59210037SARM gem5 Developers DPRINTF(TLB, " - Selecting TTBR0 (long-desc.)\n"); 59310037SARM gem5 Developers // Check if table walk is allowed 59410037SARM gem5 Developers if (currState->ttbcr.epd0) { 59510037SARM gem5 Developers if (currState->isFetch) 59610474Sandreas.hansson@arm.com return std::make_shared<PrefetchAbort>( 59710474Sandreas.hansson@arm.com currState->vaddr_tainted, 59810474Sandreas.hansson@arm.com ArmFault::TranslationLL + L1, 59910474Sandreas.hansson@arm.com isStage2, 60010474Sandreas.hansson@arm.com ArmFault::LpaeTran); 60110037SARM gem5 Developers else 60210474Sandreas.hansson@arm.com return std::make_shared<DataAbort>( 60310474Sandreas.hansson@arm.com currState->vaddr_tainted, 60410474Sandreas.hansson@arm.com TlbEntry::DomainType::NoAccess, 60510474Sandreas.hansson@arm.com currState->isWrite, 60610474Sandreas.hansson@arm.com ArmFault::TranslationLL + L1, 60710474Sandreas.hansson@arm.com isStage2, 60810474Sandreas.hansson@arm.com ArmFault::LpaeTran); 60910037SARM gem5 Developers } 61010037SARM gem5 Developers ttbr = currState->tc->readMiscReg(flattenMiscRegNsBanked( 61110037SARM gem5 Developers MISCREG_TTBR0, currState->tc, !currState->isSecure)); 61210037SARM gem5 Developers tsz = currState->ttbcr.t0sz; 61310037SARM gem5 Developers if (ttbr0_max < (1ULL << 30)) // Upper limit < 1 GB 61410037SARM gem5 Developers start_lookup_level = L2; 61510037SARM gem5 Developers } else if (currState->vaddr >= ttbr1_min) { 61610037SARM gem5 Developers DPRINTF(TLB, " - Selecting TTBR1 (long-desc.)\n"); 61710037SARM gem5 Developers // Check if table walk is allowed 61810037SARM gem5 Developers if (currState->ttbcr.epd1) { 61910037SARM gem5 Developers if (currState->isFetch) 62010474Sandreas.hansson@arm.com return std::make_shared<PrefetchAbort>( 62110474Sandreas.hansson@arm.com currState->vaddr_tainted, 62210474Sandreas.hansson@arm.com ArmFault::TranslationLL + L1, 62310474Sandreas.hansson@arm.com isStage2, 62410474Sandreas.hansson@arm.com ArmFault::LpaeTran); 62510037SARM gem5 Developers else 62610474Sandreas.hansson@arm.com return std::make_shared<DataAbort>( 62710474Sandreas.hansson@arm.com currState->vaddr_tainted, 62810474Sandreas.hansson@arm.com TlbEntry::DomainType::NoAccess, 62910474Sandreas.hansson@arm.com currState->isWrite, 63010474Sandreas.hansson@arm.com ArmFault::TranslationLL + L1, 63110474Sandreas.hansson@arm.com isStage2, 63210474Sandreas.hansson@arm.com ArmFault::LpaeTran); 63310037SARM gem5 Developers } 63410037SARM gem5 Developers ttbr = currState->tc->readMiscReg(flattenMiscRegNsBanked( 63510037SARM gem5 Developers MISCREG_TTBR1, currState->tc, !currState->isSecure)); 63610037SARM gem5 Developers tsz = currState->ttbcr.t1sz; 63710037SARM gem5 Developers if (ttbr1_min >= (1ULL << 31) + (1ULL << 30)) // Lower limit >= 3 GB 63810037SARM gem5 Developers start_lookup_level = L2; 63910037SARM gem5 Developers } else { 64010037SARM gem5 Developers // Out of boundaries -> translation fault 64110037SARM gem5 Developers if (currState->isFetch) 64210474Sandreas.hansson@arm.com return std::make_shared<PrefetchAbort>( 64310474Sandreas.hansson@arm.com currState->vaddr_tainted, 64410474Sandreas.hansson@arm.com ArmFault::TranslationLL + L1, 64510474Sandreas.hansson@arm.com isStage2, 64610474Sandreas.hansson@arm.com ArmFault::LpaeTran); 64710037SARM gem5 Developers else 64810474Sandreas.hansson@arm.com return std::make_shared<DataAbort>( 64910474Sandreas.hansson@arm.com currState->vaddr_tainted, 65010474Sandreas.hansson@arm.com TlbEntry::DomainType::NoAccess, 65110474Sandreas.hansson@arm.com currState->isWrite, ArmFault::TranslationLL + L1, 65210474Sandreas.hansson@arm.com isStage2, ArmFault::LpaeTran); 65310037SARM gem5 Developers } 65410037SARM gem5 Developers 65510037SARM gem5 Developers } 65610037SARM gem5 Developers 65710037SARM gem5 Developers // Perform lookup (ARM ARM issue C B3.6.6) 65810037SARM gem5 Developers if (start_lookup_level == L1) { 65910037SARM gem5 Developers n = 5 - tsz; 66010037SARM gem5 Developers desc_addr = mbits(ttbr, 39, n) | 66110037SARM gem5 Developers (bits(currState->vaddr, n + 26, 30) << 3); 66210037SARM gem5 Developers DPRINTF(TLB, " - Descriptor at address %#x (%s) (long-desc.)\n", 66310037SARM gem5 Developers desc_addr, currState->isSecure ? "s" : "ns"); 66410037SARM gem5 Developers } else { 66510037SARM gem5 Developers // Skip first-level lookup 66610037SARM gem5 Developers n = (tsz >= 2 ? 14 - tsz : 12); 66710037SARM gem5 Developers desc_addr = mbits(ttbr, 39, n) | 66810037SARM gem5 Developers (bits(currState->vaddr, n + 17, 21) << 3); 66910037SARM gem5 Developers DPRINTF(TLB, " - Descriptor at address %#x (%s) (long-desc.)\n", 67010037SARM gem5 Developers desc_addr, currState->isSecure ? "s" : "ns"); 67110037SARM gem5 Developers } 67210037SARM gem5 Developers 67310037SARM gem5 Developers // Trickbox address check 67411395Sandreas.sandberg@arm.com Fault f = testWalk(desc_addr, sizeof(uint64_t), 67511395Sandreas.sandberg@arm.com TlbEntry::DomainType::NoAccess, start_lookup_level); 67610037SARM gem5 Developers if (f) { 67710037SARM gem5 Developers DPRINTF(TLB, "Trickbox check caused fault on %#x\n", currState->vaddr_tainted); 67810037SARM gem5 Developers if (currState->timing) { 67910037SARM gem5 Developers pending = false; 68010037SARM gem5 Developers nextWalk(currState->tc); 68110037SARM gem5 Developers currState = NULL; 68210037SARM gem5 Developers } else { 68310037SARM gem5 Developers currState->tc = NULL; 68410037SARM gem5 Developers currState->req = NULL; 68510037SARM gem5 Developers } 68610037SARM gem5 Developers return f; 68710037SARM gem5 Developers } 68810037SARM gem5 Developers 68910037SARM gem5 Developers if (currState->sctlr.c == 0) { 69010836Sandreas.hansson@arm.com flag.set(Request::UNCACHEABLE); 69110037SARM gem5 Developers } 69210037SARM gem5 Developers 69310037SARM gem5 Developers currState->longDesc.lookupLevel = start_lookup_level; 69410037SARM gem5 Developers currState->longDesc.aarch64 = false; 69510324SCurtis.Dunham@arm.com currState->longDesc.grainSize = Grain4KB; 69610037SARM gem5 Developers 69710037SARM gem5 Developers Event *event = start_lookup_level == L1 ? (Event *) &doL1LongDescEvent 69810037SARM gem5 Developers : (Event *) &doL2LongDescEvent; 69910037SARM gem5 Developers 70010037SARM gem5 Developers bool delayed = fetchDescriptor(desc_addr, (uint8_t*)&currState->longDesc.data, 70110037SARM gem5 Developers sizeof(uint64_t), flag, start_lookup_level, 70210037SARM gem5 Developers event, &TableWalker::doLongDescriptor); 70310037SARM gem5 Developers if (!delayed) { 70410037SARM gem5 Developers f = currState->fault; 70510037SARM gem5 Developers } 70610037SARM gem5 Developers 70710037SARM gem5 Developers return f; 70810037SARM gem5 Developers} 70910037SARM gem5 Developers 71010037SARM gem5 Developersunsigned 71110037SARM gem5 DevelopersTableWalker::adjustTableSizeAArch64(unsigned tsz) 71210037SARM gem5 Developers{ 71310037SARM gem5 Developers if (tsz < 25) 71410037SARM gem5 Developers return 25; 71510037SARM gem5 Developers if (tsz > 48) 71610037SARM gem5 Developers return 48; 71710037SARM gem5 Developers return tsz; 71810037SARM gem5 Developers} 71910037SARM gem5 Developers 72010037SARM gem5 Developersbool 72110037SARM gem5 DevelopersTableWalker::checkAddrSizeFaultAArch64(Addr addr, int currPhysAddrRange) 72210037SARM gem5 Developers{ 72310037SARM gem5 Developers return (currPhysAddrRange != MaxPhysAddrRange && 72410037SARM gem5 Developers bits(addr, MaxPhysAddrRange - 1, currPhysAddrRange)); 72510037SARM gem5 Developers} 72610037SARM gem5 Developers 72710037SARM gem5 DevelopersFault 72810037SARM gem5 DevelopersTableWalker::processWalkAArch64() 72910037SARM gem5 Developers{ 73010037SARM gem5 Developers assert(currState->aarch64); 73110037SARM gem5 Developers 73210324SCurtis.Dunham@arm.com DPRINTF(TLB, "Beginning table walk for address %#llx, TCR: %#llx\n", 73310324SCurtis.Dunham@arm.com currState->vaddr_tainted, currState->tcr); 73410324SCurtis.Dunham@arm.com 73510324SCurtis.Dunham@arm.com static const GrainSize GrainMapDefault[] = 73610324SCurtis.Dunham@arm.com { Grain4KB, Grain64KB, Grain16KB, ReservedGrain }; 73710324SCurtis.Dunham@arm.com static const GrainSize GrainMap_EL1_tg1[] = 73810324SCurtis.Dunham@arm.com { ReservedGrain, Grain16KB, Grain4KB, Grain64KB }; 73910037SARM gem5 Developers 74010621SCurtis.Dunham@arm.com statWalkWaitTime.sample(curTick() - currState->startTime); 74110621SCurtis.Dunham@arm.com 74210037SARM gem5 Developers // Determine TTBR, table size, granule size and phys. address range 74310037SARM gem5 Developers Addr ttbr = 0; 74410037SARM gem5 Developers int tsz = 0, ps = 0; 74510324SCurtis.Dunham@arm.com GrainSize tg = Grain4KB; // grain size computed from tg* field 74610037SARM gem5 Developers bool fault = false; 74710037SARM gem5 Developers switch (currState->el) { 74810037SARM gem5 Developers case EL0: 74910037SARM gem5 Developers case EL1: 75010037SARM gem5 Developers switch (bits(currState->vaddr, 63,48)) { 75110037SARM gem5 Developers case 0: 75210037SARM gem5 Developers DPRINTF(TLB, " - Selecting TTBR0 (AArch64)\n"); 75310037SARM gem5 Developers ttbr = currState->tc->readMiscReg(MISCREG_TTBR0_EL1); 75410324SCurtis.Dunham@arm.com tsz = adjustTableSizeAArch64(64 - currState->tcr.t0sz); 75510324SCurtis.Dunham@arm.com tg = GrainMapDefault[currState->tcr.tg0]; 75610037SARM gem5 Developers if (bits(currState->vaddr, 63, tsz) != 0x0 || 75710324SCurtis.Dunham@arm.com currState->tcr.epd0) 75810037SARM gem5 Developers fault = true; 75910037SARM gem5 Developers break; 76010037SARM gem5 Developers case 0xffff: 76110037SARM gem5 Developers DPRINTF(TLB, " - Selecting TTBR1 (AArch64)\n"); 76210037SARM gem5 Developers ttbr = currState->tc->readMiscReg(MISCREG_TTBR1_EL1); 76310324SCurtis.Dunham@arm.com tsz = adjustTableSizeAArch64(64 - currState->tcr.t1sz); 76410324SCurtis.Dunham@arm.com tg = GrainMap_EL1_tg1[currState->tcr.tg1]; 76510037SARM gem5 Developers if (bits(currState->vaddr, 63, tsz) != mask(64-tsz) || 76610324SCurtis.Dunham@arm.com currState->tcr.epd1) 76710037SARM gem5 Developers fault = true; 76810037SARM gem5 Developers break; 76910037SARM gem5 Developers default: 77010037SARM gem5 Developers // top two bytes must be all 0s or all 1s, else invalid addr 77110037SARM gem5 Developers fault = true; 77210037SARM gem5 Developers } 77310324SCurtis.Dunham@arm.com ps = currState->tcr.ips; 77410037SARM gem5 Developers break; 77510037SARM gem5 Developers case EL2: 77610037SARM gem5 Developers case EL3: 77710037SARM gem5 Developers switch(bits(currState->vaddr, 63,48)) { 77810037SARM gem5 Developers case 0: 77910324SCurtis.Dunham@arm.com DPRINTF(TLB, " - Selecting TTBR0 (AArch64)\n"); 78010324SCurtis.Dunham@arm.com if (currState->el == EL2) 78110324SCurtis.Dunham@arm.com ttbr = currState->tc->readMiscReg(MISCREG_TTBR0_EL2); 78210324SCurtis.Dunham@arm.com else 78310324SCurtis.Dunham@arm.com ttbr = currState->tc->readMiscReg(MISCREG_TTBR0_EL3); 78410324SCurtis.Dunham@arm.com tsz = adjustTableSizeAArch64(64 - currState->tcr.t0sz); 78510324SCurtis.Dunham@arm.com tg = GrainMapDefault[currState->tcr.tg0]; 78610037SARM gem5 Developers break; 78710037SARM gem5 Developers default: 78810037SARM gem5 Developers // invalid addr if top two bytes are not all 0s 78910324SCurtis.Dunham@arm.com fault = true; 79010037SARM gem5 Developers } 79110324SCurtis.Dunham@arm.com ps = currState->tcr.ips; 79210037SARM gem5 Developers break; 79310037SARM gem5 Developers } 79410037SARM gem5 Developers 79510037SARM gem5 Developers if (fault) { 79610037SARM gem5 Developers Fault f; 79710037SARM gem5 Developers if (currState->isFetch) 79810474Sandreas.hansson@arm.com f = std::make_shared<PrefetchAbort>( 79910474Sandreas.hansson@arm.com currState->vaddr_tainted, 80010474Sandreas.hansson@arm.com ArmFault::TranslationLL + L0, isStage2, 80110474Sandreas.hansson@arm.com ArmFault::LpaeTran); 80210037SARM gem5 Developers else 80310474Sandreas.hansson@arm.com f = std::make_shared<DataAbort>( 80410474Sandreas.hansson@arm.com currState->vaddr_tainted, 80510474Sandreas.hansson@arm.com TlbEntry::DomainType::NoAccess, 80610474Sandreas.hansson@arm.com currState->isWrite, 80710474Sandreas.hansson@arm.com ArmFault::TranslationLL + L0, 80810474Sandreas.hansson@arm.com isStage2, ArmFault::LpaeTran); 80910037SARM gem5 Developers 81010037SARM gem5 Developers if (currState->timing) { 81110037SARM gem5 Developers pending = false; 81210037SARM gem5 Developers nextWalk(currState->tc); 81310037SARM gem5 Developers currState = NULL; 81410037SARM gem5 Developers } else { 81510037SARM gem5 Developers currState->tc = NULL; 81610037SARM gem5 Developers currState->req = NULL; 81710037SARM gem5 Developers } 81810037SARM gem5 Developers return f; 81910037SARM gem5 Developers 82010037SARM gem5 Developers } 82110037SARM gem5 Developers 82210324SCurtis.Dunham@arm.com if (tg == ReservedGrain) { 82310324SCurtis.Dunham@arm.com warn_once("Reserved granule size requested; gem5's IMPLEMENTATION " 82410324SCurtis.Dunham@arm.com "DEFINED behavior takes this to mean 4KB granules\n"); 82510324SCurtis.Dunham@arm.com tg = Grain4KB; 82610324SCurtis.Dunham@arm.com } 82710324SCurtis.Dunham@arm.com 82810324SCurtis.Dunham@arm.com int stride = tg - 3; 82910324SCurtis.Dunham@arm.com LookupLevel start_lookup_level = MAX_LOOKUP_LEVELS; 83010324SCurtis.Dunham@arm.com 83110037SARM gem5 Developers // Determine starting lookup level 83210324SCurtis.Dunham@arm.com // See aarch64/translation/walk in Appendix G: ARMv8 Pseudocode Library 83310324SCurtis.Dunham@arm.com // in ARM DDI 0487A. These table values correspond to the cascading tests 83410324SCurtis.Dunham@arm.com // to compute the lookup level and are of the form 83510324SCurtis.Dunham@arm.com // (grain_size + N*stride), for N = {1, 2, 3}. 83610324SCurtis.Dunham@arm.com // A value of 64 will never succeed and a value of 0 will always succeed. 83710324SCurtis.Dunham@arm.com { 83810324SCurtis.Dunham@arm.com struct GrainMap { 83910324SCurtis.Dunham@arm.com GrainSize grain_size; 84010324SCurtis.Dunham@arm.com unsigned lookup_level_cutoff[MAX_LOOKUP_LEVELS]; 84110324SCurtis.Dunham@arm.com }; 84210324SCurtis.Dunham@arm.com static const GrainMap GM[] = { 84310324SCurtis.Dunham@arm.com { Grain4KB, { 39, 30, 0, 0 } }, 84410324SCurtis.Dunham@arm.com { Grain16KB, { 47, 36, 25, 0 } }, 84510324SCurtis.Dunham@arm.com { Grain64KB, { 64, 42, 29, 0 } } 84610324SCurtis.Dunham@arm.com }; 84710324SCurtis.Dunham@arm.com 84810324SCurtis.Dunham@arm.com const unsigned *lookup = NULL; // points to a lookup_level_cutoff 84910324SCurtis.Dunham@arm.com 85010324SCurtis.Dunham@arm.com for (unsigned i = 0; i < 3; ++i) { // choose entry of GM[] 85110324SCurtis.Dunham@arm.com if (tg == GM[i].grain_size) { 85210324SCurtis.Dunham@arm.com lookup = GM[i].lookup_level_cutoff; 85310324SCurtis.Dunham@arm.com break; 85410324SCurtis.Dunham@arm.com } 85510324SCurtis.Dunham@arm.com } 85610324SCurtis.Dunham@arm.com assert(lookup); 85710324SCurtis.Dunham@arm.com 85810324SCurtis.Dunham@arm.com for (int L = L0; L != MAX_LOOKUP_LEVELS; ++L) { 85910324SCurtis.Dunham@arm.com if (tsz > lookup[L]) { 86010324SCurtis.Dunham@arm.com start_lookup_level = (LookupLevel) L; 86110324SCurtis.Dunham@arm.com break; 86210324SCurtis.Dunham@arm.com } 86310324SCurtis.Dunham@arm.com } 86410324SCurtis.Dunham@arm.com panic_if(start_lookup_level == MAX_LOOKUP_LEVELS, 86510324SCurtis.Dunham@arm.com "Table walker couldn't find lookup level\n"); 86610037SARM gem5 Developers } 86710037SARM gem5 Developers 86810037SARM gem5 Developers // Determine table base address 86910324SCurtis.Dunham@arm.com int base_addr_lo = 3 + tsz - stride * (3 - start_lookup_level) - tg; 87010037SARM gem5 Developers Addr base_addr = mbits(ttbr, 47, base_addr_lo); 87110037SARM gem5 Developers 87210037SARM gem5 Developers // Determine physical address size and raise an Address Size Fault if 87310037SARM gem5 Developers // necessary 87410037SARM gem5 Developers int pa_range = decodePhysAddrRange64(ps); 87510037SARM gem5 Developers // Clamp to lower limit 87610037SARM gem5 Developers if (pa_range > physAddrRange) 87710037SARM gem5 Developers currState->physAddrRange = physAddrRange; 87810037SARM gem5 Developers else 87910037SARM gem5 Developers currState->physAddrRange = pa_range; 88010037SARM gem5 Developers if (checkAddrSizeFaultAArch64(base_addr, currState->physAddrRange)) { 88110037SARM gem5 Developers DPRINTF(TLB, "Address size fault before any lookup\n"); 88210037SARM gem5 Developers Fault f; 88310037SARM gem5 Developers if (currState->isFetch) 88410474Sandreas.hansson@arm.com f = std::make_shared<PrefetchAbort>( 88510474Sandreas.hansson@arm.com currState->vaddr_tainted, 88610474Sandreas.hansson@arm.com ArmFault::AddressSizeLL + start_lookup_level, 88710474Sandreas.hansson@arm.com isStage2, 88810474Sandreas.hansson@arm.com ArmFault::LpaeTran); 88910037SARM gem5 Developers else 89010474Sandreas.hansson@arm.com f = std::make_shared<DataAbort>( 89110474Sandreas.hansson@arm.com currState->vaddr_tainted, 89210474Sandreas.hansson@arm.com TlbEntry::DomainType::NoAccess, 89310474Sandreas.hansson@arm.com currState->isWrite, 89410474Sandreas.hansson@arm.com ArmFault::AddressSizeLL + start_lookup_level, 89510474Sandreas.hansson@arm.com isStage2, 89610474Sandreas.hansson@arm.com ArmFault::LpaeTran); 89710037SARM gem5 Developers 89810037SARM gem5 Developers 89910037SARM gem5 Developers if (currState->timing) { 90010037SARM gem5 Developers pending = false; 90110037SARM gem5 Developers nextWalk(currState->tc); 90210037SARM gem5 Developers currState = NULL; 90310037SARM gem5 Developers } else { 90410037SARM gem5 Developers currState->tc = NULL; 90510037SARM gem5 Developers currState->req = NULL; 90610037SARM gem5 Developers } 90710037SARM gem5 Developers return f; 90810037SARM gem5 Developers 90910037SARM gem5 Developers } 91010037SARM gem5 Developers 91110037SARM gem5 Developers // Determine descriptor address 91210037SARM gem5 Developers Addr desc_addr = base_addr | 91310037SARM gem5 Developers (bits(currState->vaddr, tsz - 1, 91410324SCurtis.Dunham@arm.com stride * (3 - start_lookup_level) + tg) << 3); 91510037SARM gem5 Developers 91610037SARM gem5 Developers // Trickbox address check 91711395Sandreas.sandberg@arm.com Fault f = testWalk(desc_addr, sizeof(uint64_t), 91811395Sandreas.sandberg@arm.com TlbEntry::DomainType::NoAccess, start_lookup_level); 91910037SARM gem5 Developers if (f) { 92010037SARM gem5 Developers DPRINTF(TLB, "Trickbox check caused fault on %#x\n", currState->vaddr_tainted); 92110037SARM gem5 Developers if (currState->timing) { 92210037SARM gem5 Developers pending = false; 92310037SARM gem5 Developers nextWalk(currState->tc); 92410037SARM gem5 Developers currState = NULL; 92510037SARM gem5 Developers } else { 92610037SARM gem5 Developers currState->tc = NULL; 92710037SARM gem5 Developers currState->req = NULL; 92810037SARM gem5 Developers } 92910037SARM gem5 Developers return f; 93010037SARM gem5 Developers } 93110037SARM gem5 Developers 93210836Sandreas.hansson@arm.com Request::Flags flag = Request::PT_WALK; 93310037SARM gem5 Developers if (currState->sctlr.c == 0) { 93410836Sandreas.hansson@arm.com flag.set(Request::UNCACHEABLE); 93510037SARM gem5 Developers } 93610037SARM gem5 Developers 93711181Snathananel.premillieu@arm.com if (currState->isSecure) { 93811181Snathananel.premillieu@arm.com flag.set(Request::SECURE); 93911181Snathananel.premillieu@arm.com } 94011181Snathananel.premillieu@arm.com 94110037SARM gem5 Developers currState->longDesc.lookupLevel = start_lookup_level; 94210037SARM gem5 Developers currState->longDesc.aarch64 = true; 94310324SCurtis.Dunham@arm.com currState->longDesc.grainSize = tg; 94410037SARM gem5 Developers 9457439Sdam.sunwoo@arm.com if (currState->timing) { 94610037SARM gem5 Developers Event *event; 94710037SARM gem5 Developers switch (start_lookup_level) { 94810037SARM gem5 Developers case L0: 94910037SARM gem5 Developers event = (Event *) &doL0LongDescEvent; 95010037SARM gem5 Developers break; 95110037SARM gem5 Developers case L1: 95210037SARM gem5 Developers event = (Event *) &doL1LongDescEvent; 95310037SARM gem5 Developers break; 95410037SARM gem5 Developers case L2: 95510037SARM gem5 Developers event = (Event *) &doL2LongDescEvent; 95610037SARM gem5 Developers break; 95710037SARM gem5 Developers case L3: 95810037SARM gem5 Developers event = (Event *) &doL3LongDescEvent; 95910037SARM gem5 Developers break; 96010037SARM gem5 Developers default: 96110037SARM gem5 Developers panic("Invalid table lookup level"); 96210037SARM gem5 Developers break; 96310037SARM gem5 Developers } 96410717Sandreas.hansson@arm.com port->dmaAction(MemCmd::ReadReq, desc_addr, sizeof(uint64_t), 96510621SCurtis.Dunham@arm.com event, (uint8_t*) &currState->longDesc.data, 9669180Sandreas.hansson@arm.com currState->tc->getCpuPtr()->clockPeriod(), flag); 96710037SARM gem5 Developers DPRINTF(TLBVerbose, 96810037SARM gem5 Developers "Adding to walker fifo: queue size before adding: %d\n", 96910037SARM gem5 Developers stateQueues[start_lookup_level].size()); 97010037SARM gem5 Developers stateQueues[start_lookup_level].push_back(currState); 9717439Sdam.sunwoo@arm.com currState = NULL; 9728733Sgeoffrey.blake@arm.com } else if (!currState->functional) { 97310717Sandreas.hansson@arm.com port->dmaAction(MemCmd::ReadReq, desc_addr, sizeof(uint64_t), 97410037SARM gem5 Developers NULL, (uint8_t*) &currState->longDesc.data, 9759180Sandreas.hansson@arm.com currState->tc->getCpuPtr()->clockPeriod(), flag); 97610037SARM gem5 Developers doLongDescriptor(); 9777439Sdam.sunwoo@arm.com f = currState->fault; 9788733Sgeoffrey.blake@arm.com } else { 97910037SARM gem5 Developers RequestPtr req = new Request(desc_addr, sizeof(uint64_t), flag, 98010037SARM gem5 Developers masterId); 9818949Sandreas.hansson@arm.com PacketPtr pkt = new Packet(req, MemCmd::ReadReq); 98210037SARM gem5 Developers pkt->dataStatic((uint8_t*) &currState->longDesc.data); 98310717Sandreas.hansson@arm.com port->sendFunctional(pkt); 98410037SARM gem5 Developers doLongDescriptor(); 9858733Sgeoffrey.blake@arm.com delete req; 9868733Sgeoffrey.blake@arm.com delete pkt; 9878733Sgeoffrey.blake@arm.com f = currState->fault; 9887404SAli.Saidi@ARM.com } 9897404SAli.Saidi@ARM.com 9907439Sdam.sunwoo@arm.com return f; 9917404SAli.Saidi@ARM.com} 9927404SAli.Saidi@ARM.com 9937404SAli.Saidi@ARM.comvoid 9947439Sdam.sunwoo@arm.comTableWalker::memAttrs(ThreadContext *tc, TlbEntry &te, SCTLR sctlr, 9957439Sdam.sunwoo@arm.com uint8_t texcb, bool s) 9967404SAli.Saidi@ARM.com{ 9977439Sdam.sunwoo@arm.com // Note: tc and sctlr local variables are hiding tc and sctrl class 9987439Sdam.sunwoo@arm.com // variables 9997436Sdam.sunwoo@arm.com DPRINTF(TLBVerbose, "memAttrs texcb:%d s:%d\n", texcb, s); 10007436Sdam.sunwoo@arm.com te.shareable = false; // default value 10017582SAli.Saidi@arm.com te.nonCacheable = false; 100210037SARM gem5 Developers te.outerShareable = false; 10037439Sdam.sunwoo@arm.com if (sctlr.tre == 0 || ((sctlr.tre == 1) && (sctlr.m == 0))) { 10047404SAli.Saidi@ARM.com switch(texcb) { 10057436Sdam.sunwoo@arm.com case 0: // Stongly-ordered 10067404SAli.Saidi@ARM.com te.nonCacheable = true; 100710037SARM gem5 Developers te.mtype = TlbEntry::MemoryType::StronglyOrdered; 10087436Sdam.sunwoo@arm.com te.shareable = true; 10097436Sdam.sunwoo@arm.com te.innerAttrs = 1; 10107436Sdam.sunwoo@arm.com te.outerAttrs = 0; 10117404SAli.Saidi@ARM.com break; 10127436Sdam.sunwoo@arm.com case 1: // Shareable Device 10137436Sdam.sunwoo@arm.com te.nonCacheable = true; 101410037SARM gem5 Developers te.mtype = TlbEntry::MemoryType::Device; 10157436Sdam.sunwoo@arm.com te.shareable = true; 10167436Sdam.sunwoo@arm.com te.innerAttrs = 3; 10177436Sdam.sunwoo@arm.com te.outerAttrs = 0; 10187436Sdam.sunwoo@arm.com break; 10197436Sdam.sunwoo@arm.com case 2: // Outer and Inner Write-Through, no Write-Allocate 102010037SARM gem5 Developers te.mtype = TlbEntry::MemoryType::Normal; 10217436Sdam.sunwoo@arm.com te.shareable = s; 10227436Sdam.sunwoo@arm.com te.innerAttrs = 6; 10237436Sdam.sunwoo@arm.com te.outerAttrs = bits(texcb, 1, 0); 10247436Sdam.sunwoo@arm.com break; 10257436Sdam.sunwoo@arm.com case 3: // Outer and Inner Write-Back, no Write-Allocate 102610037SARM gem5 Developers te.mtype = TlbEntry::MemoryType::Normal; 10277436Sdam.sunwoo@arm.com te.shareable = s; 10287436Sdam.sunwoo@arm.com te.innerAttrs = 7; 10297436Sdam.sunwoo@arm.com te.outerAttrs = bits(texcb, 1, 0); 10307436Sdam.sunwoo@arm.com break; 10317436Sdam.sunwoo@arm.com case 4: // Outer and Inner Non-cacheable 10327436Sdam.sunwoo@arm.com te.nonCacheable = true; 103310037SARM gem5 Developers te.mtype = TlbEntry::MemoryType::Normal; 10347436Sdam.sunwoo@arm.com te.shareable = s; 10357436Sdam.sunwoo@arm.com te.innerAttrs = 0; 10367436Sdam.sunwoo@arm.com te.outerAttrs = bits(texcb, 1, 0); 10377436Sdam.sunwoo@arm.com break; 10387436Sdam.sunwoo@arm.com case 5: // Reserved 10397439Sdam.sunwoo@arm.com panic("Reserved texcb value!\n"); 10407436Sdam.sunwoo@arm.com break; 10417436Sdam.sunwoo@arm.com case 6: // Implementation Defined 10427439Sdam.sunwoo@arm.com panic("Implementation-defined texcb value!\n"); 10437436Sdam.sunwoo@arm.com break; 10447436Sdam.sunwoo@arm.com case 7: // Outer and Inner Write-Back, Write-Allocate 104510037SARM gem5 Developers te.mtype = TlbEntry::MemoryType::Normal; 10467436Sdam.sunwoo@arm.com te.shareable = s; 10477436Sdam.sunwoo@arm.com te.innerAttrs = 5; 10487436Sdam.sunwoo@arm.com te.outerAttrs = 1; 10497436Sdam.sunwoo@arm.com break; 10507436Sdam.sunwoo@arm.com case 8: // Non-shareable Device 10517436Sdam.sunwoo@arm.com te.nonCacheable = true; 105210037SARM gem5 Developers te.mtype = TlbEntry::MemoryType::Device; 10537436Sdam.sunwoo@arm.com te.shareable = false; 10547436Sdam.sunwoo@arm.com te.innerAttrs = 3; 10557436Sdam.sunwoo@arm.com te.outerAttrs = 0; 10567436Sdam.sunwoo@arm.com break; 10577436Sdam.sunwoo@arm.com case 9 ... 15: // Reserved 10587439Sdam.sunwoo@arm.com panic("Reserved texcb value!\n"); 10597436Sdam.sunwoo@arm.com break; 10607436Sdam.sunwoo@arm.com case 16 ... 31: // Cacheable Memory 106110037SARM gem5 Developers te.mtype = TlbEntry::MemoryType::Normal; 10627436Sdam.sunwoo@arm.com te.shareable = s; 10637404SAli.Saidi@ARM.com if (bits(texcb, 1,0) == 0 || bits(texcb, 3,2) == 0) 10647404SAli.Saidi@ARM.com te.nonCacheable = true; 10657436Sdam.sunwoo@arm.com te.innerAttrs = bits(texcb, 1, 0); 10667436Sdam.sunwoo@arm.com te.outerAttrs = bits(texcb, 3, 2); 10677404SAli.Saidi@ARM.com break; 10687436Sdam.sunwoo@arm.com default: 10697436Sdam.sunwoo@arm.com panic("More than 32 states for 5 bits?\n"); 10707404SAli.Saidi@ARM.com } 10717404SAli.Saidi@ARM.com } else { 10727438SAli.Saidi@ARM.com assert(tc); 107310037SARM gem5 Developers PRRR prrr = tc->readMiscReg(flattenMiscRegNsBanked(MISCREG_PRRR, 107410037SARM gem5 Developers currState->tc, !currState->isSecure)); 107510037SARM gem5 Developers NMRR nmrr = tc->readMiscReg(flattenMiscRegNsBanked(MISCREG_NMRR, 107610037SARM gem5 Developers currState->tc, !currState->isSecure)); 10777436Sdam.sunwoo@arm.com DPRINTF(TLBVerbose, "memAttrs PRRR:%08x NMRR:%08x\n", prrr, nmrr); 10787582SAli.Saidi@arm.com uint8_t curr_tr = 0, curr_ir = 0, curr_or = 0; 10797404SAli.Saidi@ARM.com switch(bits(texcb, 2,0)) { 10807404SAli.Saidi@ARM.com case 0: 10817436Sdam.sunwoo@arm.com curr_tr = prrr.tr0; 10827436Sdam.sunwoo@arm.com curr_ir = nmrr.ir0; 10837436Sdam.sunwoo@arm.com curr_or = nmrr.or0; 108410037SARM gem5 Developers te.outerShareable = (prrr.nos0 == 0); 10857404SAli.Saidi@ARM.com break; 10867404SAli.Saidi@ARM.com case 1: 10877436Sdam.sunwoo@arm.com curr_tr = prrr.tr1; 10887436Sdam.sunwoo@arm.com curr_ir = nmrr.ir1; 10897436Sdam.sunwoo@arm.com curr_or = nmrr.or1; 109010037SARM gem5 Developers te.outerShareable = (prrr.nos1 == 0); 10917404SAli.Saidi@ARM.com break; 10927404SAli.Saidi@ARM.com case 2: 10937436Sdam.sunwoo@arm.com curr_tr = prrr.tr2; 10947436Sdam.sunwoo@arm.com curr_ir = nmrr.ir2; 10957436Sdam.sunwoo@arm.com curr_or = nmrr.or2; 109610037SARM gem5 Developers te.outerShareable = (prrr.nos2 == 0); 10977404SAli.Saidi@ARM.com break; 10987404SAli.Saidi@ARM.com case 3: 10997436Sdam.sunwoo@arm.com curr_tr = prrr.tr3; 11007436Sdam.sunwoo@arm.com curr_ir = nmrr.ir3; 11017436Sdam.sunwoo@arm.com curr_or = nmrr.or3; 110210037SARM gem5 Developers te.outerShareable = (prrr.nos3 == 0); 11037404SAli.Saidi@ARM.com break; 11047404SAli.Saidi@ARM.com case 4: 11057436Sdam.sunwoo@arm.com curr_tr = prrr.tr4; 11067436Sdam.sunwoo@arm.com curr_ir = nmrr.ir4; 11077436Sdam.sunwoo@arm.com curr_or = nmrr.or4; 110810037SARM gem5 Developers te.outerShareable = (prrr.nos4 == 0); 11097404SAli.Saidi@ARM.com break; 11107404SAli.Saidi@ARM.com case 5: 11117436Sdam.sunwoo@arm.com curr_tr = prrr.tr5; 11127436Sdam.sunwoo@arm.com curr_ir = nmrr.ir5; 11137436Sdam.sunwoo@arm.com curr_or = nmrr.or5; 111410037SARM gem5 Developers te.outerShareable = (prrr.nos5 == 0); 11157404SAli.Saidi@ARM.com break; 11167404SAli.Saidi@ARM.com case 6: 11177404SAli.Saidi@ARM.com panic("Imp defined type\n"); 11187404SAli.Saidi@ARM.com case 7: 11197436Sdam.sunwoo@arm.com curr_tr = prrr.tr7; 11207436Sdam.sunwoo@arm.com curr_ir = nmrr.ir7; 11217436Sdam.sunwoo@arm.com curr_or = nmrr.or7; 112210037SARM gem5 Developers te.outerShareable = (prrr.nos7 == 0); 11237404SAli.Saidi@ARM.com break; 11247404SAli.Saidi@ARM.com } 11257436Sdam.sunwoo@arm.com 11267436Sdam.sunwoo@arm.com switch(curr_tr) { 11277436Sdam.sunwoo@arm.com case 0: 11287436Sdam.sunwoo@arm.com DPRINTF(TLBVerbose, "StronglyOrdered\n"); 112910037SARM gem5 Developers te.mtype = TlbEntry::MemoryType::StronglyOrdered; 11307436Sdam.sunwoo@arm.com te.nonCacheable = true; 11317436Sdam.sunwoo@arm.com te.innerAttrs = 1; 11327436Sdam.sunwoo@arm.com te.outerAttrs = 0; 11337436Sdam.sunwoo@arm.com te.shareable = true; 11347436Sdam.sunwoo@arm.com break; 11357436Sdam.sunwoo@arm.com case 1: 11367436Sdam.sunwoo@arm.com DPRINTF(TLBVerbose, "Device ds1:%d ds0:%d s:%d\n", 11377436Sdam.sunwoo@arm.com prrr.ds1, prrr.ds0, s); 113810037SARM gem5 Developers te.mtype = TlbEntry::MemoryType::Device; 11397436Sdam.sunwoo@arm.com te.nonCacheable = true; 11407436Sdam.sunwoo@arm.com te.innerAttrs = 3; 11417436Sdam.sunwoo@arm.com te.outerAttrs = 0; 11427436Sdam.sunwoo@arm.com if (prrr.ds1 && s) 11437436Sdam.sunwoo@arm.com te.shareable = true; 11447436Sdam.sunwoo@arm.com if (prrr.ds0 && !s) 11457436Sdam.sunwoo@arm.com te.shareable = true; 11467436Sdam.sunwoo@arm.com break; 11477436Sdam.sunwoo@arm.com case 2: 11487436Sdam.sunwoo@arm.com DPRINTF(TLBVerbose, "Normal ns1:%d ns0:%d s:%d\n", 11497436Sdam.sunwoo@arm.com prrr.ns1, prrr.ns0, s); 115010037SARM gem5 Developers te.mtype = TlbEntry::MemoryType::Normal; 11517436Sdam.sunwoo@arm.com if (prrr.ns1 && s) 11527436Sdam.sunwoo@arm.com te.shareable = true; 11537436Sdam.sunwoo@arm.com if (prrr.ns0 && !s) 11547436Sdam.sunwoo@arm.com te.shareable = true; 11557436Sdam.sunwoo@arm.com break; 11567436Sdam.sunwoo@arm.com case 3: 11577436Sdam.sunwoo@arm.com panic("Reserved type"); 11587436Sdam.sunwoo@arm.com } 11597436Sdam.sunwoo@arm.com 116010037SARM gem5 Developers if (te.mtype == TlbEntry::MemoryType::Normal){ 11617436Sdam.sunwoo@arm.com switch(curr_ir) { 11627436Sdam.sunwoo@arm.com case 0: 11637436Sdam.sunwoo@arm.com te.nonCacheable = true; 11647436Sdam.sunwoo@arm.com te.innerAttrs = 0; 11657436Sdam.sunwoo@arm.com break; 11667436Sdam.sunwoo@arm.com case 1: 11677436Sdam.sunwoo@arm.com te.innerAttrs = 5; 11687436Sdam.sunwoo@arm.com break; 11697436Sdam.sunwoo@arm.com case 2: 11707436Sdam.sunwoo@arm.com te.innerAttrs = 6; 11717436Sdam.sunwoo@arm.com break; 11727436Sdam.sunwoo@arm.com case 3: 11737436Sdam.sunwoo@arm.com te.innerAttrs = 7; 11747436Sdam.sunwoo@arm.com break; 11757436Sdam.sunwoo@arm.com } 11767436Sdam.sunwoo@arm.com 11777436Sdam.sunwoo@arm.com switch(curr_or) { 11787436Sdam.sunwoo@arm.com case 0: 11797436Sdam.sunwoo@arm.com te.nonCacheable = true; 11807436Sdam.sunwoo@arm.com te.outerAttrs = 0; 11817436Sdam.sunwoo@arm.com break; 11827436Sdam.sunwoo@arm.com case 1: 11837436Sdam.sunwoo@arm.com te.outerAttrs = 1; 11847436Sdam.sunwoo@arm.com break; 11857436Sdam.sunwoo@arm.com case 2: 11867436Sdam.sunwoo@arm.com te.outerAttrs = 2; 11877436Sdam.sunwoo@arm.com break; 11887436Sdam.sunwoo@arm.com case 3: 11897436Sdam.sunwoo@arm.com te.outerAttrs = 3; 11907436Sdam.sunwoo@arm.com break; 11917436Sdam.sunwoo@arm.com } 11927436Sdam.sunwoo@arm.com } 11937404SAli.Saidi@ARM.com } 119410367SAndrew.Bardsley@arm.com DPRINTF(TLBVerbose, "memAttrs: shareable: %d, innerAttrs: %d, " 119510367SAndrew.Bardsley@arm.com "outerAttrs: %d\n", 11967439Sdam.sunwoo@arm.com te.shareable, te.innerAttrs, te.outerAttrs); 119710037SARM gem5 Developers te.setAttributes(false); 119810037SARM gem5 Developers} 11997436Sdam.sunwoo@arm.com 120010037SARM gem5 Developersvoid 120110037SARM gem5 DevelopersTableWalker::memAttrsLPAE(ThreadContext *tc, TlbEntry &te, 120210037SARM gem5 Developers LongDescriptor &lDescriptor) 120310037SARM gem5 Developers{ 120410037SARM gem5 Developers assert(_haveLPAE); 12057436Sdam.sunwoo@arm.com 120610037SARM gem5 Developers uint8_t attr; 120710037SARM gem5 Developers uint8_t sh = lDescriptor.sh(); 120810037SARM gem5 Developers // Different format and source of attributes if this is a stage 2 120910037SARM gem5 Developers // translation 121010037SARM gem5 Developers if (isStage2) { 121110037SARM gem5 Developers attr = lDescriptor.memAttr(); 121210037SARM gem5 Developers uint8_t attr_3_2 = (attr >> 2) & 0x3; 121310037SARM gem5 Developers uint8_t attr_1_0 = attr & 0x3; 12147436Sdam.sunwoo@arm.com 121510037SARM gem5 Developers DPRINTF(TLBVerbose, "memAttrsLPAE MemAttr:%#x sh:%#x\n", attr, sh); 121610037SARM gem5 Developers 121710037SARM gem5 Developers if (attr_3_2 == 0) { 121810037SARM gem5 Developers te.mtype = attr_1_0 == 0 ? TlbEntry::MemoryType::StronglyOrdered 121910037SARM gem5 Developers : TlbEntry::MemoryType::Device; 122010037SARM gem5 Developers te.outerAttrs = 0; 122110037SARM gem5 Developers te.innerAttrs = attr_1_0 == 0 ? 1 : 3; 122210037SARM gem5 Developers te.nonCacheable = true; 122310037SARM gem5 Developers } else { 122410037SARM gem5 Developers te.mtype = TlbEntry::MemoryType::Normal; 122510037SARM gem5 Developers te.outerAttrs = attr_3_2 == 1 ? 0 : 122610037SARM gem5 Developers attr_3_2 == 2 ? 2 : 1; 122710037SARM gem5 Developers te.innerAttrs = attr_1_0 == 1 ? 0 : 122810037SARM gem5 Developers attr_1_0 == 2 ? 6 : 5; 122910037SARM gem5 Developers te.nonCacheable = (attr_3_2 == 1) || (attr_1_0 == 1); 123010037SARM gem5 Developers } 123110037SARM gem5 Developers } else { 123210037SARM gem5 Developers uint8_t attrIndx = lDescriptor.attrIndx(); 123310037SARM gem5 Developers 123410037SARM gem5 Developers // LPAE always uses remapping of memory attributes, irrespective of the 123510037SARM gem5 Developers // value of SCTLR.TRE 123610421Sandreas.hansson@arm.com MiscRegIndex reg = attrIndx & 0x4 ? MISCREG_MAIR1 : MISCREG_MAIR0; 123710421Sandreas.hansson@arm.com int reg_as_int = flattenMiscRegNsBanked(reg, currState->tc, 123810421Sandreas.hansson@arm.com !currState->isSecure); 123910421Sandreas.hansson@arm.com uint32_t mair = currState->tc->readMiscReg(reg_as_int); 124010037SARM gem5 Developers attr = (mair >> (8 * (attrIndx % 4))) & 0xff; 124110037SARM gem5 Developers uint8_t attr_7_4 = bits(attr, 7, 4); 124210037SARM gem5 Developers uint8_t attr_3_0 = bits(attr, 3, 0); 124310037SARM gem5 Developers DPRINTF(TLBVerbose, "memAttrsLPAE AttrIndx:%#x sh:%#x, attr %#x\n", attrIndx, sh, attr); 124410037SARM gem5 Developers 124510037SARM gem5 Developers // Note: the memory subsystem only cares about the 'cacheable' memory 124610037SARM gem5 Developers // attribute. The other attributes are only used to fill the PAR register 124710037SARM gem5 Developers // accordingly to provide the illusion of full support 124810037SARM gem5 Developers te.nonCacheable = false; 124910037SARM gem5 Developers 125010037SARM gem5 Developers switch (attr_7_4) { 125110037SARM gem5 Developers case 0x0: 125210037SARM gem5 Developers // Strongly-ordered or Device memory 125310037SARM gem5 Developers if (attr_3_0 == 0x0) 125410037SARM gem5 Developers te.mtype = TlbEntry::MemoryType::StronglyOrdered; 125510037SARM gem5 Developers else if (attr_3_0 == 0x4) 125610037SARM gem5 Developers te.mtype = TlbEntry::MemoryType::Device; 125710037SARM gem5 Developers else 125810037SARM gem5 Developers panic("Unpredictable behavior\n"); 125910037SARM gem5 Developers te.nonCacheable = true; 126010037SARM gem5 Developers te.outerAttrs = 0; 126110037SARM gem5 Developers break; 126210037SARM gem5 Developers case 0x4: 126310037SARM gem5 Developers // Normal memory, Outer Non-cacheable 126410037SARM gem5 Developers te.mtype = TlbEntry::MemoryType::Normal; 126510037SARM gem5 Developers te.outerAttrs = 0; 126610037SARM gem5 Developers if (attr_3_0 == 0x4) 126710037SARM gem5 Developers // Inner Non-cacheable 126810037SARM gem5 Developers te.nonCacheable = true; 126910037SARM gem5 Developers else if (attr_3_0 < 0x8) 127010037SARM gem5 Developers panic("Unpredictable behavior\n"); 127110037SARM gem5 Developers break; 127210037SARM gem5 Developers case 0x8: 127310037SARM gem5 Developers case 0x9: 127410037SARM gem5 Developers case 0xa: 127510037SARM gem5 Developers case 0xb: 127610037SARM gem5 Developers case 0xc: 127710037SARM gem5 Developers case 0xd: 127810037SARM gem5 Developers case 0xe: 127910037SARM gem5 Developers case 0xf: 128010037SARM gem5 Developers if (attr_7_4 & 0x4) { 128110037SARM gem5 Developers te.outerAttrs = (attr_7_4 & 1) ? 1 : 3; 128210037SARM gem5 Developers } else { 128310037SARM gem5 Developers te.outerAttrs = 0x2; 128410037SARM gem5 Developers } 128510037SARM gem5 Developers // Normal memory, Outer Cacheable 128610037SARM gem5 Developers te.mtype = TlbEntry::MemoryType::Normal; 128710037SARM gem5 Developers if (attr_3_0 != 0x4 && attr_3_0 < 0x8) 128810037SARM gem5 Developers panic("Unpredictable behavior\n"); 128910037SARM gem5 Developers break; 129010037SARM gem5 Developers default: 129110037SARM gem5 Developers panic("Unpredictable behavior\n"); 129210037SARM gem5 Developers break; 129310037SARM gem5 Developers } 129410037SARM gem5 Developers 129510037SARM gem5 Developers switch (attr_3_0) { 129610037SARM gem5 Developers case 0x0: 129710037SARM gem5 Developers te.innerAttrs = 0x1; 129810037SARM gem5 Developers break; 129910037SARM gem5 Developers case 0x4: 130010037SARM gem5 Developers te.innerAttrs = attr_7_4 == 0 ? 0x3 : 0; 130110037SARM gem5 Developers break; 130210037SARM gem5 Developers case 0x8: 130310037SARM gem5 Developers case 0x9: 130410037SARM gem5 Developers case 0xA: 130510037SARM gem5 Developers case 0xB: 130610037SARM gem5 Developers te.innerAttrs = 6; 130710037SARM gem5 Developers break; 130810037SARM gem5 Developers case 0xC: 130910037SARM gem5 Developers case 0xD: 131010037SARM gem5 Developers case 0xE: 131110037SARM gem5 Developers case 0xF: 131210037SARM gem5 Developers te.innerAttrs = attr_3_0 & 1 ? 0x5 : 0x7; 131310037SARM gem5 Developers break; 131410037SARM gem5 Developers default: 131510037SARM gem5 Developers panic("Unpredictable behavior\n"); 131610037SARM gem5 Developers break; 131710037SARM gem5 Developers } 131810037SARM gem5 Developers } 131910037SARM gem5 Developers 132010037SARM gem5 Developers te.outerShareable = sh == 2; 132110037SARM gem5 Developers te.shareable = (sh & 0x2) ? true : false; 132210037SARM gem5 Developers te.setAttributes(true); 132310037SARM gem5 Developers te.attributes |= (uint64_t) attr << 56; 132410037SARM gem5 Developers} 132510037SARM gem5 Developers 132610037SARM gem5 Developersvoid 132710037SARM gem5 DevelopersTableWalker::memAttrsAArch64(ThreadContext *tc, TlbEntry &te, uint8_t attrIndx, 132810037SARM gem5 Developers uint8_t sh) 132910037SARM gem5 Developers{ 133010037SARM gem5 Developers DPRINTF(TLBVerbose, "memAttrsAArch64 AttrIndx:%#x sh:%#x\n", attrIndx, sh); 133110037SARM gem5 Developers 133210037SARM gem5 Developers // Select MAIR 133310037SARM gem5 Developers uint64_t mair; 133410037SARM gem5 Developers switch (currState->el) { 133510037SARM gem5 Developers case EL0: 133610037SARM gem5 Developers case EL1: 133710037SARM gem5 Developers mair = tc->readMiscReg(MISCREG_MAIR_EL1); 133810037SARM gem5 Developers break; 133910037SARM gem5 Developers case EL2: 134010037SARM gem5 Developers mair = tc->readMiscReg(MISCREG_MAIR_EL2); 134110037SARM gem5 Developers break; 134210037SARM gem5 Developers case EL3: 134310037SARM gem5 Developers mair = tc->readMiscReg(MISCREG_MAIR_EL3); 134410037SARM gem5 Developers break; 134510037SARM gem5 Developers default: 134610037SARM gem5 Developers panic("Invalid exception level"); 134710037SARM gem5 Developers break; 134810037SARM gem5 Developers } 134910037SARM gem5 Developers 135010037SARM gem5 Developers // Select attributes 135110037SARM gem5 Developers uint8_t attr = bits(mair, 8 * attrIndx + 7, 8 * attrIndx); 135210037SARM gem5 Developers uint8_t attr_lo = bits(attr, 3, 0); 135310037SARM gem5 Developers uint8_t attr_hi = bits(attr, 7, 4); 135410037SARM gem5 Developers 135510037SARM gem5 Developers // Memory type 135610037SARM gem5 Developers te.mtype = attr_hi == 0 ? TlbEntry::MemoryType::Device : TlbEntry::MemoryType::Normal; 135710037SARM gem5 Developers 135810037SARM gem5 Developers // Cacheability 135910037SARM gem5 Developers te.nonCacheable = false; 136010037SARM gem5 Developers if (te.mtype == TlbEntry::MemoryType::Device || // Device memory 136110037SARM gem5 Developers attr_hi == 0x8 || // Normal memory, Outer Non-cacheable 136210037SARM gem5 Developers attr_lo == 0x8) { // Normal memory, Inner Non-cacheable 136310037SARM gem5 Developers te.nonCacheable = true; 136410037SARM gem5 Developers } 136510037SARM gem5 Developers 136610037SARM gem5 Developers te.shareable = sh == 2; 136710037SARM gem5 Developers te.outerShareable = (sh & 0x2) ? true : false; 136810037SARM gem5 Developers // Attributes formatted according to the 64-bit PAR 136910037SARM gem5 Developers te.attributes = ((uint64_t) attr << 56) | 137010037SARM gem5 Developers (1 << 11) | // LPAE bit 137110037SARM gem5 Developers (te.ns << 9) | // NS bit 137210037SARM gem5 Developers (sh << 7); 13737404SAli.Saidi@ARM.com} 13747404SAli.Saidi@ARM.com 13757404SAli.Saidi@ARM.comvoid 13767404SAli.Saidi@ARM.comTableWalker::doL1Descriptor() 13777404SAli.Saidi@ARM.com{ 137810037SARM gem5 Developers if (currState->fault != NoFault) { 137910037SARM gem5 Developers return; 138010037SARM gem5 Developers } 138110037SARM gem5 Developers 13827439Sdam.sunwoo@arm.com DPRINTF(TLB, "L1 descriptor for %#x is %#x\n", 138310037SARM gem5 Developers currState->vaddr_tainted, currState->l1Desc.data); 13847404SAli.Saidi@ARM.com TlbEntry te; 13857404SAli.Saidi@ARM.com 13867439Sdam.sunwoo@arm.com switch (currState->l1Desc.type()) { 13877404SAli.Saidi@ARM.com case L1Descriptor::Ignore: 13887404SAli.Saidi@ARM.com case L1Descriptor::Reserved: 13897946SGiacomo.Gabrielli@arm.com if (!currState->timing) { 13907439Sdam.sunwoo@arm.com currState->tc = NULL; 13917439Sdam.sunwoo@arm.com currState->req = NULL; 13927437Sdam.sunwoo@arm.com } 13937406SAli.Saidi@ARM.com DPRINTF(TLB, "L1 Descriptor Reserved/Ignore, causing fault\n"); 13947439Sdam.sunwoo@arm.com if (currState->isFetch) 13957439Sdam.sunwoo@arm.com currState->fault = 139610474Sandreas.hansson@arm.com std::make_shared<PrefetchAbort>( 139710474Sandreas.hansson@arm.com currState->vaddr_tainted, 139810474Sandreas.hansson@arm.com ArmFault::TranslationLL + L1, 139910474Sandreas.hansson@arm.com isStage2, 140010474Sandreas.hansson@arm.com ArmFault::VmsaTran); 14017406SAli.Saidi@ARM.com else 14027439Sdam.sunwoo@arm.com currState->fault = 140310474Sandreas.hansson@arm.com std::make_shared<DataAbort>( 140410474Sandreas.hansson@arm.com currState->vaddr_tainted, 140510474Sandreas.hansson@arm.com TlbEntry::DomainType::NoAccess, 140610474Sandreas.hansson@arm.com currState->isWrite, 140710474Sandreas.hansson@arm.com ArmFault::TranslationLL + L1, isStage2, 140810474Sandreas.hansson@arm.com ArmFault::VmsaTran); 14097404SAli.Saidi@ARM.com return; 14107404SAli.Saidi@ARM.com case L1Descriptor::Section: 14117439Sdam.sunwoo@arm.com if (currState->sctlr.afe && bits(currState->l1Desc.ap(), 0) == 0) { 14127436Sdam.sunwoo@arm.com /** @todo: check sctlr.ha (bit[17]) if Hardware Access Flag is 14137436Sdam.sunwoo@arm.com * enabled if set, do l1.Desc.setAp0() instead of generating 14147436Sdam.sunwoo@arm.com * AccessFlag0 14157436Sdam.sunwoo@arm.com */ 14167436Sdam.sunwoo@arm.com 141710474Sandreas.hansson@arm.com currState->fault = std::make_shared<DataAbort>( 141810474Sandreas.hansson@arm.com currState->vaddr_tainted, 141910474Sandreas.hansson@arm.com currState->l1Desc.domain(), 142010474Sandreas.hansson@arm.com currState->isWrite, 142110474Sandreas.hansson@arm.com ArmFault::AccessFlagLL + L1, 142210474Sandreas.hansson@arm.com isStage2, 142310474Sandreas.hansson@arm.com ArmFault::VmsaTran); 14247436Sdam.sunwoo@arm.com } 14257439Sdam.sunwoo@arm.com if (currState->l1Desc.supersection()) { 14267404SAli.Saidi@ARM.com panic("Haven't implemented supersections\n"); 14277404SAli.Saidi@ARM.com } 142810037SARM gem5 Developers insertTableEntry(currState->l1Desc, false); 142910037SARM gem5 Developers return; 143010037SARM gem5 Developers case L1Descriptor::PageTable: 143110037SARM gem5 Developers { 143210037SARM gem5 Developers Addr l2desc_addr; 143310037SARM gem5 Developers l2desc_addr = currState->l1Desc.l2Addr() | 143410037SARM gem5 Developers (bits(currState->vaddr, 19, 12) << 2); 143510037SARM gem5 Developers DPRINTF(TLB, "L1 descriptor points to page table at: %#x (%s)\n", 143610037SARM gem5 Developers l2desc_addr, currState->isSecure ? "s" : "ns"); 14377404SAli.Saidi@ARM.com 143810037SARM gem5 Developers // Trickbox address check 143911395Sandreas.sandberg@arm.com currState->fault = testWalk(l2desc_addr, sizeof(uint32_t), 144011395Sandreas.sandberg@arm.com currState->l1Desc.domain(), L2); 14417404SAli.Saidi@ARM.com 144210037SARM gem5 Developers if (currState->fault) { 144310037SARM gem5 Developers if (!currState->timing) { 144410037SARM gem5 Developers currState->tc = NULL; 144510037SARM gem5 Developers currState->req = NULL; 144610037SARM gem5 Developers } 144710037SARM gem5 Developers return; 144810037SARM gem5 Developers } 144910037SARM gem5 Developers 145010836Sandreas.hansson@arm.com Request::Flags flag = Request::PT_WALK; 145110037SARM gem5 Developers if (currState->isSecure) 145210037SARM gem5 Developers flag.set(Request::SECURE); 145310037SARM gem5 Developers 145410037SARM gem5 Developers bool delayed; 145510037SARM gem5 Developers delayed = fetchDescriptor(l2desc_addr, 145610037SARM gem5 Developers (uint8_t*)&currState->l2Desc.data, 145710037SARM gem5 Developers sizeof(uint32_t), flag, -1, &doL2DescEvent, 145810037SARM gem5 Developers &TableWalker::doL2Descriptor); 145910037SARM gem5 Developers if (delayed) { 146010037SARM gem5 Developers currState->delayed = true; 146110037SARM gem5 Developers } 146210037SARM gem5 Developers 146310037SARM gem5 Developers return; 146410037SARM gem5 Developers } 146510037SARM gem5 Developers default: 146610037SARM gem5 Developers panic("A new type in a 2 bit field?\n"); 146710037SARM gem5 Developers } 146810037SARM gem5 Developers} 146910037SARM gem5 Developers 147010037SARM gem5 Developersvoid 147110037SARM gem5 DevelopersTableWalker::doLongDescriptor() 147210037SARM gem5 Developers{ 147310037SARM gem5 Developers if (currState->fault != NoFault) { 147410037SARM gem5 Developers return; 147510037SARM gem5 Developers } 147610037SARM gem5 Developers 147710037SARM gem5 Developers DPRINTF(TLB, "L%d descriptor for %#llx is %#llx (%s)\n", 147810037SARM gem5 Developers currState->longDesc.lookupLevel, currState->vaddr_tainted, 147910037SARM gem5 Developers currState->longDesc.data, 148010037SARM gem5 Developers currState->aarch64 ? "AArch64" : "long-desc."); 148110037SARM gem5 Developers 148210037SARM gem5 Developers if ((currState->longDesc.type() == LongDescriptor::Block) || 148310037SARM gem5 Developers (currState->longDesc.type() == LongDescriptor::Page)) { 148410037SARM gem5 Developers DPRINTF(TLBVerbose, "Analyzing L%d descriptor: %#llx, pxn: %d, " 148510037SARM gem5 Developers "xn: %d, ap: %d, af: %d, type: %d\n", 148610037SARM gem5 Developers currState->longDesc.lookupLevel, 148710037SARM gem5 Developers currState->longDesc.data, 148810037SARM gem5 Developers currState->longDesc.pxn(), 148910037SARM gem5 Developers currState->longDesc.xn(), 149010037SARM gem5 Developers currState->longDesc.ap(), 149110037SARM gem5 Developers currState->longDesc.af(), 149210037SARM gem5 Developers currState->longDesc.type()); 149310037SARM gem5 Developers } else { 149410037SARM gem5 Developers DPRINTF(TLBVerbose, "Analyzing L%d descriptor: %#llx, type: %d\n", 149510037SARM gem5 Developers currState->longDesc.lookupLevel, 149610037SARM gem5 Developers currState->longDesc.data, 149710037SARM gem5 Developers currState->longDesc.type()); 149810037SARM gem5 Developers } 149910037SARM gem5 Developers 150010037SARM gem5 Developers TlbEntry te; 150110037SARM gem5 Developers 150210037SARM gem5 Developers switch (currState->longDesc.type()) { 150310037SARM gem5 Developers case LongDescriptor::Invalid: 15047439Sdam.sunwoo@arm.com if (!currState->timing) { 15057439Sdam.sunwoo@arm.com currState->tc = NULL; 15067439Sdam.sunwoo@arm.com currState->req = NULL; 15077437Sdam.sunwoo@arm.com } 15087404SAli.Saidi@ARM.com 150910037SARM gem5 Developers DPRINTF(TLB, "L%d descriptor Invalid, causing fault type %d\n", 151010037SARM gem5 Developers currState->longDesc.lookupLevel, 151110037SARM gem5 Developers ArmFault::TranslationLL + currState->longDesc.lookupLevel); 151210037SARM gem5 Developers if (currState->isFetch) 151310474Sandreas.hansson@arm.com currState->fault = std::make_shared<PrefetchAbort>( 151410037SARM gem5 Developers currState->vaddr_tainted, 151510037SARM gem5 Developers ArmFault::TranslationLL + currState->longDesc.lookupLevel, 151610037SARM gem5 Developers isStage2, 151710037SARM gem5 Developers ArmFault::LpaeTran); 151810037SARM gem5 Developers else 151910474Sandreas.hansson@arm.com currState->fault = std::make_shared<DataAbort>( 152010037SARM gem5 Developers currState->vaddr_tainted, 152110037SARM gem5 Developers TlbEntry::DomainType::NoAccess, 152210037SARM gem5 Developers currState->isWrite, 152310037SARM gem5 Developers ArmFault::TranslationLL + currState->longDesc.lookupLevel, 152410037SARM gem5 Developers isStage2, 152510037SARM gem5 Developers ArmFault::LpaeTran); 15267404SAli.Saidi@ARM.com return; 152710037SARM gem5 Developers case LongDescriptor::Block: 152810037SARM gem5 Developers case LongDescriptor::Page: 152910037SARM gem5 Developers { 153010037SARM gem5 Developers bool fault = false; 153110037SARM gem5 Developers bool aff = false; 153210037SARM gem5 Developers // Check for address size fault 153310037SARM gem5 Developers if (checkAddrSizeFaultAArch64( 153410037SARM gem5 Developers mbits(currState->longDesc.data, MaxPhysAddrRange - 1, 153510037SARM gem5 Developers currState->longDesc.offsetBits()), 153610037SARM gem5 Developers currState->physAddrRange)) { 153710037SARM gem5 Developers fault = true; 153810037SARM gem5 Developers DPRINTF(TLB, "L%d descriptor causing Address Size Fault\n", 153910037SARM gem5 Developers currState->longDesc.lookupLevel); 154010037SARM gem5 Developers // Check for access fault 154110037SARM gem5 Developers } else if (currState->longDesc.af() == 0) { 154210037SARM gem5 Developers fault = true; 154310037SARM gem5 Developers DPRINTF(TLB, "L%d descriptor causing Access Fault\n", 154410037SARM gem5 Developers currState->longDesc.lookupLevel); 154510037SARM gem5 Developers aff = true; 154610037SARM gem5 Developers } 154710037SARM gem5 Developers if (fault) { 154810037SARM gem5 Developers if (currState->isFetch) 154910474Sandreas.hansson@arm.com currState->fault = std::make_shared<PrefetchAbort>( 155010037SARM gem5 Developers currState->vaddr_tainted, 155110037SARM gem5 Developers (aff ? ArmFault::AccessFlagLL : ArmFault::AddressSizeLL) + 155210037SARM gem5 Developers currState->longDesc.lookupLevel, 155310037SARM gem5 Developers isStage2, 155410037SARM gem5 Developers ArmFault::LpaeTran); 155510037SARM gem5 Developers else 155610474Sandreas.hansson@arm.com currState->fault = std::make_shared<DataAbort>( 155710037SARM gem5 Developers currState->vaddr_tainted, 155810037SARM gem5 Developers TlbEntry::DomainType::NoAccess, currState->isWrite, 155910037SARM gem5 Developers (aff ? ArmFault::AccessFlagLL : ArmFault::AddressSizeLL) + 156010037SARM gem5 Developers currState->longDesc.lookupLevel, 156110037SARM gem5 Developers isStage2, 156210037SARM gem5 Developers ArmFault::LpaeTran); 156310037SARM gem5 Developers } else { 156410037SARM gem5 Developers insertTableEntry(currState->longDesc, true); 156510037SARM gem5 Developers } 156610037SARM gem5 Developers } 156710037SARM gem5 Developers return; 156810037SARM gem5 Developers case LongDescriptor::Table: 156910037SARM gem5 Developers { 157010037SARM gem5 Developers // Set hierarchical permission flags 157110037SARM gem5 Developers currState->secureLookup = currState->secureLookup && 157210037SARM gem5 Developers currState->longDesc.secureTable(); 157310037SARM gem5 Developers currState->rwTable = currState->rwTable && 157410037SARM gem5 Developers currState->longDesc.rwTable(); 157510037SARM gem5 Developers currState->userTable = currState->userTable && 157610037SARM gem5 Developers currState->longDesc.userTable(); 157710037SARM gem5 Developers currState->xnTable = currState->xnTable || 157810037SARM gem5 Developers currState->longDesc.xnTable(); 157910037SARM gem5 Developers currState->pxnTable = currState->pxnTable || 158010037SARM gem5 Developers currState->longDesc.pxnTable(); 15817404SAli.Saidi@ARM.com 158210037SARM gem5 Developers // Set up next level lookup 158310037SARM gem5 Developers Addr next_desc_addr = currState->longDesc.nextDescAddr( 158410037SARM gem5 Developers currState->vaddr); 15857439Sdam.sunwoo@arm.com 158610037SARM gem5 Developers DPRINTF(TLB, "L%d descriptor points to L%d descriptor at: %#x (%s)\n", 158710037SARM gem5 Developers currState->longDesc.lookupLevel, 158810037SARM gem5 Developers currState->longDesc.lookupLevel + 1, 158910037SARM gem5 Developers next_desc_addr, 159010037SARM gem5 Developers currState->secureLookup ? "s" : "ns"); 159110037SARM gem5 Developers 159210037SARM gem5 Developers // Check for address size fault 159310037SARM gem5 Developers if (currState->aarch64 && checkAddrSizeFaultAArch64( 159410037SARM gem5 Developers next_desc_addr, currState->physAddrRange)) { 159510037SARM gem5 Developers DPRINTF(TLB, "L%d descriptor causing Address Size Fault\n", 159610037SARM gem5 Developers currState->longDesc.lookupLevel); 159710037SARM gem5 Developers if (currState->isFetch) 159810474Sandreas.hansson@arm.com currState->fault = std::make_shared<PrefetchAbort>( 159910037SARM gem5 Developers currState->vaddr_tainted, 160010037SARM gem5 Developers ArmFault::AddressSizeLL 160110037SARM gem5 Developers + currState->longDesc.lookupLevel, 160210037SARM gem5 Developers isStage2, 160310037SARM gem5 Developers ArmFault::LpaeTran); 160410037SARM gem5 Developers else 160510474Sandreas.hansson@arm.com currState->fault = std::make_shared<DataAbort>( 160610037SARM gem5 Developers currState->vaddr_tainted, 160710037SARM gem5 Developers TlbEntry::DomainType::NoAccess, currState->isWrite, 160810037SARM gem5 Developers ArmFault::AddressSizeLL 160910037SARM gem5 Developers + currState->longDesc.lookupLevel, 161010037SARM gem5 Developers isStage2, 161110037SARM gem5 Developers ArmFault::LpaeTran); 161210037SARM gem5 Developers return; 16137437Sdam.sunwoo@arm.com } 16147404SAli.Saidi@ARM.com 161510037SARM gem5 Developers // Trickbox address check 161611395Sandreas.sandberg@arm.com currState->fault = testWalk( 161711395Sandreas.sandberg@arm.com next_desc_addr, sizeof(uint64_t), TlbEntry::DomainType::Client, 161811395Sandreas.sandberg@arm.com toLookupLevel(currState->longDesc.lookupLevel +1)); 16197404SAli.Saidi@ARM.com 162010037SARM gem5 Developers if (currState->fault) { 162110037SARM gem5 Developers if (!currState->timing) { 162210037SARM gem5 Developers currState->tc = NULL; 162310037SARM gem5 Developers currState->req = NULL; 162410037SARM gem5 Developers } 162510037SARM gem5 Developers return; 162610037SARM gem5 Developers } 162710037SARM gem5 Developers 162810836Sandreas.hansson@arm.com Request::Flags flag = Request::PT_WALK; 162910037SARM gem5 Developers if (currState->secureLookup) 163010037SARM gem5 Developers flag.set(Request::SECURE); 163110037SARM gem5 Developers 163210037SARM gem5 Developers currState->longDesc.lookupLevel = 163310037SARM gem5 Developers (LookupLevel) (currState->longDesc.lookupLevel + 1); 163410037SARM gem5 Developers Event *event = NULL; 163510037SARM gem5 Developers switch (currState->longDesc.lookupLevel) { 163610037SARM gem5 Developers case L1: 163710037SARM gem5 Developers assert(currState->aarch64); 163810037SARM gem5 Developers event = &doL1LongDescEvent; 163910037SARM gem5 Developers break; 164010037SARM gem5 Developers case L2: 164110037SARM gem5 Developers event = &doL2LongDescEvent; 164210037SARM gem5 Developers break; 164310037SARM gem5 Developers case L3: 164410037SARM gem5 Developers event = &doL3LongDescEvent; 164510037SARM gem5 Developers break; 164610037SARM gem5 Developers default: 164710037SARM gem5 Developers panic("Wrong lookup level in table walk\n"); 164810037SARM gem5 Developers break; 164910037SARM gem5 Developers } 165010037SARM gem5 Developers 165110037SARM gem5 Developers bool delayed; 165210037SARM gem5 Developers delayed = fetchDescriptor(next_desc_addr, (uint8_t*)&currState->longDesc.data, 165310037SARM gem5 Developers sizeof(uint64_t), flag, -1, event, 165410037SARM gem5 Developers &TableWalker::doLongDescriptor); 165510037SARM gem5 Developers if (delayed) { 165610037SARM gem5 Developers currState->delayed = true; 165710037SARM gem5 Developers } 16587404SAli.Saidi@ARM.com } 16597404SAli.Saidi@ARM.com return; 16607404SAli.Saidi@ARM.com default: 16617404SAli.Saidi@ARM.com panic("A new type in a 2 bit field?\n"); 16627404SAli.Saidi@ARM.com } 16637404SAli.Saidi@ARM.com} 16647404SAli.Saidi@ARM.com 16657404SAli.Saidi@ARM.comvoid 16667404SAli.Saidi@ARM.comTableWalker::doL2Descriptor() 16677404SAli.Saidi@ARM.com{ 166810037SARM gem5 Developers if (currState->fault != NoFault) { 166910037SARM gem5 Developers return; 167010037SARM gem5 Developers } 167110037SARM gem5 Developers 16727439Sdam.sunwoo@arm.com DPRINTF(TLB, "L2 descriptor for %#x is %#x\n", 167310037SARM gem5 Developers currState->vaddr_tainted, currState->l2Desc.data); 16747404SAli.Saidi@ARM.com TlbEntry te; 16757404SAli.Saidi@ARM.com 16767439Sdam.sunwoo@arm.com if (currState->l2Desc.invalid()) { 16777404SAli.Saidi@ARM.com DPRINTF(TLB, "L2 descriptor invalid, causing fault\n"); 16787946SGiacomo.Gabrielli@arm.com if (!currState->timing) { 16797439Sdam.sunwoo@arm.com currState->tc = NULL; 16807439Sdam.sunwoo@arm.com currState->req = NULL; 16817437Sdam.sunwoo@arm.com } 16827439Sdam.sunwoo@arm.com if (currState->isFetch) 168310474Sandreas.hansson@arm.com currState->fault = std::make_shared<PrefetchAbort>( 168410474Sandreas.hansson@arm.com currState->vaddr_tainted, 168510474Sandreas.hansson@arm.com ArmFault::TranslationLL + L2, 168610474Sandreas.hansson@arm.com isStage2, 168710474Sandreas.hansson@arm.com ArmFault::VmsaTran); 16887406SAli.Saidi@ARM.com else 168910474Sandreas.hansson@arm.com currState->fault = std::make_shared<DataAbort>( 169010474Sandreas.hansson@arm.com currState->vaddr_tainted, currState->l1Desc.domain(), 169110474Sandreas.hansson@arm.com currState->isWrite, ArmFault::TranslationLL + L2, 169210474Sandreas.hansson@arm.com isStage2, 169310474Sandreas.hansson@arm.com ArmFault::VmsaTran); 16947404SAli.Saidi@ARM.com return; 16957404SAli.Saidi@ARM.com } 16967404SAli.Saidi@ARM.com 16977439Sdam.sunwoo@arm.com if (currState->sctlr.afe && bits(currState->l2Desc.ap(), 0) == 0) { 16987436Sdam.sunwoo@arm.com /** @todo: check sctlr.ha (bit[17]) if Hardware Access Flag is enabled 16997436Sdam.sunwoo@arm.com * if set, do l2.Desc.setAp0() instead of generating AccessFlag0 17007436Sdam.sunwoo@arm.com */ 170110037SARM gem5 Developers DPRINTF(TLB, "Generating access fault at L2, afe: %d, ap: %d\n", 170210037SARM gem5 Developers currState->sctlr.afe, currState->l2Desc.ap()); 17037436Sdam.sunwoo@arm.com 170410474Sandreas.hansson@arm.com currState->fault = std::make_shared<DataAbort>( 170510474Sandreas.hansson@arm.com currState->vaddr_tainted, 170610474Sandreas.hansson@arm.com TlbEntry::DomainType::NoAccess, currState->isWrite, 170710474Sandreas.hansson@arm.com ArmFault::AccessFlagLL + L2, isStage2, 170810474Sandreas.hansson@arm.com ArmFault::VmsaTran); 17097436Sdam.sunwoo@arm.com } 17107436Sdam.sunwoo@arm.com 171110037SARM gem5 Developers insertTableEntry(currState->l2Desc, false); 17127437Sdam.sunwoo@arm.com} 17137437Sdam.sunwoo@arm.com 17147437Sdam.sunwoo@arm.comvoid 17157437Sdam.sunwoo@arm.comTableWalker::doL1DescriptorWrapper() 17167437Sdam.sunwoo@arm.com{ 171710037SARM gem5 Developers currState = stateQueues[L1].front(); 17187439Sdam.sunwoo@arm.com currState->delayed = false; 171910037SARM gem5 Developers // if there's a stage2 translation object we don't need it any more 172010037SARM gem5 Developers if (currState->stage2Tran) { 172110037SARM gem5 Developers delete currState->stage2Tran; 172210037SARM gem5 Developers currState->stage2Tran = NULL; 172310037SARM gem5 Developers } 172410037SARM gem5 Developers 17257437Sdam.sunwoo@arm.com 17267578Sdam.sunwoo@arm.com DPRINTF(TLBVerbose, "L1 Desc object host addr: %p\n",&currState->l1Desc.data); 17277578Sdam.sunwoo@arm.com DPRINTF(TLBVerbose, "L1 Desc object data: %08x\n",currState->l1Desc.data); 17287578Sdam.sunwoo@arm.com 172910037SARM gem5 Developers DPRINTF(TLBVerbose, "calling doL1Descriptor for vaddr:%#x\n", currState->vaddr_tainted); 17307437Sdam.sunwoo@arm.com doL1Descriptor(); 17317437Sdam.sunwoo@arm.com 173210037SARM gem5 Developers stateQueues[L1].pop_front(); 17337437Sdam.sunwoo@arm.com // Check if fault was generated 17347439Sdam.sunwoo@arm.com if (currState->fault != NoFault) { 17357439Sdam.sunwoo@arm.com currState->transState->finish(currState->fault, currState->req, 17367439Sdam.sunwoo@arm.com currState->tc, currState->mode); 173710621SCurtis.Dunham@arm.com statWalksShortTerminatedAtLevel[0]++; 17387437Sdam.sunwoo@arm.com 17397728SAli.Saidi@ARM.com pending = false; 17407728SAli.Saidi@ARM.com nextWalk(currState->tc); 17417728SAli.Saidi@ARM.com 17427439Sdam.sunwoo@arm.com currState->req = NULL; 17437439Sdam.sunwoo@arm.com currState->tc = NULL; 17447439Sdam.sunwoo@arm.com currState->delayed = false; 17458510SAli.Saidi@ARM.com delete currState; 17467437Sdam.sunwoo@arm.com } 17477439Sdam.sunwoo@arm.com else if (!currState->delayed) { 17487653Sgene.wu@arm.com // delay is not set so there is no L2 to do 174910037SARM gem5 Developers // Don't finish the translation if a stage 2 look up is underway 175010037SARM gem5 Developers if (!currState->doingStage2) { 175110621SCurtis.Dunham@arm.com statWalkServiceTime.sample(curTick() - currState->startTime); 175210037SARM gem5 Developers DPRINTF(TLBVerbose, "calling translateTiming again\n"); 175310037SARM gem5 Developers currState->fault = tlb->translateTiming(currState->req, currState->tc, 175410037SARM gem5 Developers currState->transState, currState->mode); 175510621SCurtis.Dunham@arm.com statWalksShortTerminatedAtLevel[0]++; 175610037SARM gem5 Developers } 17577437Sdam.sunwoo@arm.com 17587728SAli.Saidi@ARM.com pending = false; 17597728SAli.Saidi@ARM.com nextWalk(currState->tc); 17607728SAli.Saidi@ARM.com 17617439Sdam.sunwoo@arm.com currState->req = NULL; 17627439Sdam.sunwoo@arm.com currState->tc = NULL; 17637439Sdam.sunwoo@arm.com currState->delayed = false; 17647653Sgene.wu@arm.com delete currState; 17657653Sgene.wu@arm.com } else { 17667653Sgene.wu@arm.com // need to do L2 descriptor 176710037SARM gem5 Developers stateQueues[L2].push_back(currState); 17687437Sdam.sunwoo@arm.com } 17697439Sdam.sunwoo@arm.com currState = NULL; 17707437Sdam.sunwoo@arm.com} 17717437Sdam.sunwoo@arm.com 17727437Sdam.sunwoo@arm.comvoid 17737437Sdam.sunwoo@arm.comTableWalker::doL2DescriptorWrapper() 17747437Sdam.sunwoo@arm.com{ 177510037SARM gem5 Developers currState = stateQueues[L2].front(); 17767439Sdam.sunwoo@arm.com assert(currState->delayed); 177710037SARM gem5 Developers // if there's a stage2 translation object we don't need it any more 177810037SARM gem5 Developers if (currState->stage2Tran) { 177910037SARM gem5 Developers delete currState->stage2Tran; 178010037SARM gem5 Developers currState->stage2Tran = NULL; 178110037SARM gem5 Developers } 17827437Sdam.sunwoo@arm.com 17837439Sdam.sunwoo@arm.com DPRINTF(TLBVerbose, "calling doL2Descriptor for vaddr:%#x\n", 178410037SARM gem5 Developers currState->vaddr_tainted); 17857437Sdam.sunwoo@arm.com doL2Descriptor(); 17867437Sdam.sunwoo@arm.com 17877437Sdam.sunwoo@arm.com // Check if fault was generated 17887439Sdam.sunwoo@arm.com if (currState->fault != NoFault) { 17897439Sdam.sunwoo@arm.com currState->transState->finish(currState->fault, currState->req, 17907439Sdam.sunwoo@arm.com currState->tc, currState->mode); 179110621SCurtis.Dunham@arm.com statWalksShortTerminatedAtLevel[1]++; 17927437Sdam.sunwoo@arm.com } 17937437Sdam.sunwoo@arm.com else { 179410037SARM gem5 Developers // Don't finish the translation if a stage 2 look up is underway 179510037SARM gem5 Developers if (!currState->doingStage2) { 179610621SCurtis.Dunham@arm.com statWalkServiceTime.sample(curTick() - currState->startTime); 179710037SARM gem5 Developers DPRINTF(TLBVerbose, "calling translateTiming again\n"); 179810037SARM gem5 Developers currState->fault = tlb->translateTiming(currState->req, 179910037SARM gem5 Developers currState->tc, currState->transState, currState->mode); 180010621SCurtis.Dunham@arm.com statWalksShortTerminatedAtLevel[1]++; 180110037SARM gem5 Developers } 18027437Sdam.sunwoo@arm.com } 18037437Sdam.sunwoo@arm.com 18047728SAli.Saidi@ARM.com 180510037SARM gem5 Developers stateQueues[L2].pop_front(); 18067728SAli.Saidi@ARM.com pending = false; 18077728SAli.Saidi@ARM.com nextWalk(currState->tc); 18087728SAli.Saidi@ARM.com 18097439Sdam.sunwoo@arm.com currState->req = NULL; 18107439Sdam.sunwoo@arm.com currState->tc = NULL; 18117439Sdam.sunwoo@arm.com currState->delayed = false; 18127439Sdam.sunwoo@arm.com 18137653Sgene.wu@arm.com delete currState; 18147439Sdam.sunwoo@arm.com currState = NULL; 18157404SAli.Saidi@ARM.com} 18167404SAli.Saidi@ARM.com 18177728SAli.Saidi@ARM.comvoid 181810037SARM gem5 DevelopersTableWalker::doL0LongDescriptorWrapper() 181910037SARM gem5 Developers{ 182010037SARM gem5 Developers doLongDescriptorWrapper(L0); 182110037SARM gem5 Developers} 182210037SARM gem5 Developers 182310037SARM gem5 Developersvoid 182410037SARM gem5 DevelopersTableWalker::doL1LongDescriptorWrapper() 182510037SARM gem5 Developers{ 182610037SARM gem5 Developers doLongDescriptorWrapper(L1); 182710037SARM gem5 Developers} 182810037SARM gem5 Developers 182910037SARM gem5 Developersvoid 183010037SARM gem5 DevelopersTableWalker::doL2LongDescriptorWrapper() 183110037SARM gem5 Developers{ 183210037SARM gem5 Developers doLongDescriptorWrapper(L2); 183310037SARM gem5 Developers} 183410037SARM gem5 Developers 183510037SARM gem5 Developersvoid 183610037SARM gem5 DevelopersTableWalker::doL3LongDescriptorWrapper() 183710037SARM gem5 Developers{ 183810037SARM gem5 Developers doLongDescriptorWrapper(L3); 183910037SARM gem5 Developers} 184010037SARM gem5 Developers 184110037SARM gem5 Developersvoid 184210037SARM gem5 DevelopersTableWalker::doLongDescriptorWrapper(LookupLevel curr_lookup_level) 184310037SARM gem5 Developers{ 184410037SARM gem5 Developers currState = stateQueues[curr_lookup_level].front(); 184510037SARM gem5 Developers assert(curr_lookup_level == currState->longDesc.lookupLevel); 184610037SARM gem5 Developers currState->delayed = false; 184710037SARM gem5 Developers 184810037SARM gem5 Developers // if there's a stage2 translation object we don't need it any more 184910037SARM gem5 Developers if (currState->stage2Tran) { 185010037SARM gem5 Developers delete currState->stage2Tran; 185110037SARM gem5 Developers currState->stage2Tran = NULL; 185210037SARM gem5 Developers } 185310037SARM gem5 Developers 185410037SARM gem5 Developers DPRINTF(TLBVerbose, "calling doLongDescriptor for vaddr:%#x\n", 185510037SARM gem5 Developers currState->vaddr_tainted); 185610037SARM gem5 Developers doLongDescriptor(); 185710037SARM gem5 Developers 185810037SARM gem5 Developers stateQueues[curr_lookup_level].pop_front(); 185910037SARM gem5 Developers 186010037SARM gem5 Developers if (currState->fault != NoFault) { 186110037SARM gem5 Developers // A fault was generated 186210037SARM gem5 Developers currState->transState->finish(currState->fault, currState->req, 186310037SARM gem5 Developers currState->tc, currState->mode); 186410037SARM gem5 Developers 186510037SARM gem5 Developers pending = false; 186610037SARM gem5 Developers nextWalk(currState->tc); 186710037SARM gem5 Developers 186810037SARM gem5 Developers currState->req = NULL; 186910037SARM gem5 Developers currState->tc = NULL; 187010037SARM gem5 Developers currState->delayed = false; 187110037SARM gem5 Developers delete currState; 187210037SARM gem5 Developers } else if (!currState->delayed) { 187310037SARM gem5 Developers // No additional lookups required 187410037SARM gem5 Developers // Don't finish the translation if a stage 2 look up is underway 187510037SARM gem5 Developers if (!currState->doingStage2) { 187610037SARM gem5 Developers DPRINTF(TLBVerbose, "calling translateTiming again\n"); 187710621SCurtis.Dunham@arm.com statWalkServiceTime.sample(curTick() - currState->startTime); 187810037SARM gem5 Developers currState->fault = tlb->translateTiming(currState->req, currState->tc, 187910037SARM gem5 Developers currState->transState, 188010037SARM gem5 Developers currState->mode); 188110621SCurtis.Dunham@arm.com statWalksLongTerminatedAtLevel[(unsigned) curr_lookup_level]++; 188210037SARM gem5 Developers } 188310037SARM gem5 Developers 188410037SARM gem5 Developers pending = false; 188510037SARM gem5 Developers nextWalk(currState->tc); 188610037SARM gem5 Developers 188710037SARM gem5 Developers currState->req = NULL; 188810037SARM gem5 Developers currState->tc = NULL; 188910037SARM gem5 Developers currState->delayed = false; 189010037SARM gem5 Developers delete currState; 189110037SARM gem5 Developers } else { 189210037SARM gem5 Developers if (curr_lookup_level >= MAX_LOOKUP_LEVELS - 1) 189310037SARM gem5 Developers panic("Max. number of lookups already reached in table walk\n"); 189410037SARM gem5 Developers // Need to perform additional lookups 189510037SARM gem5 Developers stateQueues[currState->longDesc.lookupLevel].push_back(currState); 189610037SARM gem5 Developers } 189710037SARM gem5 Developers currState = NULL; 189810037SARM gem5 Developers} 189910037SARM gem5 Developers 190010037SARM gem5 Developers 190110037SARM gem5 Developersvoid 19027728SAli.Saidi@ARM.comTableWalker::nextWalk(ThreadContext *tc) 19037728SAli.Saidi@ARM.com{ 19047728SAli.Saidi@ARM.com if (pendingQueue.size()) 19059309Sandreas.hansson@arm.com schedule(doProcessEvent, clockEdge(Cycles(1))); 190610509SAli.Saidi@ARM.com else 190710509SAli.Saidi@ARM.com completeDrain(); 19087728SAli.Saidi@ARM.com} 19097728SAli.Saidi@ARM.com 191010037SARM gem5 Developersbool 191110037SARM gem5 DevelopersTableWalker::fetchDescriptor(Addr descAddr, uint8_t *data, int numBytes, 191210037SARM gem5 Developers Request::Flags flags, int queueIndex, Event *event, 191310037SARM gem5 Developers void (TableWalker::*doDescriptor)()) 191410037SARM gem5 Developers{ 191510037SARM gem5 Developers bool isTiming = currState->timing; 19167728SAli.Saidi@ARM.com 191710037SARM gem5 Developers // do the requests for the page table descriptors have to go through the 191810037SARM gem5 Developers // second stage MMU 191910037SARM gem5 Developers if (currState->stage2Req) { 192010037SARM gem5 Developers Fault fault; 192110037SARM gem5 Developers flags = flags | TLB::MustBeOne; 192210037SARM gem5 Developers 192310037SARM gem5 Developers if (isTiming) { 192410037SARM gem5 Developers Stage2MMU::Stage2Translation *tran = new 192510037SARM gem5 Developers Stage2MMU::Stage2Translation(*stage2Mmu, data, event, 192610037SARM gem5 Developers currState->vaddr); 192710037SARM gem5 Developers currState->stage2Tran = tran; 192810037SARM gem5 Developers stage2Mmu->readDataTimed(currState->tc, descAddr, tran, numBytes, 192910717Sandreas.hansson@arm.com flags); 193010037SARM gem5 Developers fault = tran->fault; 193110037SARM gem5 Developers } else { 193210037SARM gem5 Developers fault = stage2Mmu->readDataUntimed(currState->tc, 193310717Sandreas.hansson@arm.com currState->vaddr, descAddr, data, numBytes, flags, 193410037SARM gem5 Developers currState->functional); 193510037SARM gem5 Developers } 193610037SARM gem5 Developers 193710037SARM gem5 Developers if (fault != NoFault) { 193810037SARM gem5 Developers currState->fault = fault; 193910037SARM gem5 Developers } 194010037SARM gem5 Developers if (isTiming) { 194110037SARM gem5 Developers if (queueIndex >= 0) { 194210037SARM gem5 Developers DPRINTF(TLBVerbose, "Adding to walker fifo: queue size before adding: %d\n", 194310037SARM gem5 Developers stateQueues[queueIndex].size()); 194410037SARM gem5 Developers stateQueues[queueIndex].push_back(currState); 194510037SARM gem5 Developers currState = NULL; 194610037SARM gem5 Developers } 194710037SARM gem5 Developers } else { 194810037SARM gem5 Developers (this->*doDescriptor)(); 194910037SARM gem5 Developers } 195010037SARM gem5 Developers } else { 195110037SARM gem5 Developers if (isTiming) { 195210717Sandreas.hansson@arm.com port->dmaAction(MemCmd::ReadReq, descAddr, numBytes, event, data, 195310621SCurtis.Dunham@arm.com currState->tc->getCpuPtr()->clockPeriod(),flags); 195410037SARM gem5 Developers if (queueIndex >= 0) { 195510037SARM gem5 Developers DPRINTF(TLBVerbose, "Adding to walker fifo: queue size before adding: %d\n", 195610037SARM gem5 Developers stateQueues[queueIndex].size()); 195710037SARM gem5 Developers stateQueues[queueIndex].push_back(currState); 195810037SARM gem5 Developers currState = NULL; 195910037SARM gem5 Developers } 196010037SARM gem5 Developers } else if (!currState->functional) { 196110717Sandreas.hansson@arm.com port->dmaAction(MemCmd::ReadReq, descAddr, numBytes, NULL, data, 196210037SARM gem5 Developers currState->tc->getCpuPtr()->clockPeriod(), flags); 196310037SARM gem5 Developers (this->*doDescriptor)(); 196410037SARM gem5 Developers } else { 196510037SARM gem5 Developers RequestPtr req = new Request(descAddr, numBytes, flags, masterId); 196610037SARM gem5 Developers req->taskId(ContextSwitchTaskId::DMA); 196710037SARM gem5 Developers PacketPtr pkt = new Packet(req, MemCmd::ReadReq); 196810037SARM gem5 Developers pkt->dataStatic(data); 196910717Sandreas.hansson@arm.com port->sendFunctional(pkt); 197010037SARM gem5 Developers (this->*doDescriptor)(); 197110037SARM gem5 Developers delete req; 197210037SARM gem5 Developers delete pkt; 197310037SARM gem5 Developers } 197410037SARM gem5 Developers } 197510037SARM gem5 Developers return (isTiming); 197610037SARM gem5 Developers} 197710037SARM gem5 Developers 197810037SARM gem5 Developersvoid 197910037SARM gem5 DevelopersTableWalker::insertTableEntry(DescriptorBase &descriptor, bool longDescriptor) 198010037SARM gem5 Developers{ 198110037SARM gem5 Developers TlbEntry te; 198210037SARM gem5 Developers 198310037SARM gem5 Developers // Create and fill a new page table entry 198410037SARM gem5 Developers te.valid = true; 198510037SARM gem5 Developers te.longDescFormat = longDescriptor; 198610037SARM gem5 Developers te.isHyp = currState->isHyp; 198710037SARM gem5 Developers te.asid = currState->asid; 198810037SARM gem5 Developers te.vmid = currState->vmid; 198910037SARM gem5 Developers te.N = descriptor.offsetBits(); 199010037SARM gem5 Developers te.vpn = currState->vaddr >> te.N; 199110037SARM gem5 Developers te.size = (1<<te.N) - 1; 199210037SARM gem5 Developers te.pfn = descriptor.pfn(); 199310037SARM gem5 Developers te.domain = descriptor.domain(); 199410037SARM gem5 Developers te.lookupLevel = descriptor.lookupLevel; 199510037SARM gem5 Developers te.ns = !descriptor.secure(haveSecurity, currState) || isStage2; 199610037SARM gem5 Developers te.nstid = !currState->isSecure; 199710037SARM gem5 Developers te.xn = descriptor.xn(); 199810037SARM gem5 Developers if (currState->aarch64) 199910037SARM gem5 Developers te.el = currState->el; 200010037SARM gem5 Developers else 200110037SARM gem5 Developers te.el = 1; 200210037SARM gem5 Developers 200310621SCurtis.Dunham@arm.com statPageSizes[pageSizeNtoStatBin(te.N)]++; 200410621SCurtis.Dunham@arm.com statRequestOrigin[COMPLETED][currState->isFetch]++; 200510621SCurtis.Dunham@arm.com 200610037SARM gem5 Developers // ASID has no meaning for stage 2 TLB entries, so mark all stage 2 entries 200710037SARM gem5 Developers // as global 200810037SARM gem5 Developers te.global = descriptor.global(currState) || isStage2; 200910037SARM gem5 Developers if (longDescriptor) { 201010037SARM gem5 Developers LongDescriptor lDescriptor = 201110037SARM gem5 Developers dynamic_cast<LongDescriptor &>(descriptor); 201210037SARM gem5 Developers 201310037SARM gem5 Developers te.xn |= currState->xnTable; 201410037SARM gem5 Developers te.pxn = currState->pxnTable || lDescriptor.pxn(); 201510037SARM gem5 Developers if (isStage2) { 201610037SARM gem5 Developers // this is actually the HAP field, but its stored in the same bit 201710037SARM gem5 Developers // possitions as the AP field in a stage 1 translation. 201810037SARM gem5 Developers te.hap = lDescriptor.ap(); 201910037SARM gem5 Developers } else { 202010037SARM gem5 Developers te.ap = ((!currState->rwTable || descriptor.ap() >> 1) << 1) | 202110037SARM gem5 Developers (currState->userTable && (descriptor.ap() & 0x1)); 202210037SARM gem5 Developers } 202310037SARM gem5 Developers if (currState->aarch64) 202410037SARM gem5 Developers memAttrsAArch64(currState->tc, te, currState->longDesc.attrIndx(), 202510037SARM gem5 Developers currState->longDesc.sh()); 202610037SARM gem5 Developers else 202710037SARM gem5 Developers memAttrsLPAE(currState->tc, te, lDescriptor); 202810037SARM gem5 Developers } else { 202910037SARM gem5 Developers te.ap = descriptor.ap(); 203010037SARM gem5 Developers memAttrs(currState->tc, te, currState->sctlr, descriptor.texcb(), 203110037SARM gem5 Developers descriptor.shareable()); 203210037SARM gem5 Developers } 203310037SARM gem5 Developers 203410037SARM gem5 Developers // Debug output 203510037SARM gem5 Developers DPRINTF(TLB, descriptor.dbgHeader().c_str()); 203610037SARM gem5 Developers DPRINTF(TLB, " - N:%d pfn:%#x size:%#x global:%d valid:%d\n", 203710037SARM gem5 Developers te.N, te.pfn, te.size, te.global, te.valid); 203810037SARM gem5 Developers DPRINTF(TLB, " - vpn:%#x xn:%d pxn:%d ap:%d domain:%d asid:%d " 203910037SARM gem5 Developers "vmid:%d hyp:%d nc:%d ns:%d\n", te.vpn, te.xn, te.pxn, 204010037SARM gem5 Developers te.ap, static_cast<uint8_t>(te.domain), te.asid, te.vmid, te.isHyp, 204110037SARM gem5 Developers te.nonCacheable, te.ns); 204210037SARM gem5 Developers DPRINTF(TLB, " - domain from L%d desc:%d data:%#x\n", 204310037SARM gem5 Developers descriptor.lookupLevel, static_cast<uint8_t>(descriptor.domain()), 204410037SARM gem5 Developers descriptor.getRawData()); 204510037SARM gem5 Developers 204610037SARM gem5 Developers // Insert the entry into the TLB 204710037SARM gem5 Developers tlb->insert(currState->vaddr, te); 204810037SARM gem5 Developers if (!currState->timing) { 204910037SARM gem5 Developers currState->tc = NULL; 205010037SARM gem5 Developers currState->req = NULL; 205110037SARM gem5 Developers } 205210037SARM gem5 Developers} 20537728SAli.Saidi@ARM.com 20547404SAli.Saidi@ARM.comArmISA::TableWalker * 20557404SAli.Saidi@ARM.comArmTableWalkerParams::create() 20567404SAli.Saidi@ARM.com{ 20577404SAli.Saidi@ARM.com return new ArmISA::TableWalker(this); 20587404SAli.Saidi@ARM.com} 20597404SAli.Saidi@ARM.com 206010037SARM gem5 DevelopersLookupLevel 206110037SARM gem5 DevelopersTableWalker::toLookupLevel(uint8_t lookup_level_as_int) 206210037SARM gem5 Developers{ 206310037SARM gem5 Developers switch (lookup_level_as_int) { 206410037SARM gem5 Developers case L1: 206510037SARM gem5 Developers return L1; 206610037SARM gem5 Developers case L2: 206710037SARM gem5 Developers return L2; 206810037SARM gem5 Developers case L3: 206910037SARM gem5 Developers return L3; 207010037SARM gem5 Developers default: 207110037SARM gem5 Developers panic("Invalid lookup level conversion"); 207210037SARM gem5 Developers } 207310037SARM gem5 Developers} 207410621SCurtis.Dunham@arm.com 207510621SCurtis.Dunham@arm.com/* this method keeps track of the table walker queue's residency, so 207610621SCurtis.Dunham@arm.com * needs to be called whenever requests start and complete. */ 207710621SCurtis.Dunham@arm.comvoid 207810621SCurtis.Dunham@arm.comTableWalker::pendingChange() 207910621SCurtis.Dunham@arm.com{ 208010621SCurtis.Dunham@arm.com unsigned n = pendingQueue.size(); 208110621SCurtis.Dunham@arm.com if ((currState != NULL) && (currState != pendingQueue.front())) { 208210621SCurtis.Dunham@arm.com ++n; 208310621SCurtis.Dunham@arm.com } 208410621SCurtis.Dunham@arm.com 208510621SCurtis.Dunham@arm.com if (n != pendingReqs) { 208610621SCurtis.Dunham@arm.com Tick now = curTick(); 208710621SCurtis.Dunham@arm.com statPendingWalks.sample(pendingReqs, now - pendingChangeTick); 208810621SCurtis.Dunham@arm.com pendingReqs = n; 208910621SCurtis.Dunham@arm.com pendingChangeTick = now; 209010621SCurtis.Dunham@arm.com } 209110621SCurtis.Dunham@arm.com} 209210621SCurtis.Dunham@arm.com 209311395Sandreas.sandberg@arm.comFault 209411395Sandreas.sandberg@arm.comTableWalker::testWalk(Addr pa, Addr size, TlbEntry::DomainType domain, 209511395Sandreas.sandberg@arm.com LookupLevel lookup_level) 209611395Sandreas.sandberg@arm.com{ 209711395Sandreas.sandberg@arm.com return tlb->testWalk(pa, size, currState->vaddr, currState->isSecure, 209811395Sandreas.sandberg@arm.com currState->mode, domain, lookup_level); 209911395Sandreas.sandberg@arm.com} 210011395Sandreas.sandberg@arm.com 210111395Sandreas.sandberg@arm.com 210210621SCurtis.Dunham@arm.comuint8_t 210310621SCurtis.Dunham@arm.comTableWalker::pageSizeNtoStatBin(uint8_t N) 210410621SCurtis.Dunham@arm.com{ 210510621SCurtis.Dunham@arm.com /* for statPageSizes */ 210610621SCurtis.Dunham@arm.com switch(N) { 210710621SCurtis.Dunham@arm.com case 12: return 0; // 4K 210810621SCurtis.Dunham@arm.com case 14: return 1; // 16K (using 16K granule in v8-64) 210910621SCurtis.Dunham@arm.com case 16: return 2; // 64K 211010621SCurtis.Dunham@arm.com case 20: return 3; // 1M 211110621SCurtis.Dunham@arm.com case 21: return 4; // 2M-LPAE 211210621SCurtis.Dunham@arm.com case 24: return 5; // 16M 211310621SCurtis.Dunham@arm.com case 25: return 6; // 32M (using 16K granule in v8-64) 211410621SCurtis.Dunham@arm.com case 29: return 7; // 512M (using 64K granule in v8-64) 211510621SCurtis.Dunham@arm.com case 30: return 8; // 1G-LPAE 211610621SCurtis.Dunham@arm.com default: 211710621SCurtis.Dunham@arm.com panic("unknown page size"); 211810621SCurtis.Dunham@arm.com return 255; 211910621SCurtis.Dunham@arm.com } 212010621SCurtis.Dunham@arm.com} 212110621SCurtis.Dunham@arm.com 212210621SCurtis.Dunham@arm.comvoid 212310621SCurtis.Dunham@arm.comTableWalker::regStats() 212410621SCurtis.Dunham@arm.com{ 212510621SCurtis.Dunham@arm.com statWalks 212610621SCurtis.Dunham@arm.com .name(name() + ".walks") 212710621SCurtis.Dunham@arm.com .desc("Table walker walks requested") 212810621SCurtis.Dunham@arm.com ; 212910621SCurtis.Dunham@arm.com 213010621SCurtis.Dunham@arm.com statWalksShortDescriptor 213110621SCurtis.Dunham@arm.com .name(name() + ".walksShort") 213210621SCurtis.Dunham@arm.com .desc("Table walker walks initiated with short descriptors") 213310621SCurtis.Dunham@arm.com .flags(Stats::nozero) 213410621SCurtis.Dunham@arm.com ; 213510621SCurtis.Dunham@arm.com 213610621SCurtis.Dunham@arm.com statWalksLongDescriptor 213710621SCurtis.Dunham@arm.com .name(name() + ".walksLong") 213810621SCurtis.Dunham@arm.com .desc("Table walker walks initiated with long descriptors") 213910621SCurtis.Dunham@arm.com .flags(Stats::nozero) 214010621SCurtis.Dunham@arm.com ; 214110621SCurtis.Dunham@arm.com 214210621SCurtis.Dunham@arm.com statWalksShortTerminatedAtLevel 214310621SCurtis.Dunham@arm.com .init(2) 214410621SCurtis.Dunham@arm.com .name(name() + ".walksShortTerminationLevel") 214510621SCurtis.Dunham@arm.com .desc("Level at which table walker walks " 214610621SCurtis.Dunham@arm.com "with short descriptors terminate") 214710621SCurtis.Dunham@arm.com .flags(Stats::nozero) 214810621SCurtis.Dunham@arm.com ; 214910621SCurtis.Dunham@arm.com statWalksShortTerminatedAtLevel.subname(0, "Level1"); 215010621SCurtis.Dunham@arm.com statWalksShortTerminatedAtLevel.subname(1, "Level2"); 215110621SCurtis.Dunham@arm.com 215210621SCurtis.Dunham@arm.com statWalksLongTerminatedAtLevel 215310621SCurtis.Dunham@arm.com .init(4) 215410621SCurtis.Dunham@arm.com .name(name() + ".walksLongTerminationLevel") 215510621SCurtis.Dunham@arm.com .desc("Level at which table walker walks " 215610621SCurtis.Dunham@arm.com "with long descriptors terminate") 215710621SCurtis.Dunham@arm.com .flags(Stats::nozero) 215810621SCurtis.Dunham@arm.com ; 215910621SCurtis.Dunham@arm.com statWalksLongTerminatedAtLevel.subname(0, "Level0"); 216010621SCurtis.Dunham@arm.com statWalksLongTerminatedAtLevel.subname(1, "Level1"); 216110621SCurtis.Dunham@arm.com statWalksLongTerminatedAtLevel.subname(2, "Level2"); 216210621SCurtis.Dunham@arm.com statWalksLongTerminatedAtLevel.subname(3, "Level3"); 216310621SCurtis.Dunham@arm.com 216410621SCurtis.Dunham@arm.com statSquashedBefore 216510621SCurtis.Dunham@arm.com .name(name() + ".walksSquashedBefore") 216610621SCurtis.Dunham@arm.com .desc("Table walks squashed before starting") 216710621SCurtis.Dunham@arm.com .flags(Stats::nozero) 216810621SCurtis.Dunham@arm.com ; 216910621SCurtis.Dunham@arm.com 217010621SCurtis.Dunham@arm.com statSquashedAfter 217110621SCurtis.Dunham@arm.com .name(name() + ".walksSquashedAfter") 217210621SCurtis.Dunham@arm.com .desc("Table walks squashed after completion") 217310621SCurtis.Dunham@arm.com .flags(Stats::nozero) 217410621SCurtis.Dunham@arm.com ; 217510621SCurtis.Dunham@arm.com 217610621SCurtis.Dunham@arm.com statWalkWaitTime 217710621SCurtis.Dunham@arm.com .init(16) 217810621SCurtis.Dunham@arm.com .name(name() + ".walkWaitTime") 217910621SCurtis.Dunham@arm.com .desc("Table walker wait (enqueue to first request) latency") 218010621SCurtis.Dunham@arm.com .flags(Stats::pdf | Stats::nozero | Stats::nonan) 218110621SCurtis.Dunham@arm.com ; 218210621SCurtis.Dunham@arm.com 218310621SCurtis.Dunham@arm.com statWalkServiceTime 218410621SCurtis.Dunham@arm.com .init(16) 218510621SCurtis.Dunham@arm.com .name(name() + ".walkCompletionTime") 218610621SCurtis.Dunham@arm.com .desc("Table walker service (enqueue to completion) latency") 218710621SCurtis.Dunham@arm.com .flags(Stats::pdf | Stats::nozero | Stats::nonan) 218810621SCurtis.Dunham@arm.com ; 218910621SCurtis.Dunham@arm.com 219010621SCurtis.Dunham@arm.com statPendingWalks 219110621SCurtis.Dunham@arm.com .init(16) 219210621SCurtis.Dunham@arm.com .name(name() + ".walksPending") 219310621SCurtis.Dunham@arm.com .desc("Table walker pending requests distribution") 219410621SCurtis.Dunham@arm.com .flags(Stats::pdf | Stats::dist | Stats::nozero | Stats::nonan) 219510621SCurtis.Dunham@arm.com ; 219610621SCurtis.Dunham@arm.com 219710621SCurtis.Dunham@arm.com statPageSizes // see DDI 0487A D4-1661 219810621SCurtis.Dunham@arm.com .init(9) 219910621SCurtis.Dunham@arm.com .name(name() + ".walkPageSizes") 220010621SCurtis.Dunham@arm.com .desc("Table walker page sizes translated") 220110621SCurtis.Dunham@arm.com .flags(Stats::total | Stats::pdf | Stats::dist | Stats::nozero) 220210621SCurtis.Dunham@arm.com ; 220310621SCurtis.Dunham@arm.com statPageSizes.subname(0, "4K"); 220410621SCurtis.Dunham@arm.com statPageSizes.subname(1, "16K"); 220510621SCurtis.Dunham@arm.com statPageSizes.subname(2, "64K"); 220610621SCurtis.Dunham@arm.com statPageSizes.subname(3, "1M"); 220710621SCurtis.Dunham@arm.com statPageSizes.subname(4, "2M"); 220810621SCurtis.Dunham@arm.com statPageSizes.subname(5, "16M"); 220910621SCurtis.Dunham@arm.com statPageSizes.subname(6, "32M"); 221010621SCurtis.Dunham@arm.com statPageSizes.subname(7, "512M"); 221110621SCurtis.Dunham@arm.com statPageSizes.subname(8, "1G"); 221210621SCurtis.Dunham@arm.com 221310621SCurtis.Dunham@arm.com statRequestOrigin 221410621SCurtis.Dunham@arm.com .init(2,2) // Instruction/Data, requests/completed 221510621SCurtis.Dunham@arm.com .name(name() + ".walkRequestOrigin") 221610621SCurtis.Dunham@arm.com .desc("Table walker requests started/completed, data/inst") 221710621SCurtis.Dunham@arm.com .flags(Stats::total) 221810621SCurtis.Dunham@arm.com ; 221910621SCurtis.Dunham@arm.com statRequestOrigin.subname(0,"Requested"); 222010621SCurtis.Dunham@arm.com statRequestOrigin.subname(1,"Completed"); 222110621SCurtis.Dunham@arm.com statRequestOrigin.ysubname(0,"Data"); 222210621SCurtis.Dunham@arm.com statRequestOrigin.ysubname(1,"Inst"); 222310621SCurtis.Dunham@arm.com} 2224