tlb.cc revision 8229:78bf55f23338
13101Sstever@eecs.umich.edu/* 23101Sstever@eecs.umich.edu * Copyright (c) 2001-2005 The Regents of The University of Michigan 33101Sstever@eecs.umich.edu * Copyright (c) 2007 MIPS Technologies, Inc. 43101Sstever@eecs.umich.edu * All rights reserved. 53101Sstever@eecs.umich.edu * 63101Sstever@eecs.umich.edu * Redistribution and use in source and binary forms, with or without 73101Sstever@eecs.umich.edu * modification, are permitted provided that the following conditions are 83101Sstever@eecs.umich.edu * met: redistributions of source code must retain the above copyright 93101Sstever@eecs.umich.edu * notice, this list of conditions and the following disclaimer; 103101Sstever@eecs.umich.edu * redistributions in binary form must reproduce the above copyright 113101Sstever@eecs.umich.edu * notice, this list of conditions and the following disclaimer in the 123101Sstever@eecs.umich.edu * documentation and/or other materials provided with the distribution; 133101Sstever@eecs.umich.edu * neither the name of the copyright holders nor the names of its 143101Sstever@eecs.umich.edu * contributors may be used to endorse or promote products derived from 153101Sstever@eecs.umich.edu * this software without specific prior written permission. 163101Sstever@eecs.umich.edu * 173101Sstever@eecs.umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 183101Sstever@eecs.umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 193101Sstever@eecs.umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 203101Sstever@eecs.umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 213101Sstever@eecs.umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 223101Sstever@eecs.umich.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 233101Sstever@eecs.umich.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 243101Sstever@eecs.umich.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 253101Sstever@eecs.umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 263101Sstever@eecs.umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 273101Sstever@eecs.umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 283101Sstever@eecs.umich.edu * 293101Sstever@eecs.umich.edu * Authors: Nathan Binkert 303101Sstever@eecs.umich.edu * Steve Reinhardt 313101Sstever@eecs.umich.edu * Jaidev Patwardhan 323101Sstever@eecs.umich.edu */ 333101Sstever@eecs.umich.edu 343101Sstever@eecs.umich.edu#include <string> 353101Sstever@eecs.umich.edu#include <vector> 363101Sstever@eecs.umich.edu 373101Sstever@eecs.umich.edu#include "arch/mips/faults.hh" 383101Sstever@eecs.umich.edu#include "arch/mips/pagetable.hh" 393101Sstever@eecs.umich.edu#include "arch/mips/pra_constants.hh" 403101Sstever@eecs.umich.edu#include "arch/mips/tlb.hh" 413101Sstever@eecs.umich.edu#include "arch/mips/utility.hh" 423101Sstever@eecs.umich.edu#include "base/inifile.hh" 433101Sstever@eecs.umich.edu#include "base/str.hh" 443101Sstever@eecs.umich.edu#include "base/trace.hh" 453101Sstever@eecs.umich.edu#include "cpu/thread_context.hh" 463101Sstever@eecs.umich.edu#include "mem/page_table.hh" 473885Sbinkertn@umich.edu#include "params/MipsTLB.hh" 483885Sbinkertn@umich.edu#include "sim/process.hh" 494762Snate@binkert.org 503885Sbinkertn@umich.eduusing namespace std; 513885Sbinkertn@umich.eduusing namespace MipsISA; 523885Sbinkertn@umich.edu 534380Sbinkertn@umich.edu/////////////////////////////////////////////////////////////////////// 544167Sbinkertn@umich.edu// 553102Sstever@eecs.umich.edu// MIPS TLB 563101Sstever@eecs.umich.edu// 574762Snate@binkert.org 584762Snate@binkert.orgstatic inline mode_type 594762Snate@binkert.orggetOperatingMode(MiscReg Stat) 604762Snate@binkert.org{ 614762Snate@binkert.org if ((Stat & 0x10000006) != 0 || (Stat & 0x18) ==0) { 624762Snate@binkert.org return mode_kernel; 634762Snate@binkert.org } else if ((Stat & 0x18) == 0x8) { 644762Snate@binkert.org return mode_supervisor; 654762Snate@binkert.org } else if ((Stat & 0x18) == 0x10) { 665033Smilesck@eecs.umich.edu return mode_user; 675033Smilesck@eecs.umich.edu } else { 685033Smilesck@eecs.umich.edu return mode_number; 695033Smilesck@eecs.umich.edu } 705033Smilesck@eecs.umich.edu} 715033Smilesck@eecs.umich.edu 725033Smilesck@eecs.umich.edu 735033Smilesck@eecs.umich.eduTLB::TLB(const Params *p) 745033Smilesck@eecs.umich.edu : BaseTLB(p), size(p->size), nlu(0) 755033Smilesck@eecs.umich.edu{ 763101Sstever@eecs.umich.edu table = new PTE[size]; 773101Sstever@eecs.umich.edu memset(table, 0, sizeof(PTE[size])); 783101Sstever@eecs.umich.edu smallPages = 0; 795033Smilesck@eecs.umich.edu} 803101Sstever@eecs.umich.edu 813101Sstever@eecs.umich.eduTLB::~TLB() 823101Sstever@eecs.umich.edu{ 833101Sstever@eecs.umich.edu if (table) 843101Sstever@eecs.umich.edu delete [] table; 853101Sstever@eecs.umich.edu} 863101Sstever@eecs.umich.edu 873101Sstever@eecs.umich.edu// look up an entry in the TLB 883101Sstever@eecs.umich.eduMipsISA::PTE * 893101Sstever@eecs.umich.eduTLB::lookup(Addr vpn, uint8_t asn) const 903101Sstever@eecs.umich.edu{ 913101Sstever@eecs.umich.edu // assume not found... 923101Sstever@eecs.umich.edu PTE *retval = NULL; 933101Sstever@eecs.umich.edu PageTable::const_iterator i = lookupTable.find(vpn); 943101Sstever@eecs.umich.edu if (i != lookupTable.end()) { 953101Sstever@eecs.umich.edu while (i->first == vpn) { 963101Sstever@eecs.umich.edu int index = i->second; 973101Sstever@eecs.umich.edu PTE *pte = &table[index]; 983101Sstever@eecs.umich.edu 993101Sstever@eecs.umich.edu /* 1KB TLB Lookup code - from MIPS ARM Volume III - Rev. 2.50 */ 1003101Sstever@eecs.umich.edu Addr Mask = pte->Mask; 1013101Sstever@eecs.umich.edu Addr InvMask = ~Mask; 1023101Sstever@eecs.umich.edu Addr VPN = pte->VPN; 1033101Sstever@eecs.umich.edu if (((vpn & InvMask) == (VPN & InvMask)) && 1043101Sstever@eecs.umich.edu (pte->G || (asn == pte->asid))) { 1053101Sstever@eecs.umich.edu // We have a VPN + ASID Match 1063101Sstever@eecs.umich.edu retval = pte; 1073101Sstever@eecs.umich.edu break; 1083101Sstever@eecs.umich.edu } 1093101Sstever@eecs.umich.edu ++i; 1103101Sstever@eecs.umich.edu } 1113101Sstever@eecs.umich.edu } 1123101Sstever@eecs.umich.edu 1133101Sstever@eecs.umich.edu DPRINTF(TLB, "lookup %#x, asn %#x -> %s ppn %#x\n", vpn, (int)asn, 1143101Sstever@eecs.umich.edu retval ? "hit" : "miss", retval ? retval->PFN1 : 0); 1153101Sstever@eecs.umich.edu return retval; 1163101Sstever@eecs.umich.edu} 1173101Sstever@eecs.umich.edu 1183101Sstever@eecs.umich.eduMipsISA::PTE* 1193101Sstever@eecs.umich.eduTLB::getEntry(unsigned Index) const 1203101Sstever@eecs.umich.edu{ 1213101Sstever@eecs.umich.edu // Make sure that Index is valid 1223101Sstever@eecs.umich.edu assert(Index<size); 1233101Sstever@eecs.umich.edu return &table[Index]; 1243101Sstever@eecs.umich.edu} 1253101Sstever@eecs.umich.edu 1263101Sstever@eecs.umich.eduint 1273101Sstever@eecs.umich.eduTLB::probeEntry(Addr vpn, uint8_t asn) const 1283101Sstever@eecs.umich.edu{ 1295033Smilesck@eecs.umich.edu // assume not found... 1305033Smilesck@eecs.umich.edu PTE *retval = NULL; 1315033Smilesck@eecs.umich.edu int Ind = -1; 1325033Smilesck@eecs.umich.edu PageTable::const_iterator i = lookupTable.find(vpn); 1335033Smilesck@eecs.umich.edu if (i != lookupTable.end()) { 1343101Sstever@eecs.umich.edu while (i->first == vpn) { 1353101Sstever@eecs.umich.edu int index = i->second; 1363101Sstever@eecs.umich.edu PTE *pte = &table[index]; 1373101Sstever@eecs.umich.edu 1383101Sstever@eecs.umich.edu /* 1KB TLB Lookup code - from MIPS ARM Volume III - Rev. 2.50 */ 1393101Sstever@eecs.umich.edu Addr Mask = pte->Mask; 1403101Sstever@eecs.umich.edu Addr InvMask = ~Mask; 1413101Sstever@eecs.umich.edu Addr VPN = pte->VPN; 1423101Sstever@eecs.umich.edu if (((vpn & InvMask) == (VPN & InvMask)) && 1433101Sstever@eecs.umich.edu (pte->G || (asn == pte->asid))) { 1443101Sstever@eecs.umich.edu // We have a VPN + ASID Match 1453101Sstever@eecs.umich.edu retval = pte; 1463101Sstever@eecs.umich.edu Ind = index; 1473102Sstever@eecs.umich.edu break; 1483101Sstever@eecs.umich.edu } 1493101Sstever@eecs.umich.edu ++i; 1503101Sstever@eecs.umich.edu } 1513101Sstever@eecs.umich.edu } 1523101Sstever@eecs.umich.edu DPRINTF(MipsPRA,"VPN: %x, asid: %d, Result of TLBP: %d\n",vpn,asn,Ind); 1533101Sstever@eecs.umich.edu return Ind; 1543101Sstever@eecs.umich.edu} 1553101Sstever@eecs.umich.edu 1563101Sstever@eecs.umich.eduinline Fault 1573101Sstever@eecs.umich.eduTLB::checkCacheability(RequestPtr &req) 1583101Sstever@eecs.umich.edu{ 1593101Sstever@eecs.umich.edu Addr VAddrUncacheable = 0xA0000000; 1603101Sstever@eecs.umich.edu // In MIPS, cacheability is controlled by certain bits of the virtual 1613101Sstever@eecs.umich.edu // address or by the TLB entry 1623101Sstever@eecs.umich.edu if ((req->getVaddr() & VAddrUncacheable) == VAddrUncacheable) { 1633101Sstever@eecs.umich.edu // mark request as uncacheable 1643101Sstever@eecs.umich.edu req->setFlags(Request::UNCACHEABLE); 1655033Smilesck@eecs.umich.edu } 1665475Snate@binkert.org return NoFault; 1675475Snate@binkert.org} 1685475Snate@binkert.org 1695475Snate@binkert.orgvoid 1703101Sstever@eecs.umich.eduTLB::insertAt(PTE &pte, unsigned Index, int _smallPages) 1713101Sstever@eecs.umich.edu{ 1723101Sstever@eecs.umich.edu smallPages = _smallPages; 1734762Snate@binkert.org if (Index > size) { 1744762Snate@binkert.org warn("Attempted to write at index (%d) beyond TLB size (%d)", 1754762Snate@binkert.org Index, size); 1763101Sstever@eecs.umich.edu } else { 1773101Sstever@eecs.umich.edu // Update TLB 1783101Sstever@eecs.umich.edu DPRINTF(TLB, "TLB[%d]: %x %x %x %x\n", 1793101Sstever@eecs.umich.edu Index, pte.Mask << 11, 1805037Smilesck@eecs.umich.edu ((pte.VPN << 11) | pte.asid), 1813101Sstever@eecs.umich.edu ((pte.PFN0 << 6) | (pte.C0 << 3) | 1825037Smilesck@eecs.umich.edu (pte.D0 << 2) | (pte.V0 <<1) | pte.G), 1833101Sstever@eecs.umich.edu ((pte.PFN1 <<6) | (pte.C1 << 3) | 1843101Sstever@eecs.umich.edu (pte.D1 << 2) | (pte.V1 <<1) | pte.G)); 1853101Sstever@eecs.umich.edu if (table[Index].V0 == true || table[Index].V1 == true) { 1863101Sstever@eecs.umich.edu // Previous entry is valid 1873101Sstever@eecs.umich.edu PageTable::iterator i = lookupTable.find(table[Index].VPN); 1883101Sstever@eecs.umich.edu lookupTable.erase(i); 1893101Sstever@eecs.umich.edu } 1903101Sstever@eecs.umich.edu table[Index]=pte; 1913101Sstever@eecs.umich.edu // Update fast lookup table 1924762Snate@binkert.org lookupTable.insert(make_pair(table[Index].VPN, Index)); 1934762Snate@binkert.org } 1944762Snate@binkert.org} 1954762Snate@binkert.org 1964762Snate@binkert.org// insert a new TLB entry 1974762Snate@binkert.orgvoid 1984762Snate@binkert.orgTLB::insert(Addr addr, PTE &pte) 1994762Snate@binkert.org{ 2004762Snate@binkert.org fatal("TLB Insert not yet implemented\n"); 2014762Snate@binkert.org} 2024762Snate@binkert.org 2034762Snate@binkert.orgvoid 2044762Snate@binkert.orgTLB::flushAll() 2054762Snate@binkert.org{ 2064762Snate@binkert.org DPRINTF(TLB, "flushAll\n"); 2074762Snate@binkert.org memset(table, 0, sizeof(PTE[size])); 2083101Sstever@eecs.umich.edu lookupTable.clear(); 2093101Sstever@eecs.umich.edu nlu = 0; 2103101Sstever@eecs.umich.edu} 2113101Sstever@eecs.umich.edu 2123101Sstever@eecs.umich.eduvoid 2133101Sstever@eecs.umich.eduTLB::serialize(ostream &os) 2143101Sstever@eecs.umich.edu{ 2153101Sstever@eecs.umich.edu SERIALIZE_SCALAR(size); 2163101Sstever@eecs.umich.edu SERIALIZE_SCALAR(nlu); 2173101Sstever@eecs.umich.edu 2183101Sstever@eecs.umich.edu for (int i = 0; i < size; i++) { 2193101Sstever@eecs.umich.edu nameOut(os, csprintf("%s.PTE%d", name(), i)); 2203101Sstever@eecs.umich.edu table[i].serialize(os); 2213101Sstever@eecs.umich.edu } 2223101Sstever@eecs.umich.edu} 2233101Sstever@eecs.umich.edu 2243101Sstever@eecs.umich.eduvoid 2253101Sstever@eecs.umich.eduTLB::unserialize(Checkpoint *cp, const string §ion) 2263101Sstever@eecs.umich.edu{ 2273101Sstever@eecs.umich.edu UNSERIALIZE_SCALAR(size); 2283101Sstever@eecs.umich.edu UNSERIALIZE_SCALAR(nlu); 2295033Smilesck@eecs.umich.edu 2305033Smilesck@eecs.umich.edu for (int i = 0; i < size; i++) { 2313101Sstever@eecs.umich.edu table[i].unserialize(cp, csprintf("%s.PTE%d", section, i)); 2323101Sstever@eecs.umich.edu if (table[i].V0 || table[i].V1) { 2333101Sstever@eecs.umich.edu lookupTable.insert(make_pair(table[i].VPN, i)); 2343101Sstever@eecs.umich.edu } 2353101Sstever@eecs.umich.edu } 2363101Sstever@eecs.umich.edu} 2373101Sstever@eecs.umich.edu 2383101Sstever@eecs.umich.eduvoid 2393101Sstever@eecs.umich.eduTLB::regStats() 2403101Sstever@eecs.umich.edu{ 2413101Sstever@eecs.umich.edu read_hits 2423101Sstever@eecs.umich.edu .name(name() + ".read_hits") 2433101Sstever@eecs.umich.edu .desc("DTB read hits") 2443101Sstever@eecs.umich.edu ; 2453101Sstever@eecs.umich.edu 2463101Sstever@eecs.umich.edu read_misses 2473101Sstever@eecs.umich.edu .name(name() + ".read_misses") 2483101Sstever@eecs.umich.edu .desc("DTB read misses") 2493101Sstever@eecs.umich.edu ; 2503101Sstever@eecs.umich.edu 2513101Sstever@eecs.umich.edu 2523101Sstever@eecs.umich.edu read_accesses 2533101Sstever@eecs.umich.edu .name(name() + ".read_accesses") 2543101Sstever@eecs.umich.edu .desc("DTB read accesses") 2553101Sstever@eecs.umich.edu ; 2563101Sstever@eecs.umich.edu 2573101Sstever@eecs.umich.edu write_hits 2583101Sstever@eecs.umich.edu .name(name() + ".write_hits") 2594762Snate@binkert.org .desc("DTB write hits") 2604762Snate@binkert.org ; 2614762Snate@binkert.org 2624762Snate@binkert.org write_misses 2633101Sstever@eecs.umich.edu .name(name() + ".write_misses") 2643101Sstever@eecs.umich.edu .desc("DTB write misses") 2653101Sstever@eecs.umich.edu ; 2663101Sstever@eecs.umich.edu 2673101Sstever@eecs.umich.edu 2683101Sstever@eecs.umich.edu write_accesses 2693101Sstever@eecs.umich.edu .name(name() + ".write_accesses") 2703101Sstever@eecs.umich.edu .desc("DTB write accesses") 2713101Sstever@eecs.umich.edu ; 2723101Sstever@eecs.umich.edu 2733101Sstever@eecs.umich.edu hits 2743714Sstever@eecs.umich.edu .name(name() + ".hits") 2753714Sstever@eecs.umich.edu .desc("DTB hits") 2763714Sstever@eecs.umich.edu ; 2773714Sstever@eecs.umich.edu 2783714Sstever@eecs.umich.edu misses 2793714Sstever@eecs.umich.edu .name(name() + ".misses") 2803101Sstever@eecs.umich.edu .desc("DTB misses") 2813101Sstever@eecs.umich.edu ; 2823101Sstever@eecs.umich.edu 2833101Sstever@eecs.umich.edu accesses 2843101Sstever@eecs.umich.edu .name(name() + ".accesses") 2853101Sstever@eecs.umich.edu .desc("DTB accesses") 2863101Sstever@eecs.umich.edu ; 2873101Sstever@eecs.umich.edu 2883101Sstever@eecs.umich.edu hits = read_hits + write_hits; 2893101Sstever@eecs.umich.edu misses = read_misses + write_misses; 2903101Sstever@eecs.umich.edu accesses = read_accesses + write_accesses; 2913101Sstever@eecs.umich.edu} 2923101Sstever@eecs.umich.edu 2933101Sstever@eecs.umich.eduFault 2943101Sstever@eecs.umich.eduTLB::translateInst(RequestPtr req, ThreadContext *tc) 2953101Sstever@eecs.umich.edu{ 2963101Sstever@eecs.umich.edu#if !FULL_SYSTEM 2973101Sstever@eecs.umich.edu Process * p = tc->getProcessPtr(); 2983101Sstever@eecs.umich.edu 2993101Sstever@eecs.umich.edu Fault fault = p->pTable->translate(req); 3003101Sstever@eecs.umich.edu if (fault != NoFault) 3013101Sstever@eecs.umich.edu return fault; 3023101Sstever@eecs.umich.edu 3033101Sstever@eecs.umich.edu return NoFault; 3043101Sstever@eecs.umich.edu#else 3055033Smilesck@eecs.umich.edu Addr vaddr = req->getVaddr(); 3063101Sstever@eecs.umich.edu 3073101Sstever@eecs.umich.edu bool misaligned = (req->getSize() - 1) & vaddr; 3083101Sstever@eecs.umich.edu 3093101Sstever@eecs.umich.edu if (IsKSeg0(vaddr)) { 3103101Sstever@eecs.umich.edu // Address will not be translated through TLB, set response, and go! 3113101Sstever@eecs.umich.edu req->setPaddr(KSeg02Phys(vaddr)); 3123101Sstever@eecs.umich.edu if (getOperatingMode(tc->readMiscReg(MISCREG_STATUS)) != mode_kernel || 3133101Sstever@eecs.umich.edu misaligned) { 3143101Sstever@eecs.umich.edu AddressErrorFault *Flt = new AddressErrorFault(); 3153101Sstever@eecs.umich.edu /* BadVAddr must be set */ 3163101Sstever@eecs.umich.edu Flt->badVAddr = vaddr; 3176214Snate@binkert.org return Flt; 3183101Sstever@eecs.umich.edu } 3193101Sstever@eecs.umich.edu } else if(IsKSeg1(vaddr)) { 3203101Sstever@eecs.umich.edu // Address will not be translated through TLB, set response, and go! 3214762Snate@binkert.org req->setPaddr(KSeg02Phys(vaddr)); 3226214Snate@binkert.org } else { 3233101Sstever@eecs.umich.edu /* 3243101Sstever@eecs.umich.edu * This is an optimization - smallPages is updated every time a TLB 3253101Sstever@eecs.umich.edu * operation is performed. That way, we don't need to look at 3263101Sstever@eecs.umich.edu * Config3 _ SP and PageGrain _ ESP every time we do a TLB lookup 3275822Ssaidi@eecs.umich.edu */ 3285822Ssaidi@eecs.umich.edu Addr VPN; 3293101Sstever@eecs.umich.edu if (smallPages == 1) { 3303101Sstever@eecs.umich.edu VPN = (vaddr >> 11); 3313101Sstever@eecs.umich.edu } else { 3323101Sstever@eecs.umich.edu VPN = ((vaddr >> 11) & 0xFFFFFFFC); 3333101Sstever@eecs.umich.edu } 3343101Sstever@eecs.umich.edu uint8_t Asid = req->getAsid(); 3353101Sstever@eecs.umich.edu if (misaligned) { 3363101Sstever@eecs.umich.edu // Unaligned address! 3373101Sstever@eecs.umich.edu AddressErrorFault *Flt = new AddressErrorFault(); 3383101Sstever@eecs.umich.edu /* BadVAddr must be set */ 3393101Sstever@eecs.umich.edu Flt->badVAddr = vaddr; 3403101Sstever@eecs.umich.edu return Flt; 3413101Sstever@eecs.umich.edu } 3423101Sstever@eecs.umich.edu PTE *pte = lookup(VPN,Asid); 3433101Sstever@eecs.umich.edu if (pte != NULL) { 3443101Sstever@eecs.umich.edu // Ok, found something 3453101Sstever@eecs.umich.edu /* Check for valid bits */ 3463101Sstever@eecs.umich.edu int EvenOdd; 3473101Sstever@eecs.umich.edu bool Valid; 3483101Sstever@eecs.umich.edu if ((((vaddr) >> pte->AddrShiftAmount) & 1) == 0) { 3493101Sstever@eecs.umich.edu // Check even bits 3503102Sstever@eecs.umich.edu Valid = pte->V0; 3513714Sstever@eecs.umich.edu EvenOdd = 0; 3523101Sstever@eecs.umich.edu } else { 3533714Sstever@eecs.umich.edu // Check odd bits 3543714Sstever@eecs.umich.edu Valid = pte->V1; 3553714Sstever@eecs.umich.edu EvenOdd = 1; 3563101Sstever@eecs.umich.edu } 3573101Sstever@eecs.umich.edu 3584762Snate@binkert.org if (Valid == false) { 3594762Snate@binkert.org //Invalid entry 3604762Snate@binkert.org ItbInvalidFault *Flt = new ItbInvalidFault(); 3613101Sstever@eecs.umich.edu /* EntryHi VPN, ASID fields must be set */ 3623101Sstever@eecs.umich.edu Flt->entryHiAsid = Asid; 3633101Sstever@eecs.umich.edu Flt->entryHiVPN2 = (VPN >> 2); 3643101Sstever@eecs.umich.edu Flt->entryHiVPN2X = (VPN & 0x3); 3653101Sstever@eecs.umich.edu 3663101Sstever@eecs.umich.edu /* BadVAddr must be set */ 3673101Sstever@eecs.umich.edu Flt->badVAddr = vaddr; 3683101Sstever@eecs.umich.edu 3693101Sstever@eecs.umich.edu /* Context must be set */ 3703101Sstever@eecs.umich.edu Flt->contextBadVPN2 = (VPN >> 2); 3713101Sstever@eecs.umich.edu return Flt; 3723101Sstever@eecs.umich.edu } else { 3733101Sstever@eecs.umich.edu // Ok, this is really a match, set paddr 3743101Sstever@eecs.umich.edu Addr PAddr; 3753101Sstever@eecs.umich.edu if (EvenOdd == 0) { 3763101Sstever@eecs.umich.edu PAddr = pte->PFN0; 3773101Sstever@eecs.umich.edu } else { 3783101Sstever@eecs.umich.edu PAddr = pte->PFN1; 3793101Sstever@eecs.umich.edu } 3803101Sstever@eecs.umich.edu PAddr >>= (pte->AddrShiftAmount - 12); 3814446Sbinkertn@umich.edu PAddr <<= pte->AddrShiftAmount; 3823101Sstever@eecs.umich.edu PAddr |= (vaddr & pte->OffsetMask); 3835468Snate@binkert.org req->setPaddr(PAddr); 3845468Snate@binkert.org } 3855468Snate@binkert.org } else { 3865468Snate@binkert.org // Didn't find any match, return a TLB Refill Exception 3875468Snate@binkert.org ItbRefillFault *Flt = new ItbRefillFault(); 3885468Snate@binkert.org /* EntryHi VPN, ASID fields must be set */ 3895468Snate@binkert.org Flt->entryHiAsid = Asid; 3904762Snate@binkert.org Flt->entryHiVPN2 = (VPN >> 2); 3914762Snate@binkert.org Flt->entryHiVPN2X = (VPN & 0x3); 3924762Snate@binkert.org 3933101Sstever@eecs.umich.edu /* BadVAddr must be set */ 3943101Sstever@eecs.umich.edu Flt->badVAddr = vaddr; 3953101Sstever@eecs.umich.edu 3963101Sstever@eecs.umich.edu /* Context must be set */ 3973101Sstever@eecs.umich.edu Flt->contextBadVPN2 = (VPN >> 2); 3983101Sstever@eecs.umich.edu return Flt; 3993101Sstever@eecs.umich.edu } 4003101Sstever@eecs.umich.edu } 4013102Sstever@eecs.umich.edu return checkCacheability(req); 4023101Sstever@eecs.umich.edu#endif 4033101Sstever@eecs.umich.edu} 4043101Sstever@eecs.umich.edu 4054168Sbinkertn@umich.eduFault 4063101Sstever@eecs.umich.eduTLB::translateData(RequestPtr req, ThreadContext *tc, bool write) 4073101Sstever@eecs.umich.edu{ 4083101Sstever@eecs.umich.edu#if !FULL_SYSTEM 4093101Sstever@eecs.umich.edu //@TODO: This should actually use TLB instead of going directly 4103101Sstever@eecs.umich.edu // to the page table in syscall mode. 4113101Sstever@eecs.umich.edu /** 4123102Sstever@eecs.umich.edu * Check for alignment faults 4133101Sstever@eecs.umich.edu */ 4143101Sstever@eecs.umich.edu if (req->getVaddr() & (req->getSize() - 1)) { 4153101Sstever@eecs.umich.edu DPRINTF(TLB, "Alignment Fault on %#x, size = %d", req->getVaddr(), 4163101Sstever@eecs.umich.edu req->getSize()); 4173101Sstever@eecs.umich.edu return new AlignmentFault(); 4183101Sstever@eecs.umich.edu } 4193101Sstever@eecs.umich.edu 4203101Sstever@eecs.umich.edu 4213101Sstever@eecs.umich.edu Process * p = tc->getProcessPtr(); 4223101Sstever@eecs.umich.edu 4233101Sstever@eecs.umich.edu Fault fault = p->pTable->translate(req); 4243102Sstever@eecs.umich.edu if (fault != NoFault) 4253101Sstever@eecs.umich.edu return fault; 4263101Sstever@eecs.umich.edu 4273101Sstever@eecs.umich.edu return NoFault; 4283584Ssaidi@eecs.umich.edu#else 4293584Ssaidi@eecs.umich.edu Addr vaddr = req->getVaddr(); 4303584Ssaidi@eecs.umich.edu 4313584Ssaidi@eecs.umich.edu bool misaligned = (req->getSize() - 1) & vaddr; 4323584Ssaidi@eecs.umich.edu 4333101Sstever@eecs.umich.edu if (IsKSeg0(vaddr)) { 4343101Sstever@eecs.umich.edu // Address will not be translated through TLB, set response, and go! 4355033Smilesck@eecs.umich.edu req->setPaddr(KSeg02Phys(vaddr)); 4363101Sstever@eecs.umich.edu if (getOperatingMode(tc->readMiscReg(MISCREG_STATUS)) != mode_kernel || 4373101Sstever@eecs.umich.edu misaligned) { 4383101Sstever@eecs.umich.edu StoreAddressErrorFault *Flt = new StoreAddressErrorFault(); 4393101Sstever@eecs.umich.edu /* BadVAddr must be set */ 4403101Sstever@eecs.umich.edu Flt->badVAddr = vaddr; 4413101Sstever@eecs.umich.edu 4423101Sstever@eecs.umich.edu return Flt; 4433101Sstever@eecs.umich.edu } 4443101Sstever@eecs.umich.edu } else if(IsKSeg1(vaddr)) { 4453101Sstever@eecs.umich.edu // Address will not be translated through TLB, set response, and go! 4463101Sstever@eecs.umich.edu req->setPaddr(KSeg02Phys(vaddr)); 4473101Sstever@eecs.umich.edu } else { 4483101Sstever@eecs.umich.edu /* 4493101Sstever@eecs.umich.edu * This is an optimization - smallPages is updated every time a TLB 4503101Sstever@eecs.umich.edu * operation is performed. That way, we don't need to look at 4513101Sstever@eecs.umich.edu * Config3 _ SP and PageGrain _ ESP every time we do a TLB lookup 4523101Sstever@eecs.umich.edu */ 4533101Sstever@eecs.umich.edu Addr VPN = (vaddr >> 11) & 0xFFFFFFFC; 4543101Sstever@eecs.umich.edu if (smallPages == 1) { 4553101Sstever@eecs.umich.edu VPN = vaddr >> 11; 4563101Sstever@eecs.umich.edu } 4573101Sstever@eecs.umich.edu uint8_t Asid = req->getAsid(); 4583101Sstever@eecs.umich.edu PTE *pte = lookup(VPN, Asid); 4593101Sstever@eecs.umich.edu if (misaligned) { 4603101Sstever@eecs.umich.edu // Unaligned address! 4613101Sstever@eecs.umich.edu StoreAddressErrorFault *Flt = new StoreAddressErrorFault(); 4623101Sstever@eecs.umich.edu /* BadVAddr must be set */ 4633101Sstever@eecs.umich.edu Flt->badVAddr = vaddr; 4643101Sstever@eecs.umich.edu return Flt; 4653101Sstever@eecs.umich.edu } 4663101Sstever@eecs.umich.edu if (pte != NULL) { 4675219Ssaidi@eecs.umich.edu // Ok, found something 4685219Ssaidi@eecs.umich.edu /* Check for valid bits */ 4695219Ssaidi@eecs.umich.edu int EvenOdd; 4703101Sstever@eecs.umich.edu bool Valid; 4713101Sstever@eecs.umich.edu bool Dirty; 4723101Sstever@eecs.umich.edu if ((((vaddr >> pte->AddrShiftAmount) & 1)) == 0) { 4733101Sstever@eecs.umich.edu // Check even bits 4743101Sstever@eecs.umich.edu Valid = pte->V0; 4753101Sstever@eecs.umich.edu Dirty = pte->D0; 4763101Sstever@eecs.umich.edu EvenOdd = 0; 4773101Sstever@eecs.umich.edu } else { 4783101Sstever@eecs.umich.edu // Check odd bits 4793101Sstever@eecs.umich.edu Valid = pte->V1; 4803101Sstever@eecs.umich.edu Dirty = pte->D1; 4813101Sstever@eecs.umich.edu EvenOdd = 1; 4823101Sstever@eecs.umich.edu } 4833101Sstever@eecs.umich.edu 4843101Sstever@eecs.umich.edu if (Valid == false) { 4853101Sstever@eecs.umich.edu //Invalid entry 4863101Sstever@eecs.umich.edu DtbInvalidFault *Flt = new DtbInvalidFault(); 4873101Sstever@eecs.umich.edu /* EntryHi VPN, ASID fields must be set */ 4884762Snate@binkert.org Flt->entryHiAsid = Asid; 4894762Snate@binkert.org Flt->entryHiVPN2 = (VPN>>2); 4904762Snate@binkert.org Flt->entryHiVPN2X = (VPN & 0x3); 4914762Snate@binkert.org 4924762Snate@binkert.org /* BadVAddr must be set */ 4934762Snate@binkert.org Flt->badVAddr = vaddr; 4944762Snate@binkert.org 4954762Snate@binkert.org /* Context must be set */ 4964762Snate@binkert.org Flt->contextBadVPN2 = (VPN >> 2); 4973101Sstever@eecs.umich.edu 4983101Sstever@eecs.umich.edu return Flt; 4993101Sstever@eecs.umich.edu } else { 5004762Snate@binkert.org // Ok, this is really a match, set paddr 5014762Snate@binkert.org if (!Dirty) { 5024762Snate@binkert.org TLBModifiedFault *Flt = new TLBModifiedFault(); 5034762Snate@binkert.org /* EntryHi VPN, ASID fields must be set */ 5044762Snate@binkert.org Flt->entryHiAsid = Asid; 5054762Snate@binkert.org Flt->entryHiVPN2 = (VPN >> 2); 5064762Snate@binkert.org Flt->entryHiVPN2X = (VPN & 0x3); 5074762Snate@binkert.org 5084762Snate@binkert.org /* BadVAddr must be set */ 5093101Sstever@eecs.umich.edu Flt->badVAddr = vaddr; 5103101Sstever@eecs.umich.edu 5113101Sstever@eecs.umich.edu /* Context must be set */ 5123101Sstever@eecs.umich.edu Flt->contextBadVPN2 = (VPN >> 2); 5133101Sstever@eecs.umich.edu return Flt; 5143101Sstever@eecs.umich.edu } 5153101Sstever@eecs.umich.edu Addr PAddr; 5163101Sstever@eecs.umich.edu if (EvenOdd == 0) { 5173102Sstever@eecs.umich.edu PAddr = pte->PFN0; 5183101Sstever@eecs.umich.edu } else { 5193101Sstever@eecs.umich.edu PAddr = pte->PFN1; 5203101Sstever@eecs.umich.edu } 5214762Snate@binkert.org PAddr >>= (pte->AddrShiftAmount - 12); 5224762Snate@binkert.org PAddr <<= pte->AddrShiftAmount; 5234762Snate@binkert.org PAddr |= (vaddr & pte->OffsetMask); 5243101Sstever@eecs.umich.edu req->setPaddr(PAddr); 5253101Sstever@eecs.umich.edu } 5263101Sstever@eecs.umich.edu } else { 5273101Sstever@eecs.umich.edu // Didn't find any match, return a TLB Refill Exception 5283101Sstever@eecs.umich.edu DtbRefillFault *Flt = new DtbRefillFault(); 5293101Sstever@eecs.umich.edu /* EntryHi VPN, ASID fields must be set */ 5303101Sstever@eecs.umich.edu Flt->entryHiAsid = Asid; 5313101Sstever@eecs.umich.edu Flt->entryHiVPN2 = (VPN >> 2); 5323101Sstever@eecs.umich.edu Flt->entryHiVPN2X = (VPN & 0x3); 5333101Sstever@eecs.umich.edu 5343101Sstever@eecs.umich.edu /* BadVAddr must be set */ 5353101Sstever@eecs.umich.edu Flt->badVAddr = vaddr; 5363101Sstever@eecs.umich.edu 5373101Sstever@eecs.umich.edu /* Context must be set */ 5383101Sstever@eecs.umich.edu Flt->contextBadVPN2 = (VPN >> 2); 5393101Sstever@eecs.umich.edu return Flt; 5403101Sstever@eecs.umich.edu } 5413101Sstever@eecs.umich.edu } 5423101Sstever@eecs.umich.edu return checkCacheability(req); 5433101Sstever@eecs.umich.edu#endif 5444380Sbinkertn@umich.edu} 5454380Sbinkertn@umich.edu 5464380Sbinkertn@umich.eduFault 5473101Sstever@eecs.umich.eduTLB::translateAtomic(RequestPtr req, ThreadContext *tc, Mode mode) 5484380Sbinkertn@umich.edu{ 5494380Sbinkertn@umich.edu if (mode == Execute) 5504380Sbinkertn@umich.edu return translateInst(req, tc); 5513101Sstever@eecs.umich.edu else 5523101Sstever@eecs.umich.edu return translateData(req, tc, mode == Write); 5533101Sstever@eecs.umich.edu} 5543101Sstever@eecs.umich.edu 5554762Snate@binkert.orgvoid 5563101Sstever@eecs.umich.eduTLB::translateTiming(RequestPtr req, ThreadContext *tc, 5573101Sstever@eecs.umich.edu Translation *translation, Mode mode) 5583101Sstever@eecs.umich.edu{ 5593101Sstever@eecs.umich.edu assert(translation); 5603101Sstever@eecs.umich.edu translation->finish(translateAtomic(req, tc, mode), req, tc, mode); 5613101Sstever@eecs.umich.edu} 5623101Sstever@eecs.umich.edu 5633101Sstever@eecs.umich.edu 5643101Sstever@eecs.umich.eduMipsISA::PTE & 5653101Sstever@eecs.umich.eduTLB::index(bool advance) 5663101Sstever@eecs.umich.edu{ 5673101Sstever@eecs.umich.edu PTE *pte = &table[nlu]; 5683101Sstever@eecs.umich.edu 5693101Sstever@eecs.umich.edu if (advance) 5703101Sstever@eecs.umich.edu nextnlu(); 5713101Sstever@eecs.umich.edu 5723101Sstever@eecs.umich.edu return *pte; 5733101Sstever@eecs.umich.edu} 5743101Sstever@eecs.umich.edu 5753101Sstever@eecs.umich.eduMipsISA::TLB * 5764380Sbinkertn@umich.eduMipsTLBParams::create() 5773101Sstever@eecs.umich.edu{ 5783101Sstever@eecs.umich.edu return new TLB(this); 5794762Snate@binkert.org} 5804762Snate@binkert.org