pagetable_walker.cc revision 8922
15245Sgblack@eecs.umich.edu/* 25245Sgblack@eecs.umich.edu * Copyright (c) 2007 The Hewlett-Packard Development Company 35245Sgblack@eecs.umich.edu * All rights reserved. 45245Sgblack@eecs.umich.edu * 57087Snate@binkert.org * The license below extends only to copyright in the software and shall 67087Snate@binkert.org * not be construed as granting a license to any other intellectual 77087Snate@binkert.org * property including but not limited to intellectual property relating 87087Snate@binkert.org * to a hardware implementation of the functionality of the software 97087Snate@binkert.org * licensed hereunder. You may use the software subject to the license 107087Snate@binkert.org * terms below provided that you ensure that this notice is replicated 117087Snate@binkert.org * unmodified and in its entirety in all distributions of the software, 127087Snate@binkert.org * modified or unmodified, in source code or in binary form. 135245Sgblack@eecs.umich.edu * 147087Snate@binkert.org * Redistribution and use in source and binary forms, with or without 157087Snate@binkert.org * modification, are permitted provided that the following conditions are 167087Snate@binkert.org * met: redistributions of source code must retain the above copyright 177087Snate@binkert.org * notice, this list of conditions and the following disclaimer; 187087Snate@binkert.org * redistributions in binary form must reproduce the above copyright 197087Snate@binkert.org * notice, this list of conditions and the following disclaimer in the 207087Snate@binkert.org * documentation and/or other materials provided with the distribution; 217087Snate@binkert.org * neither the name of the copyright holders nor the names of its 225245Sgblack@eecs.umich.edu * contributors may be used to endorse or promote products derived from 237087Snate@binkert.org * this software without specific prior written permission. 245245Sgblack@eecs.umich.edu * 255245Sgblack@eecs.umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 265245Sgblack@eecs.umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 275245Sgblack@eecs.umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 285245Sgblack@eecs.umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 295245Sgblack@eecs.umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 305245Sgblack@eecs.umich.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 315245Sgblack@eecs.umich.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 325245Sgblack@eecs.umich.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 335245Sgblack@eecs.umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 345245Sgblack@eecs.umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 355245Sgblack@eecs.umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 365245Sgblack@eecs.umich.edu * 375245Sgblack@eecs.umich.edu * Authors: Gabe Black 385245Sgblack@eecs.umich.edu */ 395245Sgblack@eecs.umich.edu 405245Sgblack@eecs.umich.edu#include "arch/x86/pagetable.hh" 415245Sgblack@eecs.umich.edu#include "arch/x86/pagetable_walker.hh" 425245Sgblack@eecs.umich.edu#include "arch/x86/tlb.hh" 437912Shestness@cs.utexas.edu#include "arch/x86/vtophys.hh" 445245Sgblack@eecs.umich.edu#include "base/bitfield.hh" 458229Snate@binkert.org#include "cpu/base.hh" 465245Sgblack@eecs.umich.edu#include "cpu/thread_context.hh" 478232Snate@binkert.org#include "debug/PageTableWalker.hh" 485245Sgblack@eecs.umich.edu#include "mem/packet_access.hh" 495245Sgblack@eecs.umich.edu#include "mem/request.hh" 505245Sgblack@eecs.umich.edu#include "sim/system.hh" 515245Sgblack@eecs.umich.edu 525245Sgblack@eecs.umich.edunamespace X86ISA { 535245Sgblack@eecs.umich.edu 545245Sgblack@eecs.umich.edu// Unfortunately, the placement of the base field in a page table entry is 555245Sgblack@eecs.umich.edu// very erratic and would make a mess here. It might be moved here at some 565245Sgblack@eecs.umich.edu// point in the future. 575245Sgblack@eecs.umich.eduBitUnion64(PageTableEntry) 585245Sgblack@eecs.umich.edu Bitfield<63> nx; 595245Sgblack@eecs.umich.edu Bitfield<11, 9> avl; 605245Sgblack@eecs.umich.edu Bitfield<8> g; 615245Sgblack@eecs.umich.edu Bitfield<7> ps; 625245Sgblack@eecs.umich.edu Bitfield<6> d; 635245Sgblack@eecs.umich.edu Bitfield<5> a; 645245Sgblack@eecs.umich.edu Bitfield<4> pcd; 655245Sgblack@eecs.umich.edu Bitfield<3> pwt; 665245Sgblack@eecs.umich.edu Bitfield<2> u; 675245Sgblack@eecs.umich.edu Bitfield<1> w; 685245Sgblack@eecs.umich.edu Bitfield<0> p; 695245Sgblack@eecs.umich.eduEndBitUnion(PageTableEntry) 705245Sgblack@eecs.umich.edu 715895Sgblack@eecs.umich.eduFault 727912Shestness@cs.utexas.eduWalker::start(ThreadContext * _tc, BaseTLB::Translation *_translation, 737912Shestness@cs.utexas.edu RequestPtr _req, BaseTLB::Mode _mode) 745245Sgblack@eecs.umich.edu{ 757912Shestness@cs.utexas.edu // TODO: in timing mode, instead of blocking when there are other 767912Shestness@cs.utexas.edu // outstanding requests, see if this request can be coalesced with 777912Shestness@cs.utexas.edu // another one (i.e. either coalesce or start walk) 787912Shestness@cs.utexas.edu WalkerState * newState = new WalkerState(this, _translation, _req); 797912Shestness@cs.utexas.edu newState->initState(_tc, _mode, sys->getMemoryMode() == Enums::timing); 807912Shestness@cs.utexas.edu if (currStates.size()) { 817912Shestness@cs.utexas.edu assert(newState->isTiming()); 827912Shestness@cs.utexas.edu DPRINTF(PageTableWalker, "Walks in progress: %d\n", currStates.size()); 837912Shestness@cs.utexas.edu currStates.push_back(newState); 847912Shestness@cs.utexas.edu return NoFault; 857912Shestness@cs.utexas.edu } else { 867912Shestness@cs.utexas.edu currStates.push_back(newState); 877912Shestness@cs.utexas.edu Fault fault = newState->startWalk(); 887912Shestness@cs.utexas.edu if (!newState->isTiming()) { 897912Shestness@cs.utexas.edu currStates.pop_front(); 907912Shestness@cs.utexas.edu delete newState; 915895Sgblack@eecs.umich.edu } 927912Shestness@cs.utexas.edu return fault; 935245Sgblack@eecs.umich.edu } 945245Sgblack@eecs.umich.edu} 955245Sgblack@eecs.umich.edu 965895Sgblack@eecs.umich.eduFault 977912Shestness@cs.utexas.eduWalker::startFunctional(ThreadContext * _tc, Addr &addr, Addr &pageSize, 987912Shestness@cs.utexas.edu BaseTLB::Mode _mode) 995245Sgblack@eecs.umich.edu{ 1007912Shestness@cs.utexas.edu funcState.initState(_tc, _mode); 1017912Shestness@cs.utexas.edu return funcState.startFunctional(addr, pageSize); 1025245Sgblack@eecs.umich.edu} 1035245Sgblack@eecs.umich.edu 1045245Sgblack@eecs.umich.edubool 1055245Sgblack@eecs.umich.eduWalker::WalkerPort::recvTiming(PacketPtr pkt) 1065245Sgblack@eecs.umich.edu{ 1075245Sgblack@eecs.umich.edu return walker->recvTiming(pkt); 1085245Sgblack@eecs.umich.edu} 1095245Sgblack@eecs.umich.edu 1105245Sgblack@eecs.umich.edubool 1115245Sgblack@eecs.umich.eduWalker::recvTiming(PacketPtr pkt) 1125245Sgblack@eecs.umich.edu{ 1137912Shestness@cs.utexas.edu if (pkt->isResponse() || pkt->wasNacked()) { 1147912Shestness@cs.utexas.edu WalkerSenderState * senderState = 1157912Shestness@cs.utexas.edu dynamic_cast<WalkerSenderState *>(pkt->senderState); 1167912Shestness@cs.utexas.edu pkt->senderState = senderState->saved; 1177912Shestness@cs.utexas.edu WalkerState * senderWalk = senderState->senderWalk; 1187912Shestness@cs.utexas.edu bool walkComplete = senderWalk->recvPacket(pkt); 1197912Shestness@cs.utexas.edu delete senderState; 1207912Shestness@cs.utexas.edu if (walkComplete) { 1217912Shestness@cs.utexas.edu std::list<WalkerState *>::iterator iter; 1227912Shestness@cs.utexas.edu for (iter = currStates.begin(); iter != currStates.end(); iter++) { 1237912Shestness@cs.utexas.edu WalkerState * walkerState = *(iter); 1247912Shestness@cs.utexas.edu if (walkerState == senderWalk) { 1257912Shestness@cs.utexas.edu iter = currStates.erase(iter); 1267912Shestness@cs.utexas.edu break; 1277912Shestness@cs.utexas.edu } 1285245Sgblack@eecs.umich.edu } 1297912Shestness@cs.utexas.edu delete senderWalk; 1307912Shestness@cs.utexas.edu // Since we block requests when another is outstanding, we 1317912Shestness@cs.utexas.edu // need to check if there is a waiting request to be serviced 1327912Shestness@cs.utexas.edu if (currStates.size()) { 1337912Shestness@cs.utexas.edu WalkerState * newState = currStates.front(); 1347912Shestness@cs.utexas.edu if (!newState->wasStarted()) 1357912Shestness@cs.utexas.edu newState->startWalk(); 1365895Sgblack@eecs.umich.edu } 1375245Sgblack@eecs.umich.edu } 1387912Shestness@cs.utexas.edu } else { 1397912Shestness@cs.utexas.edu DPRINTF(PageTableWalker, "Received strange packet\n"); 1405245Sgblack@eecs.umich.edu } 1415245Sgblack@eecs.umich.edu return true; 1425245Sgblack@eecs.umich.edu} 1435245Sgblack@eecs.umich.edu 1445245Sgblack@eecs.umich.eduTick 1455245Sgblack@eecs.umich.eduWalker::WalkerPort::recvAtomic(PacketPtr pkt) 1465245Sgblack@eecs.umich.edu{ 1475245Sgblack@eecs.umich.edu return 0; 1485245Sgblack@eecs.umich.edu} 1495245Sgblack@eecs.umich.edu 1505245Sgblack@eecs.umich.eduvoid 1515245Sgblack@eecs.umich.eduWalker::WalkerPort::recvFunctional(PacketPtr pkt) 1525245Sgblack@eecs.umich.edu{ 1535245Sgblack@eecs.umich.edu return; 1545245Sgblack@eecs.umich.edu} 1555245Sgblack@eecs.umich.edu 1565245Sgblack@eecs.umich.eduvoid 1575245Sgblack@eecs.umich.eduWalker::WalkerPort::recvRetry() 1585245Sgblack@eecs.umich.edu{ 1595245Sgblack@eecs.umich.edu walker->recvRetry(); 1605245Sgblack@eecs.umich.edu} 1615245Sgblack@eecs.umich.edu 1625245Sgblack@eecs.umich.eduvoid 1635245Sgblack@eecs.umich.eduWalker::recvRetry() 1645245Sgblack@eecs.umich.edu{ 1657912Shestness@cs.utexas.edu std::list<WalkerState *>::iterator iter; 1667912Shestness@cs.utexas.edu for (iter = currStates.begin(); iter != currStates.end(); iter++) { 1677912Shestness@cs.utexas.edu WalkerState * walkerState = *(iter); 1687912Shestness@cs.utexas.edu if (walkerState->isRetrying()) { 1697912Shestness@cs.utexas.edu walkerState->retry(); 1707912Shestness@cs.utexas.edu } 1717912Shestness@cs.utexas.edu } 1727912Shestness@cs.utexas.edu} 1737912Shestness@cs.utexas.edu 1747912Shestness@cs.utexas.edubool Walker::sendTiming(WalkerState* sendingState, PacketPtr pkt) 1757912Shestness@cs.utexas.edu{ 1767912Shestness@cs.utexas.edu pkt->senderState = new WalkerSenderState(sendingState, pkt->senderState); 1777912Shestness@cs.utexas.edu return port.sendTiming(pkt); 1787912Shestness@cs.utexas.edu} 1797912Shestness@cs.utexas.edu 1808922Swilliam.wang@arm.comMasterPort & 1818922Swilliam.wang@arm.comWalker::getMasterPort(const std::string &if_name, int idx) 1827912Shestness@cs.utexas.edu{ 1837912Shestness@cs.utexas.edu if (if_name == "port") 1848922Swilliam.wang@arm.com return port; 1857912Shestness@cs.utexas.edu else 1868922Swilliam.wang@arm.com return MemObject::getMasterPort(if_name, idx); 1875245Sgblack@eecs.umich.edu} 1885245Sgblack@eecs.umich.edu 1895245Sgblack@eecs.umich.eduvoid 1907912Shestness@cs.utexas.eduWalker::WalkerState::initState(ThreadContext * _tc, 1917912Shestness@cs.utexas.edu BaseTLB::Mode _mode, bool _isTiming) 1927912Shestness@cs.utexas.edu{ 1937912Shestness@cs.utexas.edu assert(state == Ready); 1947912Shestness@cs.utexas.edu started = false; 1957912Shestness@cs.utexas.edu tc = _tc; 1967912Shestness@cs.utexas.edu mode = _mode; 1977912Shestness@cs.utexas.edu timing = _isTiming; 1987912Shestness@cs.utexas.edu} 1997912Shestness@cs.utexas.edu 2007912Shestness@cs.utexas.eduFault 2017912Shestness@cs.utexas.eduWalker::WalkerState::startWalk() 2027912Shestness@cs.utexas.edu{ 2037912Shestness@cs.utexas.edu Fault fault = NoFault; 2047912Shestness@cs.utexas.edu assert(started == false); 2057912Shestness@cs.utexas.edu started = true; 2067912Shestness@cs.utexas.edu setupWalk(req->getVaddr()); 2077912Shestness@cs.utexas.edu if (timing) { 2087912Shestness@cs.utexas.edu nextState = state; 2097912Shestness@cs.utexas.edu state = Waiting; 2107912Shestness@cs.utexas.edu timingFault = NoFault; 2117912Shestness@cs.utexas.edu sendPackets(); 2127912Shestness@cs.utexas.edu } else { 2137912Shestness@cs.utexas.edu do { 2147912Shestness@cs.utexas.edu walker->port.sendAtomic(read); 2157912Shestness@cs.utexas.edu PacketPtr write = NULL; 2167912Shestness@cs.utexas.edu fault = stepWalk(write); 2177912Shestness@cs.utexas.edu assert(fault == NoFault || read == NULL); 2187912Shestness@cs.utexas.edu state = nextState; 2197912Shestness@cs.utexas.edu nextState = Ready; 2207912Shestness@cs.utexas.edu if (write) 2217912Shestness@cs.utexas.edu walker->port.sendAtomic(write); 2227912Shestness@cs.utexas.edu } while(read); 2237912Shestness@cs.utexas.edu state = Ready; 2247912Shestness@cs.utexas.edu nextState = Waiting; 2257912Shestness@cs.utexas.edu } 2267912Shestness@cs.utexas.edu return fault; 2277912Shestness@cs.utexas.edu} 2287912Shestness@cs.utexas.edu 2297912Shestness@cs.utexas.eduFault 2307912Shestness@cs.utexas.eduWalker::WalkerState::startFunctional(Addr &addr, Addr &pageSize) 2317912Shestness@cs.utexas.edu{ 2327912Shestness@cs.utexas.edu Fault fault = NoFault; 2337912Shestness@cs.utexas.edu assert(started == false); 2347912Shestness@cs.utexas.edu started = true; 2357912Shestness@cs.utexas.edu setupWalk(addr); 2367912Shestness@cs.utexas.edu 2377912Shestness@cs.utexas.edu do { 2387912Shestness@cs.utexas.edu walker->port.sendFunctional(read); 2397912Shestness@cs.utexas.edu // On a functional access (page table lookup), writes should 2407912Shestness@cs.utexas.edu // not happen so this pointer is ignored after stepWalk 2417912Shestness@cs.utexas.edu PacketPtr write = NULL; 2427912Shestness@cs.utexas.edu fault = stepWalk(write); 2437912Shestness@cs.utexas.edu assert(fault == NoFault || read == NULL); 2447912Shestness@cs.utexas.edu state = nextState; 2457912Shestness@cs.utexas.edu nextState = Ready; 2467912Shestness@cs.utexas.edu } while(read); 2477912Shestness@cs.utexas.edu pageSize = entry.size; 2487912Shestness@cs.utexas.edu addr = entry.paddr; 2497912Shestness@cs.utexas.edu 2507912Shestness@cs.utexas.edu return fault; 2517912Shestness@cs.utexas.edu} 2527912Shestness@cs.utexas.edu 2537912Shestness@cs.utexas.eduFault 2547912Shestness@cs.utexas.eduWalker::WalkerState::stepWalk(PacketPtr &write) 2557912Shestness@cs.utexas.edu{ 2567912Shestness@cs.utexas.edu assert(state != Ready && state != Waiting); 2577912Shestness@cs.utexas.edu Fault fault = NoFault; 2587912Shestness@cs.utexas.edu write = NULL; 2597912Shestness@cs.utexas.edu PageTableEntry pte; 2607912Shestness@cs.utexas.edu if (dataSize == 8) 2617912Shestness@cs.utexas.edu pte = read->get<uint64_t>(); 2627912Shestness@cs.utexas.edu else 2637912Shestness@cs.utexas.edu pte = read->get<uint32_t>(); 2647912Shestness@cs.utexas.edu VAddr vaddr = entry.vaddr; 2657912Shestness@cs.utexas.edu bool uncacheable = pte.pcd; 2667912Shestness@cs.utexas.edu Addr nextRead = 0; 2677912Shestness@cs.utexas.edu bool doWrite = false; 2687912Shestness@cs.utexas.edu bool doTLBInsert = false; 2697912Shestness@cs.utexas.edu bool doEndWalk = false; 2707912Shestness@cs.utexas.edu bool badNX = pte.nx && mode == BaseTLB::Execute && enableNX; 2717912Shestness@cs.utexas.edu switch(state) { 2727912Shestness@cs.utexas.edu case LongPML4: 2737912Shestness@cs.utexas.edu DPRINTF(PageTableWalker, 2747912Shestness@cs.utexas.edu "Got long mode PML4 entry %#016x.\n", (uint64_t)pte); 2757912Shestness@cs.utexas.edu nextRead = ((uint64_t)pte & (mask(40) << 12)) + vaddr.longl3 * dataSize; 2767912Shestness@cs.utexas.edu doWrite = !pte.a; 2777912Shestness@cs.utexas.edu pte.a = 1; 2787912Shestness@cs.utexas.edu entry.writable = pte.w; 2797912Shestness@cs.utexas.edu entry.user = pte.u; 2807912Shestness@cs.utexas.edu if (badNX || !pte.p) { 2817912Shestness@cs.utexas.edu doEndWalk = true; 2827912Shestness@cs.utexas.edu fault = pageFault(pte.p); 2837912Shestness@cs.utexas.edu break; 2847912Shestness@cs.utexas.edu } 2857912Shestness@cs.utexas.edu entry.noExec = pte.nx; 2867912Shestness@cs.utexas.edu nextState = LongPDP; 2877912Shestness@cs.utexas.edu break; 2887912Shestness@cs.utexas.edu case LongPDP: 2897912Shestness@cs.utexas.edu DPRINTF(PageTableWalker, 2907912Shestness@cs.utexas.edu "Got long mode PDP entry %#016x.\n", (uint64_t)pte); 2917912Shestness@cs.utexas.edu nextRead = ((uint64_t)pte & (mask(40) << 12)) + vaddr.longl2 * dataSize; 2927912Shestness@cs.utexas.edu doWrite = !pte.a; 2937912Shestness@cs.utexas.edu pte.a = 1; 2947912Shestness@cs.utexas.edu entry.writable = entry.writable && pte.w; 2957912Shestness@cs.utexas.edu entry.user = entry.user && pte.u; 2967912Shestness@cs.utexas.edu if (badNX || !pte.p) { 2977912Shestness@cs.utexas.edu doEndWalk = true; 2987912Shestness@cs.utexas.edu fault = pageFault(pte.p); 2997912Shestness@cs.utexas.edu break; 3007912Shestness@cs.utexas.edu } 3017912Shestness@cs.utexas.edu nextState = LongPD; 3027912Shestness@cs.utexas.edu break; 3037912Shestness@cs.utexas.edu case LongPD: 3047912Shestness@cs.utexas.edu DPRINTF(PageTableWalker, 3057912Shestness@cs.utexas.edu "Got long mode PD entry %#016x.\n", (uint64_t)pte); 3067912Shestness@cs.utexas.edu doWrite = !pte.a; 3077912Shestness@cs.utexas.edu pte.a = 1; 3087912Shestness@cs.utexas.edu entry.writable = entry.writable && pte.w; 3097912Shestness@cs.utexas.edu entry.user = entry.user && pte.u; 3107912Shestness@cs.utexas.edu if (badNX || !pte.p) { 3117912Shestness@cs.utexas.edu doEndWalk = true; 3127912Shestness@cs.utexas.edu fault = pageFault(pte.p); 3137912Shestness@cs.utexas.edu break; 3147912Shestness@cs.utexas.edu } 3157912Shestness@cs.utexas.edu if (!pte.ps) { 3167912Shestness@cs.utexas.edu // 4 KB page 3177912Shestness@cs.utexas.edu entry.size = 4 * (1 << 10); 3187912Shestness@cs.utexas.edu nextRead = 3197912Shestness@cs.utexas.edu ((uint64_t)pte & (mask(40) << 12)) + vaddr.longl1 * dataSize; 3207912Shestness@cs.utexas.edu nextState = LongPTE; 3217912Shestness@cs.utexas.edu break; 3227912Shestness@cs.utexas.edu } else { 3237912Shestness@cs.utexas.edu // 2 MB page 3247912Shestness@cs.utexas.edu entry.size = 2 * (1 << 20); 3257912Shestness@cs.utexas.edu entry.paddr = (uint64_t)pte & (mask(31) << 21); 3267912Shestness@cs.utexas.edu entry.uncacheable = uncacheable; 3277912Shestness@cs.utexas.edu entry.global = pte.g; 3287912Shestness@cs.utexas.edu entry.patBit = bits(pte, 12); 3297912Shestness@cs.utexas.edu entry.vaddr = entry.vaddr & ~((2 * (1 << 20)) - 1); 3307912Shestness@cs.utexas.edu doTLBInsert = true; 3317912Shestness@cs.utexas.edu doEndWalk = true; 3327912Shestness@cs.utexas.edu break; 3337912Shestness@cs.utexas.edu } 3347912Shestness@cs.utexas.edu case LongPTE: 3357912Shestness@cs.utexas.edu DPRINTF(PageTableWalker, 3367912Shestness@cs.utexas.edu "Got long mode PTE entry %#016x.\n", (uint64_t)pte); 3377912Shestness@cs.utexas.edu doWrite = !pte.a; 3387912Shestness@cs.utexas.edu pte.a = 1; 3397912Shestness@cs.utexas.edu entry.writable = entry.writable && pte.w; 3407912Shestness@cs.utexas.edu entry.user = entry.user && pte.u; 3417912Shestness@cs.utexas.edu if (badNX || !pte.p) { 3427912Shestness@cs.utexas.edu doEndWalk = true; 3437912Shestness@cs.utexas.edu fault = pageFault(pte.p); 3447912Shestness@cs.utexas.edu break; 3457912Shestness@cs.utexas.edu } 3467912Shestness@cs.utexas.edu entry.paddr = (uint64_t)pte & (mask(40) << 12); 3477912Shestness@cs.utexas.edu entry.uncacheable = uncacheable; 3487912Shestness@cs.utexas.edu entry.global = pte.g; 3497912Shestness@cs.utexas.edu entry.patBit = bits(pte, 12); 3507912Shestness@cs.utexas.edu entry.vaddr = entry.vaddr & ~((4 * (1 << 10)) - 1); 3517912Shestness@cs.utexas.edu doTLBInsert = true; 3527912Shestness@cs.utexas.edu doEndWalk = true; 3537912Shestness@cs.utexas.edu break; 3547912Shestness@cs.utexas.edu case PAEPDP: 3557912Shestness@cs.utexas.edu DPRINTF(PageTableWalker, 3567912Shestness@cs.utexas.edu "Got legacy mode PAE PDP entry %#08x.\n", (uint32_t)pte); 3577912Shestness@cs.utexas.edu nextRead = ((uint64_t)pte & (mask(40) << 12)) + vaddr.pael2 * dataSize; 3587912Shestness@cs.utexas.edu if (!pte.p) { 3597912Shestness@cs.utexas.edu doEndWalk = true; 3607912Shestness@cs.utexas.edu fault = pageFault(pte.p); 3617912Shestness@cs.utexas.edu break; 3627912Shestness@cs.utexas.edu } 3637912Shestness@cs.utexas.edu nextState = PAEPD; 3647912Shestness@cs.utexas.edu break; 3657912Shestness@cs.utexas.edu case PAEPD: 3667912Shestness@cs.utexas.edu DPRINTF(PageTableWalker, 3677912Shestness@cs.utexas.edu "Got legacy mode PAE PD entry %#08x.\n", (uint32_t)pte); 3687912Shestness@cs.utexas.edu doWrite = !pte.a; 3697912Shestness@cs.utexas.edu pte.a = 1; 3707912Shestness@cs.utexas.edu entry.writable = pte.w; 3717912Shestness@cs.utexas.edu entry.user = pte.u; 3727912Shestness@cs.utexas.edu if (badNX || !pte.p) { 3737912Shestness@cs.utexas.edu doEndWalk = true; 3747912Shestness@cs.utexas.edu fault = pageFault(pte.p); 3757912Shestness@cs.utexas.edu break; 3767912Shestness@cs.utexas.edu } 3777912Shestness@cs.utexas.edu if (!pte.ps) { 3787912Shestness@cs.utexas.edu // 4 KB page 3797912Shestness@cs.utexas.edu entry.size = 4 * (1 << 10); 3807912Shestness@cs.utexas.edu nextRead = ((uint64_t)pte & (mask(40) << 12)) + vaddr.pael1 * dataSize; 3817912Shestness@cs.utexas.edu nextState = PAEPTE; 3827912Shestness@cs.utexas.edu break; 3837912Shestness@cs.utexas.edu } else { 3847912Shestness@cs.utexas.edu // 2 MB page 3857912Shestness@cs.utexas.edu entry.size = 2 * (1 << 20); 3867912Shestness@cs.utexas.edu entry.paddr = (uint64_t)pte & (mask(31) << 21); 3877912Shestness@cs.utexas.edu entry.uncacheable = uncacheable; 3887912Shestness@cs.utexas.edu entry.global = pte.g; 3897912Shestness@cs.utexas.edu entry.patBit = bits(pte, 12); 3907912Shestness@cs.utexas.edu entry.vaddr = entry.vaddr & ~((2 * (1 << 20)) - 1); 3917912Shestness@cs.utexas.edu doTLBInsert = true; 3927912Shestness@cs.utexas.edu doEndWalk = true; 3937912Shestness@cs.utexas.edu break; 3947912Shestness@cs.utexas.edu } 3957912Shestness@cs.utexas.edu case PAEPTE: 3967912Shestness@cs.utexas.edu DPRINTF(PageTableWalker, 3977912Shestness@cs.utexas.edu "Got legacy mode PAE PTE entry %#08x.\n", (uint32_t)pte); 3987912Shestness@cs.utexas.edu doWrite = !pte.a; 3997912Shestness@cs.utexas.edu pte.a = 1; 4007912Shestness@cs.utexas.edu entry.writable = entry.writable && pte.w; 4017912Shestness@cs.utexas.edu entry.user = entry.user && pte.u; 4027912Shestness@cs.utexas.edu if (badNX || !pte.p) { 4037912Shestness@cs.utexas.edu doEndWalk = true; 4047912Shestness@cs.utexas.edu fault = pageFault(pte.p); 4057912Shestness@cs.utexas.edu break; 4067912Shestness@cs.utexas.edu } 4077912Shestness@cs.utexas.edu entry.paddr = (uint64_t)pte & (mask(40) << 12); 4087912Shestness@cs.utexas.edu entry.uncacheable = uncacheable; 4097912Shestness@cs.utexas.edu entry.global = pte.g; 4107912Shestness@cs.utexas.edu entry.patBit = bits(pte, 7); 4117912Shestness@cs.utexas.edu entry.vaddr = entry.vaddr & ~((4 * (1 << 10)) - 1); 4127912Shestness@cs.utexas.edu doTLBInsert = true; 4137912Shestness@cs.utexas.edu doEndWalk = true; 4147912Shestness@cs.utexas.edu break; 4157912Shestness@cs.utexas.edu case PSEPD: 4167912Shestness@cs.utexas.edu DPRINTF(PageTableWalker, 4177912Shestness@cs.utexas.edu "Got legacy mode PSE PD entry %#08x.\n", (uint32_t)pte); 4187912Shestness@cs.utexas.edu doWrite = !pte.a; 4197912Shestness@cs.utexas.edu pte.a = 1; 4207912Shestness@cs.utexas.edu entry.writable = pte.w; 4217912Shestness@cs.utexas.edu entry.user = pte.u; 4227912Shestness@cs.utexas.edu if (!pte.p) { 4237912Shestness@cs.utexas.edu doEndWalk = true; 4247912Shestness@cs.utexas.edu fault = pageFault(pte.p); 4257912Shestness@cs.utexas.edu break; 4267912Shestness@cs.utexas.edu } 4277912Shestness@cs.utexas.edu if (!pte.ps) { 4287912Shestness@cs.utexas.edu // 4 KB page 4297912Shestness@cs.utexas.edu entry.size = 4 * (1 << 10); 4307912Shestness@cs.utexas.edu nextRead = 4317912Shestness@cs.utexas.edu ((uint64_t)pte & (mask(20) << 12)) + vaddr.norml2 * dataSize; 4327912Shestness@cs.utexas.edu nextState = PTE; 4337912Shestness@cs.utexas.edu break; 4347912Shestness@cs.utexas.edu } else { 4357912Shestness@cs.utexas.edu // 4 MB page 4367912Shestness@cs.utexas.edu entry.size = 4 * (1 << 20); 4377912Shestness@cs.utexas.edu entry.paddr = bits(pte, 20, 13) << 32 | bits(pte, 31, 22) << 22; 4387912Shestness@cs.utexas.edu entry.uncacheable = uncacheable; 4397912Shestness@cs.utexas.edu entry.global = pte.g; 4407912Shestness@cs.utexas.edu entry.patBit = bits(pte, 12); 4417912Shestness@cs.utexas.edu entry.vaddr = entry.vaddr & ~((4 * (1 << 20)) - 1); 4427912Shestness@cs.utexas.edu doTLBInsert = true; 4437912Shestness@cs.utexas.edu doEndWalk = true; 4447912Shestness@cs.utexas.edu break; 4457912Shestness@cs.utexas.edu } 4467912Shestness@cs.utexas.edu case PD: 4477912Shestness@cs.utexas.edu DPRINTF(PageTableWalker, 4487912Shestness@cs.utexas.edu "Got legacy mode PD entry %#08x.\n", (uint32_t)pte); 4497912Shestness@cs.utexas.edu doWrite = !pte.a; 4507912Shestness@cs.utexas.edu pte.a = 1; 4517912Shestness@cs.utexas.edu entry.writable = pte.w; 4527912Shestness@cs.utexas.edu entry.user = pte.u; 4537912Shestness@cs.utexas.edu if (!pte.p) { 4547912Shestness@cs.utexas.edu doEndWalk = true; 4557912Shestness@cs.utexas.edu fault = pageFault(pte.p); 4567912Shestness@cs.utexas.edu break; 4577912Shestness@cs.utexas.edu } 4587912Shestness@cs.utexas.edu // 4 KB page 4597912Shestness@cs.utexas.edu entry.size = 4 * (1 << 10); 4607912Shestness@cs.utexas.edu nextRead = ((uint64_t)pte & (mask(20) << 12)) + vaddr.norml2 * dataSize; 4617912Shestness@cs.utexas.edu nextState = PTE; 4627912Shestness@cs.utexas.edu break; 4637912Shestness@cs.utexas.edu case PTE: 4647912Shestness@cs.utexas.edu DPRINTF(PageTableWalker, 4657912Shestness@cs.utexas.edu "Got legacy mode PTE entry %#08x.\n", (uint32_t)pte); 4667912Shestness@cs.utexas.edu doWrite = !pte.a; 4677912Shestness@cs.utexas.edu pte.a = 1; 4687912Shestness@cs.utexas.edu entry.writable = pte.w; 4697912Shestness@cs.utexas.edu entry.user = pte.u; 4707912Shestness@cs.utexas.edu if (!pte.p) { 4717912Shestness@cs.utexas.edu doEndWalk = true; 4727912Shestness@cs.utexas.edu fault = pageFault(pte.p); 4737912Shestness@cs.utexas.edu break; 4747912Shestness@cs.utexas.edu } 4757912Shestness@cs.utexas.edu entry.paddr = (uint64_t)pte & (mask(20) << 12); 4767912Shestness@cs.utexas.edu entry.uncacheable = uncacheable; 4777912Shestness@cs.utexas.edu entry.global = pte.g; 4787912Shestness@cs.utexas.edu entry.patBit = bits(pte, 7); 4797912Shestness@cs.utexas.edu entry.vaddr = entry.vaddr & ~((4 * (1 << 10)) - 1); 4807912Shestness@cs.utexas.edu doTLBInsert = true; 4817912Shestness@cs.utexas.edu doEndWalk = true; 4827912Shestness@cs.utexas.edu break; 4837912Shestness@cs.utexas.edu default: 4847912Shestness@cs.utexas.edu panic("Unknown page table walker state %d!\n"); 4857912Shestness@cs.utexas.edu } 4867912Shestness@cs.utexas.edu if (doEndWalk) { 4877912Shestness@cs.utexas.edu if (doTLBInsert) 4887912Shestness@cs.utexas.edu if (!functional) 4897912Shestness@cs.utexas.edu walker->tlb->insert(entry.vaddr, entry); 4907912Shestness@cs.utexas.edu endWalk(); 4917912Shestness@cs.utexas.edu } else { 4927912Shestness@cs.utexas.edu PacketPtr oldRead = read; 4937912Shestness@cs.utexas.edu //If we didn't return, we're setting up another read. 4947912Shestness@cs.utexas.edu Request::Flags flags = oldRead->req->getFlags(); 4957912Shestness@cs.utexas.edu flags.set(Request::UNCACHEABLE, uncacheable); 4967912Shestness@cs.utexas.edu RequestPtr request = 4978832SAli.Saidi@ARM.com new Request(nextRead, oldRead->getSize(), flags, walker->masterId); 4988096Sgblack@eecs.umich.edu read = new Packet(request, MemCmd::ReadReq, Packet::Broadcast); 4997912Shestness@cs.utexas.edu read->allocate(); 5007912Shestness@cs.utexas.edu // If we need to write, adjust the read packet to write the modified 5017912Shestness@cs.utexas.edu // value back to memory. 5027912Shestness@cs.utexas.edu if (doWrite) { 5037912Shestness@cs.utexas.edu write = oldRead; 5047912Shestness@cs.utexas.edu write->set<uint64_t>(pte); 5057912Shestness@cs.utexas.edu write->cmd = MemCmd::WriteReq; 5067912Shestness@cs.utexas.edu write->setDest(Packet::Broadcast); 5077912Shestness@cs.utexas.edu } else { 5087912Shestness@cs.utexas.edu write = NULL; 5097912Shestness@cs.utexas.edu delete oldRead->req; 5107912Shestness@cs.utexas.edu delete oldRead; 5117912Shestness@cs.utexas.edu } 5127912Shestness@cs.utexas.edu } 5137912Shestness@cs.utexas.edu return fault; 5147912Shestness@cs.utexas.edu} 5157912Shestness@cs.utexas.edu 5167912Shestness@cs.utexas.eduvoid 5177912Shestness@cs.utexas.eduWalker::WalkerState::endWalk() 5187912Shestness@cs.utexas.edu{ 5197912Shestness@cs.utexas.edu nextState = Ready; 5207912Shestness@cs.utexas.edu delete read->req; 5217912Shestness@cs.utexas.edu delete read; 5227912Shestness@cs.utexas.edu read = NULL; 5237912Shestness@cs.utexas.edu} 5247912Shestness@cs.utexas.edu 5257912Shestness@cs.utexas.eduvoid 5267912Shestness@cs.utexas.eduWalker::WalkerState::setupWalk(Addr vaddr) 5277912Shestness@cs.utexas.edu{ 5287912Shestness@cs.utexas.edu VAddr addr = vaddr; 5297912Shestness@cs.utexas.edu CR3 cr3 = tc->readMiscRegNoEffect(MISCREG_CR3); 5307912Shestness@cs.utexas.edu // Check if we're in long mode or not 5317912Shestness@cs.utexas.edu Efer efer = tc->readMiscRegNoEffect(MISCREG_EFER); 5327912Shestness@cs.utexas.edu dataSize = 8; 5337912Shestness@cs.utexas.edu Addr topAddr; 5347912Shestness@cs.utexas.edu if (efer.lma) { 5357912Shestness@cs.utexas.edu // Do long mode. 5367912Shestness@cs.utexas.edu state = LongPML4; 5377912Shestness@cs.utexas.edu topAddr = (cr3.longPdtb << 12) + addr.longl4 * dataSize; 5387912Shestness@cs.utexas.edu enableNX = efer.nxe; 5397912Shestness@cs.utexas.edu } else { 5407912Shestness@cs.utexas.edu // We're in some flavor of legacy mode. 5417912Shestness@cs.utexas.edu CR4 cr4 = tc->readMiscRegNoEffect(MISCREG_CR4); 5427912Shestness@cs.utexas.edu if (cr4.pae) { 5437912Shestness@cs.utexas.edu // Do legacy PAE. 5447912Shestness@cs.utexas.edu state = PAEPDP; 5457912Shestness@cs.utexas.edu topAddr = (cr3.paePdtb << 5) + addr.pael3 * dataSize; 5467912Shestness@cs.utexas.edu enableNX = efer.nxe; 5477912Shestness@cs.utexas.edu } else { 5487912Shestness@cs.utexas.edu dataSize = 4; 5497912Shestness@cs.utexas.edu topAddr = (cr3.pdtb << 12) + addr.norml2 * dataSize; 5507912Shestness@cs.utexas.edu if (cr4.pse) { 5517912Shestness@cs.utexas.edu // Do legacy PSE. 5527912Shestness@cs.utexas.edu state = PSEPD; 5537912Shestness@cs.utexas.edu } else { 5547912Shestness@cs.utexas.edu // Do legacy non PSE. 5557912Shestness@cs.utexas.edu state = PD; 5567912Shestness@cs.utexas.edu } 5577912Shestness@cs.utexas.edu enableNX = false; 5587912Shestness@cs.utexas.edu } 5597912Shestness@cs.utexas.edu } 5607912Shestness@cs.utexas.edu 5617912Shestness@cs.utexas.edu nextState = Ready; 5627912Shestness@cs.utexas.edu entry.vaddr = vaddr; 5637912Shestness@cs.utexas.edu 5647912Shestness@cs.utexas.edu Request::Flags flags = Request::PHYSICAL; 5657912Shestness@cs.utexas.edu if (cr3.pcd) 5667912Shestness@cs.utexas.edu flags.set(Request::UNCACHEABLE); 5678832SAli.Saidi@ARM.com RequestPtr request = new Request(topAddr, dataSize, flags, walker->masterId); 5688096Sgblack@eecs.umich.edu read = new Packet(request, MemCmd::ReadReq, Packet::Broadcast); 5697912Shestness@cs.utexas.edu read->allocate(); 5707912Shestness@cs.utexas.edu} 5717912Shestness@cs.utexas.edu 5727912Shestness@cs.utexas.edubool 5737912Shestness@cs.utexas.eduWalker::WalkerState::recvPacket(PacketPtr pkt) 5747912Shestness@cs.utexas.edu{ 5757912Shestness@cs.utexas.edu if (pkt->isResponse() && !pkt->wasNacked()) { 5767912Shestness@cs.utexas.edu assert(inflight); 5777912Shestness@cs.utexas.edu assert(state == Waiting); 5787912Shestness@cs.utexas.edu assert(!read); 5797912Shestness@cs.utexas.edu inflight--; 5807912Shestness@cs.utexas.edu if (pkt->isRead()) { 5817912Shestness@cs.utexas.edu state = nextState; 5827912Shestness@cs.utexas.edu nextState = Ready; 5837912Shestness@cs.utexas.edu PacketPtr write = NULL; 5847912Shestness@cs.utexas.edu read = pkt; 5857912Shestness@cs.utexas.edu timingFault = stepWalk(write); 5867912Shestness@cs.utexas.edu state = Waiting; 5877912Shestness@cs.utexas.edu assert(timingFault == NoFault || read == NULL); 5887912Shestness@cs.utexas.edu if (write) { 5897912Shestness@cs.utexas.edu writes.push_back(write); 5907912Shestness@cs.utexas.edu } 5917912Shestness@cs.utexas.edu sendPackets(); 5927912Shestness@cs.utexas.edu } else { 5937912Shestness@cs.utexas.edu sendPackets(); 5947912Shestness@cs.utexas.edu } 5957912Shestness@cs.utexas.edu if (inflight == 0 && read == NULL && writes.size() == 0) { 5967912Shestness@cs.utexas.edu state = Ready; 5977912Shestness@cs.utexas.edu nextState = Waiting; 5987912Shestness@cs.utexas.edu if (timingFault == NoFault) { 5997912Shestness@cs.utexas.edu /* 6007912Shestness@cs.utexas.edu * Finish the translation. Now that we now the right entry is 6017912Shestness@cs.utexas.edu * in the TLB, this should work with no memory accesses. 6027912Shestness@cs.utexas.edu * There could be new faults unrelated to the table walk like 6037912Shestness@cs.utexas.edu * permissions violations, so we'll need the return value as 6047912Shestness@cs.utexas.edu * well. 6057912Shestness@cs.utexas.edu */ 6067912Shestness@cs.utexas.edu bool delayedResponse; 6077912Shestness@cs.utexas.edu Fault fault = walker->tlb->translate(req, tc, NULL, mode, 6087912Shestness@cs.utexas.edu delayedResponse, true); 6097912Shestness@cs.utexas.edu assert(!delayedResponse); 6107912Shestness@cs.utexas.edu // Let the CPU continue. 6117912Shestness@cs.utexas.edu translation->finish(fault, req, tc, mode); 6127912Shestness@cs.utexas.edu } else { 6137912Shestness@cs.utexas.edu // There was a fault during the walk. Let the CPU know. 6147912Shestness@cs.utexas.edu translation->finish(timingFault, req, tc, mode); 6157912Shestness@cs.utexas.edu } 6167912Shestness@cs.utexas.edu return true; 6177912Shestness@cs.utexas.edu } 6187912Shestness@cs.utexas.edu } else if (pkt->wasNacked()) { 6197912Shestness@cs.utexas.edu DPRINTF(PageTableWalker, "Request was nacked. Entering retry state\n"); 6207912Shestness@cs.utexas.edu pkt->reinitNacked(); 6217912Shestness@cs.utexas.edu if (!walker->sendTiming(this, pkt)) { 6227912Shestness@cs.utexas.edu inflight--; 6237912Shestness@cs.utexas.edu retrying = true; 6247912Shestness@cs.utexas.edu if (pkt->isWrite()) { 6257912Shestness@cs.utexas.edu writes.push_back(pkt); 6267912Shestness@cs.utexas.edu } else { 6277912Shestness@cs.utexas.edu assert(!read); 6287912Shestness@cs.utexas.edu read = pkt; 6297912Shestness@cs.utexas.edu } 6307912Shestness@cs.utexas.edu } 6317912Shestness@cs.utexas.edu } 6327912Shestness@cs.utexas.edu return false; 6337912Shestness@cs.utexas.edu} 6347912Shestness@cs.utexas.edu 6357912Shestness@cs.utexas.eduvoid 6367912Shestness@cs.utexas.eduWalker::WalkerState::sendPackets() 6375245Sgblack@eecs.umich.edu{ 6385245Sgblack@eecs.umich.edu //If we're already waiting for the port to become available, just return. 6395245Sgblack@eecs.umich.edu if (retrying) 6405245Sgblack@eecs.umich.edu return; 6415245Sgblack@eecs.umich.edu 6425245Sgblack@eecs.umich.edu //Reads always have priority 6435245Sgblack@eecs.umich.edu if (read) { 6445897Sgblack@eecs.umich.edu PacketPtr pkt = read; 6455897Sgblack@eecs.umich.edu read = NULL; 6465897Sgblack@eecs.umich.edu inflight++; 6477912Shestness@cs.utexas.edu if (!walker->sendTiming(this, pkt)) { 6485245Sgblack@eecs.umich.edu retrying = true; 6495897Sgblack@eecs.umich.edu read = pkt; 6505897Sgblack@eecs.umich.edu inflight--; 6515245Sgblack@eecs.umich.edu return; 6525245Sgblack@eecs.umich.edu } 6535245Sgblack@eecs.umich.edu } 6545245Sgblack@eecs.umich.edu //Send off as many of the writes as we can. 6555245Sgblack@eecs.umich.edu while (writes.size()) { 6565245Sgblack@eecs.umich.edu PacketPtr write = writes.back(); 6575897Sgblack@eecs.umich.edu writes.pop_back(); 6585897Sgblack@eecs.umich.edu inflight++; 6597912Shestness@cs.utexas.edu if (!walker->sendTiming(this, write)) { 6605245Sgblack@eecs.umich.edu retrying = true; 6615897Sgblack@eecs.umich.edu writes.push_back(write); 6625897Sgblack@eecs.umich.edu inflight--; 6635245Sgblack@eecs.umich.edu return; 6645245Sgblack@eecs.umich.edu } 6655245Sgblack@eecs.umich.edu } 6665245Sgblack@eecs.umich.edu} 6675245Sgblack@eecs.umich.edu 6687912Shestness@cs.utexas.edubool 6697912Shestness@cs.utexas.eduWalker::WalkerState::isRetrying() 6705245Sgblack@eecs.umich.edu{ 6717912Shestness@cs.utexas.edu return retrying; 6727912Shestness@cs.utexas.edu} 6737912Shestness@cs.utexas.edu 6747912Shestness@cs.utexas.edubool 6757912Shestness@cs.utexas.eduWalker::WalkerState::isTiming() 6767912Shestness@cs.utexas.edu{ 6777912Shestness@cs.utexas.edu return timing; 6787912Shestness@cs.utexas.edu} 6797912Shestness@cs.utexas.edu 6807912Shestness@cs.utexas.edubool 6817912Shestness@cs.utexas.eduWalker::WalkerState::wasStarted() 6827912Shestness@cs.utexas.edu{ 6837912Shestness@cs.utexas.edu return started; 6847912Shestness@cs.utexas.edu} 6857912Shestness@cs.utexas.edu 6867912Shestness@cs.utexas.eduvoid 6877912Shestness@cs.utexas.eduWalker::WalkerState::retry() 6887912Shestness@cs.utexas.edu{ 6897912Shestness@cs.utexas.edu retrying = false; 6907912Shestness@cs.utexas.edu sendPackets(); 6915245Sgblack@eecs.umich.edu} 6925245Sgblack@eecs.umich.edu 6935895Sgblack@eecs.umich.eduFault 6947912Shestness@cs.utexas.eduWalker::WalkerState::pageFault(bool present) 6955895Sgblack@eecs.umich.edu{ 6965904Sgblack@eecs.umich.edu DPRINTF(PageTableWalker, "Raising page fault.\n"); 6975895Sgblack@eecs.umich.edu HandyM5Reg m5reg = tc->readMiscRegNoEffect(MISCREG_M5_REG); 6986023Snate@binkert.org if (mode == BaseTLB::Execute && !enableNX) 6996023Snate@binkert.org mode = BaseTLB::Read; 7006023Snate@binkert.org return new PageFault(entry.vaddr, present, mode, m5reg.cpl == 3, false); 7015895Sgblack@eecs.umich.edu} 7025895Sgblack@eecs.umich.edu 7037912Shestness@cs.utexas.edu/* end namespace X86ISA */ } 7045245Sgblack@eecs.umich.edu 7055245Sgblack@eecs.umich.eduX86ISA::Walker * 7065245Sgblack@eecs.umich.eduX86PagetableWalkerParams::create() 7075245Sgblack@eecs.umich.edu{ 7085245Sgblack@eecs.umich.edu return new X86ISA::Walker(this); 7095245Sgblack@eecs.umich.edu} 710