table_walker.cc revision 10037
17404SAli.Saidi@ARM.com/* 210037SARM gem5 Developers * Copyright (c) 2010, 2012-2013 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 417404SAli.Saidi@ARM.com#include "arch/arm/faults.hh" 4210037SARM gem5 Developers#include "arch/arm/stage2_mmu.hh" 4310037SARM gem5 Developers#include "arch/arm/system.hh" 447404SAli.Saidi@ARM.com#include "arch/arm/table_walker.hh" 457404SAli.Saidi@ARM.com#include "arch/arm/tlb.hh" 467728SAli.Saidi@ARM.com#include "cpu/base.hh" 477404SAli.Saidi@ARM.com#include "cpu/thread_context.hh" 488245Snate@binkert.org#include "debug/Checkpoint.hh" 499152Satgutier@umich.edu#include "debug/Drain.hh" 508245Snate@binkert.org#include "debug/TLB.hh" 518245Snate@binkert.org#include "debug/TLBVerbose.hh" 527748SAli.Saidi@ARM.com#include "sim/system.hh" 537404SAli.Saidi@ARM.com 547404SAli.Saidi@ARM.comusing namespace ArmISA; 557404SAli.Saidi@ARM.com 567404SAli.Saidi@ARM.comTableWalker::TableWalker(const Params *p) 5710037SARM gem5 Developers : MemObject(p), port(this, p->sys), drainManager(NULL), 5810037SARM gem5 Developers stage2Mmu(NULL), isStage2(p->is_stage2), tlb(NULL), 5910037SARM gem5 Developers currState(NULL), pending(false), masterId(p->sys->getMasterId(name())), 609258SAli.Saidi@ARM.com numSquashable(p->num_squash_per_cycle), 6110037SARM gem5 Developers doL1DescEvent(this), doL2DescEvent(this), 6210037SARM gem5 Developers doL0LongDescEvent(this), doL1LongDescEvent(this), doL2LongDescEvent(this), 6310037SARM gem5 Developers doL3LongDescEvent(this), 6410037SARM gem5 Developers doProcessEvent(this) 657439Sdam.sunwoo@arm.com{ 667576SAli.Saidi@ARM.com sctlr = 0; 6710037SARM gem5 Developers 6810037SARM gem5 Developers // Cache system-level properties 6910037SARM gem5 Developers if (FullSystem) { 7010037SARM gem5 Developers armSys = dynamic_cast<ArmSystem *>(p->sys); 7110037SARM gem5 Developers assert(armSys); 7210037SARM gem5 Developers haveSecurity = armSys->haveSecurity(); 7310037SARM gem5 Developers _haveLPAE = armSys->haveLPAE(); 7410037SARM gem5 Developers _haveVirtualization = armSys->haveVirtualization(); 7510037SARM gem5 Developers physAddrRange = armSys->physAddrRange(); 7610037SARM gem5 Developers _haveLargeAsid64 = armSys->haveLargeAsid64(); 7710037SARM gem5 Developers } else { 7810037SARM gem5 Developers armSys = NULL; 7910037SARM gem5 Developers haveSecurity = _haveLPAE = _haveVirtualization = false; 8010037SARM gem5 Developers _haveLargeAsid64 = false; 8110037SARM gem5 Developers physAddrRange = 32; 8210037SARM gem5 Developers } 8310037SARM gem5 Developers 847439Sdam.sunwoo@arm.com} 857404SAli.Saidi@ARM.com 867404SAli.Saidi@ARM.comTableWalker::~TableWalker() 877404SAli.Saidi@ARM.com{ 887404SAli.Saidi@ARM.com ; 897404SAli.Saidi@ARM.com} 907404SAli.Saidi@ARM.com 9110037SARM gem5 DevelopersTableWalker::WalkerState::WalkerState() : stage2Tran(NULL), l2Desc(l1Desc) 9210037SARM gem5 Developers{ 9310037SARM gem5 Developers} 9410037SARM gem5 Developers 959152Satgutier@umich.eduvoid 969152Satgutier@umich.eduTableWalker::completeDrain() 979152Satgutier@umich.edu{ 9810037SARM gem5 Developers if (drainManager && stateQueues[L1].empty() && stateQueues[L2].empty() && 999152Satgutier@umich.edu pendingQueue.empty()) { 1009342SAndreas.Sandberg@arm.com setDrainState(Drainable::Drained); 1019152Satgutier@umich.edu DPRINTF(Drain, "TableWalker done draining, processing drain event\n"); 1029342SAndreas.Sandberg@arm.com drainManager->signalDrainDone(); 1039342SAndreas.Sandberg@arm.com drainManager = NULL; 1049152Satgutier@umich.edu } 1059152Satgutier@umich.edu} 1069152Satgutier@umich.edu 1077748SAli.Saidi@ARM.comunsigned int 1089342SAndreas.Sandberg@arm.comTableWalker::drain(DrainManager *dm) 1097404SAli.Saidi@ARM.com{ 1109342SAndreas.Sandberg@arm.com unsigned int count = port.drain(dm); 1119152Satgutier@umich.edu 11210037SARM gem5 Developers bool state_queues_not_empty = false; 1139152Satgutier@umich.edu 11410037SARM gem5 Developers for (int i = 0; i < MAX_LOOKUP_LEVELS; ++i) { 11510037SARM gem5 Developers if (!stateQueues[i].empty()) { 11610037SARM gem5 Developers state_queues_not_empty = true; 11710037SARM gem5 Developers break; 11810037SARM gem5 Developers } 11910037SARM gem5 Developers } 12010037SARM gem5 Developers 12110037SARM gem5 Developers if (state_queues_not_empty || pendingQueue.size()) { 1229342SAndreas.Sandberg@arm.com drainManager = dm; 1239342SAndreas.Sandberg@arm.com setDrainState(Drainable::Draining); 1249152Satgutier@umich.edu DPRINTF(Drain, "TableWalker not drained\n"); 1259152Satgutier@umich.edu 1269152Satgutier@umich.edu // return port drain count plus the table walker itself needs to drain 1279152Satgutier@umich.edu return count + 1; 12810037SARM gem5 Developers } else { 12910037SARM gem5 Developers setDrainState(Drainable::Drained); 13010037SARM gem5 Developers DPRINTF(Drain, "TableWalker free, no need to drain\n"); 1319152Satgutier@umich.edu 13210037SARM gem5 Developers // table walker is drained, but its ports may still need to be drained 13310037SARM gem5 Developers return count; 1347733SAli.Saidi@ARM.com } 1357404SAli.Saidi@ARM.com} 1367404SAli.Saidi@ARM.com 1377748SAli.Saidi@ARM.comvoid 1389342SAndreas.Sandberg@arm.comTableWalker::drainResume() 1397748SAli.Saidi@ARM.com{ 1409342SAndreas.Sandberg@arm.com Drainable::drainResume(); 1419524SAndreas.Sandberg@ARM.com if (params()->sys->isTimingMode() && currState) { 1429152Satgutier@umich.edu delete currState; 1439152Satgutier@umich.edu currState = NULL; 1447748SAli.Saidi@ARM.com } 1457748SAli.Saidi@ARM.com} 1467748SAli.Saidi@ARM.com 1479294Sandreas.hansson@arm.comBaseMasterPort& 1489294Sandreas.hansson@arm.comTableWalker::getMasterPort(const std::string &if_name, PortID idx) 1497404SAli.Saidi@ARM.com{ 1507404SAli.Saidi@ARM.com if (if_name == "port") { 1518922Swilliam.wang@arm.com return port; 1527404SAli.Saidi@ARM.com } 1538922Swilliam.wang@arm.com return MemObject::getMasterPort(if_name, idx); 1547404SAli.Saidi@ARM.com} 1557404SAli.Saidi@ARM.com 1567404SAli.Saidi@ARM.comFault 15710037SARM gem5 DevelopersTableWalker::walk(RequestPtr _req, ThreadContext *_tc, uint16_t _asid, 15810037SARM gem5 Developers uint8_t _vmid, bool _isHyp, TLB::Mode _mode, 15910037SARM gem5 Developers TLB::Translation *_trans, bool _timing, bool _functional, 16010037SARM gem5 Developers bool secure, TLB::ArmTranslationType tranType) 1617404SAli.Saidi@ARM.com{ 1628733Sgeoffrey.blake@arm.com assert(!(_functional && _timing)); 16310037SARM gem5 Developers 1647439Sdam.sunwoo@arm.com if (!currState) { 1657439Sdam.sunwoo@arm.com // For atomic mode, a new WalkerState instance should be only created 1667439Sdam.sunwoo@arm.com // once per TLB. For timing mode, a new instance is generated for every 1677439Sdam.sunwoo@arm.com // TLB miss. 1687439Sdam.sunwoo@arm.com DPRINTF(TLBVerbose, "creating new instance of WalkerState\n"); 1697404SAli.Saidi@ARM.com 1707439Sdam.sunwoo@arm.com currState = new WalkerState(); 1717439Sdam.sunwoo@arm.com currState->tableWalker = this; 1728202SAli.Saidi@ARM.com } else if (_timing) { 1738202SAli.Saidi@ARM.com // This is a translation that was completed and then faulted again 1748202SAli.Saidi@ARM.com // because some underlying parameters that affect the translation 1758202SAli.Saidi@ARM.com // changed out from under us (e.g. asid). It will either be a 1768202SAli.Saidi@ARM.com // misprediction, in which case nothing will happen or we'll use 1778202SAli.Saidi@ARM.com // this fault to re-execute the faulting instruction which should clean 1788202SAli.Saidi@ARM.com // up everything. 17910037SARM gem5 Developers if (currState->vaddr_tainted == _req->getVaddr()) { 1808202SAli.Saidi@ARM.com return new ReExec; 1818202SAli.Saidi@ARM.com } 1827439Sdam.sunwoo@arm.com } 1837439Sdam.sunwoo@arm.com 1847439Sdam.sunwoo@arm.com currState->tc = _tc; 18510037SARM gem5 Developers currState->aarch64 = opModeIs64(currOpMode(_tc)); 18610037SARM gem5 Developers currState->el = currEL(_tc); 1877439Sdam.sunwoo@arm.com currState->transState = _trans; 1887439Sdam.sunwoo@arm.com currState->req = _req; 1897439Sdam.sunwoo@arm.com currState->fault = NoFault; 19010037SARM gem5 Developers currState->asid = _asid; 19110037SARM gem5 Developers currState->vmid = _vmid; 19210037SARM gem5 Developers currState->isHyp = _isHyp; 1937439Sdam.sunwoo@arm.com currState->timing = _timing; 1948733Sgeoffrey.blake@arm.com currState->functional = _functional; 1957439Sdam.sunwoo@arm.com currState->mode = _mode; 19610037SARM gem5 Developers currState->tranType = tranType; 19710037SARM gem5 Developers currState->isSecure = secure; 19810037SARM gem5 Developers currState->physAddrRange = physAddrRange; 1997404SAli.Saidi@ARM.com 2007436Sdam.sunwoo@arm.com /** @todo These should be cached or grabbed from cached copies in 2017436Sdam.sunwoo@arm.com the TLB, all these miscreg reads are expensive */ 20210037SARM gem5 Developers currState->vaddr_tainted = currState->req->getVaddr(); 20310037SARM gem5 Developers if (currState->aarch64) 20410037SARM gem5 Developers currState->vaddr = purifyTaggedAddr(currState->vaddr_tainted, 20510037SARM gem5 Developers currState->tc, currState->el); 20610037SARM gem5 Developers else 20710037SARM gem5 Developers currState->vaddr = currState->vaddr_tainted; 20810037SARM gem5 Developers 20910037SARM gem5 Developers if (currState->aarch64) { 21010037SARM gem5 Developers switch (currState->el) { 21110037SARM gem5 Developers case EL0: 21210037SARM gem5 Developers case EL1: 21310037SARM gem5 Developers currState->sctlr = currState->tc->readMiscReg(MISCREG_SCTLR_EL1); 21410037SARM gem5 Developers currState->ttbcr = currState->tc->readMiscReg(MISCREG_TCR_EL1); 21510037SARM gem5 Developers break; 21610037SARM gem5 Developers // @todo: uncomment this to enable Virtualization 21710037SARM gem5 Developers // case EL2: 21810037SARM gem5 Developers // assert(haveVirtualization); 21910037SARM gem5 Developers // currState->sctlr = currState->tc->readMiscReg(MISCREG_SCTLR_EL2); 22010037SARM gem5 Developers // currState->ttbcr = currState->tc->readMiscReg(MISCREG_TCR_EL2); 22110037SARM gem5 Developers // break; 22210037SARM gem5 Developers case EL3: 22310037SARM gem5 Developers assert(haveSecurity); 22410037SARM gem5 Developers currState->sctlr = currState->tc->readMiscReg(MISCREG_SCTLR_EL3); 22510037SARM gem5 Developers currState->ttbcr = currState->tc->readMiscReg(MISCREG_TCR_EL3); 22610037SARM gem5 Developers break; 22710037SARM gem5 Developers default: 22810037SARM gem5 Developers panic("Invalid exception level"); 22910037SARM gem5 Developers break; 23010037SARM gem5 Developers } 23110037SARM gem5 Developers } else { 23210037SARM gem5 Developers currState->sctlr = currState->tc->readMiscReg(flattenMiscRegNsBanked( 23310037SARM gem5 Developers MISCREG_SCTLR, currState->tc, !currState->isSecure)); 23410037SARM gem5 Developers currState->ttbcr = currState->tc->readMiscReg(flattenMiscRegNsBanked( 23510037SARM gem5 Developers MISCREG_TTBCR, currState->tc, !currState->isSecure)); 23610037SARM gem5 Developers currState->htcr = currState->tc->readMiscReg(MISCREG_HTCR); 23710037SARM gem5 Developers currState->hcr = currState->tc->readMiscReg(MISCREG_HCR); 23810037SARM gem5 Developers currState->vtcr = currState->tc->readMiscReg(MISCREG_VTCR); 23910037SARM gem5 Developers } 2407439Sdam.sunwoo@arm.com sctlr = currState->sctlr; 2417439Sdam.sunwoo@arm.com 2427439Sdam.sunwoo@arm.com currState->isFetch = (currState->mode == TLB::Execute); 2437439Sdam.sunwoo@arm.com currState->isWrite = (currState->mode == TLB::Write); 2447439Sdam.sunwoo@arm.com 24510037SARM gem5 Developers // We only do a second stage of translation if we're not secure, or in 24610037SARM gem5 Developers // hyp mode, the second stage MMU is enabled, and this table walker 24710037SARM gem5 Developers // instance is the first stage. 24810037SARM gem5 Developers currState->doingStage2 = false; 24910037SARM gem5 Developers // @todo: for now disable this in AArch64 (HCR is not set) 25010037SARM gem5 Developers currState->stage2Req = !currState->aarch64 && currState->hcr.vm && 25110037SARM gem5 Developers !isStage2 && !currState->isSecure && !currState->isHyp; 2527728SAli.Saidi@ARM.com 25310037SARM gem5 Developers bool long_desc_format = currState->aarch64 || 25410037SARM gem5 Developers (_haveLPAE && currState->ttbcr.eae) || 25510037SARM gem5 Developers _isHyp || isStage2; 25610037SARM gem5 Developers 25710037SARM gem5 Developers if (long_desc_format) { 25810037SARM gem5 Developers // Helper variables used for hierarchical permissions 25910037SARM gem5 Developers currState->secureLookup = currState->isSecure; 26010037SARM gem5 Developers currState->rwTable = true; 26110037SARM gem5 Developers currState->userTable = true; 26210037SARM gem5 Developers currState->xnTable = false; 26310037SARM gem5 Developers currState->pxnTable = false; 26410037SARM gem5 Developers } 26510037SARM gem5 Developers 26610037SARM gem5 Developers if (!currState->timing) { 26710037SARM gem5 Developers if (currState->aarch64) 26810037SARM gem5 Developers return processWalkAArch64(); 26910037SARM gem5 Developers else if (long_desc_format) 27010037SARM gem5 Developers return processWalkLPAE(); 27110037SARM gem5 Developers else 27210037SARM gem5 Developers return processWalk(); 27310037SARM gem5 Developers } 2747728SAli.Saidi@ARM.com 2758067SAli.Saidi@ARM.com if (pending || pendingQueue.size()) { 2767728SAli.Saidi@ARM.com pendingQueue.push_back(currState); 2777728SAli.Saidi@ARM.com currState = NULL; 2787728SAli.Saidi@ARM.com } else { 2797728SAli.Saidi@ARM.com pending = true; 28010037SARM gem5 Developers if (currState->aarch64) 28110037SARM gem5 Developers return processWalkAArch64(); 28210037SARM gem5 Developers else if (long_desc_format) 28310037SARM gem5 Developers return processWalkLPAE(); 28410037SARM gem5 Developers else 28510037SARM gem5 Developers return processWalk(); 2867728SAli.Saidi@ARM.com } 2877728SAli.Saidi@ARM.com 2887728SAli.Saidi@ARM.com return NoFault; 2897728SAli.Saidi@ARM.com} 2907728SAli.Saidi@ARM.com 2917728SAli.Saidi@ARM.comvoid 2927728SAli.Saidi@ARM.comTableWalker::processWalkWrapper() 2937728SAli.Saidi@ARM.com{ 2947728SAli.Saidi@ARM.com assert(!currState); 2957728SAli.Saidi@ARM.com assert(pendingQueue.size()); 2967728SAli.Saidi@ARM.com currState = pendingQueue.front(); 2979258SAli.Saidi@ARM.com 29810037SARM gem5 Developers ExceptionLevel target_el = EL0; 29910037SARM gem5 Developers if (currState->aarch64) 30010037SARM gem5 Developers target_el = currEL(currState->tc); 30110037SARM gem5 Developers else 30210037SARM gem5 Developers target_el = EL1; 30310037SARM gem5 Developers 3049535Smrinmoy.ghosh@arm.com // Check if a previous walk filled this request already 30510037SARM gem5 Developers // @TODO Should this always be the TLB or should we look in the stage2 TLB? 30610037SARM gem5 Developers TlbEntry* te = tlb->lookup(currState->vaddr, currState->asid, 30710037SARM gem5 Developers currState->vmid, currState->isHyp, currState->isSecure, true, false, 30810037SARM gem5 Developers target_el); 3099258SAli.Saidi@ARM.com 3109535Smrinmoy.ghosh@arm.com // Check if we still need to have a walk for this request. If the requesting 3119535Smrinmoy.ghosh@arm.com // instruction has been squashed, or a previous walk has filled the TLB with 3129535Smrinmoy.ghosh@arm.com // a match, we just want to get rid of the walk. The latter could happen 3139535Smrinmoy.ghosh@arm.com // when there are multiple outstanding misses to a single page and a 3149535Smrinmoy.ghosh@arm.com // previous request has been successfully translated. 3159535Smrinmoy.ghosh@arm.com if (!currState->transState->squashed() && !te) { 3169258SAli.Saidi@ARM.com // We've got a valid request, lets process it 3179258SAli.Saidi@ARM.com pending = true; 3189258SAli.Saidi@ARM.com pendingQueue.pop_front(); 31910037SARM gem5 Developers if (currState->aarch64) 32010037SARM gem5 Developers processWalkAArch64(); 32110037SARM gem5 Developers else if ((_haveLPAE && currState->ttbcr.eae) || currState->isHyp || isStage2) 32210037SARM gem5 Developers processWalkLPAE(); 32310037SARM gem5 Developers else 32410037SARM gem5 Developers processWalk(); 3259258SAli.Saidi@ARM.com return; 3269258SAli.Saidi@ARM.com } 3279258SAli.Saidi@ARM.com 3289258SAli.Saidi@ARM.com 3299258SAli.Saidi@ARM.com // If the instruction that we were translating for has been 3309258SAli.Saidi@ARM.com // squashed we shouldn't bother. 3319258SAli.Saidi@ARM.com unsigned num_squashed = 0; 3329258SAli.Saidi@ARM.com ThreadContext *tc = currState->tc; 3339258SAli.Saidi@ARM.com while ((num_squashed < numSquashable) && currState && 3349535Smrinmoy.ghosh@arm.com (currState->transState->squashed() || te)) { 3359258SAli.Saidi@ARM.com pendingQueue.pop_front(); 3369258SAli.Saidi@ARM.com num_squashed++; 3379258SAli.Saidi@ARM.com 33810037SARM gem5 Developers DPRINTF(TLB, "Squashing table walk for address %#x\n", 33910037SARM gem5 Developers currState->vaddr_tainted); 3409258SAli.Saidi@ARM.com 3419535Smrinmoy.ghosh@arm.com if (currState->transState->squashed()) { 3429535Smrinmoy.ghosh@arm.com // finish the translation which will delete the translation object 3439535Smrinmoy.ghosh@arm.com currState->transState->finish(new UnimpFault("Squashed Inst"), 3449535Smrinmoy.ghosh@arm.com currState->req, currState->tc, currState->mode); 3459535Smrinmoy.ghosh@arm.com } else { 3469535Smrinmoy.ghosh@arm.com // translate the request now that we know it will work 34710037SARM gem5 Developers tlb->translateTiming(currState->req, currState->tc, 34810037SARM gem5 Developers currState->transState, currState->mode); 34910037SARM gem5 Developers 3509535Smrinmoy.ghosh@arm.com } 3519258SAli.Saidi@ARM.com 3529258SAli.Saidi@ARM.com // delete the current request 3539258SAli.Saidi@ARM.com delete currState; 3549258SAli.Saidi@ARM.com 3559258SAli.Saidi@ARM.com // peak at the next one 3569535Smrinmoy.ghosh@arm.com if (pendingQueue.size()) { 3579258SAli.Saidi@ARM.com currState = pendingQueue.front(); 35810037SARM gem5 Developers te = tlb->lookup(currState->vaddr, currState->asid, 35910037SARM gem5 Developers currState->vmid, currState->isHyp, currState->isSecure, true, 36010037SARM gem5 Developers false, target_el); 3619535Smrinmoy.ghosh@arm.com } else { 3629535Smrinmoy.ghosh@arm.com // Terminate the loop, nothing more to do 3639258SAli.Saidi@ARM.com currState = NULL; 3649535Smrinmoy.ghosh@arm.com } 3659258SAli.Saidi@ARM.com } 3669258SAli.Saidi@ARM.com 3679258SAli.Saidi@ARM.com // if we've still got pending translations schedule more work 3689258SAli.Saidi@ARM.com nextWalk(tc); 3699258SAli.Saidi@ARM.com currState = NULL; 3709438SAndreas.Sandberg@ARM.com completeDrain(); 3717728SAli.Saidi@ARM.com} 3727728SAli.Saidi@ARM.com 3737728SAli.Saidi@ARM.comFault 3747728SAli.Saidi@ARM.comTableWalker::processWalk() 3757728SAli.Saidi@ARM.com{ 3767404SAli.Saidi@ARM.com Addr ttbr = 0; 3777404SAli.Saidi@ARM.com 3787404SAli.Saidi@ARM.com // If translation isn't enabled, we shouldn't be here 37910037SARM gem5 Developers assert(currState->sctlr.m || isStage2); 3807404SAli.Saidi@ARM.com 38110037SARM gem5 Developers DPRINTF(TLB, "Beginning table walk for address %#x, TTBCR: %#x, bits:%#x\n", 38210037SARM gem5 Developers currState->vaddr_tainted, currState->ttbcr, mbits(currState->vaddr, 31, 38310037SARM gem5 Developers 32 - currState->ttbcr.n)); 3847406SAli.Saidi@ARM.com 38510037SARM gem5 Developers if (currState->ttbcr.n == 0 || !mbits(currState->vaddr, 31, 38610037SARM gem5 Developers 32 - currState->ttbcr.n)) { 3877406SAli.Saidi@ARM.com DPRINTF(TLB, " - Selecting TTBR0\n"); 38810037SARM gem5 Developers // Check if table walk is allowed when Security Extensions are enabled 38910037SARM gem5 Developers if (haveSecurity && currState->ttbcr.pd0) { 39010037SARM gem5 Developers if (currState->isFetch) 39110037SARM gem5 Developers return new PrefetchAbort(currState->vaddr_tainted, 39210037SARM gem5 Developers ArmFault::TranslationLL + L1, 39310037SARM gem5 Developers isStage2, 39410037SARM gem5 Developers ArmFault::VmsaTran); 39510037SARM gem5 Developers else 39610037SARM gem5 Developers return new DataAbort(currState->vaddr_tainted, 39710037SARM gem5 Developers TlbEntry::DomainType::NoAccess, currState->isWrite, 39810037SARM gem5 Developers ArmFault::TranslationLL + L1, isStage2, 39910037SARM gem5 Developers ArmFault::VmsaTran); 40010037SARM gem5 Developers } 40110037SARM gem5 Developers ttbr = currState->tc->readMiscReg(flattenMiscRegNsBanked( 40210037SARM gem5 Developers MISCREG_TTBR0, currState->tc, !currState->isSecure)); 4037404SAli.Saidi@ARM.com } else { 4047406SAli.Saidi@ARM.com DPRINTF(TLB, " - Selecting TTBR1\n"); 40510037SARM gem5 Developers // Check if table walk is allowed when Security Extensions are enabled 40610037SARM gem5 Developers if (haveSecurity && currState->ttbcr.pd1) { 40710037SARM gem5 Developers if (currState->isFetch) 40810037SARM gem5 Developers return new PrefetchAbort(currState->vaddr_tainted, 40910037SARM gem5 Developers ArmFault::TranslationLL + L1, 41010037SARM gem5 Developers isStage2, 41110037SARM gem5 Developers ArmFault::VmsaTran); 41210037SARM gem5 Developers else 41310037SARM gem5 Developers return new DataAbort(currState->vaddr_tainted, 41410037SARM gem5 Developers TlbEntry::DomainType::NoAccess, currState->isWrite, 41510037SARM gem5 Developers ArmFault::TranslationLL + L1, isStage2, 41610037SARM gem5 Developers ArmFault::VmsaTran); 41710037SARM gem5 Developers } 41810037SARM gem5 Developers ttbr = currState->tc->readMiscReg(flattenMiscRegNsBanked( 41910037SARM gem5 Developers MISCREG_TTBR1, currState->tc, !currState->isSecure)); 42010037SARM gem5 Developers currState->ttbcr.n = 0; 4217404SAli.Saidi@ARM.com } 4227404SAli.Saidi@ARM.com 42310037SARM gem5 Developers Addr l1desc_addr = mbits(ttbr, 31, 14 - currState->ttbcr.n) | 42410037SARM gem5 Developers (bits(currState->vaddr, 31 - currState->ttbcr.n, 20) << 2); 42510037SARM gem5 Developers DPRINTF(TLB, " - Descriptor at address %#x (%s)\n", l1desc_addr, 42610037SARM gem5 Developers currState->isSecure ? "s" : "ns"); 4277404SAli.Saidi@ARM.com 4287404SAli.Saidi@ARM.com // Trickbox address check 4297439Sdam.sunwoo@arm.com Fault f; 43010037SARM gem5 Developers f = tlb->walkTrickBoxCheck(l1desc_addr, currState->isSecure, 43110037SARM gem5 Developers currState->vaddr, sizeof(uint32_t), currState->isFetch, 43210037SARM gem5 Developers currState->isWrite, TlbEntry::DomainType::NoAccess, L1); 4337439Sdam.sunwoo@arm.com if (f) { 43410037SARM gem5 Developers DPRINTF(TLB, "Trickbox check caused fault on %#x\n", currState->vaddr_tainted); 4357579Sminkyu.jeong@arm.com if (currState->timing) { 4367728SAli.Saidi@ARM.com pending = false; 4377728SAli.Saidi@ARM.com nextWalk(currState->tc); 4387579Sminkyu.jeong@arm.com currState = NULL; 4397579Sminkyu.jeong@arm.com } else { 4407579Sminkyu.jeong@arm.com currState->tc = NULL; 4417579Sminkyu.jeong@arm.com currState->req = NULL; 4427579Sminkyu.jeong@arm.com } 4437579Sminkyu.jeong@arm.com return f; 4447404SAli.Saidi@ARM.com } 4457404SAli.Saidi@ARM.com 4467946SGiacomo.Gabrielli@arm.com Request::Flags flag = 0; 4477946SGiacomo.Gabrielli@arm.com if (currState->sctlr.c == 0) { 4487946SGiacomo.Gabrielli@arm.com flag = Request::UNCACHEABLE; 4497946SGiacomo.Gabrielli@arm.com } 4507946SGiacomo.Gabrielli@arm.com 45110037SARM gem5 Developers bool delayed; 45210037SARM gem5 Developers delayed = fetchDescriptor(l1desc_addr, (uint8_t*)&currState->l1Desc.data, 45310037SARM gem5 Developers sizeof(uint32_t), flag, L1, &doL1DescEvent, 45410037SARM gem5 Developers &TableWalker::doL1Descriptor); 45510037SARM gem5 Developers if (!delayed) { 45610037SARM gem5 Developers f = currState->fault; 45710037SARM gem5 Developers } 45810037SARM gem5 Developers 45910037SARM gem5 Developers return f; 46010037SARM gem5 Developers} 46110037SARM gem5 Developers 46210037SARM gem5 DevelopersFault 46310037SARM gem5 DevelopersTableWalker::processWalkLPAE() 46410037SARM gem5 Developers{ 46510037SARM gem5 Developers Addr ttbr, ttbr0_max, ttbr1_min, desc_addr; 46610037SARM gem5 Developers int tsz, n; 46710037SARM gem5 Developers LookupLevel start_lookup_level = L1; 46810037SARM gem5 Developers 46910037SARM gem5 Developers DPRINTF(TLB, "Beginning table walk for address %#x, TTBCR: %#x\n", 47010037SARM gem5 Developers currState->vaddr_tainted, currState->ttbcr); 47110037SARM gem5 Developers 47210037SARM gem5 Developers Request::Flags flag = 0; 47310037SARM gem5 Developers if (currState->isSecure) 47410037SARM gem5 Developers flag.set(Request::SECURE); 47510037SARM gem5 Developers 47610037SARM gem5 Developers // work out which base address register to use, if in hyp mode we always 47710037SARM gem5 Developers // use HTTBR 47810037SARM gem5 Developers if (isStage2) { 47910037SARM gem5 Developers DPRINTF(TLB, " - Selecting VTTBR (long-desc.)\n"); 48010037SARM gem5 Developers ttbr = currState->tc->readMiscReg(MISCREG_VTTBR); 48110037SARM gem5 Developers tsz = sext<4>(currState->vtcr.t0sz); 48210037SARM gem5 Developers start_lookup_level = currState->vtcr.sl0 ? L1 : L2; 48310037SARM gem5 Developers } else if (currState->isHyp) { 48410037SARM gem5 Developers DPRINTF(TLB, " - Selecting HTTBR (long-desc.)\n"); 48510037SARM gem5 Developers ttbr = currState->tc->readMiscReg(MISCREG_HTTBR); 48610037SARM gem5 Developers tsz = currState->htcr.t0sz; 48710037SARM gem5 Developers } else { 48810037SARM gem5 Developers assert(_haveLPAE && currState->ttbcr.eae); 48910037SARM gem5 Developers 49010037SARM gem5 Developers // Determine boundaries of TTBR0/1 regions 49110037SARM gem5 Developers if (currState->ttbcr.t0sz) 49210037SARM gem5 Developers ttbr0_max = (1ULL << (32 - currState->ttbcr.t0sz)) - 1; 49310037SARM gem5 Developers else if (currState->ttbcr.t1sz) 49410037SARM gem5 Developers ttbr0_max = (1ULL << 32) - 49510037SARM gem5 Developers (1ULL << (32 - currState->ttbcr.t1sz)) - 1; 49610037SARM gem5 Developers else 49710037SARM gem5 Developers ttbr0_max = (1ULL << 32) - 1; 49810037SARM gem5 Developers if (currState->ttbcr.t1sz) 49910037SARM gem5 Developers ttbr1_min = (1ULL << 32) - (1ULL << (32 - currState->ttbcr.t1sz)); 50010037SARM gem5 Developers else 50110037SARM gem5 Developers ttbr1_min = (1ULL << (32 - currState->ttbcr.t0sz)); 50210037SARM gem5 Developers 50310037SARM gem5 Developers // The following code snippet selects the appropriate translation table base 50410037SARM gem5 Developers // address (TTBR0 or TTBR1) and the appropriate starting lookup level 50510037SARM gem5 Developers // depending on the address range supported by the translation table (ARM 50610037SARM gem5 Developers // ARM issue C B3.6.4) 50710037SARM gem5 Developers if (currState->vaddr <= ttbr0_max) { 50810037SARM gem5 Developers DPRINTF(TLB, " - Selecting TTBR0 (long-desc.)\n"); 50910037SARM gem5 Developers // Check if table walk is allowed 51010037SARM gem5 Developers if (currState->ttbcr.epd0) { 51110037SARM gem5 Developers if (currState->isFetch) 51210037SARM gem5 Developers return new PrefetchAbort(currState->vaddr_tainted, 51310037SARM gem5 Developers ArmFault::TranslationLL + L1, 51410037SARM gem5 Developers isStage2, 51510037SARM gem5 Developers ArmFault::LpaeTran); 51610037SARM gem5 Developers else 51710037SARM gem5 Developers return new DataAbort(currState->vaddr_tainted, 51810037SARM gem5 Developers TlbEntry::DomainType::NoAccess, 51910037SARM gem5 Developers currState->isWrite, 52010037SARM gem5 Developers ArmFault::TranslationLL + L1, 52110037SARM gem5 Developers isStage2, 52210037SARM gem5 Developers ArmFault::LpaeTran); 52310037SARM gem5 Developers } 52410037SARM gem5 Developers ttbr = currState->tc->readMiscReg(flattenMiscRegNsBanked( 52510037SARM gem5 Developers MISCREG_TTBR0, currState->tc, !currState->isSecure)); 52610037SARM gem5 Developers tsz = currState->ttbcr.t0sz; 52710037SARM gem5 Developers if (ttbr0_max < (1ULL << 30)) // Upper limit < 1 GB 52810037SARM gem5 Developers start_lookup_level = L2; 52910037SARM gem5 Developers } else if (currState->vaddr >= ttbr1_min) { 53010037SARM gem5 Developers DPRINTF(TLB, " - Selecting TTBR1 (long-desc.)\n"); 53110037SARM gem5 Developers // Check if table walk is allowed 53210037SARM gem5 Developers if (currState->ttbcr.epd1) { 53310037SARM gem5 Developers if (currState->isFetch) 53410037SARM gem5 Developers return new PrefetchAbort(currState->vaddr_tainted, 53510037SARM gem5 Developers ArmFault::TranslationLL + L1, 53610037SARM gem5 Developers isStage2, 53710037SARM gem5 Developers ArmFault::LpaeTran); 53810037SARM gem5 Developers else 53910037SARM gem5 Developers return new DataAbort(currState->vaddr_tainted, 54010037SARM gem5 Developers TlbEntry::DomainType::NoAccess, 54110037SARM gem5 Developers currState->isWrite, 54210037SARM gem5 Developers ArmFault::TranslationLL + L1, 54310037SARM gem5 Developers isStage2, 54410037SARM gem5 Developers ArmFault::LpaeTran); 54510037SARM gem5 Developers } 54610037SARM gem5 Developers ttbr = currState->tc->readMiscReg(flattenMiscRegNsBanked( 54710037SARM gem5 Developers MISCREG_TTBR1, currState->tc, !currState->isSecure)); 54810037SARM gem5 Developers tsz = currState->ttbcr.t1sz; 54910037SARM gem5 Developers if (ttbr1_min >= (1ULL << 31) + (1ULL << 30)) // Lower limit >= 3 GB 55010037SARM gem5 Developers start_lookup_level = L2; 55110037SARM gem5 Developers } else { 55210037SARM gem5 Developers // Out of boundaries -> translation fault 55310037SARM gem5 Developers if (currState->isFetch) 55410037SARM gem5 Developers return new PrefetchAbort(currState->vaddr_tainted, 55510037SARM gem5 Developers ArmFault::TranslationLL + L1, 55610037SARM gem5 Developers isStage2, 55710037SARM gem5 Developers ArmFault::LpaeTran); 55810037SARM gem5 Developers else 55910037SARM gem5 Developers return new DataAbort(currState->vaddr_tainted, 56010037SARM gem5 Developers TlbEntry::DomainType::NoAccess, 56110037SARM gem5 Developers currState->isWrite, ArmFault::TranslationLL + L1, 56210037SARM gem5 Developers isStage2, ArmFault::LpaeTran); 56310037SARM gem5 Developers } 56410037SARM gem5 Developers 56510037SARM gem5 Developers } 56610037SARM gem5 Developers 56710037SARM gem5 Developers // Perform lookup (ARM ARM issue C B3.6.6) 56810037SARM gem5 Developers if (start_lookup_level == L1) { 56910037SARM gem5 Developers n = 5 - tsz; 57010037SARM gem5 Developers desc_addr = mbits(ttbr, 39, n) | 57110037SARM gem5 Developers (bits(currState->vaddr, n + 26, 30) << 3); 57210037SARM gem5 Developers DPRINTF(TLB, " - Descriptor at address %#x (%s) (long-desc.)\n", 57310037SARM gem5 Developers desc_addr, currState->isSecure ? "s" : "ns"); 57410037SARM gem5 Developers } else { 57510037SARM gem5 Developers // Skip first-level lookup 57610037SARM gem5 Developers n = (tsz >= 2 ? 14 - tsz : 12); 57710037SARM gem5 Developers desc_addr = mbits(ttbr, 39, n) | 57810037SARM gem5 Developers (bits(currState->vaddr, n + 17, 21) << 3); 57910037SARM gem5 Developers DPRINTF(TLB, " - Descriptor at address %#x (%s) (long-desc.)\n", 58010037SARM gem5 Developers desc_addr, currState->isSecure ? "s" : "ns"); 58110037SARM gem5 Developers } 58210037SARM gem5 Developers 58310037SARM gem5 Developers // Trickbox address check 58410037SARM gem5 Developers Fault f = tlb->walkTrickBoxCheck(desc_addr, currState->isSecure, 58510037SARM gem5 Developers currState->vaddr, sizeof(uint64_t), currState->isFetch, 58610037SARM gem5 Developers currState->isWrite, TlbEntry::DomainType::NoAccess, 58710037SARM gem5 Developers start_lookup_level); 58810037SARM gem5 Developers if (f) { 58910037SARM gem5 Developers DPRINTF(TLB, "Trickbox check caused fault on %#x\n", currState->vaddr_tainted); 59010037SARM gem5 Developers if (currState->timing) { 59110037SARM gem5 Developers pending = false; 59210037SARM gem5 Developers nextWalk(currState->tc); 59310037SARM gem5 Developers currState = NULL; 59410037SARM gem5 Developers } else { 59510037SARM gem5 Developers currState->tc = NULL; 59610037SARM gem5 Developers currState->req = NULL; 59710037SARM gem5 Developers } 59810037SARM gem5 Developers return f; 59910037SARM gem5 Developers } 60010037SARM gem5 Developers 60110037SARM gem5 Developers if (currState->sctlr.c == 0) { 60210037SARM gem5 Developers flag = Request::UNCACHEABLE; 60310037SARM gem5 Developers } 60410037SARM gem5 Developers 60510037SARM gem5 Developers if (currState->isSecure) 60610037SARM gem5 Developers flag.set(Request::SECURE); 60710037SARM gem5 Developers 60810037SARM gem5 Developers currState->longDesc.lookupLevel = start_lookup_level; 60910037SARM gem5 Developers currState->longDesc.aarch64 = false; 61010037SARM gem5 Developers currState->longDesc.largeGrain = false; 61110037SARM gem5 Developers currState->longDesc.grainSize = 12; 61210037SARM gem5 Developers 61310037SARM gem5 Developers Event *event = start_lookup_level == L1 ? (Event *) &doL1LongDescEvent 61410037SARM gem5 Developers : (Event *) &doL2LongDescEvent; 61510037SARM gem5 Developers 61610037SARM gem5 Developers bool delayed = fetchDescriptor(desc_addr, (uint8_t*)&currState->longDesc.data, 61710037SARM gem5 Developers sizeof(uint64_t), flag, start_lookup_level, 61810037SARM gem5 Developers event, &TableWalker::doLongDescriptor); 61910037SARM gem5 Developers if (!delayed) { 62010037SARM gem5 Developers f = currState->fault; 62110037SARM gem5 Developers } 62210037SARM gem5 Developers 62310037SARM gem5 Developers return f; 62410037SARM gem5 Developers} 62510037SARM gem5 Developers 62610037SARM gem5 Developersunsigned 62710037SARM gem5 DevelopersTableWalker::adjustTableSizeAArch64(unsigned tsz) 62810037SARM gem5 Developers{ 62910037SARM gem5 Developers if (tsz < 25) 63010037SARM gem5 Developers return 25; 63110037SARM gem5 Developers if (tsz > 48) 63210037SARM gem5 Developers return 48; 63310037SARM gem5 Developers return tsz; 63410037SARM gem5 Developers} 63510037SARM gem5 Developers 63610037SARM gem5 Developersbool 63710037SARM gem5 DevelopersTableWalker::checkAddrSizeFaultAArch64(Addr addr, int currPhysAddrRange) 63810037SARM gem5 Developers{ 63910037SARM gem5 Developers return (currPhysAddrRange != MaxPhysAddrRange && 64010037SARM gem5 Developers bits(addr, MaxPhysAddrRange - 1, currPhysAddrRange)); 64110037SARM gem5 Developers} 64210037SARM gem5 Developers 64310037SARM gem5 DevelopersFault 64410037SARM gem5 DevelopersTableWalker::processWalkAArch64() 64510037SARM gem5 Developers{ 64610037SARM gem5 Developers assert(currState->aarch64); 64710037SARM gem5 Developers 64810037SARM gem5 Developers DPRINTF(TLB, "Beginning table walk for address %#llx, TTBCR: %#llx\n", 64910037SARM gem5 Developers currState->vaddr_tainted, currState->ttbcr); 65010037SARM gem5 Developers 65110037SARM gem5 Developers // Determine TTBR, table size, granule size and phys. address range 65210037SARM gem5 Developers Addr ttbr = 0; 65310037SARM gem5 Developers int tsz = 0, ps = 0; 65410037SARM gem5 Developers bool large_grain = false; 65510037SARM gem5 Developers bool fault = false; 65610037SARM gem5 Developers switch (currState->el) { 65710037SARM gem5 Developers case EL0: 65810037SARM gem5 Developers case EL1: 65910037SARM gem5 Developers switch (bits(currState->vaddr, 63,48)) { 66010037SARM gem5 Developers case 0: 66110037SARM gem5 Developers DPRINTF(TLB, " - Selecting TTBR0 (AArch64)\n"); 66210037SARM gem5 Developers ttbr = currState->tc->readMiscReg(MISCREG_TTBR0_EL1); 66310037SARM gem5 Developers tsz = adjustTableSizeAArch64(64 - currState->ttbcr.t0sz); 66410037SARM gem5 Developers large_grain = currState->ttbcr.tg0; 66510037SARM gem5 Developers if (bits(currState->vaddr, 63, tsz) != 0x0 || 66610037SARM gem5 Developers currState->ttbcr.epd0) 66710037SARM gem5 Developers fault = true; 66810037SARM gem5 Developers break; 66910037SARM gem5 Developers case 0xffff: 67010037SARM gem5 Developers DPRINTF(TLB, " - Selecting TTBR1 (AArch64)\n"); 67110037SARM gem5 Developers ttbr = currState->tc->readMiscReg(MISCREG_TTBR1_EL1); 67210037SARM gem5 Developers tsz = adjustTableSizeAArch64(64 - currState->ttbcr.t1sz); 67310037SARM gem5 Developers large_grain = currState->ttbcr.tg1; 67410037SARM gem5 Developers if (bits(currState->vaddr, 63, tsz) != mask(64-tsz) || 67510037SARM gem5 Developers currState->ttbcr.epd1) 67610037SARM gem5 Developers fault = true; 67710037SARM gem5 Developers break; 67810037SARM gem5 Developers default: 67910037SARM gem5 Developers // top two bytes must be all 0s or all 1s, else invalid addr 68010037SARM gem5 Developers fault = true; 68110037SARM gem5 Developers } 68210037SARM gem5 Developers ps = currState->ttbcr.ips; 68310037SARM gem5 Developers break; 68410037SARM gem5 Developers case EL2: 68510037SARM gem5 Developers case EL3: 68610037SARM gem5 Developers switch(bits(currState->vaddr, 63,48)) { 68710037SARM gem5 Developers case 0: 68810037SARM gem5 Developers DPRINTF(TLB, " - Selecting TTBR0 (AArch64)\n"); 68910037SARM gem5 Developers if (currState->el == EL2) 69010037SARM gem5 Developers ttbr = currState->tc->readMiscReg(MISCREG_TTBR0_EL2); 69110037SARM gem5 Developers else 69210037SARM gem5 Developers ttbr = currState->tc->readMiscReg(MISCREG_TTBR0_EL3); 69310037SARM gem5 Developers tsz = adjustTableSizeAArch64(64 - currState->ttbcr.t0sz); 69410037SARM gem5 Developers large_grain = currState->ttbcr.tg0; 69510037SARM gem5 Developers break; 69610037SARM gem5 Developers default: 69710037SARM gem5 Developers // invalid addr if top two bytes are not all 0s 69810037SARM gem5 Developers fault = true; 69910037SARM gem5 Developers } 70010037SARM gem5 Developers ps = currState->ttbcr.ps; 70110037SARM gem5 Developers break; 70210037SARM gem5 Developers } 70310037SARM gem5 Developers 70410037SARM gem5 Developers if (fault) { 70510037SARM gem5 Developers Fault f; 70610037SARM gem5 Developers if (currState->isFetch) 70710037SARM gem5 Developers f = new PrefetchAbort(currState->vaddr_tainted, 70810037SARM gem5 Developers ArmFault::TranslationLL + L0, isStage2, 70910037SARM gem5 Developers ArmFault::LpaeTran); 71010037SARM gem5 Developers else 71110037SARM gem5 Developers f = new DataAbort(currState->vaddr_tainted, 71210037SARM gem5 Developers TlbEntry::DomainType::NoAccess, 71310037SARM gem5 Developers currState->isWrite, 71410037SARM gem5 Developers ArmFault::TranslationLL + L0, 71510037SARM gem5 Developers isStage2, ArmFault::LpaeTran); 71610037SARM gem5 Developers 71710037SARM gem5 Developers if (currState->timing) { 71810037SARM gem5 Developers pending = false; 71910037SARM gem5 Developers nextWalk(currState->tc); 72010037SARM gem5 Developers currState = NULL; 72110037SARM gem5 Developers } else { 72210037SARM gem5 Developers currState->tc = NULL; 72310037SARM gem5 Developers currState->req = NULL; 72410037SARM gem5 Developers } 72510037SARM gem5 Developers return f; 72610037SARM gem5 Developers 72710037SARM gem5 Developers } 72810037SARM gem5 Developers 72910037SARM gem5 Developers // Determine starting lookup level 73010037SARM gem5 Developers LookupLevel start_lookup_level; 73110037SARM gem5 Developers int grain_size, stride; 73210037SARM gem5 Developers if (large_grain) { // 64 KB granule 73310037SARM gem5 Developers grain_size = 16; 73410037SARM gem5 Developers stride = grain_size - 3; 73510037SARM gem5 Developers if (tsz > grain_size + 2 * stride) 73610037SARM gem5 Developers start_lookup_level = L1; 73710037SARM gem5 Developers else if (tsz > grain_size + stride) 73810037SARM gem5 Developers start_lookup_level = L2; 73910037SARM gem5 Developers else 74010037SARM gem5 Developers start_lookup_level = L3; 74110037SARM gem5 Developers } else { // 4 KB granule 74210037SARM gem5 Developers grain_size = 12; 74310037SARM gem5 Developers stride = grain_size - 3; 74410037SARM gem5 Developers if (tsz > grain_size + 3 * stride) 74510037SARM gem5 Developers start_lookup_level = L0; 74610037SARM gem5 Developers else if (tsz > grain_size + 2 * stride) 74710037SARM gem5 Developers start_lookup_level = L1; 74810037SARM gem5 Developers else 74910037SARM gem5 Developers start_lookup_level = L2; 75010037SARM gem5 Developers } 75110037SARM gem5 Developers 75210037SARM gem5 Developers // Determine table base address 75310037SARM gem5 Developers int base_addr_lo = 3 + tsz - stride * (3 - start_lookup_level) - 75410037SARM gem5 Developers grain_size; 75510037SARM gem5 Developers Addr base_addr = mbits(ttbr, 47, base_addr_lo); 75610037SARM gem5 Developers 75710037SARM gem5 Developers // Determine physical address size and raise an Address Size Fault if 75810037SARM gem5 Developers // necessary 75910037SARM gem5 Developers int pa_range = decodePhysAddrRange64(ps); 76010037SARM gem5 Developers // Clamp to lower limit 76110037SARM gem5 Developers if (pa_range > physAddrRange) 76210037SARM gem5 Developers currState->physAddrRange = physAddrRange; 76310037SARM gem5 Developers else 76410037SARM gem5 Developers currState->physAddrRange = pa_range; 76510037SARM gem5 Developers if (checkAddrSizeFaultAArch64(base_addr, currState->physAddrRange)) { 76610037SARM gem5 Developers DPRINTF(TLB, "Address size fault before any lookup\n"); 76710037SARM gem5 Developers Fault f; 76810037SARM gem5 Developers if (currState->isFetch) 76910037SARM gem5 Developers f = new PrefetchAbort(currState->vaddr_tainted, 77010037SARM gem5 Developers ArmFault::AddressSizeLL + start_lookup_level, 77110037SARM gem5 Developers isStage2, 77210037SARM gem5 Developers ArmFault::LpaeTran); 77310037SARM gem5 Developers else 77410037SARM gem5 Developers f = new DataAbort(currState->vaddr_tainted, 77510037SARM gem5 Developers TlbEntry::DomainType::NoAccess, 77610037SARM gem5 Developers currState->isWrite, 77710037SARM gem5 Developers ArmFault::AddressSizeLL + start_lookup_level, 77810037SARM gem5 Developers isStage2, 77910037SARM gem5 Developers ArmFault::LpaeTran); 78010037SARM gem5 Developers 78110037SARM gem5 Developers 78210037SARM gem5 Developers if (currState->timing) { 78310037SARM gem5 Developers pending = false; 78410037SARM gem5 Developers nextWalk(currState->tc); 78510037SARM gem5 Developers currState = NULL; 78610037SARM gem5 Developers } else { 78710037SARM gem5 Developers currState->tc = NULL; 78810037SARM gem5 Developers currState->req = NULL; 78910037SARM gem5 Developers } 79010037SARM gem5 Developers return f; 79110037SARM gem5 Developers 79210037SARM gem5 Developers } 79310037SARM gem5 Developers 79410037SARM gem5 Developers // Determine descriptor address 79510037SARM gem5 Developers Addr desc_addr = base_addr | 79610037SARM gem5 Developers (bits(currState->vaddr, tsz - 1, 79710037SARM gem5 Developers stride * (3 - start_lookup_level) + grain_size) << 3); 79810037SARM gem5 Developers 79910037SARM gem5 Developers // Trickbox address check 80010037SARM gem5 Developers Fault f = tlb->walkTrickBoxCheck(desc_addr, currState->isSecure, 80110037SARM gem5 Developers currState->vaddr, sizeof(uint64_t), currState->isFetch, 80210037SARM gem5 Developers currState->isWrite, TlbEntry::DomainType::NoAccess, 80310037SARM gem5 Developers start_lookup_level); 80410037SARM gem5 Developers if (f) { 80510037SARM gem5 Developers DPRINTF(TLB, "Trickbox check caused fault on %#x\n", currState->vaddr_tainted); 80610037SARM gem5 Developers if (currState->timing) { 80710037SARM gem5 Developers pending = false; 80810037SARM gem5 Developers nextWalk(currState->tc); 80910037SARM gem5 Developers currState = NULL; 81010037SARM gem5 Developers } else { 81110037SARM gem5 Developers currState->tc = NULL; 81210037SARM gem5 Developers currState->req = NULL; 81310037SARM gem5 Developers } 81410037SARM gem5 Developers return f; 81510037SARM gem5 Developers } 81610037SARM gem5 Developers 81710037SARM gem5 Developers Request::Flags flag = 0; 81810037SARM gem5 Developers if (currState->sctlr.c == 0) { 81910037SARM gem5 Developers flag = Request::UNCACHEABLE; 82010037SARM gem5 Developers } 82110037SARM gem5 Developers 82210037SARM gem5 Developers currState->longDesc.lookupLevel = start_lookup_level; 82310037SARM gem5 Developers currState->longDesc.aarch64 = true; 82410037SARM gem5 Developers currState->longDesc.largeGrain = large_grain; 82510037SARM gem5 Developers currState->longDesc.grainSize = grain_size; 82610037SARM gem5 Developers 8277439Sdam.sunwoo@arm.com if (currState->timing) { 82810037SARM gem5 Developers Event *event; 82910037SARM gem5 Developers switch (start_lookup_level) { 83010037SARM gem5 Developers case L0: 83110037SARM gem5 Developers event = (Event *) &doL0LongDescEvent; 83210037SARM gem5 Developers break; 83310037SARM gem5 Developers case L1: 83410037SARM gem5 Developers event = (Event *) &doL1LongDescEvent; 83510037SARM gem5 Developers break; 83610037SARM gem5 Developers case L2: 83710037SARM gem5 Developers event = (Event *) &doL2LongDescEvent; 83810037SARM gem5 Developers break; 83910037SARM gem5 Developers case L3: 84010037SARM gem5 Developers event = (Event *) &doL3LongDescEvent; 84110037SARM gem5 Developers break; 84210037SARM gem5 Developers default: 84310037SARM gem5 Developers panic("Invalid table lookup level"); 84410037SARM gem5 Developers break; 84510037SARM gem5 Developers } 84610037SARM gem5 Developers port.dmaAction(MemCmd::ReadReq, desc_addr, sizeof(uint64_t), event, 84710037SARM gem5 Developers (uint8_t*) &currState->longDesc.data, 8489180Sandreas.hansson@arm.com currState->tc->getCpuPtr()->clockPeriod(), flag); 84910037SARM gem5 Developers DPRINTF(TLBVerbose, 85010037SARM gem5 Developers "Adding to walker fifo: queue size before adding: %d\n", 85110037SARM gem5 Developers stateQueues[start_lookup_level].size()); 85210037SARM gem5 Developers stateQueues[start_lookup_level].push_back(currState); 8537439Sdam.sunwoo@arm.com currState = NULL; 8548733Sgeoffrey.blake@arm.com } else if (!currState->functional) { 85510037SARM gem5 Developers port.dmaAction(MemCmd::ReadReq, desc_addr, sizeof(uint64_t), 85610037SARM gem5 Developers NULL, (uint8_t*) &currState->longDesc.data, 8579180Sandreas.hansson@arm.com currState->tc->getCpuPtr()->clockPeriod(), flag); 85810037SARM gem5 Developers doLongDescriptor(); 8597439Sdam.sunwoo@arm.com f = currState->fault; 8608733Sgeoffrey.blake@arm.com } else { 86110037SARM gem5 Developers RequestPtr req = new Request(desc_addr, sizeof(uint64_t), flag, 86210037SARM gem5 Developers masterId); 8638949Sandreas.hansson@arm.com PacketPtr pkt = new Packet(req, MemCmd::ReadReq); 86410037SARM gem5 Developers pkt->dataStatic((uint8_t*) &currState->longDesc.data); 8658851Sandreas.hansson@arm.com port.sendFunctional(pkt); 86610037SARM gem5 Developers doLongDescriptor(); 8678733Sgeoffrey.blake@arm.com delete req; 8688733Sgeoffrey.blake@arm.com delete pkt; 8698733Sgeoffrey.blake@arm.com f = currState->fault; 8707404SAli.Saidi@ARM.com } 8717404SAli.Saidi@ARM.com 8727439Sdam.sunwoo@arm.com return f; 8737404SAli.Saidi@ARM.com} 8747404SAli.Saidi@ARM.com 8757404SAli.Saidi@ARM.comvoid 8767439Sdam.sunwoo@arm.comTableWalker::memAttrs(ThreadContext *tc, TlbEntry &te, SCTLR sctlr, 8777439Sdam.sunwoo@arm.com uint8_t texcb, bool s) 8787404SAli.Saidi@ARM.com{ 8797439Sdam.sunwoo@arm.com // Note: tc and sctlr local variables are hiding tc and sctrl class 8807439Sdam.sunwoo@arm.com // variables 8817436Sdam.sunwoo@arm.com DPRINTF(TLBVerbose, "memAttrs texcb:%d s:%d\n", texcb, s); 8827436Sdam.sunwoo@arm.com te.shareable = false; // default value 8837582SAli.Saidi@arm.com te.nonCacheable = false; 88410037SARM gem5 Developers te.outerShareable = false; 8857439Sdam.sunwoo@arm.com if (sctlr.tre == 0 || ((sctlr.tre == 1) && (sctlr.m == 0))) { 8867404SAli.Saidi@ARM.com switch(texcb) { 8877436Sdam.sunwoo@arm.com case 0: // Stongly-ordered 8887404SAli.Saidi@ARM.com te.nonCacheable = true; 88910037SARM gem5 Developers te.mtype = TlbEntry::MemoryType::StronglyOrdered; 8907436Sdam.sunwoo@arm.com te.shareable = true; 8917436Sdam.sunwoo@arm.com te.innerAttrs = 1; 8927436Sdam.sunwoo@arm.com te.outerAttrs = 0; 8937404SAli.Saidi@ARM.com break; 8947436Sdam.sunwoo@arm.com case 1: // Shareable Device 8957436Sdam.sunwoo@arm.com te.nonCacheable = true; 89610037SARM gem5 Developers te.mtype = TlbEntry::MemoryType::Device; 8977436Sdam.sunwoo@arm.com te.shareable = true; 8987436Sdam.sunwoo@arm.com te.innerAttrs = 3; 8997436Sdam.sunwoo@arm.com te.outerAttrs = 0; 9007436Sdam.sunwoo@arm.com break; 9017436Sdam.sunwoo@arm.com case 2: // Outer and Inner Write-Through, no Write-Allocate 90210037SARM gem5 Developers te.mtype = TlbEntry::MemoryType::Normal; 9037436Sdam.sunwoo@arm.com te.shareable = s; 9047436Sdam.sunwoo@arm.com te.innerAttrs = 6; 9057436Sdam.sunwoo@arm.com te.outerAttrs = bits(texcb, 1, 0); 9067436Sdam.sunwoo@arm.com break; 9077436Sdam.sunwoo@arm.com case 3: // Outer and Inner Write-Back, no Write-Allocate 90810037SARM gem5 Developers te.mtype = TlbEntry::MemoryType::Normal; 9097436Sdam.sunwoo@arm.com te.shareable = s; 9107436Sdam.sunwoo@arm.com te.innerAttrs = 7; 9117436Sdam.sunwoo@arm.com te.outerAttrs = bits(texcb, 1, 0); 9127436Sdam.sunwoo@arm.com break; 9137436Sdam.sunwoo@arm.com case 4: // Outer and Inner Non-cacheable 9147436Sdam.sunwoo@arm.com te.nonCacheable = true; 91510037SARM gem5 Developers te.mtype = TlbEntry::MemoryType::Normal; 9167436Sdam.sunwoo@arm.com te.shareable = s; 9177436Sdam.sunwoo@arm.com te.innerAttrs = 0; 9187436Sdam.sunwoo@arm.com te.outerAttrs = bits(texcb, 1, 0); 9197436Sdam.sunwoo@arm.com break; 9207436Sdam.sunwoo@arm.com case 5: // Reserved 9217439Sdam.sunwoo@arm.com panic("Reserved texcb value!\n"); 9227436Sdam.sunwoo@arm.com break; 9237436Sdam.sunwoo@arm.com case 6: // Implementation Defined 9247439Sdam.sunwoo@arm.com panic("Implementation-defined texcb value!\n"); 9257436Sdam.sunwoo@arm.com break; 9267436Sdam.sunwoo@arm.com case 7: // Outer and Inner Write-Back, Write-Allocate 92710037SARM gem5 Developers te.mtype = TlbEntry::MemoryType::Normal; 9287436Sdam.sunwoo@arm.com te.shareable = s; 9297436Sdam.sunwoo@arm.com te.innerAttrs = 5; 9307436Sdam.sunwoo@arm.com te.outerAttrs = 1; 9317436Sdam.sunwoo@arm.com break; 9327436Sdam.sunwoo@arm.com case 8: // Non-shareable Device 9337436Sdam.sunwoo@arm.com te.nonCacheable = true; 93410037SARM gem5 Developers te.mtype = TlbEntry::MemoryType::Device; 9357436Sdam.sunwoo@arm.com te.shareable = false; 9367436Sdam.sunwoo@arm.com te.innerAttrs = 3; 9377436Sdam.sunwoo@arm.com te.outerAttrs = 0; 9387436Sdam.sunwoo@arm.com break; 9397436Sdam.sunwoo@arm.com case 9 ... 15: // Reserved 9407439Sdam.sunwoo@arm.com panic("Reserved texcb value!\n"); 9417436Sdam.sunwoo@arm.com break; 9427436Sdam.sunwoo@arm.com case 16 ... 31: // Cacheable Memory 94310037SARM gem5 Developers te.mtype = TlbEntry::MemoryType::Normal; 9447436Sdam.sunwoo@arm.com te.shareable = s; 9457404SAli.Saidi@ARM.com if (bits(texcb, 1,0) == 0 || bits(texcb, 3,2) == 0) 9467404SAli.Saidi@ARM.com te.nonCacheable = true; 9477436Sdam.sunwoo@arm.com te.innerAttrs = bits(texcb, 1, 0); 9487436Sdam.sunwoo@arm.com te.outerAttrs = bits(texcb, 3, 2); 9497404SAli.Saidi@ARM.com break; 9507436Sdam.sunwoo@arm.com default: 9517436Sdam.sunwoo@arm.com panic("More than 32 states for 5 bits?\n"); 9527404SAli.Saidi@ARM.com } 9537404SAli.Saidi@ARM.com } else { 9547438SAli.Saidi@ARM.com assert(tc); 95510037SARM gem5 Developers PRRR prrr = tc->readMiscReg(flattenMiscRegNsBanked(MISCREG_PRRR, 95610037SARM gem5 Developers currState->tc, !currState->isSecure)); 95710037SARM gem5 Developers NMRR nmrr = tc->readMiscReg(flattenMiscRegNsBanked(MISCREG_NMRR, 95810037SARM gem5 Developers currState->tc, !currState->isSecure)); 9597436Sdam.sunwoo@arm.com DPRINTF(TLBVerbose, "memAttrs PRRR:%08x NMRR:%08x\n", prrr, nmrr); 9607582SAli.Saidi@arm.com uint8_t curr_tr = 0, curr_ir = 0, curr_or = 0; 9617404SAli.Saidi@ARM.com switch(bits(texcb, 2,0)) { 9627404SAli.Saidi@ARM.com case 0: 9637436Sdam.sunwoo@arm.com curr_tr = prrr.tr0; 9647436Sdam.sunwoo@arm.com curr_ir = nmrr.ir0; 9657436Sdam.sunwoo@arm.com curr_or = nmrr.or0; 96610037SARM gem5 Developers te.outerShareable = (prrr.nos0 == 0); 9677404SAli.Saidi@ARM.com break; 9687404SAli.Saidi@ARM.com case 1: 9697436Sdam.sunwoo@arm.com curr_tr = prrr.tr1; 9707436Sdam.sunwoo@arm.com curr_ir = nmrr.ir1; 9717436Sdam.sunwoo@arm.com curr_or = nmrr.or1; 97210037SARM gem5 Developers te.outerShareable = (prrr.nos1 == 0); 9737404SAli.Saidi@ARM.com break; 9747404SAli.Saidi@ARM.com case 2: 9757436Sdam.sunwoo@arm.com curr_tr = prrr.tr2; 9767436Sdam.sunwoo@arm.com curr_ir = nmrr.ir2; 9777436Sdam.sunwoo@arm.com curr_or = nmrr.or2; 97810037SARM gem5 Developers te.outerShareable = (prrr.nos2 == 0); 9797404SAli.Saidi@ARM.com break; 9807404SAli.Saidi@ARM.com case 3: 9817436Sdam.sunwoo@arm.com curr_tr = prrr.tr3; 9827436Sdam.sunwoo@arm.com curr_ir = nmrr.ir3; 9837436Sdam.sunwoo@arm.com curr_or = nmrr.or3; 98410037SARM gem5 Developers te.outerShareable = (prrr.nos3 == 0); 9857404SAli.Saidi@ARM.com break; 9867404SAli.Saidi@ARM.com case 4: 9877436Sdam.sunwoo@arm.com curr_tr = prrr.tr4; 9887436Sdam.sunwoo@arm.com curr_ir = nmrr.ir4; 9897436Sdam.sunwoo@arm.com curr_or = nmrr.or4; 99010037SARM gem5 Developers te.outerShareable = (prrr.nos4 == 0); 9917404SAli.Saidi@ARM.com break; 9927404SAli.Saidi@ARM.com case 5: 9937436Sdam.sunwoo@arm.com curr_tr = prrr.tr5; 9947436Sdam.sunwoo@arm.com curr_ir = nmrr.ir5; 9957436Sdam.sunwoo@arm.com curr_or = nmrr.or5; 99610037SARM gem5 Developers te.outerShareable = (prrr.nos5 == 0); 9977404SAli.Saidi@ARM.com break; 9987404SAli.Saidi@ARM.com case 6: 9997404SAli.Saidi@ARM.com panic("Imp defined type\n"); 10007404SAli.Saidi@ARM.com case 7: 10017436Sdam.sunwoo@arm.com curr_tr = prrr.tr7; 10027436Sdam.sunwoo@arm.com curr_ir = nmrr.ir7; 10037436Sdam.sunwoo@arm.com curr_or = nmrr.or7; 100410037SARM gem5 Developers te.outerShareable = (prrr.nos7 == 0); 10057404SAli.Saidi@ARM.com break; 10067404SAli.Saidi@ARM.com } 10077436Sdam.sunwoo@arm.com 10087436Sdam.sunwoo@arm.com switch(curr_tr) { 10097436Sdam.sunwoo@arm.com case 0: 10107436Sdam.sunwoo@arm.com DPRINTF(TLBVerbose, "StronglyOrdered\n"); 101110037SARM gem5 Developers te.mtype = TlbEntry::MemoryType::StronglyOrdered; 10127436Sdam.sunwoo@arm.com te.nonCacheable = true; 10137436Sdam.sunwoo@arm.com te.innerAttrs = 1; 10147436Sdam.sunwoo@arm.com te.outerAttrs = 0; 10157436Sdam.sunwoo@arm.com te.shareable = true; 10167436Sdam.sunwoo@arm.com break; 10177436Sdam.sunwoo@arm.com case 1: 10187436Sdam.sunwoo@arm.com DPRINTF(TLBVerbose, "Device ds1:%d ds0:%d s:%d\n", 10197436Sdam.sunwoo@arm.com prrr.ds1, prrr.ds0, s); 102010037SARM gem5 Developers te.mtype = TlbEntry::MemoryType::Device; 10217436Sdam.sunwoo@arm.com te.nonCacheable = true; 10227436Sdam.sunwoo@arm.com te.innerAttrs = 3; 10237436Sdam.sunwoo@arm.com te.outerAttrs = 0; 10247436Sdam.sunwoo@arm.com if (prrr.ds1 && s) 10257436Sdam.sunwoo@arm.com te.shareable = true; 10267436Sdam.sunwoo@arm.com if (prrr.ds0 && !s) 10277436Sdam.sunwoo@arm.com te.shareable = true; 10287436Sdam.sunwoo@arm.com break; 10297436Sdam.sunwoo@arm.com case 2: 10307436Sdam.sunwoo@arm.com DPRINTF(TLBVerbose, "Normal ns1:%d ns0:%d s:%d\n", 10317436Sdam.sunwoo@arm.com prrr.ns1, prrr.ns0, s); 103210037SARM gem5 Developers te.mtype = TlbEntry::MemoryType::Normal; 10337436Sdam.sunwoo@arm.com if (prrr.ns1 && s) 10347436Sdam.sunwoo@arm.com te.shareable = true; 10357436Sdam.sunwoo@arm.com if (prrr.ns0 && !s) 10367436Sdam.sunwoo@arm.com te.shareable = true; 10377436Sdam.sunwoo@arm.com break; 10387436Sdam.sunwoo@arm.com case 3: 10397436Sdam.sunwoo@arm.com panic("Reserved type"); 10407436Sdam.sunwoo@arm.com } 10417436Sdam.sunwoo@arm.com 104210037SARM gem5 Developers if (te.mtype == TlbEntry::MemoryType::Normal){ 10437436Sdam.sunwoo@arm.com switch(curr_ir) { 10447436Sdam.sunwoo@arm.com case 0: 10457436Sdam.sunwoo@arm.com te.nonCacheable = true; 10467436Sdam.sunwoo@arm.com te.innerAttrs = 0; 10477436Sdam.sunwoo@arm.com break; 10487436Sdam.sunwoo@arm.com case 1: 10497436Sdam.sunwoo@arm.com te.innerAttrs = 5; 10507436Sdam.sunwoo@arm.com break; 10517436Sdam.sunwoo@arm.com case 2: 10527436Sdam.sunwoo@arm.com te.innerAttrs = 6; 10537436Sdam.sunwoo@arm.com break; 10547436Sdam.sunwoo@arm.com case 3: 10557436Sdam.sunwoo@arm.com te.innerAttrs = 7; 10567436Sdam.sunwoo@arm.com break; 10577436Sdam.sunwoo@arm.com } 10587436Sdam.sunwoo@arm.com 10597436Sdam.sunwoo@arm.com switch(curr_or) { 10607436Sdam.sunwoo@arm.com case 0: 10617436Sdam.sunwoo@arm.com te.nonCacheable = true; 10627436Sdam.sunwoo@arm.com te.outerAttrs = 0; 10637436Sdam.sunwoo@arm.com break; 10647436Sdam.sunwoo@arm.com case 1: 10657436Sdam.sunwoo@arm.com te.outerAttrs = 1; 10667436Sdam.sunwoo@arm.com break; 10677436Sdam.sunwoo@arm.com case 2: 10687436Sdam.sunwoo@arm.com te.outerAttrs = 2; 10697436Sdam.sunwoo@arm.com break; 10707436Sdam.sunwoo@arm.com case 3: 10717436Sdam.sunwoo@arm.com te.outerAttrs = 3; 10727436Sdam.sunwoo@arm.com break; 10737436Sdam.sunwoo@arm.com } 10747436Sdam.sunwoo@arm.com } 10757404SAli.Saidi@ARM.com } 10767439Sdam.sunwoo@arm.com DPRINTF(TLBVerbose, "memAttrs: shareable: %d, innerAttrs: %d, \ 10777439Sdam.sunwoo@arm.com outerAttrs: %d\n", 10787439Sdam.sunwoo@arm.com te.shareable, te.innerAttrs, te.outerAttrs); 107910037SARM gem5 Developers te.setAttributes(false); 108010037SARM gem5 Developers} 10817436Sdam.sunwoo@arm.com 108210037SARM gem5 Developersvoid 108310037SARM gem5 DevelopersTableWalker::memAttrsLPAE(ThreadContext *tc, TlbEntry &te, 108410037SARM gem5 Developers LongDescriptor &lDescriptor) 108510037SARM gem5 Developers{ 108610037SARM gem5 Developers assert(_haveLPAE); 10877436Sdam.sunwoo@arm.com 108810037SARM gem5 Developers uint8_t attr; 108910037SARM gem5 Developers uint8_t sh = lDescriptor.sh(); 109010037SARM gem5 Developers // Different format and source of attributes if this is a stage 2 109110037SARM gem5 Developers // translation 109210037SARM gem5 Developers if (isStage2) { 109310037SARM gem5 Developers attr = lDescriptor.memAttr(); 109410037SARM gem5 Developers uint8_t attr_3_2 = (attr >> 2) & 0x3; 109510037SARM gem5 Developers uint8_t attr_1_0 = attr & 0x3; 10967436Sdam.sunwoo@arm.com 109710037SARM gem5 Developers DPRINTF(TLBVerbose, "memAttrsLPAE MemAttr:%#x sh:%#x\n", attr, sh); 109810037SARM gem5 Developers 109910037SARM gem5 Developers if (attr_3_2 == 0) { 110010037SARM gem5 Developers te.mtype = attr_1_0 == 0 ? TlbEntry::MemoryType::StronglyOrdered 110110037SARM gem5 Developers : TlbEntry::MemoryType::Device; 110210037SARM gem5 Developers te.outerAttrs = 0; 110310037SARM gem5 Developers te.innerAttrs = attr_1_0 == 0 ? 1 : 3; 110410037SARM gem5 Developers te.nonCacheable = true; 110510037SARM gem5 Developers } else { 110610037SARM gem5 Developers te.mtype = TlbEntry::MemoryType::Normal; 110710037SARM gem5 Developers te.outerAttrs = attr_3_2 == 1 ? 0 : 110810037SARM gem5 Developers attr_3_2 == 2 ? 2 : 1; 110910037SARM gem5 Developers te.innerAttrs = attr_1_0 == 1 ? 0 : 111010037SARM gem5 Developers attr_1_0 == 2 ? 6 : 5; 111110037SARM gem5 Developers te.nonCacheable = (attr_3_2 == 1) || (attr_1_0 == 1); 111210037SARM gem5 Developers } 111310037SARM gem5 Developers } else { 111410037SARM gem5 Developers uint8_t attrIndx = lDescriptor.attrIndx(); 111510037SARM gem5 Developers 111610037SARM gem5 Developers // LPAE always uses remapping of memory attributes, irrespective of the 111710037SARM gem5 Developers // value of SCTLR.TRE 111810037SARM gem5 Developers int reg = attrIndx & 0x4 ? MISCREG_MAIR1 : MISCREG_MAIR0; 111910037SARM gem5 Developers reg = flattenMiscRegNsBanked(reg, currState->tc, !currState->isSecure); 112010037SARM gem5 Developers uint32_t mair = currState->tc->readMiscReg(reg); 112110037SARM gem5 Developers attr = (mair >> (8 * (attrIndx % 4))) & 0xff; 112210037SARM gem5 Developers uint8_t attr_7_4 = bits(attr, 7, 4); 112310037SARM gem5 Developers uint8_t attr_3_0 = bits(attr, 3, 0); 112410037SARM gem5 Developers DPRINTF(TLBVerbose, "memAttrsLPAE AttrIndx:%#x sh:%#x, attr %#x\n", attrIndx, sh, attr); 112510037SARM gem5 Developers 112610037SARM gem5 Developers // Note: the memory subsystem only cares about the 'cacheable' memory 112710037SARM gem5 Developers // attribute. The other attributes are only used to fill the PAR register 112810037SARM gem5 Developers // accordingly to provide the illusion of full support 112910037SARM gem5 Developers te.nonCacheable = false; 113010037SARM gem5 Developers 113110037SARM gem5 Developers switch (attr_7_4) { 113210037SARM gem5 Developers case 0x0: 113310037SARM gem5 Developers // Strongly-ordered or Device memory 113410037SARM gem5 Developers if (attr_3_0 == 0x0) 113510037SARM gem5 Developers te.mtype = TlbEntry::MemoryType::StronglyOrdered; 113610037SARM gem5 Developers else if (attr_3_0 == 0x4) 113710037SARM gem5 Developers te.mtype = TlbEntry::MemoryType::Device; 113810037SARM gem5 Developers else 113910037SARM gem5 Developers panic("Unpredictable behavior\n"); 114010037SARM gem5 Developers te.nonCacheable = true; 114110037SARM gem5 Developers te.outerAttrs = 0; 114210037SARM gem5 Developers break; 114310037SARM gem5 Developers case 0x4: 114410037SARM gem5 Developers // Normal memory, Outer Non-cacheable 114510037SARM gem5 Developers te.mtype = TlbEntry::MemoryType::Normal; 114610037SARM gem5 Developers te.outerAttrs = 0; 114710037SARM gem5 Developers if (attr_3_0 == 0x4) 114810037SARM gem5 Developers // Inner Non-cacheable 114910037SARM gem5 Developers te.nonCacheable = true; 115010037SARM gem5 Developers else if (attr_3_0 < 0x8) 115110037SARM gem5 Developers panic("Unpredictable behavior\n"); 115210037SARM gem5 Developers break; 115310037SARM gem5 Developers case 0x8: 115410037SARM gem5 Developers case 0x9: 115510037SARM gem5 Developers case 0xa: 115610037SARM gem5 Developers case 0xb: 115710037SARM gem5 Developers case 0xc: 115810037SARM gem5 Developers case 0xd: 115910037SARM gem5 Developers case 0xe: 116010037SARM gem5 Developers case 0xf: 116110037SARM gem5 Developers if (attr_7_4 & 0x4) { 116210037SARM gem5 Developers te.outerAttrs = (attr_7_4 & 1) ? 1 : 3; 116310037SARM gem5 Developers } else { 116410037SARM gem5 Developers te.outerAttrs = 0x2; 116510037SARM gem5 Developers } 116610037SARM gem5 Developers // Normal memory, Outer Cacheable 116710037SARM gem5 Developers te.mtype = TlbEntry::MemoryType::Normal; 116810037SARM gem5 Developers if (attr_3_0 != 0x4 && attr_3_0 < 0x8) 116910037SARM gem5 Developers panic("Unpredictable behavior\n"); 117010037SARM gem5 Developers break; 117110037SARM gem5 Developers default: 117210037SARM gem5 Developers panic("Unpredictable behavior\n"); 117310037SARM gem5 Developers break; 117410037SARM gem5 Developers } 117510037SARM gem5 Developers 117610037SARM gem5 Developers switch (attr_3_0) { 117710037SARM gem5 Developers case 0x0: 117810037SARM gem5 Developers te.innerAttrs = 0x1; 117910037SARM gem5 Developers break; 118010037SARM gem5 Developers case 0x4: 118110037SARM gem5 Developers te.innerAttrs = attr_7_4 == 0 ? 0x3 : 0; 118210037SARM gem5 Developers break; 118310037SARM gem5 Developers case 0x8: 118410037SARM gem5 Developers case 0x9: 118510037SARM gem5 Developers case 0xA: 118610037SARM gem5 Developers case 0xB: 118710037SARM gem5 Developers te.innerAttrs = 6; 118810037SARM gem5 Developers break; 118910037SARM gem5 Developers case 0xC: 119010037SARM gem5 Developers case 0xD: 119110037SARM gem5 Developers case 0xE: 119210037SARM gem5 Developers case 0xF: 119310037SARM gem5 Developers te.innerAttrs = attr_3_0 & 1 ? 0x5 : 0x7; 119410037SARM gem5 Developers break; 119510037SARM gem5 Developers default: 119610037SARM gem5 Developers panic("Unpredictable behavior\n"); 119710037SARM gem5 Developers break; 119810037SARM gem5 Developers } 119910037SARM gem5 Developers } 120010037SARM gem5 Developers 120110037SARM gem5 Developers te.outerShareable = sh == 2; 120210037SARM gem5 Developers te.shareable = (sh & 0x2) ? true : false; 120310037SARM gem5 Developers te.setAttributes(true); 120410037SARM gem5 Developers te.attributes |= (uint64_t) attr << 56; 120510037SARM gem5 Developers} 120610037SARM gem5 Developers 120710037SARM gem5 Developersvoid 120810037SARM gem5 DevelopersTableWalker::memAttrsAArch64(ThreadContext *tc, TlbEntry &te, uint8_t attrIndx, 120910037SARM gem5 Developers uint8_t sh) 121010037SARM gem5 Developers{ 121110037SARM gem5 Developers DPRINTF(TLBVerbose, "memAttrsAArch64 AttrIndx:%#x sh:%#x\n", attrIndx, sh); 121210037SARM gem5 Developers 121310037SARM gem5 Developers // Select MAIR 121410037SARM gem5 Developers uint64_t mair; 121510037SARM gem5 Developers switch (currState->el) { 121610037SARM gem5 Developers case EL0: 121710037SARM gem5 Developers case EL1: 121810037SARM gem5 Developers mair = tc->readMiscReg(MISCREG_MAIR_EL1); 121910037SARM gem5 Developers break; 122010037SARM gem5 Developers case EL2: 122110037SARM gem5 Developers mair = tc->readMiscReg(MISCREG_MAIR_EL2); 122210037SARM gem5 Developers break; 122310037SARM gem5 Developers case EL3: 122410037SARM gem5 Developers mair = tc->readMiscReg(MISCREG_MAIR_EL3); 122510037SARM gem5 Developers break; 122610037SARM gem5 Developers default: 122710037SARM gem5 Developers panic("Invalid exception level"); 122810037SARM gem5 Developers break; 122910037SARM gem5 Developers } 123010037SARM gem5 Developers 123110037SARM gem5 Developers // Select attributes 123210037SARM gem5 Developers uint8_t attr = bits(mair, 8 * attrIndx + 7, 8 * attrIndx); 123310037SARM gem5 Developers uint8_t attr_lo = bits(attr, 3, 0); 123410037SARM gem5 Developers uint8_t attr_hi = bits(attr, 7, 4); 123510037SARM gem5 Developers 123610037SARM gem5 Developers // Memory type 123710037SARM gem5 Developers te.mtype = attr_hi == 0 ? TlbEntry::MemoryType::Device : TlbEntry::MemoryType::Normal; 123810037SARM gem5 Developers 123910037SARM gem5 Developers // Cacheability 124010037SARM gem5 Developers te.nonCacheable = false; 124110037SARM gem5 Developers if (te.mtype == TlbEntry::MemoryType::Device || // Device memory 124210037SARM gem5 Developers attr_hi == 0x8 || // Normal memory, Outer Non-cacheable 124310037SARM gem5 Developers attr_lo == 0x8) { // Normal memory, Inner Non-cacheable 124410037SARM gem5 Developers te.nonCacheable = true; 124510037SARM gem5 Developers } 124610037SARM gem5 Developers 124710037SARM gem5 Developers te.shareable = sh == 2; 124810037SARM gem5 Developers te.outerShareable = (sh & 0x2) ? true : false; 124910037SARM gem5 Developers // Attributes formatted according to the 64-bit PAR 125010037SARM gem5 Developers te.attributes = ((uint64_t) attr << 56) | 125110037SARM gem5 Developers (1 << 11) | // LPAE bit 125210037SARM gem5 Developers (te.ns << 9) | // NS bit 125310037SARM gem5 Developers (sh << 7); 12547404SAli.Saidi@ARM.com} 12557404SAli.Saidi@ARM.com 12567404SAli.Saidi@ARM.comvoid 12577404SAli.Saidi@ARM.comTableWalker::doL1Descriptor() 12587404SAli.Saidi@ARM.com{ 125910037SARM gem5 Developers if (currState->fault != NoFault) { 126010037SARM gem5 Developers return; 126110037SARM gem5 Developers } 126210037SARM gem5 Developers 12637439Sdam.sunwoo@arm.com DPRINTF(TLB, "L1 descriptor for %#x is %#x\n", 126410037SARM gem5 Developers currState->vaddr_tainted, currState->l1Desc.data); 12657404SAli.Saidi@ARM.com TlbEntry te; 12667404SAli.Saidi@ARM.com 12677439Sdam.sunwoo@arm.com switch (currState->l1Desc.type()) { 12687404SAli.Saidi@ARM.com case L1Descriptor::Ignore: 12697404SAli.Saidi@ARM.com case L1Descriptor::Reserved: 12707946SGiacomo.Gabrielli@arm.com if (!currState->timing) { 12717439Sdam.sunwoo@arm.com currState->tc = NULL; 12727439Sdam.sunwoo@arm.com currState->req = NULL; 12737437Sdam.sunwoo@arm.com } 12747406SAli.Saidi@ARM.com DPRINTF(TLB, "L1 Descriptor Reserved/Ignore, causing fault\n"); 12757439Sdam.sunwoo@arm.com if (currState->isFetch) 12767439Sdam.sunwoo@arm.com currState->fault = 127710037SARM gem5 Developers new PrefetchAbort(currState->vaddr_tainted, 127810037SARM gem5 Developers ArmFault::TranslationLL + L1, 127910037SARM gem5 Developers isStage2, 128010037SARM gem5 Developers ArmFault::VmsaTran); 12817406SAli.Saidi@ARM.com else 12827439Sdam.sunwoo@arm.com currState->fault = 128310037SARM gem5 Developers new DataAbort(currState->vaddr_tainted, 128410037SARM gem5 Developers TlbEntry::DomainType::NoAccess, 128510037SARM gem5 Developers currState->isWrite, 128610037SARM gem5 Developers ArmFault::TranslationLL + L1, isStage2, 128710037SARM gem5 Developers ArmFault::VmsaTran); 12887404SAli.Saidi@ARM.com return; 12897404SAli.Saidi@ARM.com case L1Descriptor::Section: 12907439Sdam.sunwoo@arm.com if (currState->sctlr.afe && bits(currState->l1Desc.ap(), 0) == 0) { 12917436Sdam.sunwoo@arm.com /** @todo: check sctlr.ha (bit[17]) if Hardware Access Flag is 12927436Sdam.sunwoo@arm.com * enabled if set, do l1.Desc.setAp0() instead of generating 12937436Sdam.sunwoo@arm.com * AccessFlag0 12947436Sdam.sunwoo@arm.com */ 12957436Sdam.sunwoo@arm.com 129610037SARM gem5 Developers currState->fault = new DataAbort(currState->vaddr_tainted, 129710037SARM gem5 Developers currState->l1Desc.domain(), 129810037SARM gem5 Developers currState->isWrite, 129910037SARM gem5 Developers ArmFault::AccessFlagLL + L1, 130010037SARM gem5 Developers isStage2, 130110037SARM gem5 Developers ArmFault::VmsaTran); 13027436Sdam.sunwoo@arm.com } 13037439Sdam.sunwoo@arm.com if (currState->l1Desc.supersection()) { 13047404SAli.Saidi@ARM.com panic("Haven't implemented supersections\n"); 13057404SAli.Saidi@ARM.com } 130610037SARM gem5 Developers insertTableEntry(currState->l1Desc, false); 130710037SARM gem5 Developers return; 130810037SARM gem5 Developers case L1Descriptor::PageTable: 130910037SARM gem5 Developers { 131010037SARM gem5 Developers Addr l2desc_addr; 131110037SARM gem5 Developers l2desc_addr = currState->l1Desc.l2Addr() | 131210037SARM gem5 Developers (bits(currState->vaddr, 19, 12) << 2); 131310037SARM gem5 Developers DPRINTF(TLB, "L1 descriptor points to page table at: %#x (%s)\n", 131410037SARM gem5 Developers l2desc_addr, currState->isSecure ? "s" : "ns"); 13157404SAli.Saidi@ARM.com 131610037SARM gem5 Developers // Trickbox address check 131710037SARM gem5 Developers currState->fault = tlb->walkTrickBoxCheck( 131810037SARM gem5 Developers l2desc_addr, currState->isSecure, currState->vaddr, 131910037SARM gem5 Developers sizeof(uint32_t), currState->isFetch, currState->isWrite, 132010037SARM gem5 Developers currState->l1Desc.domain(), L2); 13217404SAli.Saidi@ARM.com 132210037SARM gem5 Developers if (currState->fault) { 132310037SARM gem5 Developers if (!currState->timing) { 132410037SARM gem5 Developers currState->tc = NULL; 132510037SARM gem5 Developers currState->req = NULL; 132610037SARM gem5 Developers } 132710037SARM gem5 Developers return; 132810037SARM gem5 Developers } 132910037SARM gem5 Developers 133010037SARM gem5 Developers Request::Flags flag = 0; 133110037SARM gem5 Developers if (currState->isSecure) 133210037SARM gem5 Developers flag.set(Request::SECURE); 133310037SARM gem5 Developers 133410037SARM gem5 Developers bool delayed; 133510037SARM gem5 Developers delayed = fetchDescriptor(l2desc_addr, 133610037SARM gem5 Developers (uint8_t*)&currState->l2Desc.data, 133710037SARM gem5 Developers sizeof(uint32_t), flag, -1, &doL2DescEvent, 133810037SARM gem5 Developers &TableWalker::doL2Descriptor); 133910037SARM gem5 Developers if (delayed) { 134010037SARM gem5 Developers currState->delayed = true; 134110037SARM gem5 Developers } 134210037SARM gem5 Developers 134310037SARM gem5 Developers return; 134410037SARM gem5 Developers } 134510037SARM gem5 Developers default: 134610037SARM gem5 Developers panic("A new type in a 2 bit field?\n"); 134710037SARM gem5 Developers } 134810037SARM gem5 Developers} 134910037SARM gem5 Developers 135010037SARM gem5 Developersvoid 135110037SARM gem5 DevelopersTableWalker::doLongDescriptor() 135210037SARM gem5 Developers{ 135310037SARM gem5 Developers if (currState->fault != NoFault) { 135410037SARM gem5 Developers return; 135510037SARM gem5 Developers } 135610037SARM gem5 Developers 135710037SARM gem5 Developers DPRINTF(TLB, "L%d descriptor for %#llx is %#llx (%s)\n", 135810037SARM gem5 Developers currState->longDesc.lookupLevel, currState->vaddr_tainted, 135910037SARM gem5 Developers currState->longDesc.data, 136010037SARM gem5 Developers currState->aarch64 ? "AArch64" : "long-desc."); 136110037SARM gem5 Developers 136210037SARM gem5 Developers if ((currState->longDesc.type() == LongDescriptor::Block) || 136310037SARM gem5 Developers (currState->longDesc.type() == LongDescriptor::Page)) { 136410037SARM gem5 Developers DPRINTF(TLBVerbose, "Analyzing L%d descriptor: %#llx, pxn: %d, " 136510037SARM gem5 Developers "xn: %d, ap: %d, af: %d, type: %d\n", 136610037SARM gem5 Developers currState->longDesc.lookupLevel, 136710037SARM gem5 Developers currState->longDesc.data, 136810037SARM gem5 Developers currState->longDesc.pxn(), 136910037SARM gem5 Developers currState->longDesc.xn(), 137010037SARM gem5 Developers currState->longDesc.ap(), 137110037SARM gem5 Developers currState->longDesc.af(), 137210037SARM gem5 Developers currState->longDesc.type()); 137310037SARM gem5 Developers } else { 137410037SARM gem5 Developers DPRINTF(TLBVerbose, "Analyzing L%d descriptor: %#llx, type: %d\n", 137510037SARM gem5 Developers currState->longDesc.lookupLevel, 137610037SARM gem5 Developers currState->longDesc.data, 137710037SARM gem5 Developers currState->longDesc.type()); 137810037SARM gem5 Developers } 137910037SARM gem5 Developers 138010037SARM gem5 Developers TlbEntry te; 138110037SARM gem5 Developers 138210037SARM gem5 Developers switch (currState->longDesc.type()) { 138310037SARM gem5 Developers case LongDescriptor::Invalid: 13847439Sdam.sunwoo@arm.com if (!currState->timing) { 13857439Sdam.sunwoo@arm.com currState->tc = NULL; 13867439Sdam.sunwoo@arm.com currState->req = NULL; 13877437Sdam.sunwoo@arm.com } 13887404SAli.Saidi@ARM.com 138910037SARM gem5 Developers DPRINTF(TLB, "L%d descriptor Invalid, causing fault type %d\n", 139010037SARM gem5 Developers currState->longDesc.lookupLevel, 139110037SARM gem5 Developers ArmFault::TranslationLL + currState->longDesc.lookupLevel); 139210037SARM gem5 Developers if (currState->isFetch) 139310037SARM gem5 Developers currState->fault = new PrefetchAbort( 139410037SARM gem5 Developers currState->vaddr_tainted, 139510037SARM gem5 Developers ArmFault::TranslationLL + currState->longDesc.lookupLevel, 139610037SARM gem5 Developers isStage2, 139710037SARM gem5 Developers ArmFault::LpaeTran); 139810037SARM gem5 Developers else 139910037SARM gem5 Developers currState->fault = new DataAbort( 140010037SARM gem5 Developers currState->vaddr_tainted, 140110037SARM gem5 Developers TlbEntry::DomainType::NoAccess, 140210037SARM gem5 Developers currState->isWrite, 140310037SARM gem5 Developers ArmFault::TranslationLL + currState->longDesc.lookupLevel, 140410037SARM gem5 Developers isStage2, 140510037SARM gem5 Developers ArmFault::LpaeTran); 14067404SAli.Saidi@ARM.com return; 140710037SARM gem5 Developers case LongDescriptor::Block: 140810037SARM gem5 Developers case LongDescriptor::Page: 140910037SARM gem5 Developers { 141010037SARM gem5 Developers bool fault = false; 141110037SARM gem5 Developers bool aff = false; 141210037SARM gem5 Developers // Check for address size fault 141310037SARM gem5 Developers if (checkAddrSizeFaultAArch64( 141410037SARM gem5 Developers mbits(currState->longDesc.data, MaxPhysAddrRange - 1, 141510037SARM gem5 Developers currState->longDesc.offsetBits()), 141610037SARM gem5 Developers currState->physAddrRange)) { 141710037SARM gem5 Developers fault = true; 141810037SARM gem5 Developers DPRINTF(TLB, "L%d descriptor causing Address Size Fault\n", 141910037SARM gem5 Developers currState->longDesc.lookupLevel); 142010037SARM gem5 Developers // Check for access fault 142110037SARM gem5 Developers } else if (currState->longDesc.af() == 0) { 142210037SARM gem5 Developers fault = true; 142310037SARM gem5 Developers DPRINTF(TLB, "L%d descriptor causing Access Fault\n", 142410037SARM gem5 Developers currState->longDesc.lookupLevel); 142510037SARM gem5 Developers aff = true; 142610037SARM gem5 Developers } 142710037SARM gem5 Developers if (fault) { 142810037SARM gem5 Developers if (currState->isFetch) 142910037SARM gem5 Developers currState->fault = new PrefetchAbort( 143010037SARM gem5 Developers currState->vaddr_tainted, 143110037SARM gem5 Developers (aff ? ArmFault::AccessFlagLL : ArmFault::AddressSizeLL) + 143210037SARM gem5 Developers currState->longDesc.lookupLevel, 143310037SARM gem5 Developers isStage2, 143410037SARM gem5 Developers ArmFault::LpaeTran); 143510037SARM gem5 Developers else 143610037SARM gem5 Developers currState->fault = new DataAbort( 143710037SARM gem5 Developers currState->vaddr_tainted, 143810037SARM gem5 Developers TlbEntry::DomainType::NoAccess, currState->isWrite, 143910037SARM gem5 Developers (aff ? ArmFault::AccessFlagLL : ArmFault::AddressSizeLL) + 144010037SARM gem5 Developers currState->longDesc.lookupLevel, 144110037SARM gem5 Developers isStage2, 144210037SARM gem5 Developers ArmFault::LpaeTran); 144310037SARM gem5 Developers } else { 144410037SARM gem5 Developers insertTableEntry(currState->longDesc, true); 144510037SARM gem5 Developers } 144610037SARM gem5 Developers } 144710037SARM gem5 Developers return; 144810037SARM gem5 Developers case LongDescriptor::Table: 144910037SARM gem5 Developers { 145010037SARM gem5 Developers // Set hierarchical permission flags 145110037SARM gem5 Developers currState->secureLookup = currState->secureLookup && 145210037SARM gem5 Developers currState->longDesc.secureTable(); 145310037SARM gem5 Developers currState->rwTable = currState->rwTable && 145410037SARM gem5 Developers currState->longDesc.rwTable(); 145510037SARM gem5 Developers currState->userTable = currState->userTable && 145610037SARM gem5 Developers currState->longDesc.userTable(); 145710037SARM gem5 Developers currState->xnTable = currState->xnTable || 145810037SARM gem5 Developers currState->longDesc.xnTable(); 145910037SARM gem5 Developers currState->pxnTable = currState->pxnTable || 146010037SARM gem5 Developers currState->longDesc.pxnTable(); 14617404SAli.Saidi@ARM.com 146210037SARM gem5 Developers // Set up next level lookup 146310037SARM gem5 Developers Addr next_desc_addr = currState->longDesc.nextDescAddr( 146410037SARM gem5 Developers currState->vaddr); 14657439Sdam.sunwoo@arm.com 146610037SARM gem5 Developers DPRINTF(TLB, "L%d descriptor points to L%d descriptor at: %#x (%s)\n", 146710037SARM gem5 Developers currState->longDesc.lookupLevel, 146810037SARM gem5 Developers currState->longDesc.lookupLevel + 1, 146910037SARM gem5 Developers next_desc_addr, 147010037SARM gem5 Developers currState->secureLookup ? "s" : "ns"); 147110037SARM gem5 Developers 147210037SARM gem5 Developers // Check for address size fault 147310037SARM gem5 Developers if (currState->aarch64 && checkAddrSizeFaultAArch64( 147410037SARM gem5 Developers next_desc_addr, currState->physAddrRange)) { 147510037SARM gem5 Developers DPRINTF(TLB, "L%d descriptor causing Address Size Fault\n", 147610037SARM gem5 Developers currState->longDesc.lookupLevel); 147710037SARM gem5 Developers if (currState->isFetch) 147810037SARM gem5 Developers currState->fault = new PrefetchAbort( 147910037SARM gem5 Developers currState->vaddr_tainted, 148010037SARM gem5 Developers ArmFault::AddressSizeLL 148110037SARM gem5 Developers + currState->longDesc.lookupLevel, 148210037SARM gem5 Developers isStage2, 148310037SARM gem5 Developers ArmFault::LpaeTran); 148410037SARM gem5 Developers else 148510037SARM gem5 Developers currState->fault = new DataAbort( 148610037SARM gem5 Developers currState->vaddr_tainted, 148710037SARM gem5 Developers TlbEntry::DomainType::NoAccess, currState->isWrite, 148810037SARM gem5 Developers ArmFault::AddressSizeLL 148910037SARM gem5 Developers + currState->longDesc.lookupLevel, 149010037SARM gem5 Developers isStage2, 149110037SARM gem5 Developers ArmFault::LpaeTran); 149210037SARM gem5 Developers return; 14937437Sdam.sunwoo@arm.com } 14947404SAli.Saidi@ARM.com 149510037SARM gem5 Developers // Trickbox address check 149610037SARM gem5 Developers currState->fault = tlb->walkTrickBoxCheck( 149710037SARM gem5 Developers next_desc_addr, currState->vaddr, 149810037SARM gem5 Developers currState->vaddr, sizeof(uint64_t), 149910037SARM gem5 Developers currState->isFetch, currState->isWrite, 150010037SARM gem5 Developers TlbEntry::DomainType::Client, 150110037SARM gem5 Developers toLookupLevel(currState->longDesc.lookupLevel +1)); 15027404SAli.Saidi@ARM.com 150310037SARM gem5 Developers if (currState->fault) { 150410037SARM gem5 Developers if (!currState->timing) { 150510037SARM gem5 Developers currState->tc = NULL; 150610037SARM gem5 Developers currState->req = NULL; 150710037SARM gem5 Developers } 150810037SARM gem5 Developers return; 150910037SARM gem5 Developers } 151010037SARM gem5 Developers 151110037SARM gem5 Developers Request::Flags flag = 0; 151210037SARM gem5 Developers if (currState->secureLookup) 151310037SARM gem5 Developers flag.set(Request::SECURE); 151410037SARM gem5 Developers 151510037SARM gem5 Developers currState->longDesc.lookupLevel = 151610037SARM gem5 Developers (LookupLevel) (currState->longDesc.lookupLevel + 1); 151710037SARM gem5 Developers Event *event = NULL; 151810037SARM gem5 Developers switch (currState->longDesc.lookupLevel) { 151910037SARM gem5 Developers case L1: 152010037SARM gem5 Developers assert(currState->aarch64); 152110037SARM gem5 Developers event = &doL1LongDescEvent; 152210037SARM gem5 Developers break; 152310037SARM gem5 Developers case L2: 152410037SARM gem5 Developers event = &doL2LongDescEvent; 152510037SARM gem5 Developers break; 152610037SARM gem5 Developers case L3: 152710037SARM gem5 Developers event = &doL3LongDescEvent; 152810037SARM gem5 Developers break; 152910037SARM gem5 Developers default: 153010037SARM gem5 Developers panic("Wrong lookup level in table walk\n"); 153110037SARM gem5 Developers break; 153210037SARM gem5 Developers } 153310037SARM gem5 Developers 153410037SARM gem5 Developers bool delayed; 153510037SARM gem5 Developers delayed = fetchDescriptor(next_desc_addr, (uint8_t*)&currState->longDesc.data, 153610037SARM gem5 Developers sizeof(uint64_t), flag, -1, event, 153710037SARM gem5 Developers &TableWalker::doLongDescriptor); 153810037SARM gem5 Developers if (delayed) { 153910037SARM gem5 Developers currState->delayed = true; 154010037SARM gem5 Developers } 15417404SAli.Saidi@ARM.com } 15427404SAli.Saidi@ARM.com return; 15437404SAli.Saidi@ARM.com default: 15447404SAli.Saidi@ARM.com panic("A new type in a 2 bit field?\n"); 15457404SAli.Saidi@ARM.com } 15467404SAli.Saidi@ARM.com} 15477404SAli.Saidi@ARM.com 15487404SAli.Saidi@ARM.comvoid 15497404SAli.Saidi@ARM.comTableWalker::doL2Descriptor() 15507404SAli.Saidi@ARM.com{ 155110037SARM gem5 Developers if (currState->fault != NoFault) { 155210037SARM gem5 Developers return; 155310037SARM gem5 Developers } 155410037SARM gem5 Developers 15557439Sdam.sunwoo@arm.com DPRINTF(TLB, "L2 descriptor for %#x is %#x\n", 155610037SARM gem5 Developers currState->vaddr_tainted, currState->l2Desc.data); 15577404SAli.Saidi@ARM.com TlbEntry te; 15587404SAli.Saidi@ARM.com 15597439Sdam.sunwoo@arm.com if (currState->l2Desc.invalid()) { 15607404SAli.Saidi@ARM.com DPRINTF(TLB, "L2 descriptor invalid, causing fault\n"); 15617946SGiacomo.Gabrielli@arm.com if (!currState->timing) { 15627439Sdam.sunwoo@arm.com currState->tc = NULL; 15637439Sdam.sunwoo@arm.com currState->req = NULL; 15647437Sdam.sunwoo@arm.com } 15657439Sdam.sunwoo@arm.com if (currState->isFetch) 15667439Sdam.sunwoo@arm.com currState->fault = 156710037SARM gem5 Developers new PrefetchAbort(currState->vaddr_tainted, 156810037SARM gem5 Developers ArmFault::TranslationLL + L2, 156910037SARM gem5 Developers isStage2, 157010037SARM gem5 Developers ArmFault::VmsaTran); 15717406SAli.Saidi@ARM.com else 15727439Sdam.sunwoo@arm.com currState->fault = 157310037SARM gem5 Developers new DataAbort(currState->vaddr_tainted, currState->l1Desc.domain(), 157410037SARM gem5 Developers currState->isWrite, ArmFault::TranslationLL + L2, 157510037SARM gem5 Developers isStage2, 157610037SARM gem5 Developers ArmFault::VmsaTran); 15777404SAli.Saidi@ARM.com return; 15787404SAli.Saidi@ARM.com } 15797404SAli.Saidi@ARM.com 15807439Sdam.sunwoo@arm.com if (currState->sctlr.afe && bits(currState->l2Desc.ap(), 0) == 0) { 15817436Sdam.sunwoo@arm.com /** @todo: check sctlr.ha (bit[17]) if Hardware Access Flag is enabled 15827436Sdam.sunwoo@arm.com * if set, do l2.Desc.setAp0() instead of generating AccessFlag0 15837436Sdam.sunwoo@arm.com */ 158410037SARM gem5 Developers DPRINTF(TLB, "Generating access fault at L2, afe: %d, ap: %d\n", 158510037SARM gem5 Developers currState->sctlr.afe, currState->l2Desc.ap()); 15867436Sdam.sunwoo@arm.com 15877439Sdam.sunwoo@arm.com currState->fault = 158810037SARM gem5 Developers new DataAbort(currState->vaddr_tainted, 158910037SARM gem5 Developers TlbEntry::DomainType::NoAccess, currState->isWrite, 159010037SARM gem5 Developers ArmFault::AccessFlagLL + L2, isStage2, 159110037SARM gem5 Developers ArmFault::VmsaTran); 15927436Sdam.sunwoo@arm.com } 15937436Sdam.sunwoo@arm.com 159410037SARM gem5 Developers insertTableEntry(currState->l2Desc, false); 15957437Sdam.sunwoo@arm.com} 15967437Sdam.sunwoo@arm.com 15977437Sdam.sunwoo@arm.comvoid 15987437Sdam.sunwoo@arm.comTableWalker::doL1DescriptorWrapper() 15997437Sdam.sunwoo@arm.com{ 160010037SARM gem5 Developers currState = stateQueues[L1].front(); 16017439Sdam.sunwoo@arm.com currState->delayed = false; 160210037SARM gem5 Developers // if there's a stage2 translation object we don't need it any more 160310037SARM gem5 Developers if (currState->stage2Tran) { 160410037SARM gem5 Developers delete currState->stage2Tran; 160510037SARM gem5 Developers currState->stage2Tran = NULL; 160610037SARM gem5 Developers } 160710037SARM gem5 Developers 16087437Sdam.sunwoo@arm.com 16097578Sdam.sunwoo@arm.com DPRINTF(TLBVerbose, "L1 Desc object host addr: %p\n",&currState->l1Desc.data); 16107578Sdam.sunwoo@arm.com DPRINTF(TLBVerbose, "L1 Desc object data: %08x\n",currState->l1Desc.data); 16117578Sdam.sunwoo@arm.com 161210037SARM gem5 Developers DPRINTF(TLBVerbose, "calling doL1Descriptor for vaddr:%#x\n", currState->vaddr_tainted); 16137437Sdam.sunwoo@arm.com doL1Descriptor(); 16147437Sdam.sunwoo@arm.com 161510037SARM gem5 Developers stateQueues[L1].pop_front(); 16169152Satgutier@umich.edu completeDrain(); 16177437Sdam.sunwoo@arm.com // Check if fault was generated 16187439Sdam.sunwoo@arm.com if (currState->fault != NoFault) { 16197439Sdam.sunwoo@arm.com currState->transState->finish(currState->fault, currState->req, 16207439Sdam.sunwoo@arm.com currState->tc, currState->mode); 16217437Sdam.sunwoo@arm.com 16227728SAli.Saidi@ARM.com pending = false; 16237728SAli.Saidi@ARM.com nextWalk(currState->tc); 16247728SAli.Saidi@ARM.com 16257439Sdam.sunwoo@arm.com currState->req = NULL; 16267439Sdam.sunwoo@arm.com currState->tc = NULL; 16277439Sdam.sunwoo@arm.com currState->delayed = false; 16288510SAli.Saidi@ARM.com delete currState; 16297437Sdam.sunwoo@arm.com } 16307439Sdam.sunwoo@arm.com else if (!currState->delayed) { 16317653Sgene.wu@arm.com // delay is not set so there is no L2 to do 163210037SARM gem5 Developers // Don't finish the translation if a stage 2 look up is underway 163310037SARM gem5 Developers if (!currState->doingStage2) { 163410037SARM gem5 Developers DPRINTF(TLBVerbose, "calling translateTiming again\n"); 163510037SARM gem5 Developers currState->fault = tlb->translateTiming(currState->req, currState->tc, 163610037SARM gem5 Developers currState->transState, currState->mode); 163710037SARM gem5 Developers } 16387437Sdam.sunwoo@arm.com 16397728SAli.Saidi@ARM.com pending = false; 16407728SAli.Saidi@ARM.com nextWalk(currState->tc); 16417728SAli.Saidi@ARM.com 16427439Sdam.sunwoo@arm.com currState->req = NULL; 16437439Sdam.sunwoo@arm.com currState->tc = NULL; 16447439Sdam.sunwoo@arm.com currState->delayed = false; 16457653Sgene.wu@arm.com delete currState; 16467653Sgene.wu@arm.com } else { 16477653Sgene.wu@arm.com // need to do L2 descriptor 164810037SARM gem5 Developers stateQueues[L2].push_back(currState); 16497437Sdam.sunwoo@arm.com } 16507439Sdam.sunwoo@arm.com currState = NULL; 16517437Sdam.sunwoo@arm.com} 16527437Sdam.sunwoo@arm.com 16537437Sdam.sunwoo@arm.comvoid 16547437Sdam.sunwoo@arm.comTableWalker::doL2DescriptorWrapper() 16557437Sdam.sunwoo@arm.com{ 165610037SARM gem5 Developers currState = stateQueues[L2].front(); 16577439Sdam.sunwoo@arm.com assert(currState->delayed); 165810037SARM gem5 Developers // if there's a stage2 translation object we don't need it any more 165910037SARM gem5 Developers if (currState->stage2Tran) { 166010037SARM gem5 Developers delete currState->stage2Tran; 166110037SARM gem5 Developers currState->stage2Tran = NULL; 166210037SARM gem5 Developers } 16637437Sdam.sunwoo@arm.com 16647439Sdam.sunwoo@arm.com DPRINTF(TLBVerbose, "calling doL2Descriptor for vaddr:%#x\n", 166510037SARM gem5 Developers currState->vaddr_tainted); 16667437Sdam.sunwoo@arm.com doL2Descriptor(); 16677437Sdam.sunwoo@arm.com 16687437Sdam.sunwoo@arm.com // Check if fault was generated 16697439Sdam.sunwoo@arm.com if (currState->fault != NoFault) { 16707439Sdam.sunwoo@arm.com currState->transState->finish(currState->fault, currState->req, 16717439Sdam.sunwoo@arm.com currState->tc, currState->mode); 16727437Sdam.sunwoo@arm.com } 16737437Sdam.sunwoo@arm.com else { 167410037SARM gem5 Developers // Don't finish the translation if a stage 2 look up is underway 167510037SARM gem5 Developers if (!currState->doingStage2) { 167610037SARM gem5 Developers DPRINTF(TLBVerbose, "calling translateTiming again\n"); 167710037SARM gem5 Developers currState->fault = tlb->translateTiming(currState->req, 167810037SARM gem5 Developers currState->tc, currState->transState, currState->mode); 167910037SARM gem5 Developers } 16807437Sdam.sunwoo@arm.com } 16817437Sdam.sunwoo@arm.com 16827728SAli.Saidi@ARM.com 168310037SARM gem5 Developers stateQueues[L2].pop_front(); 16849152Satgutier@umich.edu completeDrain(); 16857728SAli.Saidi@ARM.com pending = false; 16867728SAli.Saidi@ARM.com nextWalk(currState->tc); 16877728SAli.Saidi@ARM.com 16887439Sdam.sunwoo@arm.com currState->req = NULL; 16897439Sdam.sunwoo@arm.com currState->tc = NULL; 16907439Sdam.sunwoo@arm.com currState->delayed = false; 16917439Sdam.sunwoo@arm.com 16927653Sgene.wu@arm.com delete currState; 16937439Sdam.sunwoo@arm.com currState = NULL; 16947404SAli.Saidi@ARM.com} 16957404SAli.Saidi@ARM.com 16967728SAli.Saidi@ARM.comvoid 169710037SARM gem5 DevelopersTableWalker::doL0LongDescriptorWrapper() 169810037SARM gem5 Developers{ 169910037SARM gem5 Developers doLongDescriptorWrapper(L0); 170010037SARM gem5 Developers} 170110037SARM gem5 Developers 170210037SARM gem5 Developersvoid 170310037SARM gem5 DevelopersTableWalker::doL1LongDescriptorWrapper() 170410037SARM gem5 Developers{ 170510037SARM gem5 Developers doLongDescriptorWrapper(L1); 170610037SARM gem5 Developers} 170710037SARM gem5 Developers 170810037SARM gem5 Developersvoid 170910037SARM gem5 DevelopersTableWalker::doL2LongDescriptorWrapper() 171010037SARM gem5 Developers{ 171110037SARM gem5 Developers doLongDescriptorWrapper(L2); 171210037SARM gem5 Developers} 171310037SARM gem5 Developers 171410037SARM gem5 Developersvoid 171510037SARM gem5 DevelopersTableWalker::doL3LongDescriptorWrapper() 171610037SARM gem5 Developers{ 171710037SARM gem5 Developers doLongDescriptorWrapper(L3); 171810037SARM gem5 Developers} 171910037SARM gem5 Developers 172010037SARM gem5 Developersvoid 172110037SARM gem5 DevelopersTableWalker::doLongDescriptorWrapper(LookupLevel curr_lookup_level) 172210037SARM gem5 Developers{ 172310037SARM gem5 Developers currState = stateQueues[curr_lookup_level].front(); 172410037SARM gem5 Developers assert(curr_lookup_level == currState->longDesc.lookupLevel); 172510037SARM gem5 Developers currState->delayed = false; 172610037SARM gem5 Developers 172710037SARM gem5 Developers // if there's a stage2 translation object we don't need it any more 172810037SARM gem5 Developers if (currState->stage2Tran) { 172910037SARM gem5 Developers delete currState->stage2Tran; 173010037SARM gem5 Developers currState->stage2Tran = NULL; 173110037SARM gem5 Developers } 173210037SARM gem5 Developers 173310037SARM gem5 Developers DPRINTF(TLBVerbose, "calling doLongDescriptor for vaddr:%#x\n", 173410037SARM gem5 Developers currState->vaddr_tainted); 173510037SARM gem5 Developers doLongDescriptor(); 173610037SARM gem5 Developers 173710037SARM gem5 Developers stateQueues[curr_lookup_level].pop_front(); 173810037SARM gem5 Developers 173910037SARM gem5 Developers if (currState->fault != NoFault) { 174010037SARM gem5 Developers // A fault was generated 174110037SARM gem5 Developers currState->transState->finish(currState->fault, currState->req, 174210037SARM gem5 Developers currState->tc, currState->mode); 174310037SARM gem5 Developers 174410037SARM gem5 Developers pending = false; 174510037SARM gem5 Developers nextWalk(currState->tc); 174610037SARM gem5 Developers 174710037SARM gem5 Developers currState->req = NULL; 174810037SARM gem5 Developers currState->tc = NULL; 174910037SARM gem5 Developers currState->delayed = false; 175010037SARM gem5 Developers delete currState; 175110037SARM gem5 Developers } else if (!currState->delayed) { 175210037SARM gem5 Developers // No additional lookups required 175310037SARM gem5 Developers // Don't finish the translation if a stage 2 look up is underway 175410037SARM gem5 Developers if (!currState->doingStage2) { 175510037SARM gem5 Developers DPRINTF(TLBVerbose, "calling translateTiming again\n"); 175610037SARM gem5 Developers currState->fault = tlb->translateTiming(currState->req, currState->tc, 175710037SARM gem5 Developers currState->transState, 175810037SARM gem5 Developers currState->mode); 175910037SARM gem5 Developers } 176010037SARM gem5 Developers 176110037SARM gem5 Developers pending = false; 176210037SARM gem5 Developers nextWalk(currState->tc); 176310037SARM gem5 Developers 176410037SARM gem5 Developers currState->req = NULL; 176510037SARM gem5 Developers currState->tc = NULL; 176610037SARM gem5 Developers currState->delayed = false; 176710037SARM gem5 Developers delete currState; 176810037SARM gem5 Developers } else { 176910037SARM gem5 Developers if (curr_lookup_level >= MAX_LOOKUP_LEVELS - 1) 177010037SARM gem5 Developers panic("Max. number of lookups already reached in table walk\n"); 177110037SARM gem5 Developers // Need to perform additional lookups 177210037SARM gem5 Developers stateQueues[currState->longDesc.lookupLevel].push_back(currState); 177310037SARM gem5 Developers } 177410037SARM gem5 Developers currState = NULL; 177510037SARM gem5 Developers} 177610037SARM gem5 Developers 177710037SARM gem5 Developers 177810037SARM gem5 Developersvoid 17797728SAli.Saidi@ARM.comTableWalker::nextWalk(ThreadContext *tc) 17807728SAli.Saidi@ARM.com{ 17817728SAli.Saidi@ARM.com if (pendingQueue.size()) 17829309Sandreas.hansson@arm.com schedule(doProcessEvent, clockEdge(Cycles(1))); 17837728SAli.Saidi@ARM.com} 17847728SAli.Saidi@ARM.com 178510037SARM gem5 Developersbool 178610037SARM gem5 DevelopersTableWalker::fetchDescriptor(Addr descAddr, uint8_t *data, int numBytes, 178710037SARM gem5 Developers Request::Flags flags, int queueIndex, Event *event, 178810037SARM gem5 Developers void (TableWalker::*doDescriptor)()) 178910037SARM gem5 Developers{ 179010037SARM gem5 Developers bool isTiming = currState->timing; 17917728SAli.Saidi@ARM.com 179210037SARM gem5 Developers // do the requests for the page table descriptors have to go through the 179310037SARM gem5 Developers // second stage MMU 179410037SARM gem5 Developers if (currState->stage2Req) { 179510037SARM gem5 Developers Fault fault; 179610037SARM gem5 Developers flags = flags | TLB::MustBeOne; 179710037SARM gem5 Developers 179810037SARM gem5 Developers if (isTiming) { 179910037SARM gem5 Developers Stage2MMU::Stage2Translation *tran = new 180010037SARM gem5 Developers Stage2MMU::Stage2Translation(*stage2Mmu, data, event, 180110037SARM gem5 Developers currState->vaddr); 180210037SARM gem5 Developers currState->stage2Tran = tran; 180310037SARM gem5 Developers stage2Mmu->readDataTimed(currState->tc, descAddr, tran, numBytes, 180410037SARM gem5 Developers flags, masterId); 180510037SARM gem5 Developers fault = tran->fault; 180610037SARM gem5 Developers } else { 180710037SARM gem5 Developers fault = stage2Mmu->readDataUntimed(currState->tc, 180810037SARM gem5 Developers currState->vaddr, descAddr, data, numBytes, flags, masterId, 180910037SARM gem5 Developers currState->functional); 181010037SARM gem5 Developers } 181110037SARM gem5 Developers 181210037SARM gem5 Developers if (fault != NoFault) { 181310037SARM gem5 Developers currState->fault = fault; 181410037SARM gem5 Developers } 181510037SARM gem5 Developers if (isTiming) { 181610037SARM gem5 Developers if (queueIndex >= 0) { 181710037SARM gem5 Developers DPRINTF(TLBVerbose, "Adding to walker fifo: queue size before adding: %d\n", 181810037SARM gem5 Developers stateQueues[queueIndex].size()); 181910037SARM gem5 Developers stateQueues[queueIndex].push_back(currState); 182010037SARM gem5 Developers currState = NULL; 182110037SARM gem5 Developers } 182210037SARM gem5 Developers } else { 182310037SARM gem5 Developers (this->*doDescriptor)(); 182410037SARM gem5 Developers } 182510037SARM gem5 Developers } else { 182610037SARM gem5 Developers if (isTiming) { 182710037SARM gem5 Developers port.dmaAction(MemCmd::ReadReq, descAddr, numBytes, event, data, 182810037SARM gem5 Developers currState->tc->getCpuPtr()->clockPeriod(), flags); 182910037SARM gem5 Developers if (queueIndex >= 0) { 183010037SARM gem5 Developers DPRINTF(TLBVerbose, "Adding to walker fifo: queue size before adding: %d\n", 183110037SARM gem5 Developers stateQueues[queueIndex].size()); 183210037SARM gem5 Developers stateQueues[queueIndex].push_back(currState); 183310037SARM gem5 Developers currState = NULL; 183410037SARM gem5 Developers } 183510037SARM gem5 Developers } else if (!currState->functional) { 183610037SARM gem5 Developers port.dmaAction(MemCmd::ReadReq, descAddr, numBytes, NULL, data, 183710037SARM gem5 Developers currState->tc->getCpuPtr()->clockPeriod(), flags); 183810037SARM gem5 Developers (this->*doDescriptor)(); 183910037SARM gem5 Developers } else { 184010037SARM gem5 Developers RequestPtr req = new Request(descAddr, numBytes, flags, masterId); 184110037SARM gem5 Developers req->taskId(ContextSwitchTaskId::DMA); 184210037SARM gem5 Developers PacketPtr pkt = new Packet(req, MemCmd::ReadReq); 184310037SARM gem5 Developers pkt->dataStatic(data); 184410037SARM gem5 Developers port.sendFunctional(pkt); 184510037SARM gem5 Developers (this->*doDescriptor)(); 184610037SARM gem5 Developers delete req; 184710037SARM gem5 Developers delete pkt; 184810037SARM gem5 Developers } 184910037SARM gem5 Developers } 185010037SARM gem5 Developers return (isTiming); 185110037SARM gem5 Developers} 185210037SARM gem5 Developers 185310037SARM gem5 Developersvoid 185410037SARM gem5 DevelopersTableWalker::insertTableEntry(DescriptorBase &descriptor, bool longDescriptor) 185510037SARM gem5 Developers{ 185610037SARM gem5 Developers TlbEntry te; 185710037SARM gem5 Developers 185810037SARM gem5 Developers // Create and fill a new page table entry 185910037SARM gem5 Developers te.valid = true; 186010037SARM gem5 Developers te.longDescFormat = longDescriptor; 186110037SARM gem5 Developers te.isHyp = currState->isHyp; 186210037SARM gem5 Developers te.asid = currState->asid; 186310037SARM gem5 Developers te.vmid = currState->vmid; 186410037SARM gem5 Developers te.N = descriptor.offsetBits(); 186510037SARM gem5 Developers te.vpn = currState->vaddr >> te.N; 186610037SARM gem5 Developers te.size = (1<<te.N) - 1; 186710037SARM gem5 Developers te.pfn = descriptor.pfn(); 186810037SARM gem5 Developers te.domain = descriptor.domain(); 186910037SARM gem5 Developers te.lookupLevel = descriptor.lookupLevel; 187010037SARM gem5 Developers te.ns = !descriptor.secure(haveSecurity, currState) || isStage2; 187110037SARM gem5 Developers te.nstid = !currState->isSecure; 187210037SARM gem5 Developers te.xn = descriptor.xn(); 187310037SARM gem5 Developers if (currState->aarch64) 187410037SARM gem5 Developers te.el = currState->el; 187510037SARM gem5 Developers else 187610037SARM gem5 Developers te.el = 1; 187710037SARM gem5 Developers 187810037SARM gem5 Developers // ASID has no meaning for stage 2 TLB entries, so mark all stage 2 entries 187910037SARM gem5 Developers // as global 188010037SARM gem5 Developers te.global = descriptor.global(currState) || isStage2; 188110037SARM gem5 Developers if (longDescriptor) { 188210037SARM gem5 Developers LongDescriptor lDescriptor = 188310037SARM gem5 Developers dynamic_cast<LongDescriptor &>(descriptor); 188410037SARM gem5 Developers 188510037SARM gem5 Developers te.xn |= currState->xnTable; 188610037SARM gem5 Developers te.pxn = currState->pxnTable || lDescriptor.pxn(); 188710037SARM gem5 Developers if (isStage2) { 188810037SARM gem5 Developers // this is actually the HAP field, but its stored in the same bit 188910037SARM gem5 Developers // possitions as the AP field in a stage 1 translation. 189010037SARM gem5 Developers te.hap = lDescriptor.ap(); 189110037SARM gem5 Developers } else { 189210037SARM gem5 Developers te.ap = ((!currState->rwTable || descriptor.ap() >> 1) << 1) | 189310037SARM gem5 Developers (currState->userTable && (descriptor.ap() & 0x1)); 189410037SARM gem5 Developers } 189510037SARM gem5 Developers if (currState->aarch64) 189610037SARM gem5 Developers memAttrsAArch64(currState->tc, te, currState->longDesc.attrIndx(), 189710037SARM gem5 Developers currState->longDesc.sh()); 189810037SARM gem5 Developers else 189910037SARM gem5 Developers memAttrsLPAE(currState->tc, te, lDescriptor); 190010037SARM gem5 Developers } else { 190110037SARM gem5 Developers te.ap = descriptor.ap(); 190210037SARM gem5 Developers memAttrs(currState->tc, te, currState->sctlr, descriptor.texcb(), 190310037SARM gem5 Developers descriptor.shareable()); 190410037SARM gem5 Developers } 190510037SARM gem5 Developers 190610037SARM gem5 Developers // Debug output 190710037SARM gem5 Developers DPRINTF(TLB, descriptor.dbgHeader().c_str()); 190810037SARM gem5 Developers DPRINTF(TLB, " - N:%d pfn:%#x size:%#x global:%d valid:%d\n", 190910037SARM gem5 Developers te.N, te.pfn, te.size, te.global, te.valid); 191010037SARM gem5 Developers DPRINTF(TLB, " - vpn:%#x xn:%d pxn:%d ap:%d domain:%d asid:%d " 191110037SARM gem5 Developers "vmid:%d hyp:%d nc:%d ns:%d\n", te.vpn, te.xn, te.pxn, 191210037SARM gem5 Developers te.ap, static_cast<uint8_t>(te.domain), te.asid, te.vmid, te.isHyp, 191310037SARM gem5 Developers te.nonCacheable, te.ns); 191410037SARM gem5 Developers DPRINTF(TLB, " - domain from L%d desc:%d data:%#x\n", 191510037SARM gem5 Developers descriptor.lookupLevel, static_cast<uint8_t>(descriptor.domain()), 191610037SARM gem5 Developers descriptor.getRawData()); 191710037SARM gem5 Developers 191810037SARM gem5 Developers // Insert the entry into the TLB 191910037SARM gem5 Developers tlb->insert(currState->vaddr, te); 192010037SARM gem5 Developers if (!currState->timing) { 192110037SARM gem5 Developers currState->tc = NULL; 192210037SARM gem5 Developers currState->req = NULL; 192310037SARM gem5 Developers } 192410037SARM gem5 Developers} 19257728SAli.Saidi@ARM.com 19267404SAli.Saidi@ARM.comArmISA::TableWalker * 19277404SAli.Saidi@ARM.comArmTableWalkerParams::create() 19287404SAli.Saidi@ARM.com{ 19297404SAli.Saidi@ARM.com return new ArmISA::TableWalker(this); 19307404SAli.Saidi@ARM.com} 19317404SAli.Saidi@ARM.com 193210037SARM gem5 DevelopersLookupLevel 193310037SARM gem5 DevelopersTableWalker::toLookupLevel(uint8_t lookup_level_as_int) 193410037SARM gem5 Developers{ 193510037SARM gem5 Developers switch (lookup_level_as_int) { 193610037SARM gem5 Developers case L1: 193710037SARM gem5 Developers return L1; 193810037SARM gem5 Developers case L2: 193910037SARM gem5 Developers return L2; 194010037SARM gem5 Developers case L3: 194110037SARM gem5 Developers return L3; 194210037SARM gem5 Developers default: 194310037SARM gem5 Developers panic("Invalid lookup level conversion"); 194410037SARM gem5 Developers } 194510037SARM gem5 Developers} 1946