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