tlb.cc revision 2166
1955SN/A/* 2955SN/A * Copyright (c) 2001-2005 The Regents of The University of Michigan 39812Sandreas.hansson@arm.com * All rights reserved. 49812Sandreas.hansson@arm.com * 59812Sandreas.hansson@arm.com * Redistribution and use in source and binary forms, with or without 69812Sandreas.hansson@arm.com * modification, are permitted provided that the following conditions are 79812Sandreas.hansson@arm.com * met: redistributions of source code must retain the above copyright 89812Sandreas.hansson@arm.com * notice, this list of conditions and the following disclaimer; 99812Sandreas.hansson@arm.com * redistributions in binary form must reproduce the above copyright 109812Sandreas.hansson@arm.com * notice, this list of conditions and the following disclaimer in the 119812Sandreas.hansson@arm.com * documentation and/or other materials provided with the distribution; 129812Sandreas.hansson@arm.com * neither the name of the copyright holders nor the names of its 139812Sandreas.hansson@arm.com * contributors may be used to endorse or promote products derived from 149812Sandreas.hansson@arm.com * this software without specific prior written permission. 157816Ssteve.reinhardt@amd.com * 165871Snate@binkert.org * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 171762SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18955SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19955SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20955SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21955SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22955SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23955SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24955SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25955SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26955SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27955SN/A */ 28955SN/A 29955SN/A#include <sstream> 30955SN/A#include <string> 31955SN/A#include <vector> 32955SN/A 33955SN/A#include "arch/alpha/alpha_memory.hh" 34955SN/A#include "base/inifile.hh" 35955SN/A#include "base/str.hh" 36955SN/A#include "base/trace.hh" 37955SN/A#include "config/alpha_tlaser.hh" 38955SN/A#include "cpu/exec_context.hh" 39955SN/A#include "sim/builder.hh" 40955SN/A 41955SN/Ausing namespace std; 422665Ssaidi@eecs.umich.eduusing namespace EV5; 432665Ssaidi@eecs.umich.edu 445863Snate@binkert.org/////////////////////////////////////////////////////////////////////// 45955SN/A// 46955SN/A// Alpha TLB 47955SN/A// 48955SN/A#ifdef DEBUG 49955SN/Abool uncacheBit39 = false; 508878Ssteve.reinhardt@amd.combool uncacheBit40 = false; 512632Sstever@eecs.umich.edu#endif 528878Ssteve.reinhardt@amd.com 532632Sstever@eecs.umich.edu#define MODE2MASK(X) (1 << (X)) 54955SN/A 558878Ssteve.reinhardt@amd.comAlphaTLB::AlphaTLB(const string &name, int s) 562632Sstever@eecs.umich.edu : SimObject(name), size(s), nlu(0) 572761Sstever@eecs.umich.edu{ 582632Sstever@eecs.umich.edu table = new AlphaISA::PTE[size]; 592632Sstever@eecs.umich.edu memset(table, 0, sizeof(AlphaISA::PTE[size])); 602632Sstever@eecs.umich.edu} 612761Sstever@eecs.umich.edu 622761Sstever@eecs.umich.eduAlphaTLB::~AlphaTLB() 632761Sstever@eecs.umich.edu{ 648878Ssteve.reinhardt@amd.com if (table) 658878Ssteve.reinhardt@amd.com delete [] table; 662761Sstever@eecs.umich.edu} 672761Sstever@eecs.umich.edu 682761Sstever@eecs.umich.edu// look up an entry in the TLB 692761Sstever@eecs.umich.eduAlphaISA::PTE * 702761Sstever@eecs.umich.eduAlphaTLB::lookup(Addr vpn, uint8_t asn) const 718878Ssteve.reinhardt@amd.com{ 728878Ssteve.reinhardt@amd.com // assume not found... 732632Sstever@eecs.umich.edu AlphaISA::PTE *retval = NULL; 742632Sstever@eecs.umich.edu 758878Ssteve.reinhardt@amd.com PageTable::const_iterator i = lookupTable.find(vpn); 768878Ssteve.reinhardt@amd.com if (i != lookupTable.end()) { 772632Sstever@eecs.umich.edu while (i->first == vpn) { 78955SN/A int index = i->second; 79955SN/A AlphaISA::PTE *pte = &table[index]; 80955SN/A assert(pte->valid); 815863Snate@binkert.org if (vpn == pte->tag && (pte->asma || pte->asn == asn)) { 825863Snate@binkert.org retval = pte; 835863Snate@binkert.org break; 845863Snate@binkert.org } 855863Snate@binkert.org 865863Snate@binkert.org ++i; 875863Snate@binkert.org } 885863Snate@binkert.org } 895863Snate@binkert.org 905863Snate@binkert.org DPRINTF(TLB, "lookup %#x, asn %#x -> %s ppn %#x\n", vpn, (int)asn, 915863Snate@binkert.org retval ? "hit" : "miss", retval ? retval->ppn : 0); 928878Ssteve.reinhardt@amd.com return retval; 935863Snate@binkert.org} 945863Snate@binkert.org 955863Snate@binkert.org 969812Sandreas.hansson@arm.comvoid 979812Sandreas.hansson@arm.comAlphaTLB::checkCacheability(MemReqPtr &req) 985863Snate@binkert.org{ 999812Sandreas.hansson@arm.com // in Alpha, cacheability is controlled by upper-level bits of the 1005863Snate@binkert.org // physical address 1015863Snate@binkert.org 1025863Snate@binkert.org /* 1039812Sandreas.hansson@arm.com * We support having the uncacheable bit in either bit 39 or bit 40. 1049812Sandreas.hansson@arm.com * The Turbolaser platform (and EV5) support having the bit in 39, but 1055863Snate@binkert.org * Tsunami (which Linux assumes uses an EV6) generates accesses with 1065863Snate@binkert.org * the bit in 40. So we must check for both, but we have debug flags 1078878Ssteve.reinhardt@amd.com * to catch a weird case where both are used, which shouldn't happen. 1085863Snate@binkert.org */ 1095863Snate@binkert.org 1105863Snate@binkert.org 1116654Snate@binkert.org#if ALPHA_TLASER 11210196SCurtis.Dunham@arm.com if (req->paddr & PAddrUncachedBit39) { 113955SN/A#else 1145396Ssaidi@eecs.umich.edu if (req->paddr & PAddrUncachedBit43) { 1155863Snate@binkert.org#endif 1165863Snate@binkert.org // IPR memory space not implemented 1174202Sbinkertn@umich.edu if (PAddrIprSpace(req->paddr)) { 1185863Snate@binkert.org if (!req->xc->misspeculating()) { 1195863Snate@binkert.org switch (req->paddr) { 1205863Snate@binkert.org case ULL(0xFFFFF00188): 1215863Snate@binkert.org req->data = 0; 122955SN/A break; 1236654Snate@binkert.org 1245273Sstever@gmail.com default: 1255871Snate@binkert.org panic("IPR memory space not implemented! PA=%x\n", 1265273Sstever@gmail.com req->paddr); 1276655Snate@binkert.org } 1288878Ssteve.reinhardt@amd.com } 1296655Snate@binkert.org } else { 1306655Snate@binkert.org // mark request as uncacheable 1319219Spower.jg@gmail.com req->flags |= UNCACHEABLE; 1326655Snate@binkert.org 1335871Snate@binkert.org#if !ALPHA_TLASER 1346654Snate@binkert.org // Clear bits 42:35 of the physical address (10-2 in Tsunami manual) 1358947Sandreas.hansson@arm.com req->paddr &= PAddrUncachedMask; 1365396Ssaidi@eecs.umich.edu#endif 1378120Sgblack@eecs.umich.edu } 1388120Sgblack@eecs.umich.edu } 1398120Sgblack@eecs.umich.edu} 1408120Sgblack@eecs.umich.edu 1418120Sgblack@eecs.umich.edu 1428120Sgblack@eecs.umich.edu// insert a new TLB entry 1438120Sgblack@eecs.umich.eduvoid 1448120Sgblack@eecs.umich.eduAlphaTLB::insert(Addr addr, AlphaISA::PTE &pte) 1458879Ssteve.reinhardt@amd.com{ 1468879Ssteve.reinhardt@amd.com AlphaISA::VAddr vaddr = addr; 1478879Ssteve.reinhardt@amd.com if (table[nlu].valid) { 1488879Ssteve.reinhardt@amd.com Addr oldvpn = table[nlu].tag; 1498879Ssteve.reinhardt@amd.com PageTable::iterator i = lookupTable.find(oldvpn); 1508879Ssteve.reinhardt@amd.com 1518879Ssteve.reinhardt@amd.com if (i == lookupTable.end()) 1528879Ssteve.reinhardt@amd.com panic("TLB entry not found in lookupTable"); 1538879Ssteve.reinhardt@amd.com 1548879Ssteve.reinhardt@amd.com int index; 1558879Ssteve.reinhardt@amd.com while ((index = i->second) != nlu) { 1568879Ssteve.reinhardt@amd.com if (table[index].tag != oldvpn) 1578879Ssteve.reinhardt@amd.com panic("TLB entry not found in lookupTable"); 1588120Sgblack@eecs.umich.edu 1598120Sgblack@eecs.umich.edu ++i; 1608120Sgblack@eecs.umich.edu } 1618120Sgblack@eecs.umich.edu 1628120Sgblack@eecs.umich.edu DPRINTF(TLB, "remove @%d: %#x -> %#x\n", nlu, oldvpn, table[nlu].ppn); 1638120Sgblack@eecs.umich.edu 1648120Sgblack@eecs.umich.edu lookupTable.erase(i); 1658120Sgblack@eecs.umich.edu } 1668120Sgblack@eecs.umich.edu 1678120Sgblack@eecs.umich.edu DPRINTF(TLB, "insert @%d: %#x -> %#x\n", nlu, vaddr.vpn(), pte.ppn); 1688120Sgblack@eecs.umich.edu 1698120Sgblack@eecs.umich.edu table[nlu] = pte; 1708120Sgblack@eecs.umich.edu table[nlu].tag = vaddr.vpn(); 1718120Sgblack@eecs.umich.edu table[nlu].valid = true; 1728879Ssteve.reinhardt@amd.com 1738879Ssteve.reinhardt@amd.com lookupTable.insert(make_pair(vaddr.vpn(), nlu)); 1748879Ssteve.reinhardt@amd.com nextnlu(); 1758879Ssteve.reinhardt@amd.com} 17610458Sandreas.hansson@arm.com 17710458Sandreas.hansson@arm.comvoid 17810458Sandreas.hansson@arm.comAlphaTLB::flushAll() 1798879Ssteve.reinhardt@amd.com{ 1808879Ssteve.reinhardt@amd.com DPRINTF(TLB, "flushAll\n"); 1818879Ssteve.reinhardt@amd.com memset(table, 0, sizeof(AlphaISA::PTE[size])); 1828879Ssteve.reinhardt@amd.com lookupTable.clear(); 1839227Sandreas.hansson@arm.com nlu = 0; 1849227Sandreas.hansson@arm.com} 1858879Ssteve.reinhardt@amd.com 1868879Ssteve.reinhardt@amd.comvoid 1878879Ssteve.reinhardt@amd.comAlphaTLB::flushProcesses() 1888879Ssteve.reinhardt@amd.com{ 18910453SAndrew.Bardsley@arm.com PageTable::iterator i = lookupTable.begin(); 19010453SAndrew.Bardsley@arm.com PageTable::iterator end = lookupTable.end(); 19110453SAndrew.Bardsley@arm.com while (i != end) { 19210456SCurtis.Dunham@arm.com int index = i->second; 19310456SCurtis.Dunham@arm.com AlphaISA::PTE *pte = &table[index]; 19410456SCurtis.Dunham@arm.com assert(pte->valid); 19510457Sandreas.hansson@arm.com 19610457Sandreas.hansson@arm.com // we can't increment i after we erase it, so save a copy and 1978120Sgblack@eecs.umich.edu // increment it to get the next entry now 1988947Sandreas.hansson@arm.com PageTable::iterator cur = i; 1997816Ssteve.reinhardt@amd.com ++i; 2005871Snate@binkert.org 2015871Snate@binkert.org if (!pte->asma) { 2026121Snate@binkert.org DPRINTF(TLB, "flush @%d: %#x -> %#x\n", index, pte->tag, pte->ppn); 2035871Snate@binkert.org pte->valid = false; 2045871Snate@binkert.org lookupTable.erase(cur); 2059926Sstan.czerniawski@arm.com } 2069926Sstan.czerniawski@arm.com } 2079119Sandreas.hansson@arm.com} 20810068Sandreas.hansson@arm.com 20910068Sandreas.hansson@arm.comvoid 210955SN/AAlphaTLB::flushAddr(Addr addr, uint8_t asn) 2119416SAndreas.Sandberg@ARM.com{ 2129416SAndreas.Sandberg@ARM.com AlphaISA::VAddr vaddr = addr; 2139416SAndreas.Sandberg@ARM.com 2149416SAndreas.Sandberg@ARM.com PageTable::iterator i = lookupTable.find(vaddr.vpn()); 2159416SAndreas.Sandberg@ARM.com if (i == lookupTable.end()) 2169416SAndreas.Sandberg@ARM.com return; 2179416SAndreas.Sandberg@ARM.com 2185871Snate@binkert.org while (i->first == vaddr.vpn()) { 21910584Sandreas.hansson@arm.com int index = i->second; 2209416SAndreas.Sandberg@ARM.com AlphaISA::PTE *pte = &table[index]; 2219416SAndreas.Sandberg@ARM.com assert(pte->valid); 2225871Snate@binkert.org 223955SN/A if (vaddr.vpn() == pte->tag && (pte->asma || pte->asn == asn)) { 22410671Sandreas.hansson@arm.com DPRINTF(TLB, "flushaddr @%d: %#x -> %#x\n", index, vaddr.vpn(), 22510671Sandreas.hansson@arm.com pte->ppn); 22610671Sandreas.hansson@arm.com 22710671Sandreas.hansson@arm.com // invalidate this entry 2288881Smarc.orr@gmail.com pte->valid = false; 2296121Snate@binkert.org 2306121Snate@binkert.org lookupTable.erase(i); 2311533SN/A } 2329239Sandreas.hansson@arm.com 2339239Sandreas.hansson@arm.com ++i; 2349239Sandreas.hansson@arm.com } 2359239Sandreas.hansson@arm.com} 2369239Sandreas.hansson@arm.com 2379239Sandreas.hansson@arm.com 2389239Sandreas.hansson@arm.comvoid 2399239Sandreas.hansson@arm.comAlphaTLB::serialize(ostream &os) 2409239Sandreas.hansson@arm.com{ 2419239Sandreas.hansson@arm.com SERIALIZE_SCALAR(size); 2429239Sandreas.hansson@arm.com SERIALIZE_SCALAR(nlu); 2439239Sandreas.hansson@arm.com 2446655Snate@binkert.org for (int i = 0; i < size; i++) { 2456655Snate@binkert.org nameOut(os, csprintf("%s.PTE%d", name(), i)); 2466655Snate@binkert.org table[i].serialize(os); 2476655Snate@binkert.org } 2485871Snate@binkert.org} 2495871Snate@binkert.org 2505863Snate@binkert.orgvoid 2515871Snate@binkert.orgAlphaTLB::unserialize(Checkpoint *cp, const string §ion) 2528878Ssteve.reinhardt@amd.com{ 2535871Snate@binkert.org UNSERIALIZE_SCALAR(size); 2545871Snate@binkert.org UNSERIALIZE_SCALAR(nlu); 2555871Snate@binkert.org 2565863Snate@binkert.org for (int i = 0; i < size; i++) { 2576121Snate@binkert.org table[i].unserialize(cp, csprintf("%s.PTE%d", section, i)); 2585863Snate@binkert.org if (table[i].valid) { 2595871Snate@binkert.org lookupTable.insert(make_pair(table[i].tag, i)); 2608336Ssteve.reinhardt@amd.com } 2618336Ssteve.reinhardt@amd.com } 2628336Ssteve.reinhardt@amd.com} 2638336Ssteve.reinhardt@amd.com 2644678Snate@binkert.org 2658336Ssteve.reinhardt@amd.com/////////////////////////////////////////////////////////////////////// 2668336Ssteve.reinhardt@amd.com// 2678336Ssteve.reinhardt@amd.com// Alpha ITB 2684678Snate@binkert.org// 2694678Snate@binkert.orgAlphaITB::AlphaITB(const std::string &name, int size) 2704678Snate@binkert.org : AlphaTLB(name, size) 2714678Snate@binkert.org{} 2727827Snate@binkert.org 2737827Snate@binkert.org 2748336Ssteve.reinhardt@amd.comvoid 2754678Snate@binkert.orgAlphaITB::regStats() 2768336Ssteve.reinhardt@amd.com{ 2778336Ssteve.reinhardt@amd.com hits 2788336Ssteve.reinhardt@amd.com .name(name() + ".hits") 2798336Ssteve.reinhardt@amd.com .desc("ITB hits"); 2808336Ssteve.reinhardt@amd.com misses 2818336Ssteve.reinhardt@amd.com .name(name() + ".misses") 2825871Snate@binkert.org .desc("ITB misses"); 2835871Snate@binkert.org acv 2848336Ssteve.reinhardt@amd.com .name(name() + ".acv") 2858336Ssteve.reinhardt@amd.com .desc("ITB acv"); 2868336Ssteve.reinhardt@amd.com accesses 2878336Ssteve.reinhardt@amd.com .name(name() + ".accesses") 2888336Ssteve.reinhardt@amd.com .desc("ITB accesses"); 2895871Snate@binkert.org 2908336Ssteve.reinhardt@amd.com accesses = hits + misses; 2918336Ssteve.reinhardt@amd.com} 2928336Ssteve.reinhardt@amd.com 2938336Ssteve.reinhardt@amd.comvoid 2948336Ssteve.reinhardt@amd.comAlphaITB::fault(Addr pc, ExecContext *xc) const 2954678Snate@binkert.org{ 2965871Snate@binkert.org uint64_t *ipr = xc->regs.ipr; 2974678Snate@binkert.org 2988336Ssteve.reinhardt@amd.com if (!xc->misspeculating()) { 2998336Ssteve.reinhardt@amd.com ipr[AlphaISA::IPR_ITB_TAG] = pc; 3008336Ssteve.reinhardt@amd.com ipr[AlphaISA::IPR_IFAULT_VA_FORM] = 3018336Ssteve.reinhardt@amd.com ipr[AlphaISA::IPR_IVPTBR] | (AlphaISA::VAddr(pc).vpn() << 3); 3028336Ssteve.reinhardt@amd.com } 3038336Ssteve.reinhardt@amd.com} 3048336Ssteve.reinhardt@amd.com 3058336Ssteve.reinhardt@amd.com 3068336Ssteve.reinhardt@amd.comFault 3078336Ssteve.reinhardt@amd.comAlphaITB::translate(MemReqPtr &req) const 3088336Ssteve.reinhardt@amd.com{ 3098336Ssteve.reinhardt@amd.com InternalProcReg *ipr = req->xc->regs.ipr; 3108336Ssteve.reinhardt@amd.com 3118336Ssteve.reinhardt@amd.com if (AlphaISA::PcPAL(req->vaddr)) { 3128336Ssteve.reinhardt@amd.com // strip off PAL PC marker (lsb is 1) 3138336Ssteve.reinhardt@amd.com req->paddr = (req->vaddr & ~3) & PAddrImplMask; 3148336Ssteve.reinhardt@amd.com hits++; 3155871Snate@binkert.org return NoFault; 3166121Snate@binkert.org } 317955SN/A 318955SN/A if (req->flags & PHYSICAL) { 3192632Sstever@eecs.umich.edu req->paddr = req->vaddr; 3202632Sstever@eecs.umich.edu } else { 321955SN/A // verify that this is a good virtual address 322955SN/A if (!validVirtualAddress(req->vaddr)) { 323955SN/A fault(req->vaddr, req->xc); 324955SN/A acv++; 3258878Ssteve.reinhardt@amd.com return new ItbAcvFault; 326955SN/A } 3272632Sstever@eecs.umich.edu 3282632Sstever@eecs.umich.edu 3292632Sstever@eecs.umich.edu // VA<42:41> == 2, VA<39:13> maps directly to PA<39:13> for EV5 3302632Sstever@eecs.umich.edu // VA<47:41> == 0x7e, VA<40:13> maps directly to PA<40:13> for EV6 3312632Sstever@eecs.umich.edu#if ALPHA_TLASER 3322632Sstever@eecs.umich.edu if ((MCSR_SP(ipr[AlphaISA::IPR_MCSR]) & 2) && 3332632Sstever@eecs.umich.edu VAddrSpaceEV5(req->vaddr) == 2) { 3348268Ssteve.reinhardt@amd.com#else 3358268Ssteve.reinhardt@amd.com if (VAddrSpaceEV6(req->vaddr) == 0x7e) { 3368268Ssteve.reinhardt@amd.com#endif 3378268Ssteve.reinhardt@amd.com // only valid in kernel mode 3388268Ssteve.reinhardt@amd.com if (ICM_CM(ipr[AlphaISA::IPR_ICM]) != 3398268Ssteve.reinhardt@amd.com AlphaISA::mode_kernel) { 3408268Ssteve.reinhardt@amd.com fault(req->vaddr, req->xc); 3412632Sstever@eecs.umich.edu acv++; 3422632Sstever@eecs.umich.edu return new ItbAcvFault; 3432632Sstever@eecs.umich.edu } 3442632Sstever@eecs.umich.edu 3458268Ssteve.reinhardt@amd.com req->paddr = req->vaddr & PAddrImplMask; 3462632Sstever@eecs.umich.edu 3478268Ssteve.reinhardt@amd.com#if !ALPHA_TLASER 3488268Ssteve.reinhardt@amd.com // sign extend the physical address properly 3498268Ssteve.reinhardt@amd.com if (req->paddr & PAddrUncachedBit40) 3508268Ssteve.reinhardt@amd.com req->paddr |= ULL(0xf0000000000); 3513718Sstever@eecs.umich.edu else 3522634Sstever@eecs.umich.edu req->paddr &= ULL(0xffffffffff); 3532634Sstever@eecs.umich.edu#endif 3545863Snate@binkert.org 3552638Sstever@eecs.umich.edu } else { 3568268Ssteve.reinhardt@amd.com // not a physical address: need to look up pte 3572632Sstever@eecs.umich.edu AlphaISA::PTE *pte = lookup(AlphaISA::VAddr(req->vaddr).vpn(), 3582632Sstever@eecs.umich.edu DTB_ASN_ASN(ipr[AlphaISA::IPR_DTB_ASN])); 3592632Sstever@eecs.umich.edu 3602632Sstever@eecs.umich.edu if (!pte) { 3612632Sstever@eecs.umich.edu fault(req->vaddr, req->xc); 3621858SN/A misses++; 3633716Sstever@eecs.umich.edu return new ItbPageFault; 3642638Sstever@eecs.umich.edu } 3652638Sstever@eecs.umich.edu 3662638Sstever@eecs.umich.edu req->paddr = (pte->ppn << AlphaISA::PageShift) + 3672638Sstever@eecs.umich.edu (AlphaISA::VAddr(req->vaddr).offset() & ~3); 3682638Sstever@eecs.umich.edu 3692638Sstever@eecs.umich.edu // check permissions for this access 3702638Sstever@eecs.umich.edu if (!(pte->xre & (1 << ICM_CM(ipr[AlphaISA::IPR_ICM])))) { 3715863Snate@binkert.org // instruction access fault 3725863Snate@binkert.org fault(req->vaddr, req->xc); 3735863Snate@binkert.org acv++; 374955SN/A return new ItbAcvFault; 3755341Sstever@gmail.com } 3765341Sstever@gmail.com 3775863Snate@binkert.org hits++; 3787756SAli.Saidi@ARM.com } 3795341Sstever@gmail.com } 3806121Snate@binkert.org 3814494Ssaidi@eecs.umich.edu // check that the physical address is ok (catch bad physical addresses) 3826121Snate@binkert.org if (req->paddr & ~PAddrImplMask) 3831105SN/A return genMachineCheckFault(); 3842667Sstever@eecs.umich.edu 3852667Sstever@eecs.umich.edu checkCacheability(req); 3862667Sstever@eecs.umich.edu 3872667Sstever@eecs.umich.edu return NoFault; 3886121Snate@binkert.org} 3892667Sstever@eecs.umich.edu 3905341Sstever@gmail.com/////////////////////////////////////////////////////////////////////// 3915863Snate@binkert.org// 3925341Sstever@gmail.com// Alpha DTB 3935341Sstever@gmail.com// 3945341Sstever@gmail.comAlphaDTB::AlphaDTB(const std::string &name, int size) 3958120Sgblack@eecs.umich.edu : AlphaTLB(name, size) 3965341Sstever@gmail.com{} 3978120Sgblack@eecs.umich.edu 3985341Sstever@gmail.comvoid 3998120Sgblack@eecs.umich.eduAlphaDTB::regStats() 4006121Snate@binkert.org{ 4016121Snate@binkert.org read_hits 4028980Ssteve.reinhardt@amd.com .name(name() + ".read_hits") 4039396Sandreas.hansson@arm.com .desc("DTB read hits") 4045397Ssaidi@eecs.umich.edu ; 4055397Ssaidi@eecs.umich.edu 4067727SAli.Saidi@ARM.com read_misses 4078268Ssteve.reinhardt@amd.com .name(name() + ".read_misses") 4086168Snate@binkert.org .desc("DTB read misses") 4095341Sstever@gmail.com ; 4108120Sgblack@eecs.umich.edu 4118120Sgblack@eecs.umich.edu read_acv 4128120Sgblack@eecs.umich.edu .name(name() + ".read_acv") 4136814Sgblack@eecs.umich.edu .desc("DTB read access violations") 4145863Snate@binkert.org ; 4158120Sgblack@eecs.umich.edu 4165341Sstever@gmail.com read_accesses 4175863Snate@binkert.org .name(name() + ".read_accesses") 4188268Ssteve.reinhardt@amd.com .desc("DTB read accesses") 4196121Snate@binkert.org ; 4206121Snate@binkert.org 4218268Ssteve.reinhardt@amd.com write_hits 4225742Snate@binkert.org .name(name() + ".write_hits") 4235742Snate@binkert.org .desc("DTB write hits") 4245341Sstever@gmail.com ; 4255742Snate@binkert.org 4265742Snate@binkert.org write_misses 4275341Sstever@gmail.com .name(name() + ".write_misses") 4286017Snate@binkert.org .desc("DTB write misses") 4296121Snate@binkert.org ; 4306017Snate@binkert.org 4317816Ssteve.reinhardt@amd.com write_acv 4327756SAli.Saidi@ARM.com .name(name() + ".write_acv") 4337756SAli.Saidi@ARM.com .desc("DTB write access violations") 4347756SAli.Saidi@ARM.com ; 4357756SAli.Saidi@ARM.com 4367756SAli.Saidi@ARM.com write_accesses 4377756SAli.Saidi@ARM.com .name(name() + ".write_accesses") 4387756SAli.Saidi@ARM.com .desc("DTB write accesses") 4397756SAli.Saidi@ARM.com ; 4407816Ssteve.reinhardt@amd.com 4417816Ssteve.reinhardt@amd.com hits 4427816Ssteve.reinhardt@amd.com .name(name() + ".hits") 4437816Ssteve.reinhardt@amd.com .desc("DTB hits") 4447816Ssteve.reinhardt@amd.com ; 4457816Ssteve.reinhardt@amd.com 4467816Ssteve.reinhardt@amd.com misses 4477816Ssteve.reinhardt@amd.com .name(name() + ".misses") 4487816Ssteve.reinhardt@amd.com .desc("DTB misses") 4497816Ssteve.reinhardt@amd.com ; 4507756SAli.Saidi@ARM.com 4517816Ssteve.reinhardt@amd.com acv 4527816Ssteve.reinhardt@amd.com .name(name() + ".acv") 4537816Ssteve.reinhardt@amd.com .desc("DTB access violations") 4547816Ssteve.reinhardt@amd.com ; 4557816Ssteve.reinhardt@amd.com 4567816Ssteve.reinhardt@amd.com accesses 4577816Ssteve.reinhardt@amd.com .name(name() + ".accesses") 4587816Ssteve.reinhardt@amd.com .desc("DTB accesses") 4597816Ssteve.reinhardt@amd.com ; 4607816Ssteve.reinhardt@amd.com 4617816Ssteve.reinhardt@amd.com hits = read_hits + write_hits; 4627816Ssteve.reinhardt@amd.com misses = read_misses + write_misses; 4637816Ssteve.reinhardt@amd.com acv = read_acv + write_acv; 4647816Ssteve.reinhardt@amd.com accesses = read_accesses + write_accesses; 4657816Ssteve.reinhardt@amd.com} 4667816Ssteve.reinhardt@amd.com 4677816Ssteve.reinhardt@amd.comvoid 4687816Ssteve.reinhardt@amd.comAlphaDTB::fault(MemReqPtr &req, uint64_t flags) const 4697816Ssteve.reinhardt@amd.com{ 4707816Ssteve.reinhardt@amd.com ExecContext *xc = req->xc; 4717816Ssteve.reinhardt@amd.com AlphaISA::VAddr vaddr = req->vaddr; 4727816Ssteve.reinhardt@amd.com uint64_t *ipr = xc->regs.ipr; 4737816Ssteve.reinhardt@amd.com 4747816Ssteve.reinhardt@amd.com // Set fault address and flags. Even though we're modeling an 4757816Ssteve.reinhardt@amd.com // EV5, we use the EV6 technique of not latching fault registers 4767816Ssteve.reinhardt@amd.com // on VPTE loads (instead of locking the registers until IPR_VA is 4777816Ssteve.reinhardt@amd.com // read, like the EV5). The EV6 approach is cleaner and seems to 4787816Ssteve.reinhardt@amd.com // work with EV5 PAL code, but not the other way around. 4797816Ssteve.reinhardt@amd.com if (!xc->misspeculating() 4807816Ssteve.reinhardt@amd.com && !(req->flags & VPTE) && !(req->flags & NO_FAULT)) { 4817816Ssteve.reinhardt@amd.com // set VA register with faulting address 4827816Ssteve.reinhardt@amd.com ipr[AlphaISA::IPR_VA] = req->vaddr; 4837816Ssteve.reinhardt@amd.com 4847816Ssteve.reinhardt@amd.com // set MM_STAT register flags 4857816Ssteve.reinhardt@amd.com ipr[AlphaISA::IPR_MM_STAT] = 4867816Ssteve.reinhardt@amd.com (((Opcode(xc->getInst()) & 0x3f) << 11) 4877816Ssteve.reinhardt@amd.com | ((Ra(xc->getInst()) & 0x1f) << 6) 4887816Ssteve.reinhardt@amd.com | (flags & 0x3f)); 4897816Ssteve.reinhardt@amd.com 4907816Ssteve.reinhardt@amd.com // set VA_FORM register with faulting formatted address 4917816Ssteve.reinhardt@amd.com ipr[AlphaISA::IPR_VA_FORM] = 4927816Ssteve.reinhardt@amd.com ipr[AlphaISA::IPR_MVPTBR] | (vaddr.vpn() << 3); 4937816Ssteve.reinhardt@amd.com } 4947816Ssteve.reinhardt@amd.com} 4957816Ssteve.reinhardt@amd.com 4967816Ssteve.reinhardt@amd.comFault 4977816Ssteve.reinhardt@amd.comAlphaDTB::translate(MemReqPtr &req, bool write) const 4987816Ssteve.reinhardt@amd.com{ 4997816Ssteve.reinhardt@amd.com RegFile *regs = &req->xc->regs; 5007816Ssteve.reinhardt@amd.com Addr pc = regs->pc; 5017816Ssteve.reinhardt@amd.com InternalProcReg *ipr = regs->ipr; 5027816Ssteve.reinhardt@amd.com 5037816Ssteve.reinhardt@amd.com AlphaISA::mode_type mode = 5047816Ssteve.reinhardt@amd.com (AlphaISA::mode_type)DTB_CM_CM(ipr[AlphaISA::IPR_DTB_CM]); 5057816Ssteve.reinhardt@amd.com 5067816Ssteve.reinhardt@amd.com 5077816Ssteve.reinhardt@amd.com /** 5087816Ssteve.reinhardt@amd.com * Check for alignment faults 5097816Ssteve.reinhardt@amd.com */ 5107816Ssteve.reinhardt@amd.com if (req->vaddr & (req->size - 1)) { 5117816Ssteve.reinhardt@amd.com fault(req, write ? MM_STAT_WR_MASK : 0); 5128947Sandreas.hansson@arm.com DPRINTF(TLB, "Alignment Fault on %#x, size = %d", req->vaddr, 5138947Sandreas.hansson@arm.com req->size); 5147756SAli.Saidi@ARM.com return genAlignmentFault(); 5158120Sgblack@eecs.umich.edu } 5167756SAli.Saidi@ARM.com 5177756SAli.Saidi@ARM.com if (pc & 0x1) { 5187756SAli.Saidi@ARM.com mode = (req->flags & ALTMODE) ? 5197756SAli.Saidi@ARM.com (AlphaISA::mode_type)ALT_MODE_AM(ipr[AlphaISA::IPR_ALT_MODE]) 5207816Ssteve.reinhardt@amd.com : AlphaISA::mode_kernel; 5217816Ssteve.reinhardt@amd.com } 5227816Ssteve.reinhardt@amd.com 5237816Ssteve.reinhardt@amd.com if (req->flags & PHYSICAL) { 5247816Ssteve.reinhardt@amd.com req->paddr = req->vaddr; 5257816Ssteve.reinhardt@amd.com } else { 5267816Ssteve.reinhardt@amd.com // verify that this is a good virtual address 5277816Ssteve.reinhardt@amd.com if (!validVirtualAddress(req->vaddr)) { 5287816Ssteve.reinhardt@amd.com fault(req, (write ? MM_STAT_WR_MASK : 0) | 5297816Ssteve.reinhardt@amd.com MM_STAT_BAD_VA_MASK | 5307756SAli.Saidi@ARM.com MM_STAT_ACV_MASK); 5317756SAli.Saidi@ARM.com 5329227Sandreas.hansson@arm.com if (write) { write_acv++; } else { read_acv++; } 5339227Sandreas.hansson@arm.com return new DtbPageFault; 5349227Sandreas.hansson@arm.com } 5359227Sandreas.hansson@arm.com 5369590Sandreas@sandberg.pp.se // Check for "superpage" mapping 5379590Sandreas@sandberg.pp.se#if ALPHA_TLASER 5389590Sandreas@sandberg.pp.se if ((MCSR_SP(ipr[AlphaISA::IPR_MCSR]) & 2) && 5399590Sandreas@sandberg.pp.se VAddrSpaceEV5(req->vaddr) == 2) { 5409590Sandreas@sandberg.pp.se#else 5419590Sandreas@sandberg.pp.se if (VAddrSpaceEV6(req->vaddr) == 0x7e) { 5426654Snate@binkert.org#endif 5436654Snate@binkert.org 5445871Snate@binkert.org // only valid in kernel mode 5456121Snate@binkert.org if (DTB_CM_CM(ipr[AlphaISA::IPR_DTB_CM]) != 5468946Sandreas.hansson@arm.com AlphaISA::mode_kernel) { 5479419Sandreas.hansson@arm.com fault(req, ((write ? MM_STAT_WR_MASK : 0) | 5483940Ssaidi@eecs.umich.edu MM_STAT_ACV_MASK)); 5493918Ssaidi@eecs.umich.edu if (write) { write_acv++; } else { read_acv++; } 5503918Ssaidi@eecs.umich.edu return new DtbAcvFault; 5511858SN/A } 5529556Sandreas.hansson@arm.com 5539556Sandreas.hansson@arm.com req->paddr = req->vaddr & PAddrImplMask; 5549556Sandreas.hansson@arm.com 5559556Sandreas.hansson@arm.com#if !ALPHA_TLASER 5569556Sandreas.hansson@arm.com // sign extend the physical address properly 5579556Sandreas.hansson@arm.com if (req->paddr & PAddrUncachedBit40) 5589556Sandreas.hansson@arm.com req->paddr |= ULL(0xf0000000000); 5599556Sandreas.hansson@arm.com else 5609556Sandreas.hansson@arm.com req->paddr &= ULL(0xffffffffff); 5619556Sandreas.hansson@arm.com#endif 5629556Sandreas.hansson@arm.com 5639556Sandreas.hansson@arm.com } else { 5649556Sandreas.hansson@arm.com if (write) 5659556Sandreas.hansson@arm.com write_accesses++; 5669556Sandreas.hansson@arm.com else 5679556Sandreas.hansson@arm.com read_accesses++; 5689556Sandreas.hansson@arm.com 5699556Sandreas.hansson@arm.com // not a physical address: need to look up pte 5709556Sandreas.hansson@arm.com AlphaISA::PTE *pte = lookup(AlphaISA::VAddr(req->vaddr).vpn(), 5719556Sandreas.hansson@arm.com DTB_ASN_ASN(ipr[AlphaISA::IPR_DTB_ASN])); 5729556Sandreas.hansson@arm.com 5739556Sandreas.hansson@arm.com if (!pte) { 5749556Sandreas.hansson@arm.com // page fault 5759556Sandreas.hansson@arm.com fault(req, (write ? MM_STAT_WR_MASK : 0) | 5769556Sandreas.hansson@arm.com MM_STAT_DTB_MISS_MASK); 5779556Sandreas.hansson@arm.com if (write) { write_misses++; } else { read_misses++; } 5789556Sandreas.hansson@arm.com return (req->flags & VPTE) ? 5799556Sandreas.hansson@arm.com (Fault)(new PDtbMissFault) : 5809556Sandreas.hansson@arm.com (Fault)(new NDtbMissFault); 5819556Sandreas.hansson@arm.com } 5829556Sandreas.hansson@arm.com 5839556Sandreas.hansson@arm.com req->paddr = (pte->ppn << AlphaISA::PageShift) + 5846121Snate@binkert.org AlphaISA::VAddr(req->vaddr).offset(); 58510238Sandreas.hansson@arm.com 58610238Sandreas.hansson@arm.com if (write) { 58710238Sandreas.hansson@arm.com if (!(pte->xwe & MODE2MASK(mode))) { 58810238Sandreas.hansson@arm.com // declare the instruction access fault 5899420Sandreas.hansson@arm.com fault(req, MM_STAT_WR_MASK | 59010238Sandreas.hansson@arm.com MM_STAT_ACV_MASK | 59110238Sandreas.hansson@arm.com (pte->fonw ? MM_STAT_FONW_MASK : 0)); 5929420Sandreas.hansson@arm.com write_acv++; 5939420Sandreas.hansson@arm.com return new DtbPageFault; 5949420Sandreas.hansson@arm.com } 5959420Sandreas.hansson@arm.com if (pte->fonw) { 5969420Sandreas.hansson@arm.com fault(req, MM_STAT_WR_MASK | 59710264Sandreas.hansson@arm.com MM_STAT_FONW_MASK); 59810264Sandreas.hansson@arm.com write_acv++; 59910264Sandreas.hansson@arm.com return new DtbPageFault; 60010264Sandreas.hansson@arm.com } 60110264Sandreas.hansson@arm.com } else { 60210264Sandreas.hansson@arm.com if (!(pte->xre & MODE2MASK(mode))) { 60310264Sandreas.hansson@arm.com fault(req, MM_STAT_ACV_MASK | 60410264Sandreas.hansson@arm.com (pte->fonr ? MM_STAT_FONR_MASK : 0)); 60510264Sandreas.hansson@arm.com read_acv++; 60610264Sandreas.hansson@arm.com return new DtbAcvFault; 60710264Sandreas.hansson@arm.com } 60810264Sandreas.hansson@arm.com if (pte->fonr) { 60910264Sandreas.hansson@arm.com fault(req, MM_STAT_FONR_MASK); 61010264Sandreas.hansson@arm.com read_acv++; 61110264Sandreas.hansson@arm.com return new DtbPageFault; 61210264Sandreas.hansson@arm.com } 61310457Sandreas.hansson@arm.com } 61410457Sandreas.hansson@arm.com } 61510457Sandreas.hansson@arm.com 61610457Sandreas.hansson@arm.com if (write) 61710457Sandreas.hansson@arm.com write_hits++; 61810457Sandreas.hansson@arm.com else 61910457Sandreas.hansson@arm.com read_hits++; 62010457Sandreas.hansson@arm.com } 62110457Sandreas.hansson@arm.com 62210238Sandreas.hansson@arm.com // check that the physical address is ok (catch bad physical addresses) 62310238Sandreas.hansson@arm.com if (req->paddr & ~PAddrImplMask) 62410238Sandreas.hansson@arm.com return genMachineCheckFault(); 62510238Sandreas.hansson@arm.com 62610238Sandreas.hansson@arm.com checkCacheability(req); 62710238Sandreas.hansson@arm.com 62810416Sandreas.hansson@arm.com return NoFault; 62910238Sandreas.hansson@arm.com} 6309227Sandreas.hansson@arm.com 63110238Sandreas.hansson@arm.comAlphaISA::PTE & 63210416Sandreas.hansson@arm.comAlphaTLB::index(bool advance) 63310416Sandreas.hansson@arm.com{ 6349227Sandreas.hansson@arm.com AlphaISA::PTE *pte = &table[nlu]; 6359590Sandreas@sandberg.pp.se 6369590Sandreas@sandberg.pp.se if (advance) 6379590Sandreas@sandberg.pp.se nextnlu(); 6388737Skoansin.tan@gmail.com 63910238Sandreas.hansson@arm.com return *pte; 64010238Sandreas.hansson@arm.com} 6419420Sandreas.hansson@arm.com 6428737Skoansin.tan@gmail.comDEFINE_SIM_OBJECT_CLASS_NAME("AlphaTLB", AlphaTLB) 64310106SMitch.Hayenga@arm.com 6448737Skoansin.tan@gmail.comBEGIN_DECLARE_SIM_OBJECT_PARAMS(AlphaITB) 6458737Skoansin.tan@gmail.com 64610238Sandreas.hansson@arm.com Param<int> size; 64710238Sandreas.hansson@arm.com 6488737Skoansin.tan@gmail.comEND_DECLARE_SIM_OBJECT_PARAMS(AlphaITB) 6498737Skoansin.tan@gmail.com 6508737Skoansin.tan@gmail.comBEGIN_INIT_SIM_OBJECT_PARAMS(AlphaITB) 6518737Skoansin.tan@gmail.com 6528737Skoansin.tan@gmail.com INIT_PARAM_DFLT(size, "TLB size", 48) 6538737Skoansin.tan@gmail.com 6549556Sandreas.hansson@arm.comEND_INIT_SIM_OBJECT_PARAMS(AlphaITB) 6559556Sandreas.hansson@arm.com 6569556Sandreas.hansson@arm.com 6579556Sandreas.hansson@arm.comCREATE_SIM_OBJECT(AlphaITB) 6589556Sandreas.hansson@arm.com{ 6599556Sandreas.hansson@arm.com return new AlphaITB(getInstanceName(), size); 6609556Sandreas.hansson@arm.com} 6619556Sandreas.hansson@arm.com 66210278SAndreas.Sandberg@ARM.comREGISTER_SIM_OBJECT("AlphaITB", AlphaITB) 66310278SAndreas.Sandberg@ARM.com 66410278SAndreas.Sandberg@ARM.comBEGIN_DECLARE_SIM_OBJECT_PARAMS(AlphaDTB) 66510278SAndreas.Sandberg@ARM.com 66610278SAndreas.Sandberg@ARM.com Param<int> size; 66710278SAndreas.Sandberg@ARM.com 6689556Sandreas.hansson@arm.comEND_DECLARE_SIM_OBJECT_PARAMS(AlphaDTB) 6699590Sandreas@sandberg.pp.se 6709590Sandreas@sandberg.pp.seBEGIN_INIT_SIM_OBJECT_PARAMS(AlphaDTB) 6719420Sandreas.hansson@arm.com 6729846Sandreas.hansson@arm.com INIT_PARAM_DFLT(size, "TLB size", 64) 6739846Sandreas.hansson@arm.com 6749846Sandreas.hansson@arm.comEND_INIT_SIM_OBJECT_PARAMS(AlphaDTB) 6759846Sandreas.hansson@arm.com 6768946Sandreas.hansson@arm.com 6773918Ssaidi@eecs.umich.eduCREATE_SIM_OBJECT(AlphaDTB) 6789068SAli.Saidi@ARM.com{ 6799068SAli.Saidi@ARM.com return new AlphaDTB(getInstanceName(), size); 6809068SAli.Saidi@ARM.com} 6819068SAli.Saidi@ARM.com 6829068SAli.Saidi@ARM.comREGISTER_SIM_OBJECT("AlphaDTB", AlphaDTB) 6839068SAli.Saidi@ARM.com 6849068SAli.Saidi@ARM.com