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