tlb.cc revision 6038:4c21637acedd
111308Santhony.gutierrez@amd.com/* 211308Santhony.gutierrez@amd.com * Copyright (c) 2001-2005 The Regents of The University of Michigan 311308Santhony.gutierrez@amd.com * Copyright (c) 2007 MIPS Technologies, Inc. 411308Santhony.gutierrez@amd.com * All rights reserved. 511308Santhony.gutierrez@amd.com * 611308Santhony.gutierrez@amd.com * Redistribution and use in source and binary forms, with or without 711308Santhony.gutierrez@amd.com * modification, are permitted provided that the following conditions are 811308Santhony.gutierrez@amd.com * met: redistributions of source code must retain the above copyright 911308Santhony.gutierrez@amd.com * notice, this list of conditions and the following disclaimer; 1011308Santhony.gutierrez@amd.com * redistributions in binary form must reproduce the above copyright 1111308Santhony.gutierrez@amd.com * notice, this list of conditions and the following disclaimer in the 1211308Santhony.gutierrez@amd.com * documentation and/or other materials provided with the distribution; 1311308Santhony.gutierrez@amd.com * neither the name of the copyright holders nor the names of its 1411308Santhony.gutierrez@amd.com * contributors may be used to endorse or promote products derived from 1511308Santhony.gutierrez@amd.com * this software without specific prior written permission. 1611308Santhony.gutierrez@amd.com * 1711308Santhony.gutierrez@amd.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 1811308Santhony.gutierrez@amd.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 1911308Santhony.gutierrez@amd.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 2011308Santhony.gutierrez@amd.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 2111308Santhony.gutierrez@amd.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 2211308Santhony.gutierrez@amd.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 2311308Santhony.gutierrez@amd.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2411308Santhony.gutierrez@amd.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2511308Santhony.gutierrez@amd.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2611308Santhony.gutierrez@amd.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 2711308Santhony.gutierrez@amd.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2811308Santhony.gutierrez@amd.com * 2911308Santhony.gutierrez@amd.com * Authors: Nathan Binkert 3011308Santhony.gutierrez@amd.com * Steve Reinhardt 3111308Santhony.gutierrez@amd.com * Jaidev Patwardhan 3211308Santhony.gutierrez@amd.com */ 3311308Santhony.gutierrez@amd.com 3411308Santhony.gutierrez@amd.com#include <string> 3511308Santhony.gutierrez@amd.com#include <vector> 3611308Santhony.gutierrez@amd.com 3711308Santhony.gutierrez@amd.com#include "arch/mips/pra_constants.hh" 3811308Santhony.gutierrez@amd.com#include "arch/mips/pagetable.hh" 3911308Santhony.gutierrez@amd.com#include "arch/mips/tlb.hh" 4011308Santhony.gutierrez@amd.com#include "arch/mips/faults.hh" 4111308Santhony.gutierrez@amd.com#include "arch/mips/utility.hh" 4211308Santhony.gutierrez@amd.com#include "base/inifile.hh" 4311308Santhony.gutierrez@amd.com#include "base/str.hh" 4411308Santhony.gutierrez@amd.com#include "base/trace.hh" 4511308Santhony.gutierrez@amd.com#include "cpu/thread_context.hh" 4611308Santhony.gutierrez@amd.com#include "sim/process.hh" 4711308Santhony.gutierrez@amd.com#include "mem/page_table.hh" 4811308Santhony.gutierrez@amd.com#include "params/MipsTLB.hh" 4911308Santhony.gutierrez@amd.com 5011308Santhony.gutierrez@amd.com 5111308Santhony.gutierrez@amd.comusing namespace std; 5211308Santhony.gutierrez@amd.comusing namespace MipsISA; 5311308Santhony.gutierrez@amd.com 5411308Santhony.gutierrez@amd.com/////////////////////////////////////////////////////////////////////// 5511641Salexandru.dutu@amd.com// 5611641Salexandru.dutu@amd.com// MIPS TLB 5711641Salexandru.dutu@amd.com// 5811641Salexandru.dutu@amd.com 5911641Salexandru.dutu@amd.com#define MODE2MASK(X) (1 << (X)) 6011641Salexandru.dutu@amd.com 6111641Salexandru.dutu@amd.comTLB::TLB(const Params *p) 6211641Salexandru.dutu@amd.com : BaseTLB(p), size(p->size), nlu(0) 6311641Salexandru.dutu@amd.com{ 6411641Salexandru.dutu@amd.com table = new MipsISA::PTE[size]; 6511641Salexandru.dutu@amd.com memset(table, 0, sizeof(MipsISA::PTE[size])); 6611641Salexandru.dutu@amd.com smallPages=0; 6711641Salexandru.dutu@amd.com} 6811641Salexandru.dutu@amd.com 6911641Salexandru.dutu@amd.comTLB::~TLB() 7011641Salexandru.dutu@amd.com{ 7111641Salexandru.dutu@amd.com if (table) 7211641Salexandru.dutu@amd.com delete [] table; 7311641Salexandru.dutu@amd.com} 7411641Salexandru.dutu@amd.com 7511641Salexandru.dutu@amd.com// look up an entry in the TLB 7611308Santhony.gutierrez@amd.comMipsISA::PTE * 7711308Santhony.gutierrez@amd.comTLB::lookup(Addr vpn, uint8_t asn) const 7811308Santhony.gutierrez@amd.com{ 7911308Santhony.gutierrez@amd.com // assume not found... 8011308Santhony.gutierrez@amd.com MipsISA::PTE *retval = NULL; 8111308Santhony.gutierrez@amd.com PageTable::const_iterator i = lookupTable.find(vpn); 8211308Santhony.gutierrez@amd.com if (i != lookupTable.end()) { 8311308Santhony.gutierrez@amd.com while (i->first == vpn) { 8411308Santhony.gutierrez@amd.com int index = i->second; 8511308Santhony.gutierrez@amd.com MipsISA::PTE *pte = &table[index]; 8611308Santhony.gutierrez@amd.com 8711308Santhony.gutierrez@amd.com /* 1KB TLB Lookup code - from MIPS ARM Volume III - Rev. 2.50 */ 8811308Santhony.gutierrez@amd.com Addr Mask = pte->Mask; 8911308Santhony.gutierrez@amd.com Addr InvMask = ~Mask; 9011308Santhony.gutierrez@amd.com Addr VPN = pte->VPN; 9111308Santhony.gutierrez@amd.com // warn("Valid: %d - %d\n",pte->V0,pte->V1); 9211308Santhony.gutierrez@amd.com if(((vpn & InvMask) == (VPN & InvMask)) && (pte->G || (asn == pte->asid))) 9311308Santhony.gutierrez@amd.com { // We have a VPN + ASID Match 9411308Santhony.gutierrez@amd.com retval = pte; 9511308Santhony.gutierrez@amd.com break; 9611308Santhony.gutierrez@amd.com } 9711308Santhony.gutierrez@amd.com ++i; 9811308Santhony.gutierrez@amd.com } 9911308Santhony.gutierrez@amd.com } 10011308Santhony.gutierrez@amd.com 10111308Santhony.gutierrez@amd.com DPRINTF(TLB, "lookup %#x, asn %#x -> %s ppn %#x\n", vpn, (int)asn, 10211308Santhony.gutierrez@amd.com retval ? "hit" : "miss", retval ? retval->PFN1 : 0); 10311308Santhony.gutierrez@amd.com return retval; 10411308Santhony.gutierrez@amd.com} 10511308Santhony.gutierrez@amd.com 10611308Santhony.gutierrez@amd.comMipsISA::PTE* TLB::getEntry(unsigned Index) const 10711534Sjohn.kalamatianos@amd.com{ 10811308Santhony.gutierrez@amd.com // Make sure that Index is valid 10911308Santhony.gutierrez@amd.com assert(Index<size); 11011308Santhony.gutierrez@amd.com return &table[Index]; 11111308Santhony.gutierrez@amd.com} 11211308Santhony.gutierrez@amd.com 11311308Santhony.gutierrez@amd.comint TLB::probeEntry(Addr vpn,uint8_t asn) const 11411308Santhony.gutierrez@amd.com{ 11511534Sjohn.kalamatianos@amd.com // assume not found... 11611308Santhony.gutierrez@amd.com MipsISA::PTE *retval = NULL; 11711308Santhony.gutierrez@amd.com int Ind=-1; 11811534Sjohn.kalamatianos@amd.com PageTable::const_iterator i = lookupTable.find(vpn); 11911534Sjohn.kalamatianos@amd.com if (i != lookupTable.end()) { 12011308Santhony.gutierrez@amd.com while (i->first == vpn) { 12111534Sjohn.kalamatianos@amd.com int index = i->second; 12211308Santhony.gutierrez@amd.com MipsISA::PTE *pte = &table[index]; 12311308Santhony.gutierrez@amd.com 12411308Santhony.gutierrez@amd.com /* 1KB TLB Lookup code - from MIPS ARM Volume III - Rev. 2.50 */ 12511308Santhony.gutierrez@amd.com Addr Mask = pte->Mask; 12611308Santhony.gutierrez@amd.com Addr InvMask = ~Mask; 12711308Santhony.gutierrez@amd.com Addr VPN = pte->VPN; 12811308Santhony.gutierrez@amd.com if(((vpn & InvMask) == (VPN & InvMask)) && (pte->G || (asn == pte->asid))) 12911308Santhony.gutierrez@amd.com { // We have a VPN + ASID Match 13011308Santhony.gutierrez@amd.com retval = pte; 13111308Santhony.gutierrez@amd.com Ind = index; 13211308Santhony.gutierrez@amd.com break; 13311308Santhony.gutierrez@amd.com } 13411308Santhony.gutierrez@amd.com 13511308Santhony.gutierrez@amd.com ++i; 13611308Santhony.gutierrez@amd.com } 13711308Santhony.gutierrez@amd.com } 13811308Santhony.gutierrez@amd.com DPRINTF(MipsPRA,"VPN: %x, asid: %d, Result of TLBP: %d\n",vpn,asn,Ind); 13911308Santhony.gutierrez@amd.com return Ind; 14011308Santhony.gutierrez@amd.com} 14111308Santhony.gutierrez@amd.comFault inline 14211308Santhony.gutierrez@amd.comTLB::checkCacheability(RequestPtr &req) 14311308Santhony.gutierrez@amd.com{ 14411308Santhony.gutierrez@amd.com Addr VAddrUncacheable = 0xA0000000; 14511308Santhony.gutierrez@amd.com // In MIPS, cacheability is controlled by certain bits of the virtual address 14611308Santhony.gutierrez@amd.com // or by the TLB entry 14711308Santhony.gutierrez@amd.com if((req->getVaddr() & VAddrUncacheable) == VAddrUncacheable) { 14811308Santhony.gutierrez@amd.com // mark request as uncacheable 14911308Santhony.gutierrez@amd.com req->setFlags(Request::UNCACHEABLE); 15011308Santhony.gutierrez@amd.com } 15111639Salexandru.dutu@amd.com return NoFault; 15211308Santhony.gutierrez@amd.com} 15311639Salexandru.dutu@amd.comvoid TLB::insertAt(MipsISA::PTE &pte, unsigned Index, int _smallPages) 15411639Salexandru.dutu@amd.com{ 15511639Salexandru.dutu@amd.com smallPages=_smallPages; 15611639Salexandru.dutu@amd.com if(Index > size){ 15711308Santhony.gutierrez@amd.com warn("Attempted to write at index (%d) beyond TLB size (%d)",Index,size); 15811308Santhony.gutierrez@amd.com } else { 15911308Santhony.gutierrez@amd.com // Update TLB 16011639Salexandru.dutu@amd.com DPRINTF(TLB,"TLB[%d]: %x %x %x %x\n",Index,pte.Mask<<11,((pte.VPN << 11) | pte.asid),((pte.PFN0 <<6) | (pte.C0 << 3) | (pte.D0 << 2) | (pte.V0 <<1) | pte.G), 16111308Santhony.gutierrez@amd.com ((pte.PFN1 <<6) | (pte.C1 << 3) | (pte.D1 << 2) | (pte.V1 <<1) | pte.G)); 16211308Santhony.gutierrez@amd.com if(table[Index].V0 == true || table[Index].V1 == true){ // Previous entry is valid 16311308Santhony.gutierrez@amd.com PageTable::iterator i = lookupTable.find(table[Index].VPN); 16411308Santhony.gutierrez@amd.com lookupTable.erase(i); 16511308Santhony.gutierrez@amd.com } 16611308Santhony.gutierrez@amd.com table[Index]=pte; 16711308Santhony.gutierrez@amd.com // Update fast lookup table 16811308Santhony.gutierrez@amd.com lookupTable.insert(make_pair(table[Index].VPN, Index)); 16911308Santhony.gutierrez@amd.com // int TestIndex=probeEntry(pte.VPN,pte.asid); 17011308Santhony.gutierrez@amd.com // warn("Inserted at: %d, Found at: %d (%x)\n",Index,TestIndex,pte.Mask); 17111308Santhony.gutierrez@amd.com } 17211308Santhony.gutierrez@amd.com 17311308Santhony.gutierrez@amd.com} 17411308Santhony.gutierrez@amd.com 17511308Santhony.gutierrez@amd.com// insert a new TLB entry 17611308Santhony.gutierrez@amd.comvoid 17711308Santhony.gutierrez@amd.comTLB::insert(Addr addr, MipsISA::PTE &pte) 17811308Santhony.gutierrez@amd.com{ 17911308Santhony.gutierrez@amd.com fatal("TLB Insert not yet implemented\n"); 18011308Santhony.gutierrez@amd.com 18111308Santhony.gutierrez@amd.com 18211308Santhony.gutierrez@amd.com /* MipsISA::VAddr vaddr = addr; 18311308Santhony.gutierrez@amd.com if (table[nlu].valid) { 18411308Santhony.gutierrez@amd.com Addr oldvpn = table[nlu].tag; 18511308Santhony.gutierrez@amd.com PageTable::iterator i = lookupTable.find(oldvpn); 18611308Santhony.gutierrez@amd.com 18711308Santhony.gutierrez@amd.com if (i == lookupTable.end()) 18811308Santhony.gutierrez@amd.com panic("TLB entry not found in lookupTable"); 18911639Salexandru.dutu@amd.com 19011639Salexandru.dutu@amd.com int index; 19111639Salexandru.dutu@amd.com while ((index = i->second) != nlu) { 19211639Salexandru.dutu@amd.com if (table[index].tag != oldvpn) 19311639Salexandru.dutu@amd.com panic("TLB entry not found in lookupTable"); 19411639Salexandru.dutu@amd.com 19511639Salexandru.dutu@amd.com ++i; 19611639Salexandru.dutu@amd.com } 19711643Salexandru.dutu@amd.com 19811643Salexandru.dutu@amd.com DPRINTF(TLB, "remove @%d: %#x -> %#x\n", nlu, oldvpn, table[nlu].ppn); 19911639Salexandru.dutu@amd.com 20011639Salexandru.dutu@amd.com lookupTable.erase(i); 20111308Santhony.gutierrez@amd.com } 20211639Salexandru.dutu@amd.com 20311308Santhony.gutierrez@amd.com DPRINTF(TLB, "insert @%d: %#x -> %#x\n", nlu, vaddr.vpn(), pte.ppn); 20411308Santhony.gutierrez@amd.com 20511639Salexandru.dutu@amd.com table[nlu] = pte; 20611308Santhony.gutierrez@amd.com table[nlu].tag = vaddr.vpn(); 20711639Salexandru.dutu@amd.com table[nlu].valid = true; 20811308Santhony.gutierrez@amd.com 20911639Salexandru.dutu@amd.com lookupTable.insert(make_pair(vaddr.vpn(), nlu)); 21011308Santhony.gutierrez@amd.com nextnlu(); 21111639Salexandru.dutu@amd.com */ 21211308Santhony.gutierrez@amd.com} 21311639Salexandru.dutu@amd.com 21411639Salexandru.dutu@amd.comvoid 21511639Salexandru.dutu@amd.comTLB::flushAll() 21611639Salexandru.dutu@amd.com{ 21711639Salexandru.dutu@amd.com DPRINTF(TLB, "flushAll\n"); 21811308Santhony.gutierrez@amd.com memset(table, 0, sizeof(MipsISA::PTE[size])); 21911639Salexandru.dutu@amd.com lookupTable.clear(); 22011639Salexandru.dutu@amd.com nlu = 0; 22111308Santhony.gutierrez@amd.com} 22211308Santhony.gutierrez@amd.com 22311308Santhony.gutierrez@amd.comvoid 22411308Santhony.gutierrez@amd.comTLB::serialize(ostream &os) 22511308Santhony.gutierrez@amd.com{ 22611308Santhony.gutierrez@amd.com SERIALIZE_SCALAR(size); 22711308Santhony.gutierrez@amd.com SERIALIZE_SCALAR(nlu); 22811639Salexandru.dutu@amd.com 22911308Santhony.gutierrez@amd.com for (int i = 0; i < size; i++) { 23011639Salexandru.dutu@amd.com nameOut(os, csprintf("%s.PTE%d", name(), i)); 23111308Santhony.gutierrez@amd.com table[i].serialize(os); 23211639Salexandru.dutu@amd.com } 23311308Santhony.gutierrez@amd.com} 23411308Santhony.gutierrez@amd.com 23511639Salexandru.dutu@amd.comvoid 23611308Santhony.gutierrez@amd.comTLB::unserialize(Checkpoint *cp, const string §ion) 23711639Salexandru.dutu@amd.com{ 23811308Santhony.gutierrez@amd.com UNSERIALIZE_SCALAR(size); 23911639Salexandru.dutu@amd.com UNSERIALIZE_SCALAR(nlu); 24011308Santhony.gutierrez@amd.com 24111308Santhony.gutierrez@amd.com for (int i = 0; i < size; i++) { 24211639Salexandru.dutu@amd.com table[i].unserialize(cp, csprintf("%s.PTE%d", section, i)); 24311308Santhony.gutierrez@amd.com if (table[i].V0 || table[i].V1) { 24411308Santhony.gutierrez@amd.com lookupTable.insert(make_pair(table[i].VPN, i)); 24511639Salexandru.dutu@amd.com } 24611639Salexandru.dutu@amd.com } 24711308Santhony.gutierrez@amd.com} 24811308Santhony.gutierrez@amd.com 24911308Santhony.gutierrez@amd.comvoid 25011308Santhony.gutierrez@amd.comTLB::regStats() 25111308Santhony.gutierrez@amd.com{ 25211308Santhony.gutierrez@amd.com read_hits 25311308Santhony.gutierrez@amd.com .name(name() + ".read_hits") 25411308Santhony.gutierrez@amd.com .desc("DTB read hits") 25511308Santhony.gutierrez@amd.com ; 25611308Santhony.gutierrez@amd.com 25711308Santhony.gutierrez@amd.com read_misses 25811308Santhony.gutierrez@amd.com .name(name() + ".read_misses") 25911308Santhony.gutierrez@amd.com .desc("DTB read misses") 26011308Santhony.gutierrez@amd.com ; 26111308Santhony.gutierrez@amd.com 26211308Santhony.gutierrez@amd.com 26311308Santhony.gutierrez@amd.com read_accesses 26411308Santhony.gutierrez@amd.com .name(name() + ".read_accesses") 26511308Santhony.gutierrez@amd.com .desc("DTB read accesses") 26611308Santhony.gutierrez@amd.com ; 26711308Santhony.gutierrez@amd.com 26811308Santhony.gutierrez@amd.com write_hits 26911308Santhony.gutierrez@amd.com .name(name() + ".write_hits") 27011308Santhony.gutierrez@amd.com .desc("DTB write hits") 27111308Santhony.gutierrez@amd.com ; 27211308Santhony.gutierrez@amd.com 27311308Santhony.gutierrez@amd.com write_misses 27411308Santhony.gutierrez@amd.com .name(name() + ".write_misses") 27511308Santhony.gutierrez@amd.com .desc("DTB write misses") 27611308Santhony.gutierrez@amd.com ; 27711308Santhony.gutierrez@amd.com 27811308Santhony.gutierrez@amd.com 27911308Santhony.gutierrez@amd.com write_accesses 28011308Santhony.gutierrez@amd.com .name(name() + ".write_accesses") 28111308Santhony.gutierrez@amd.com .desc("DTB write accesses") 28211308Santhony.gutierrez@amd.com ; 28311308Santhony.gutierrez@amd.com 28411308Santhony.gutierrez@amd.com hits 28511308Santhony.gutierrez@amd.com .name(name() + ".hits") 28611308Santhony.gutierrez@amd.com .desc("DTB hits") 28711308Santhony.gutierrez@amd.com ; 28811308Santhony.gutierrez@amd.com 28911308Santhony.gutierrez@amd.com misses 29011308Santhony.gutierrez@amd.com .name(name() + ".misses") 29111308Santhony.gutierrez@amd.com .desc("DTB misses") 29211308Santhony.gutierrez@amd.com ; 29311308Santhony.gutierrez@amd.com 29411534Sjohn.kalamatianos@amd.com invalids 29511308Santhony.gutierrez@amd.com .name(name() + ".invalids") 29611534Sjohn.kalamatianos@amd.com .desc("DTB access violations") 29711308Santhony.gutierrez@amd.com ; 29811308Santhony.gutierrez@amd.com 29911308Santhony.gutierrez@amd.com accesses 30011308Santhony.gutierrez@amd.com .name(name() + ".accesses") 30111308Santhony.gutierrez@amd.com .desc("DTB accesses") 30211308Santhony.gutierrez@amd.com ; 30311308Santhony.gutierrez@amd.com 30411308Santhony.gutierrez@amd.com hits = read_hits + write_hits; 30511308Santhony.gutierrez@amd.com misses = read_misses + write_misses; 30611308Santhony.gutierrez@amd.com accesses = read_accesses + write_accesses; 30711308Santhony.gutierrez@amd.com} 30811308Santhony.gutierrez@amd.com 30911308Santhony.gutierrez@amd.comFault 31011308Santhony.gutierrez@amd.comTLB::translateInst(RequestPtr req, ThreadContext *tc) 31111308Santhony.gutierrez@amd.com{ 31211308Santhony.gutierrez@amd.com#if !FULL_SYSTEM 31311308Santhony.gutierrez@amd.com Process * p = tc->getProcessPtr(); 31411308Santhony.gutierrez@amd.com 31511308Santhony.gutierrez@amd.com Fault fault = p->pTable->translate(req); 31611308Santhony.gutierrez@amd.com if(fault != NoFault) 31711308Santhony.gutierrez@amd.com return fault; 31811308Santhony.gutierrez@amd.com 31911308Santhony.gutierrez@amd.com return NoFault; 32011308Santhony.gutierrez@amd.com#else 32111308Santhony.gutierrez@amd.com if(MipsISA::IsKSeg0(req->getVaddr())) 32211308Santhony.gutierrez@amd.com { 32311308Santhony.gutierrez@amd.com // Address will not be translated through TLB, set response, and go! 32411308Santhony.gutierrez@amd.com req->setPaddr(MipsISA::KSeg02Phys(req->getVaddr())); 32511308Santhony.gutierrez@amd.com if(MipsISA::getOperatingMode(tc->readMiscReg(MipsISA::Status)) != mode_kernel || req->isMisaligned()) 32611308Santhony.gutierrez@amd.com { 32711308Santhony.gutierrez@amd.com AddressErrorFault *Flt = new AddressErrorFault(); 32811308Santhony.gutierrez@amd.com /* BadVAddr must be set */ 32911308Santhony.gutierrez@amd.com Flt->BadVAddr = req->getVaddr(); 33011639Salexandru.dutu@amd.com return Flt; 33111308Santhony.gutierrez@amd.com } 33211308Santhony.gutierrez@amd.com } 33311308Santhony.gutierrez@amd.com else if(MipsISA::IsKSeg1(req->getVaddr())) 33411308Santhony.gutierrez@amd.com { 33511308Santhony.gutierrez@amd.com // Address will not be translated through TLB, set response, and go! 33611308Santhony.gutierrez@amd.com req->setPaddr(MipsISA::KSeg02Phys(req->getVaddr())); 33711308Santhony.gutierrez@amd.com } 33811308Santhony.gutierrez@amd.com else 33911308Santhony.gutierrez@amd.com { 34011308Santhony.gutierrez@amd.com /* This is an optimization - smallPages is updated every time a TLB operation is performed 34111308Santhony.gutierrez@amd.com That way, we don't need to look at Config3 _ SP and PageGrain _ ESP every time we 34211308Santhony.gutierrez@amd.com do a TLB lookup */ 34311308Santhony.gutierrez@amd.com Addr VPN; 34411308Santhony.gutierrez@amd.com if(smallPages==1){ 34511308Santhony.gutierrez@amd.com VPN=((req->getVaddr() >> 11)); 34611308Santhony.gutierrez@amd.com } else { 34711308Santhony.gutierrez@amd.com VPN=((req->getVaddr() >> 11) & 0xFFFFFFFC); 34811308Santhony.gutierrez@amd.com } 34911308Santhony.gutierrez@amd.com uint8_t Asid = req->getAsid(); 35011308Santhony.gutierrez@amd.com if(req->isMisaligned()){ // Unaligned address! 35111640Salexandru.dutu@amd.com AddressErrorFault *Flt = new AddressErrorFault(); 35211640Salexandru.dutu@amd.com /* BadVAddr must be set */ 35311640Salexandru.dutu@amd.com Flt->BadVAddr = req->getVaddr(); 35411640Salexandru.dutu@amd.com return Flt; 35511640Salexandru.dutu@amd.com } 35611640Salexandru.dutu@amd.com MipsISA::PTE *pte = lookup(VPN,Asid); 35711308Santhony.gutierrez@amd.com if(pte != NULL) 35811308Santhony.gutierrez@amd.com {// Ok, found something 35911308Santhony.gutierrez@amd.com /* Check for valid bits */ 36011308Santhony.gutierrez@amd.com int EvenOdd; 36111308Santhony.gutierrez@amd.com bool Valid; 36211308Santhony.gutierrez@amd.com if((((req->getVaddr()) >> pte->AddrShiftAmount) & 1) ==0){ 36311308Santhony.gutierrez@amd.com // Check even bits 36411308Santhony.gutierrez@amd.com Valid = pte->V0; 36511641Salexandru.dutu@amd.com EvenOdd = 0; 36611308Santhony.gutierrez@amd.com } else { 36711308Santhony.gutierrez@amd.com // Check odd bits 36811308Santhony.gutierrez@amd.com Valid = pte->V1; 369 EvenOdd = 1; 370 } 371 372 if(Valid == false) 373 {//Invalid entry 374 ItbInvalidFault *Flt = new ItbInvalidFault(); 375 /* EntryHi VPN, ASID fields must be set */ 376 Flt->EntryHi_Asid = Asid; 377 Flt->EntryHi_VPN2 = (VPN>>2); 378 Flt->EntryHi_VPN2X = (VPN & 0x3); 379 380 /* BadVAddr must be set */ 381 Flt->BadVAddr = req->getVaddr(); 382 383 /* Context must be set */ 384 Flt->Context_BadVPN2 = (VPN >> 2); 385 return Flt; 386 } 387 else 388 {// Ok, this is really a match, set paddr 389 // hits++; 390 Addr PAddr; 391 if(EvenOdd == 0){ 392 PAddr = pte->PFN0; 393 }else{ 394 PAddr = pte->PFN1; 395 } 396 PAddr >>= (pte->AddrShiftAmount-12); 397 PAddr <<= pte->AddrShiftAmount; 398 PAddr |= ((req->getVaddr()) & pte->OffsetMask); 399 req->setPaddr(PAddr); 400 401 402 } 403 } 404 else 405 { // Didn't find any match, return a TLB Refill Exception 406 // misses++; 407 ItbRefillFault *Flt=new ItbRefillFault(); 408 /* EntryHi VPN, ASID fields must be set */ 409 Flt->EntryHi_Asid = Asid; 410 Flt->EntryHi_VPN2 = (VPN>>2); 411 Flt->EntryHi_VPN2X = (VPN & 0x3); 412 413 414 /* BadVAddr must be set */ 415 Flt->BadVAddr = req->getVaddr(); 416 417 /* Context must be set */ 418 Flt->Context_BadVPN2 = (VPN >> 2); 419 return Flt; 420 } 421 } 422 return checkCacheability(req); 423#endif 424} 425 426Fault 427TLB::translateData(RequestPtr req, ThreadContext *tc, bool write) 428{ 429#if !FULL_SYSTEM 430 //@TODO: This should actually use TLB instead of going directly 431 // to the page table in syscall mode. 432 /** 433 * Check for alignment faults 434 */ 435 if (req->getVaddr() & (req->getSize() - 1)) { 436 DPRINTF(TLB, "Alignment Fault on %#x, size = %d", req->getVaddr(), 437 req->getSize()); 438 return new AlignmentFault(); 439 } 440 441 442 Process * p = tc->getProcessPtr(); 443 444 Fault fault = p->pTable->translate(req); 445 if(fault != NoFault) 446 return fault; 447 448 return NoFault; 449#else 450 if(MipsISA::IsKSeg0(req->getVaddr())) 451 { 452 // Address will not be translated through TLB, set response, and go! 453 req->setPaddr(MipsISA::KSeg02Phys(req->getVaddr())); 454 if(MipsISA::getOperatingMode(tc->readMiscReg(MipsISA::Status)) != mode_kernel || req->isMisaligned()) 455 { 456 StoreAddressErrorFault *Flt = new StoreAddressErrorFault(); 457 /* BadVAddr must be set */ 458 Flt->BadVAddr = req->getVaddr(); 459 460 return Flt; 461 } 462 } 463 else if(MipsISA::IsKSeg1(req->getVaddr())) 464 { 465 // Address will not be translated through TLB, set response, and go! 466 req->setPaddr(MipsISA::KSeg02Phys(req->getVaddr())); 467 } 468 else 469 { 470 /* This is an optimization - smallPages is updated every time a TLB operation is performed 471 That way, we don't need to look at Config3 _ SP and PageGrain _ ESP every time we 472 do a TLB lookup */ 473 Addr VPN=((req->getVaddr() >> 11) & 0xFFFFFFFC); 474 if(smallPages==1){ 475 VPN=((req->getVaddr() >> 11)); 476 } 477 uint8_t Asid = req->getAsid(); 478 MipsISA::PTE *pte = lookup(VPN,Asid); 479 if(req->isMisaligned()){ // Unaligned address! 480 StoreAddressErrorFault *Flt = new StoreAddressErrorFault(); 481 /* BadVAddr must be set */ 482 Flt->BadVAddr = req->getVaddr(); 483 return Flt; 484 } 485 if(pte != NULL) 486 {// Ok, found something 487 /* Check for valid bits */ 488 int EvenOdd; 489 bool Valid; 490 bool Dirty; 491 if(((((req->getVaddr()) >> pte->AddrShiftAmount) & 1)) ==0){ 492 // Check even bits 493 Valid = pte->V0; 494 Dirty = pte->D0; 495 EvenOdd = 0; 496 497 } else { 498 // Check odd bits 499 Valid = pte->V1; 500 Dirty = pte->D1; 501 EvenOdd = 1; 502 } 503 504 if(Valid == false) 505 {//Invalid entry 506 // invalids++; 507 DtbInvalidFault *Flt = new DtbInvalidFault(); 508 /* EntryHi VPN, ASID fields must be set */ 509 Flt->EntryHi_Asid = Asid; 510 Flt->EntryHi_VPN2 = (VPN>>2); 511 Flt->EntryHi_VPN2X = (VPN & 0x3); 512 513 514 /* BadVAddr must be set */ 515 Flt->BadVAddr = req->getVaddr(); 516 517 /* Context must be set */ 518 Flt->Context_BadVPN2 = (VPN >> 2); 519 520 return Flt; 521 } 522 else 523 {// Ok, this is really a match, set paddr 524 // hits++; 525 if(!Dirty) 526 { 527 TLBModifiedFault *Flt = new TLBModifiedFault(); 528 /* EntryHi VPN, ASID fields must be set */ 529 Flt->EntryHi_Asid = Asid; 530 Flt->EntryHi_VPN2 = (VPN>>2); 531 Flt->EntryHi_VPN2X = (VPN & 0x3); 532 533 534 /* BadVAddr must be set */ 535 Flt->BadVAddr = req->getVaddr(); 536 537 /* Context must be set */ 538 Flt->Context_BadVPN2 = (VPN >> 2); 539 return Flt; 540 541 } 542 Addr PAddr; 543 if(EvenOdd == 0){ 544 PAddr = pte->PFN0; 545 }else{ 546 PAddr = pte->PFN1; 547 } 548 PAddr >>= (pte->AddrShiftAmount-12); 549 PAddr <<= pte->AddrShiftAmount; 550 PAddr |= ((req->getVaddr()) & pte->OffsetMask); 551 req->setPaddr(PAddr); 552 } 553 } 554 else 555 { // Didn't find any match, return a TLB Refill Exception 556 // misses++; 557 DtbRefillFault *Flt=new DtbRefillFault(); 558 /* EntryHi VPN, ASID fields must be set */ 559 Flt->EntryHi_Asid = Asid; 560 Flt->EntryHi_VPN2 = (VPN>>2); 561 Flt->EntryHi_VPN2X = (VPN & 0x3); 562 563 564 /* BadVAddr must be set */ 565 Flt->BadVAddr = req->getVaddr(); 566 567 /* Context must be set */ 568 Flt->Context_BadVPN2 = (VPN >> 2); 569 return Flt; 570 } 571 } 572 return checkCacheability(req); 573#endif 574} 575 576Fault 577TLB::translateAtomic(RequestPtr req, ThreadContext *tc, Mode mode) 578{ 579 if (mode == Execute) 580 return translateInst(req, tc); 581 else 582 return translateData(req, tc, mode == Write); 583} 584 585void 586TLB::translateTiming(RequestPtr req, ThreadContext *tc, 587 Translation *translation, Mode mode) 588{ 589 assert(translation); 590 translation->finish(translateAtomic(req, tc, mode), req, tc, mode); 591} 592 593 594MipsISA::PTE & 595TLB::index(bool advance) 596{ 597 MipsISA::PTE *pte = &table[nlu]; 598 599 if (advance) 600 nextnlu(); 601 602 return *pte; 603} 604 605MipsISA::TLB * 606MipsTLBParams::create() 607{ 608 return new MipsISA::TLB(this); 609} 610