table_walker.cc revision 7653:968302e54850
1955SN/A/* 2955SN/A * Copyright (c) 2010 ARM Limited 31762SN/A * All rights reserved 4955SN/A * 5955SN/A * The license below extends only to copyright in the software and shall 6955SN/A * not be construed as granting a license to any other intellectual 7955SN/A * property including but not limited to intellectual property relating 8955SN/A * to a hardware implementation of the functionality of the software 9955SN/A * licensed hereunder. You may use the software subject to the license 10955SN/A * terms below provided that you ensure that this notice is replicated 11955SN/A * unmodified and in its entirety in all distributions of the software, 12955SN/A * modified or unmodified, in source code or in binary form. 13955SN/A * 14955SN/A * Redistribution and use in source and binary forms, with or without 15955SN/A * modification, are permitted provided that the following conditions are 16955SN/A * met: redistributions of source code must retain the above copyright 17955SN/A * notice, this list of conditions and the following disclaimer; 18955SN/A * redistributions in binary form must reproduce the above copyright 19955SN/A * notice, this list of conditions and the following disclaimer in the 20955SN/A * documentation and/or other materials provided with the distribution; 21955SN/A * neither the name of the copyright holders nor the names of its 22955SN/A * contributors may be used to endorse or promote products derived from 23955SN/A * this software without specific prior written permission. 24955SN/A * 25955SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 26955SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 27955SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 282665Ssaidi@eecs.umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 292665Ssaidi@eecs.umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 30955SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 31955SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 32955SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 33955SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 34955SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 352632Sstever@eecs.umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 362632Sstever@eecs.umich.edu * 372632Sstever@eecs.umich.edu * Authors: Ali Saidi 382632Sstever@eecs.umich.edu */ 39955SN/A 402632Sstever@eecs.umich.edu#include "arch/arm/faults.hh" 412632Sstever@eecs.umich.edu#include "arch/arm/table_walker.hh" 422632Sstever@eecs.umich.edu#include "arch/arm/tlb.hh" 432632Sstever@eecs.umich.edu#include "dev/io_device.hh" 442632Sstever@eecs.umich.edu#include "cpu/thread_context.hh" 452632Sstever@eecs.umich.edu 462632Sstever@eecs.umich.eduusing namespace ArmISA; 472632Sstever@eecs.umich.edu 482632Sstever@eecs.umich.eduTableWalker::TableWalker(const Params *p) 492632Sstever@eecs.umich.edu : MemObject(p), port(NULL), tlb(NULL), 502632Sstever@eecs.umich.edu currState(NULL), doL1DescEvent(this), doL2DescEvent(this) 512632Sstever@eecs.umich.edu{ 522632Sstever@eecs.umich.edu sctlr = 0; 532632Sstever@eecs.umich.edu} 542632Sstever@eecs.umich.edu 552632Sstever@eecs.umich.eduTableWalker::~TableWalker() 562632Sstever@eecs.umich.edu{ 572632Sstever@eecs.umich.edu ; 582632Sstever@eecs.umich.edu} 592632Sstever@eecs.umich.edu 60955SN/A 61955SN/Aunsigned int 62955SN/Adrain(Event *de) 63955SN/A{ 64955SN/A panic("Not implemented\n"); 65955SN/A} 66955SN/A 672656Sstever@eecs.umich.eduPort* 682656Sstever@eecs.umich.eduTableWalker::getPort(const std::string &if_name, int idx) 692656Sstever@eecs.umich.edu{ 702656Sstever@eecs.umich.edu if (if_name == "port") { 712656Sstever@eecs.umich.edu if (port != NULL) 722656Sstever@eecs.umich.edu fatal("%s: port already connected to %s", 732656Sstever@eecs.umich.edu name(), port->getPeer()->name()); 742653Sstever@eecs.umich.edu System *sys = params()->sys; 752653Sstever@eecs.umich.edu Tick minb = params()->min_backoff; 762653Sstever@eecs.umich.edu Tick maxb = params()->max_backoff; 772653Sstever@eecs.umich.edu port = new DmaPort(this, sys, minb, maxb); 782653Sstever@eecs.umich.edu return port; 792653Sstever@eecs.umich.edu } 802653Sstever@eecs.umich.edu return NULL; 812653Sstever@eecs.umich.edu} 822653Sstever@eecs.umich.edu 832653Sstever@eecs.umich.eduFault 842653Sstever@eecs.umich.eduTableWalker::walk(RequestPtr _req, ThreadContext *_tc, uint8_t _cid, TLB::Mode _mode, 851852SN/A TLB::Translation *_trans, bool _timing) 86955SN/A{ 87955SN/A if (!currState) { 88955SN/A // For atomic mode, a new WalkerState instance should be only created 892632Sstever@eecs.umich.edu // once per TLB. For timing mode, a new instance is generated for every 902632Sstever@eecs.umich.edu // TLB miss. 91955SN/A DPRINTF(TLBVerbose, "creating new instance of WalkerState\n"); 921533SN/A 932632Sstever@eecs.umich.edu currState = new WalkerState(); 941533SN/A currState->tableWalker = this; 95955SN/A } 96955SN/A else if (_timing) { 972632Sstever@eecs.umich.edu panic("currState should always be empty in timing mode!\n"); 982632Sstever@eecs.umich.edu } 99955SN/A 100955SN/A currState->tc = _tc; 101955SN/A currState->transState = _trans; 102955SN/A currState->req = _req; 1032632Sstever@eecs.umich.edu currState->fault = NoFault; 104955SN/A currState->contextId = _cid; 1052632Sstever@eecs.umich.edu currState->timing = _timing; 106955SN/A currState->mode = _mode; 107955SN/A 1082632Sstever@eecs.umich.edu /** @todo These should be cached or grabbed from cached copies in 1092632Sstever@eecs.umich.edu the TLB, all these miscreg reads are expensive */ 1102632Sstever@eecs.umich.edu currState->vaddr = currState->req->getVaddr() & ~PcModeMask; 1112632Sstever@eecs.umich.edu currState->sctlr = currState->tc->readMiscReg(MISCREG_SCTLR); 1122632Sstever@eecs.umich.edu sctlr = currState->sctlr; 1132632Sstever@eecs.umich.edu currState->cpsr = currState->tc->readMiscReg(MISCREG_CPSR); 1142632Sstever@eecs.umich.edu currState->N = currState->tc->readMiscReg(MISCREG_TTBCR); 1152632Sstever@eecs.umich.edu 1162632Sstever@eecs.umich.edu currState->isFetch = (currState->mode == TLB::Execute); 1172632Sstever@eecs.umich.edu currState->isWrite = (currState->mode == TLB::Write); 1182632Sstever@eecs.umich.edu currState->isPriv = (currState->cpsr.mode != MODE_USER); 1192632Sstever@eecs.umich.edu 1202632Sstever@eecs.umich.edu Addr ttbr = 0; 1212632Sstever@eecs.umich.edu 1222632Sstever@eecs.umich.edu // If translation isn't enabled, we shouldn't be here 1232632Sstever@eecs.umich.edu assert(currState->sctlr.m); 1242632Sstever@eecs.umich.edu 1252634Sstever@eecs.umich.edu DPRINTF(TLB, "Begining table walk for address %#x, TTBCR: %#x, bits:%#x\n", 1262634Sstever@eecs.umich.edu currState->vaddr, currState->N, mbits(currState->vaddr, 31, 1272632Sstever@eecs.umich.edu 32-currState->N)); 1282638Sstever@eecs.umich.edu 1292632Sstever@eecs.umich.edu if (currState->N == 0 || !mbits(currState->vaddr, 31, 32-currState->N)) { 1302632Sstever@eecs.umich.edu DPRINTF(TLB, " - Selecting TTBR0\n"); 1312632Sstever@eecs.umich.edu ttbr = currState->tc->readMiscReg(MISCREG_TTBR0); 1322632Sstever@eecs.umich.edu } else { 1332632Sstever@eecs.umich.edu DPRINTF(TLB, " - Selecting TTBR1\n"); 1342632Sstever@eecs.umich.edu ttbr = currState->tc->readMiscReg(MISCREG_TTBR1); 1351858SN/A currState->N = 0; 1362638Sstever@eecs.umich.edu } 1372638Sstever@eecs.umich.edu 1382638Sstever@eecs.umich.edu Addr l1desc_addr = mbits(ttbr, 31, 14-currState->N) | 1392638Sstever@eecs.umich.edu (bits(currState->vaddr,31-currState->N,20) << 2); 1402638Sstever@eecs.umich.edu DPRINTF(TLB, " - Descriptor at address %#x\n", l1desc_addr); 1412638Sstever@eecs.umich.edu 1422638Sstever@eecs.umich.edu 1432638Sstever@eecs.umich.edu // Trickbox address check 1442634Sstever@eecs.umich.edu Fault f; 1452634Sstever@eecs.umich.edu f = tlb->walkTrickBoxCheck(l1desc_addr, currState->vaddr, sizeof(uint32_t), 1462634Sstever@eecs.umich.edu currState->isFetch, currState->isWrite, 0, true); 147955SN/A if (f) { 148955SN/A if (currState->timing) { 149955SN/A currState->transState->finish(f, currState->req, 150955SN/A currState->tc, currState->mode); 151955SN/A currState = NULL; 152955SN/A } else { 153955SN/A currState->tc = NULL; 154955SN/A currState->req = NULL; 1551858SN/A } 1561858SN/A return f; 1572632Sstever@eecs.umich.edu } 158955SN/A 1591858SN/A if (currState->timing) { 1601105SN/A port->dmaAction(MemCmd::ReadReq, l1desc_addr, sizeof(uint32_t), 1611869SN/A &doL1DescEvent, (uint8_t*)&currState->l1Desc.data, (Tick)0); 1621869SN/A DPRINTF(TLBVerbose, "Adding to walker fifo: queue size before adding: %d\n", 1631869SN/A stateQueueL1.size()); 1641869SN/A stateQueueL1.push_back(currState); 1651869SN/A currState = NULL; 1661065SN/A } else { 1672632Sstever@eecs.umich.edu Request::Flags flag = 0; 1682632Sstever@eecs.umich.edu if (currState->sctlr.c == 0){ 169955SN/A flag = Request::UNCACHEABLE; 1701858SN/A } 1711858SN/A port->dmaAction(MemCmd::ReadReq, l1desc_addr, sizeof(uint32_t), 1721858SN/A NULL, (uint8_t*)&currState->l1Desc.data, (Tick)0, flag); 1731858SN/A doL1Descriptor(); 1741851SN/A f = currState->fault; 1751851SN/A } 1761858SN/A 1772632Sstever@eecs.umich.edu return f; 178955SN/A} 1792656Sstever@eecs.umich.edu 1802656Sstever@eecs.umich.eduvoid 1812656Sstever@eecs.umich.eduTableWalker::memAttrs(ThreadContext *tc, TlbEntry &te, SCTLR sctlr, 1822656Sstever@eecs.umich.edu uint8_t texcb, bool s) 1832656Sstever@eecs.umich.edu{ 1842656Sstever@eecs.umich.edu // Note: tc and sctlr local variables are hiding tc and sctrl class 1852656Sstever@eecs.umich.edu // variables 1862656Sstever@eecs.umich.edu DPRINTF(TLBVerbose, "memAttrs texcb:%d s:%d\n", texcb, s); 1872656Sstever@eecs.umich.edu te.shareable = false; // default value 1882656Sstever@eecs.umich.edu te.nonCacheable = false; 1892656Sstever@eecs.umich.edu bool outer_shareable = false; 1902656Sstever@eecs.umich.edu if (sctlr.tre == 0 || ((sctlr.tre == 1) && (sctlr.m == 0))) { 1912656Sstever@eecs.umich.edu switch(texcb) { 1922656Sstever@eecs.umich.edu case 0: // Stongly-ordered 1932656Sstever@eecs.umich.edu te.nonCacheable = true; 1942656Sstever@eecs.umich.edu te.mtype = TlbEntry::StronglyOrdered; 1952655Sstever@eecs.umich.edu te.shareable = true; 1962655Sstever@eecs.umich.edu te.innerAttrs = 1; 1971858SN/A te.outerAttrs = 0; 1981858SN/A break; 1992638Sstever@eecs.umich.edu case 1: // Shareable Device 2002638Sstever@eecs.umich.edu te.nonCacheable = true; 2012638Sstever@eecs.umich.edu te.mtype = TlbEntry::Device; 2022638Sstever@eecs.umich.edu te.shareable = true; 2032638Sstever@eecs.umich.edu te.innerAttrs = 3; 2041858SN/A te.outerAttrs = 0; 2051858SN/A break; 2061858SN/A case 2: // Outer and Inner Write-Through, no Write-Allocate 2071858SN/A te.mtype = TlbEntry::Normal; 2081858SN/A te.shareable = s; 2091858SN/A te.innerAttrs = 6; 2101858SN/A te.outerAttrs = bits(texcb, 1, 0); 2111859SN/A break; 2121858SN/A case 3: // Outer and Inner Write-Back, no Write-Allocate 2131858SN/A te.mtype = TlbEntry::Normal; 2141858SN/A te.shareable = s; 2151859SN/A te.innerAttrs = 7; 2161859SN/A te.outerAttrs = bits(texcb, 1, 0); 2171862SN/A break; 2181862SN/A case 4: // Outer and Inner Non-cacheable 2191862SN/A te.nonCacheable = true; 2201862SN/A te.mtype = TlbEntry::Normal; 2211859SN/A te.shareable = s; 2221859SN/A te.innerAttrs = 0; 2231963SN/A te.outerAttrs = bits(texcb, 1, 0); 2241963SN/A break; 2251859SN/A case 5: // Reserved 2261859SN/A panic("Reserved texcb value!\n"); 2271859SN/A break; 2281859SN/A case 6: // Implementation Defined 2291859SN/A panic("Implementation-defined texcb value!\n"); 2301859SN/A break; 2311859SN/A case 7: // Outer and Inner Write-Back, Write-Allocate 2321859SN/A te.mtype = TlbEntry::Normal; 2331862SN/A te.shareable = s; 2341859SN/A te.innerAttrs = 5; 2351859SN/A te.outerAttrs = 1; 2361859SN/A break; 2371858SN/A case 8: // Non-shareable Device 2381858SN/A te.nonCacheable = true; 2392139SN/A te.mtype = TlbEntry::Device; 2402139SN/A te.shareable = false; 2412139SN/A te.innerAttrs = 3; 2422155SN/A te.outerAttrs = 0; 2432623SN/A break; 2442637Sstever@eecs.umich.edu case 9 ... 15: // Reserved 2452155SN/A panic("Reserved texcb value!\n"); 2461869SN/A break; 2471869SN/A case 16 ... 31: // Cacheable Memory 2481869SN/A te.mtype = TlbEntry::Normal; 2491869SN/A te.shareable = s; 2501869SN/A if (bits(texcb, 1,0) == 0 || bits(texcb, 3,2) == 0) 2512139SN/A te.nonCacheable = true; 2521869SN/A te.innerAttrs = bits(texcb, 1, 0); 2532508SN/A te.outerAttrs = bits(texcb, 3, 2); 2542508SN/A break; 2552508SN/A default: 2562508SN/A panic("More than 32 states for 5 bits?\n"); 2572635Sstever@eecs.umich.edu } 2582635Sstever@eecs.umich.edu } else { 2591869SN/A assert(tc); 2601869SN/A PRRR prrr = tc->readMiscReg(MISCREG_PRRR); 2611869SN/A NMRR nmrr = tc->readMiscReg(MISCREG_NMRR); 2621869SN/A DPRINTF(TLBVerbose, "memAttrs PRRR:%08x NMRR:%08x\n", prrr, nmrr); 2631869SN/A uint8_t curr_tr = 0, curr_ir = 0, curr_or = 0; 2641869SN/A switch(bits(texcb, 2,0)) { 2651869SN/A case 0: 2661869SN/A curr_tr = prrr.tr0; 2671965SN/A curr_ir = nmrr.ir0; 2681965SN/A curr_or = nmrr.or0; 2691965SN/A outer_shareable = (prrr.nos0 == 0); 2701869SN/A break; 2711869SN/A case 1: 2721869SN/A curr_tr = prrr.tr1; 2731869SN/A curr_ir = nmrr.ir1; 2741884SN/A curr_or = nmrr.or1; 2751884SN/A outer_shareable = (prrr.nos1 == 0); 2761884SN/A break; 2771869SN/A case 2: 2781858SN/A curr_tr = prrr.tr2; 2791869SN/A curr_ir = nmrr.ir2; 2801869SN/A curr_or = nmrr.or2; 2811869SN/A outer_shareable = (prrr.nos2 == 0); 2821869SN/A break; 2831869SN/A case 3: 2841858SN/A curr_tr = prrr.tr3; 2851869SN/A curr_ir = nmrr.ir3; 2861869SN/A curr_or = nmrr.or3; 2871869SN/A outer_shareable = (prrr.nos3 == 0); 2881869SN/A break; 2891869SN/A case 4: 2901869SN/A curr_tr = prrr.tr4; 2911869SN/A curr_ir = nmrr.ir4; 2921869SN/A curr_or = nmrr.or4; 2931869SN/A outer_shareable = (prrr.nos4 == 0); 2941869SN/A break; 2951858SN/A case 5: 296955SN/A curr_tr = prrr.tr5; 297955SN/A curr_ir = nmrr.ir5; 2981869SN/A curr_or = nmrr.or5; 2991869SN/A outer_shareable = (prrr.nos5 == 0); 3001869SN/A break; 3011869SN/A case 6: 3021869SN/A panic("Imp defined type\n"); 3031869SN/A case 7: 3041869SN/A curr_tr = prrr.tr7; 3051869SN/A curr_ir = nmrr.ir7; 3061869SN/A curr_or = nmrr.or7; 3071869SN/A outer_shareable = (prrr.nos7 == 0); 3081869SN/A break; 3091869SN/A } 3101869SN/A 3111869SN/A switch(curr_tr) { 3121869SN/A case 0: 3131869SN/A DPRINTF(TLBVerbose, "StronglyOrdered\n"); 3141869SN/A te.mtype = TlbEntry::StronglyOrdered; 3151869SN/A te.nonCacheable = true; 3161869SN/A te.innerAttrs = 1; 3171869SN/A te.outerAttrs = 0; 3181869SN/A te.shareable = true; 3191869SN/A break; 3201869SN/A case 1: 3211869SN/A DPRINTF(TLBVerbose, "Device ds1:%d ds0:%d s:%d\n", 3221869SN/A prrr.ds1, prrr.ds0, s); 3231869SN/A te.mtype = TlbEntry::Device; 3241869SN/A te.nonCacheable = true; 3251869SN/A te.innerAttrs = 3; 3261869SN/A te.outerAttrs = 0; 3271869SN/A if (prrr.ds1 && s) 3281869SN/A te.shareable = true; 3291869SN/A if (prrr.ds0 && !s) 3301869SN/A te.shareable = true; 3311869SN/A break; 3321869SN/A case 2: 3331869SN/A DPRINTF(TLBVerbose, "Normal ns1:%d ns0:%d s:%d\n", 3341869SN/A prrr.ns1, prrr.ns0, s); 3351869SN/A te.mtype = TlbEntry::Normal; 3361869SN/A if (prrr.ns1 && s) 3372655Sstever@eecs.umich.edu te.shareable = true; 3382655Sstever@eecs.umich.edu if (prrr.ns0 && !s) 3392655Sstever@eecs.umich.edu te.shareable = true; 3402655Sstever@eecs.umich.edu break; 3412655Sstever@eecs.umich.edu case 3: 3422655Sstever@eecs.umich.edu panic("Reserved type"); 3432655Sstever@eecs.umich.edu } 3442655Sstever@eecs.umich.edu 3452655Sstever@eecs.umich.edu if (te.mtype == TlbEntry::Normal){ 3462655Sstever@eecs.umich.edu switch(curr_ir) { 3472655Sstever@eecs.umich.edu case 0: 3482655Sstever@eecs.umich.edu te.nonCacheable = true; 3492655Sstever@eecs.umich.edu te.innerAttrs = 0; 3502655Sstever@eecs.umich.edu break; 3512655Sstever@eecs.umich.edu case 1: 3522655Sstever@eecs.umich.edu te.innerAttrs = 5; 3532655Sstever@eecs.umich.edu break; 3542655Sstever@eecs.umich.edu case 2: 3552655Sstever@eecs.umich.edu te.innerAttrs = 6; 3562655Sstever@eecs.umich.edu break; 3572655Sstever@eecs.umich.edu case 3: 3582655Sstever@eecs.umich.edu te.innerAttrs = 7; 3592655Sstever@eecs.umich.edu break; 3602655Sstever@eecs.umich.edu } 3612655Sstever@eecs.umich.edu 3622655Sstever@eecs.umich.edu switch(curr_or) { 3632634Sstever@eecs.umich.edu case 0: 3642634Sstever@eecs.umich.edu te.nonCacheable = true; 3652634Sstever@eecs.umich.edu te.outerAttrs = 0; 3662634Sstever@eecs.umich.edu break; 3672634Sstever@eecs.umich.edu case 1: 3682634Sstever@eecs.umich.edu te.outerAttrs = 1; 3692638Sstever@eecs.umich.edu break; 3702638Sstever@eecs.umich.edu case 2: 3712638Sstever@eecs.umich.edu te.outerAttrs = 2; 3722638Sstever@eecs.umich.edu break; 3732638Sstever@eecs.umich.edu case 3: 3741869SN/A te.outerAttrs = 3; 3751869SN/A break; 376955SN/A } 377955SN/A } 378955SN/A } 379955SN/A DPRINTF(TLBVerbose, "memAttrs: shareable: %d, innerAttrs: %d, \ 3801858SN/A outerAttrs: %d\n", 3811858SN/A te.shareable, te.innerAttrs, te.outerAttrs); 3821858SN/A 3832632Sstever@eecs.umich.edu /** Formatting for Physical Address Register (PAR) 3842632Sstever@eecs.umich.edu * Only including lower bits (TLB info here) 3852632Sstever@eecs.umich.edu * PAR: 3862632Sstever@eecs.umich.edu * PA [31:12] 3872632Sstever@eecs.umich.edu * Reserved [11] 3882634Sstever@eecs.umich.edu * TLB info [10:1] 3892638Sstever@eecs.umich.edu * NOS [10] (Not Outer Sharable) 3902023SN/A * NS [9] (Non-Secure) 3912632Sstever@eecs.umich.edu * -- [8] (Implementation Defined) 3922632Sstever@eecs.umich.edu * SH [7] (Sharable) 3932632Sstever@eecs.umich.edu * Inner[6:4](Inner memory attributes) 3942632Sstever@eecs.umich.edu * Outer[3:2](Outer memory attributes) 3952632Sstever@eecs.umich.edu * SS [1] (SuperSection) 3962632Sstever@eecs.umich.edu * F [0] (Fault, Fault Status in [6:1] if faulted) 3972632Sstever@eecs.umich.edu */ 3982632Sstever@eecs.umich.edu te.attributes = ( 3992632Sstever@eecs.umich.edu ((outer_shareable ? 0:1) << 10) | 4002632Sstever@eecs.umich.edu // TODO: NS Bit 4012632Sstever@eecs.umich.edu ((te.shareable ? 1:0) << 7) | 4022023SN/A (te.innerAttrs << 4) | 4032632Sstever@eecs.umich.edu (te.outerAttrs << 2) 4042632Sstever@eecs.umich.edu // TODO: Supersection bit 4051889SN/A // TODO: Fault bit 4061889SN/A ); 4072632Sstever@eecs.umich.edu 4082632Sstever@eecs.umich.edu 4092632Sstever@eecs.umich.edu} 4102632Sstever@eecs.umich.edu 4112632Sstever@eecs.umich.eduvoid 4122632Sstever@eecs.umich.eduTableWalker::doL1Descriptor() 4132632Sstever@eecs.umich.edu{ 4142632Sstever@eecs.umich.edu DPRINTF(TLB, "L1 descriptor for %#x is %#x\n", 4152632Sstever@eecs.umich.edu currState->vaddr, currState->l1Desc.data); 4162632Sstever@eecs.umich.edu TlbEntry te; 4172632Sstever@eecs.umich.edu 4182632Sstever@eecs.umich.edu switch (currState->l1Desc.type()) { 4192632Sstever@eecs.umich.edu case L1Descriptor::Ignore: 4202632Sstever@eecs.umich.edu case L1Descriptor::Reserved: 4211888SN/A if (!currState->delayed) { 4221888SN/A currState->tc = NULL; 4231869SN/A currState->req = NULL; 4241869SN/A } 4251858SN/A DPRINTF(TLB, "L1 Descriptor Reserved/Ignore, causing fault\n"); 4262598SN/A if (currState->isFetch) 4272598SN/A currState->fault = 4282598SN/A new PrefetchAbort(currState->vaddr, ArmFault::Translation0); 4292598SN/A else 4302598SN/A currState->fault = 4311858SN/A new DataAbort(currState->vaddr, 0, currState->isWrite, 4321858SN/A ArmFault::Translation0); 4331858SN/A return; 4341858SN/A case L1Descriptor::Section: 4351858SN/A if (currState->sctlr.afe && bits(currState->l1Desc.ap(), 0) == 0) { 4361858SN/A /** @todo: check sctlr.ha (bit[17]) if Hardware Access Flag is 4371858SN/A * enabled if set, do l1.Desc.setAp0() instead of generating 4381858SN/A * AccessFlag0 4391858SN/A */ 4401871SN/A 4411858SN/A currState->fault = new DataAbort(currState->vaddr, 4421858SN/A currState->l1Desc.domain(), currState->isWrite, 4431858SN/A ArmFault::AccessFlag0); 4441858SN/A } 4451858SN/A if (currState->l1Desc.supersection()) { 4461858SN/A panic("Haven't implemented supersections\n"); 4471858SN/A } 4481858SN/A te.N = 20; 4491858SN/A te.pfn = currState->l1Desc.pfn(); 4501858SN/A te.size = (1<<te.N) - 1; 4511858SN/A te.global = !currState->l1Desc.global(); 4521859SN/A te.valid = true; 4531859SN/A te.vpn = currState->vaddr >> te.N; 4541869SN/A te.sNp = true; 4551888SN/A te.xn = currState->l1Desc.xn(); 4562632Sstever@eecs.umich.edu te.ap = currState->l1Desc.ap(); 4571869SN/A te.domain = currState->l1Desc.domain(); 4581884SN/A te.asid = currState->contextId; 4591884SN/A memAttrs(currState->tc, te, currState->sctlr, 4601884SN/A currState->l1Desc.texcb(), currState->l1Desc.shareable()); 4611884SN/A 4621884SN/A DPRINTF(TLB, "Inserting Section Descriptor into TLB\n"); 4631884SN/A DPRINTF(TLB, " - N:%d pfn:%#x size: %#x global:%d valid: %d\n", 4641965SN/A te.N, te.pfn, te.size, te.global, te.valid); 4651965SN/A DPRINTF(TLB, " - vpn:%#x sNp: %d xn:%d ap:%d domain: %d asid:%d nc:%d\n", 4661965SN/A te.vpn, te.sNp, te.xn, te.ap, te.domain, te.asid, 467955SN/A te.nonCacheable); 4681869SN/A DPRINTF(TLB, " - domain from l1 desc: %d data: %#x bits:%d\n", 4691869SN/A currState->l1Desc.domain(), currState->l1Desc.data, 4702632Sstever@eecs.umich.edu (currState->l1Desc.data >> 5) & 0xF ); 4711869SN/A 4721869SN/A if (!currState->timing) { 4731869SN/A currState->tc = NULL; 4742632Sstever@eecs.umich.edu currState->req = NULL; 4752632Sstever@eecs.umich.edu } 4762632Sstever@eecs.umich.edu tlb->insert(currState->vaddr, te); 4772632Sstever@eecs.umich.edu 478955SN/A return; 4792598SN/A case L1Descriptor::PageTable: 4802598SN/A Addr l2desc_addr; 481955SN/A l2desc_addr = currState->l1Desc.l2Addr() | 482955SN/A (bits(currState->vaddr, 19,12) << 2); 483955SN/A DPRINTF(TLB, "L1 descriptor points to page table at: %#x\n", 4841530SN/A l2desc_addr); 485955SN/A 486955SN/A // Trickbox address check 487955SN/A currState->fault = tlb->walkTrickBoxCheck(l2desc_addr, currState->vaddr, 488 sizeof(uint32_t), currState->isFetch, currState->isWrite, 489 currState->l1Desc.domain(), false); 490 491 if (currState->fault) { 492 if (!currState->timing) { 493 currState->tc = NULL; 494 currState->req = NULL; 495 } 496 return; 497 } 498 499 500 if (currState->timing) { 501 currState->delayed = true; 502 port->dmaAction(MemCmd::ReadReq, l2desc_addr, sizeof(uint32_t), 503 &doL2DescEvent, (uint8_t*)&currState->l2Desc.data, 0); 504 } else { 505 port->dmaAction(MemCmd::ReadReq, l2desc_addr, sizeof(uint32_t), 506 NULL, (uint8_t*)&currState->l2Desc.data, 0); 507 doL2Descriptor(); 508 } 509 return; 510 default: 511 panic("A new type in a 2 bit field?\n"); 512 } 513} 514 515void 516TableWalker::doL2Descriptor() 517{ 518 DPRINTF(TLB, "L2 descriptor for %#x is %#x\n", 519 currState->vaddr, currState->l2Desc.data); 520 TlbEntry te; 521 522 if (currState->l2Desc.invalid()) { 523 DPRINTF(TLB, "L2 descriptor invalid, causing fault\n"); 524 if (!currState->delayed) { 525 currState->tc = NULL; 526 currState->req = NULL; 527 } 528 if (currState->isFetch) 529 currState->fault = 530 new PrefetchAbort(currState->vaddr, ArmFault::Translation1); 531 else 532 currState->fault = 533 new DataAbort(currState->vaddr, currState->l1Desc.domain(), 534 currState->isWrite, ArmFault::Translation1); 535 return; 536 } 537 538 if (currState->sctlr.afe && bits(currState->l2Desc.ap(), 0) == 0) { 539 /** @todo: check sctlr.ha (bit[17]) if Hardware Access Flag is enabled 540 * if set, do l2.Desc.setAp0() instead of generating AccessFlag0 541 */ 542 543 currState->fault = 544 new DataAbort(currState->vaddr, 0, currState->isWrite, 545 ArmFault::AccessFlag1); 546 547 } 548 549 if (currState->l2Desc.large()) { 550 te.N = 16; 551 te.pfn = currState->l2Desc.pfn(); 552 } else { 553 te.N = 12; 554 te.pfn = currState->l2Desc.pfn(); 555 } 556 557 te.valid = true; 558 te.size = (1 << te.N) - 1; 559 te.asid = currState->contextId; 560 te.sNp = false; 561 te.vpn = currState->vaddr >> te.N; 562 te.global = currState->l2Desc.global(); 563 te.xn = currState->l2Desc.xn(); 564 te.ap = currState->l2Desc.ap(); 565 te.domain = currState->l1Desc.domain(); 566 memAttrs(currState->tc, te, currState->sctlr, currState->l2Desc.texcb(), 567 currState->l2Desc.shareable()); 568 569 if (!currState->delayed) { 570 currState->tc = NULL; 571 currState->req = NULL; 572 } 573 tlb->insert(currState->vaddr, te); 574} 575 576void 577TableWalker::doL1DescriptorWrapper() 578{ 579 currState = stateQueueL1.front(); 580 currState->delayed = false; 581 582 DPRINTF(TLBVerbose, "L1 Desc object host addr: %p\n",&currState->l1Desc.data); 583 DPRINTF(TLBVerbose, "L1 Desc object data: %08x\n",currState->l1Desc.data); 584 585 DPRINTF(TLBVerbose, "calling doL1Descriptor for vaddr:%#x\n", currState->vaddr); 586 doL1Descriptor(); 587 588 stateQueueL1.pop_front(); 589 // Check if fault was generated 590 if (currState->fault != NoFault) { 591 currState->transState->finish(currState->fault, currState->req, 592 currState->tc, currState->mode); 593 594 currState->req = NULL; 595 currState->tc = NULL; 596 currState->delayed = false; 597 598 } 599 else if (!currState->delayed) { 600 // delay is not set so there is no L2 to do 601 DPRINTF(TLBVerbose, "calling translateTiming again\n"); 602 currState->fault = tlb->translateTiming(currState->req, currState->tc, 603 currState->transState, currState->mode); 604 605 currState->req = NULL; 606 currState->tc = NULL; 607 currState->delayed = false; 608 609 delete currState; 610 } else { 611 // need to do L2 descriptor 612 stateQueueL2.push_back(currState); 613 } 614 currState = NULL; 615} 616 617void 618TableWalker::doL2DescriptorWrapper() 619{ 620 currState = stateQueueL2.front(); 621 assert(currState->delayed); 622 623 DPRINTF(TLBVerbose, "calling doL2Descriptor for vaddr:%#x\n", 624 currState->vaddr); 625 doL2Descriptor(); 626 627 // Check if fault was generated 628 if (currState->fault != NoFault) { 629 currState->transState->finish(currState->fault, currState->req, 630 currState->tc, currState->mode); 631 } 632 else { 633 DPRINTF(TLBVerbose, "calling translateTiming again\n"); 634 currState->fault = tlb->translateTiming(currState->req, currState->tc, 635 currState->transState, currState->mode); 636 } 637 638 currState->req = NULL; 639 currState->tc = NULL; 640 currState->delayed = false; 641 642 stateQueueL2.pop_front(); 643 delete currState; 644 currState = NULL; 645} 646 647ArmISA::TableWalker * 648ArmTableWalkerParams::create() 649{ 650 return new ArmISA::TableWalker(this); 651} 652 653