tlb.cc revision 8232
14997Sgblack@eecs.umich.edu/*
25268Sksewell@umich.edu * Copyright (c) 2001-2005 The Regents of The University of Michigan
35254Sksewell@umich.edu * Copyright (c) 2007 MIPS Technologies, Inc.
45254Sksewell@umich.edu * All rights reserved.
54997Sgblack@eecs.umich.edu *
65254Sksewell@umich.edu * Redistribution and use in source and binary forms, with or without
75254Sksewell@umich.edu * modification, are permitted provided that the following conditions are
85254Sksewell@umich.edu * met: redistributions of source code must retain the above copyright
95254Sksewell@umich.edu * notice, this list of conditions and the following disclaimer;
105254Sksewell@umich.edu * redistributions in binary form must reproduce the above copyright
115254Sksewell@umich.edu * notice, this list of conditions and the following disclaimer in the
125254Sksewell@umich.edu * documentation and/or other materials provided with the distribution;
135254Sksewell@umich.edu * neither the name of the copyright holders nor the names of its
145254Sksewell@umich.edu * contributors may be used to endorse or promote products derived from
155254Sksewell@umich.edu * this software without specific prior written permission.
164997Sgblack@eecs.umich.edu *
175254Sksewell@umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
185254Sksewell@umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
195254Sksewell@umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
205254Sksewell@umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
215254Sksewell@umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
225254Sksewell@umich.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
235254Sksewell@umich.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
245254Sksewell@umich.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
255254Sksewell@umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
265254Sksewell@umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
275254Sksewell@umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
284997Sgblack@eecs.umich.edu *
295268Sksewell@umich.edu * Authors: Nathan Binkert
305268Sksewell@umich.edu *          Steve Reinhardt
315268Sksewell@umich.edu *          Jaidev Patwardhan
324997Sgblack@eecs.umich.edu */
334997Sgblack@eecs.umich.edu
345222Sksewell@umich.edu#include <string>
355222Sksewell@umich.edu#include <vector>
364997Sgblack@eecs.umich.edu
378229Snate@binkert.org#include "arch/mips/faults.hh"
388229Snate@binkert.org#include "arch/mips/pagetable.hh"
395222Sksewell@umich.edu#include "arch/mips/pra_constants.hh"
404997Sgblack@eecs.umich.edu#include "arch/mips/tlb.hh"
415222Sksewell@umich.edu#include "arch/mips/utility.hh"
425222Sksewell@umich.edu#include "base/inifile.hh"
435222Sksewell@umich.edu#include "base/str.hh"
445222Sksewell@umich.edu#include "base/trace.hh"
455222Sksewell@umich.edu#include "cpu/thread_context.hh"
468232Snate@binkert.org#include "debug/MipsPRA.hh"
478232Snate@binkert.org#include "debug/TLB.hh"
485224Sksewell@umich.edu#include "mem/page_table.hh"
495222Sksewell@umich.edu#include "params/MipsTLB.hh"
508229Snate@binkert.org#include "sim/process.hh"
514997Sgblack@eecs.umich.edu
525222Sksewell@umich.eduusing namespace std;
535222Sksewell@umich.eduusing namespace MipsISA;
545019Sgblack@eecs.umich.edu
555222Sksewell@umich.edu///////////////////////////////////////////////////////////////////////
565222Sksewell@umich.edu//
575222Sksewell@umich.edu//  MIPS TLB
585222Sksewell@umich.edu//
595019Sgblack@eecs.umich.edu
606329Sgblack@eecs.umich.edustatic inline mode_type
616329Sgblack@eecs.umich.edugetOperatingMode(MiscReg Stat)
626329Sgblack@eecs.umich.edu{
636378Sgblack@eecs.umich.edu    if ((Stat & 0x10000006) != 0 || (Stat & 0x18) ==0) {
646329Sgblack@eecs.umich.edu        return mode_kernel;
656378Sgblack@eecs.umich.edu    } else if ((Stat & 0x18) == 0x8) {
666329Sgblack@eecs.umich.edu        return mode_supervisor;
676378Sgblack@eecs.umich.edu    } else if ((Stat & 0x18) == 0x10) {
686329Sgblack@eecs.umich.edu        return mode_user;
696329Sgblack@eecs.umich.edu    } else {
706329Sgblack@eecs.umich.edu        return mode_number;
716329Sgblack@eecs.umich.edu    }
726329Sgblack@eecs.umich.edu}
736329Sgblack@eecs.umich.edu
746329Sgblack@eecs.umich.edu
755222Sksewell@umich.eduTLB::TLB(const Params *p)
765358Sgblack@eecs.umich.edu    : BaseTLB(p), size(p->size), nlu(0)
775222Sksewell@umich.edu{
786378Sgblack@eecs.umich.edu    table = new PTE[size];
796378Sgblack@eecs.umich.edu    memset(table, 0, sizeof(PTE[size]));
806378Sgblack@eecs.umich.edu    smallPages = 0;
815222Sksewell@umich.edu}
825222Sksewell@umich.edu
835222Sksewell@umich.eduTLB::~TLB()
845222Sksewell@umich.edu{
855222Sksewell@umich.edu    if (table)
865222Sksewell@umich.edu        delete [] table;
875222Sksewell@umich.edu}
885222Sksewell@umich.edu
895222Sksewell@umich.edu// look up an entry in the TLB
905222Sksewell@umich.eduMipsISA::PTE *
915222Sksewell@umich.eduTLB::lookup(Addr vpn, uint8_t asn) const
925222Sksewell@umich.edu{
935222Sksewell@umich.edu    // assume not found...
946378Sgblack@eecs.umich.edu    PTE *retval = NULL;
955222Sksewell@umich.edu    PageTable::const_iterator i = lookupTable.find(vpn);
965222Sksewell@umich.edu    if (i != lookupTable.end()) {
975222Sksewell@umich.edu        while (i->first == vpn) {
985222Sksewell@umich.edu            int index = i->second;
996378Sgblack@eecs.umich.edu            PTE *pte = &table[index];
1005222Sksewell@umich.edu
1015222Sksewell@umich.edu            /* 1KB TLB Lookup code - from MIPS ARM Volume III - Rev. 2.50 */
1025222Sksewell@umich.edu            Addr Mask = pte->Mask;
1035222Sksewell@umich.edu            Addr InvMask = ~Mask;
1045222Sksewell@umich.edu            Addr VPN  = pte->VPN;
1056378Sgblack@eecs.umich.edu            if (((vpn & InvMask) == (VPN & InvMask)) &&
1066378Sgblack@eecs.umich.edu                    (pte->G  || (asn == pte->asid))) {
1076378Sgblack@eecs.umich.edu                // We have a VPN + ASID Match
1085222Sksewell@umich.edu                retval = pte;
1095222Sksewell@umich.edu                break;
1106378Sgblack@eecs.umich.edu            }
1115222Sksewell@umich.edu            ++i;
1125222Sksewell@umich.edu        }
1135019Sgblack@eecs.umich.edu    }
1145019Sgblack@eecs.umich.edu
1155222Sksewell@umich.edu    DPRINTF(TLB, "lookup %#x, asn %#x -> %s ppn %#x\n", vpn, (int)asn,
1165222Sksewell@umich.edu            retval ? "hit" : "miss", retval ? retval->PFN1 : 0);
1175222Sksewell@umich.edu    return retval;
1185222Sksewell@umich.edu}
1195222Sksewell@umich.edu
1206378Sgblack@eecs.umich.eduMipsISA::PTE*
1216378Sgblack@eecs.umich.eduTLB::getEntry(unsigned Index) const
1225222Sksewell@umich.edu{
1235222Sksewell@umich.edu    // Make sure that Index is valid
1245222Sksewell@umich.edu    assert(Index<size);
1255222Sksewell@umich.edu    return &table[Index];
1265222Sksewell@umich.edu}
1275222Sksewell@umich.edu
1286378Sgblack@eecs.umich.eduint
1296378Sgblack@eecs.umich.eduTLB::probeEntry(Addr vpn, uint8_t asn) const
1305222Sksewell@umich.edu{
1315222Sksewell@umich.edu    // assume not found...
1326378Sgblack@eecs.umich.edu    PTE *retval = NULL;
1336378Sgblack@eecs.umich.edu    int Ind = -1;
1345222Sksewell@umich.edu    PageTable::const_iterator i = lookupTable.find(vpn);
1355222Sksewell@umich.edu    if (i != lookupTable.end()) {
1365222Sksewell@umich.edu        while (i->first == vpn) {
1375222Sksewell@umich.edu            int index = i->second;
1386378Sgblack@eecs.umich.edu            PTE *pte = &table[index];
1395222Sksewell@umich.edu
1405222Sksewell@umich.edu            /* 1KB TLB Lookup code - from MIPS ARM Volume III - Rev. 2.50 */
1415222Sksewell@umich.edu            Addr Mask = pte->Mask;
1425222Sksewell@umich.edu            Addr InvMask = ~Mask;
1436378Sgblack@eecs.umich.edu            Addr VPN = pte->VPN;
1446378Sgblack@eecs.umich.edu            if (((vpn & InvMask) == (VPN & InvMask)) &&
1456378Sgblack@eecs.umich.edu                    (pte->G  || (asn == pte->asid))) {
1466378Sgblack@eecs.umich.edu                // We have a VPN + ASID Match
1475222Sksewell@umich.edu                retval = pte;
1485222Sksewell@umich.edu                Ind = index;
1495222Sksewell@umich.edu                break;
1506378Sgblack@eecs.umich.edu            }
1515222Sksewell@umich.edu            ++i;
1525222Sksewell@umich.edu        }
1535222Sksewell@umich.edu    }
1545222Sksewell@umich.edu    DPRINTF(MipsPRA,"VPN: %x, asid: %d, Result of TLBP: %d\n",vpn,asn,Ind);
1555222Sksewell@umich.edu    return Ind;
1565222Sksewell@umich.edu}
1576378Sgblack@eecs.umich.edu
1586378Sgblack@eecs.umich.eduinline Fault
1595222Sksewell@umich.eduTLB::checkCacheability(RequestPtr &req)
1605222Sksewell@umich.edu{
1616378Sgblack@eecs.umich.edu    Addr VAddrUncacheable = 0xA0000000;
1626378Sgblack@eecs.umich.edu    // In MIPS, cacheability is controlled by certain bits of the virtual
1636378Sgblack@eecs.umich.edu    // address or by the TLB entry
1646378Sgblack@eecs.umich.edu    if ((req->getVaddr() & VAddrUncacheable) == VAddrUncacheable) {
1656378Sgblack@eecs.umich.edu        // mark request as uncacheable
1666378Sgblack@eecs.umich.edu        req->setFlags(Request::UNCACHEABLE);
1676378Sgblack@eecs.umich.edu    }
1686378Sgblack@eecs.umich.edu    return NoFault;
1695222Sksewell@umich.edu}
1706378Sgblack@eecs.umich.edu
1716378Sgblack@eecs.umich.eduvoid
1726378Sgblack@eecs.umich.eduTLB::insertAt(PTE &pte, unsigned Index, int _smallPages)
1735222Sksewell@umich.edu{
1746378Sgblack@eecs.umich.edu    smallPages = _smallPages;
1756378Sgblack@eecs.umich.edu    if (Index > size) {
1766378Sgblack@eecs.umich.edu        warn("Attempted to write at index (%d) beyond TLB size (%d)",
1776378Sgblack@eecs.umich.edu                Index, size);
1786378Sgblack@eecs.umich.edu    } else {
1796378Sgblack@eecs.umich.edu        // Update TLB
1806378Sgblack@eecs.umich.edu        DPRINTF(TLB, "TLB[%d]: %x %x %x %x\n",
1816378Sgblack@eecs.umich.edu                Index, pte.Mask << 11,
1826378Sgblack@eecs.umich.edu                ((pte.VPN << 11) | pte.asid),
1836378Sgblack@eecs.umich.edu                ((pte.PFN0 << 6) | (pte.C0 << 3) |
1846378Sgblack@eecs.umich.edu                 (pte.D0 << 2) | (pte.V0 <<1) | pte.G),
1856378Sgblack@eecs.umich.edu                ((pte.PFN1 <<6) | (pte.C1 << 3) |
1866378Sgblack@eecs.umich.edu                 (pte.D1 << 2) | (pte.V1 <<1) | pte.G));
1876378Sgblack@eecs.umich.edu        if (table[Index].V0 == true || table[Index].V1 == true) {
1886378Sgblack@eecs.umich.edu            // Previous entry is valid
1896378Sgblack@eecs.umich.edu            PageTable::iterator i = lookupTable.find(table[Index].VPN);
1906378Sgblack@eecs.umich.edu            lookupTable.erase(i);
1916378Sgblack@eecs.umich.edu        }
1926378Sgblack@eecs.umich.edu        table[Index]=pte;
1936378Sgblack@eecs.umich.edu        // Update fast lookup table
1946378Sgblack@eecs.umich.edu        lookupTable.insert(make_pair(table[Index].VPN, Index));
1955222Sksewell@umich.edu    }
1965222Sksewell@umich.edu}
1975222Sksewell@umich.edu
1985222Sksewell@umich.edu// insert a new TLB entry
1995222Sksewell@umich.eduvoid
2006378Sgblack@eecs.umich.eduTLB::insert(Addr addr, PTE &pte)
2015222Sksewell@umich.edu{
2026378Sgblack@eecs.umich.edu    fatal("TLB Insert not yet implemented\n");
2035222Sksewell@umich.edu}
2045222Sksewell@umich.edu
2055222Sksewell@umich.eduvoid
2065222Sksewell@umich.eduTLB::flushAll()
2075222Sksewell@umich.edu{
2085222Sksewell@umich.edu    DPRINTF(TLB, "flushAll\n");
2096378Sgblack@eecs.umich.edu    memset(table, 0, sizeof(PTE[size]));
2105222Sksewell@umich.edu    lookupTable.clear();
2115222Sksewell@umich.edu    nlu = 0;
2125222Sksewell@umich.edu}
2135222Sksewell@umich.edu
2145222Sksewell@umich.eduvoid
2155222Sksewell@umich.eduTLB::serialize(ostream &os)
2165222Sksewell@umich.edu{
2175222Sksewell@umich.edu    SERIALIZE_SCALAR(size);
2185222Sksewell@umich.edu    SERIALIZE_SCALAR(nlu);
2195222Sksewell@umich.edu
2205222Sksewell@umich.edu    for (int i = 0; i < size; i++) {
2215222Sksewell@umich.edu        nameOut(os, csprintf("%s.PTE%d", name(), i));
2225222Sksewell@umich.edu        table[i].serialize(os);
2235222Sksewell@umich.edu    }
2245222Sksewell@umich.edu}
2255222Sksewell@umich.edu
2265222Sksewell@umich.eduvoid
2275222Sksewell@umich.eduTLB::unserialize(Checkpoint *cp, const string &section)
2285222Sksewell@umich.edu{
2295222Sksewell@umich.edu    UNSERIALIZE_SCALAR(size);
2305222Sksewell@umich.edu    UNSERIALIZE_SCALAR(nlu);
2315222Sksewell@umich.edu
2325222Sksewell@umich.edu    for (int i = 0; i < size; i++) {
2335222Sksewell@umich.edu        table[i].unserialize(cp, csprintf("%s.PTE%d", section, i));
2345222Sksewell@umich.edu        if (table[i].V0 || table[i].V1) {
2355222Sksewell@umich.edu            lookupTable.insert(make_pair(table[i].VPN, i));
2365222Sksewell@umich.edu        }
2375222Sksewell@umich.edu    }
2385222Sksewell@umich.edu}
2395222Sksewell@umich.edu
2405222Sksewell@umich.eduvoid
2415222Sksewell@umich.eduTLB::regStats()
2425222Sksewell@umich.edu{
2435222Sksewell@umich.edu    read_hits
2445222Sksewell@umich.edu        .name(name() + ".read_hits")
2455222Sksewell@umich.edu        .desc("DTB read hits")
2465222Sksewell@umich.edu        ;
2475222Sksewell@umich.edu
2485222Sksewell@umich.edu    read_misses
2495222Sksewell@umich.edu        .name(name() + ".read_misses")
2505222Sksewell@umich.edu        .desc("DTB read misses")
2515222Sksewell@umich.edu        ;
2525222Sksewell@umich.edu
2535222Sksewell@umich.edu
2545222Sksewell@umich.edu    read_accesses
2555222Sksewell@umich.edu        .name(name() + ".read_accesses")
2565222Sksewell@umich.edu        .desc("DTB read accesses")
2575222Sksewell@umich.edu        ;
2585222Sksewell@umich.edu
2595222Sksewell@umich.edu    write_hits
2605222Sksewell@umich.edu        .name(name() + ".write_hits")
2615222Sksewell@umich.edu        .desc("DTB write hits")
2625222Sksewell@umich.edu        ;
2635222Sksewell@umich.edu
2645222Sksewell@umich.edu    write_misses
2655222Sksewell@umich.edu        .name(name() + ".write_misses")
2665222Sksewell@umich.edu        .desc("DTB write misses")
2675222Sksewell@umich.edu        ;
2685222Sksewell@umich.edu
2695222Sksewell@umich.edu
2705222Sksewell@umich.edu    write_accesses
2715222Sksewell@umich.edu        .name(name() + ".write_accesses")
2725222Sksewell@umich.edu        .desc("DTB write accesses")
2735222Sksewell@umich.edu        ;
2745222Sksewell@umich.edu
2755222Sksewell@umich.edu    hits
2765222Sksewell@umich.edu        .name(name() + ".hits")
2775222Sksewell@umich.edu        .desc("DTB hits")
2785222Sksewell@umich.edu        ;
2795222Sksewell@umich.edu
2805222Sksewell@umich.edu    misses
2815222Sksewell@umich.edu        .name(name() + ".misses")
2825222Sksewell@umich.edu        .desc("DTB misses")
2835222Sksewell@umich.edu        ;
2845222Sksewell@umich.edu
2855222Sksewell@umich.edu    accesses
2865222Sksewell@umich.edu        .name(name() + ".accesses")
2875222Sksewell@umich.edu        .desc("DTB accesses")
2885222Sksewell@umich.edu        ;
2895222Sksewell@umich.edu
2905222Sksewell@umich.edu    hits = read_hits + write_hits;
2915222Sksewell@umich.edu    misses = read_misses + write_misses;
2925222Sksewell@umich.edu    accesses = read_accesses + write_accesses;
2935222Sksewell@umich.edu}
2945222Sksewell@umich.edu
2955222Sksewell@umich.eduFault
2966022Sgblack@eecs.umich.eduTLB::translateInst(RequestPtr req, ThreadContext *tc)
2975222Sksewell@umich.edu{
2985224Sksewell@umich.edu#if !FULL_SYSTEM
2995224Sksewell@umich.edu    Process * p = tc->getProcessPtr();
3005224Sksewell@umich.edu
3015224Sksewell@umich.edu    Fault fault = p->pTable->translate(req);
3026378Sgblack@eecs.umich.edu    if (fault != NoFault)
3035224Sksewell@umich.edu        return fault;
3045224Sksewell@umich.edu
3055224Sksewell@umich.edu    return NoFault;
3065224Sksewell@umich.edu#else
3077708Sgblack@eecs.umich.edu    Addr vaddr = req->getVaddr();
3087708Sgblack@eecs.umich.edu
3097708Sgblack@eecs.umich.edu    bool misaligned = (req->getSize() - 1) & vaddr;
3107708Sgblack@eecs.umich.edu
3117708Sgblack@eecs.umich.edu    if (IsKSeg0(vaddr)) {
3126378Sgblack@eecs.umich.edu        // Address will not be translated through TLB, set response, and go!
3137708Sgblack@eecs.umich.edu        req->setPaddr(KSeg02Phys(vaddr));
3146383Sgblack@eecs.umich.edu        if (getOperatingMode(tc->readMiscReg(MISCREG_STATUS)) != mode_kernel ||
3157708Sgblack@eecs.umich.edu                misaligned) {
3166378Sgblack@eecs.umich.edu            AddressErrorFault *Flt = new AddressErrorFault();
3176378Sgblack@eecs.umich.edu            /* BadVAddr must be set */
3187708Sgblack@eecs.umich.edu            Flt->badVAddr = vaddr;
3196378Sgblack@eecs.umich.edu            return Flt;
3206378Sgblack@eecs.umich.edu        }
3217708Sgblack@eecs.umich.edu    } else if(IsKSeg1(vaddr)) {
3226378Sgblack@eecs.umich.edu        // Address will not be translated through TLB, set response, and go!
3237708Sgblack@eecs.umich.edu        req->setPaddr(KSeg02Phys(vaddr));
3246378Sgblack@eecs.umich.edu    } else {
3256378Sgblack@eecs.umich.edu      /*
3266378Sgblack@eecs.umich.edu       * This is an optimization - smallPages is updated every time a TLB
3276378Sgblack@eecs.umich.edu       * operation is performed. That way, we don't need to look at
3286378Sgblack@eecs.umich.edu       * Config3 _ SP and PageGrain _ ESP every time we do a TLB lookup
3296378Sgblack@eecs.umich.edu       */
3306378Sgblack@eecs.umich.edu      Addr VPN;
3316378Sgblack@eecs.umich.edu      if (smallPages == 1) {
3327708Sgblack@eecs.umich.edu        VPN = (vaddr >> 11);
3336378Sgblack@eecs.umich.edu      } else {
3347708Sgblack@eecs.umich.edu        VPN = ((vaddr >> 11) & 0xFFFFFFFC);
3356378Sgblack@eecs.umich.edu      }
3366378Sgblack@eecs.umich.edu      uint8_t Asid = req->getAsid();
3377708Sgblack@eecs.umich.edu      if (misaligned) {
3386378Sgblack@eecs.umich.edu          // Unaligned address!
3395222Sksewell@umich.edu          AddressErrorFault *Flt = new AddressErrorFault();
3405222Sksewell@umich.edu          /* BadVAddr must be set */
3417708Sgblack@eecs.umich.edu          Flt->badVAddr = vaddr;
3425222Sksewell@umich.edu          return Flt;
3435222Sksewell@umich.edu      }
3446378Sgblack@eecs.umich.edu      PTE *pte = lookup(VPN,Asid);
3456378Sgblack@eecs.umich.edu      if (pte != NULL) {
3466378Sgblack@eecs.umich.edu          // Ok, found something
3475222Sksewell@umich.edu          /* Check for valid bits */
3485222Sksewell@umich.edu          int EvenOdd;
3495222Sksewell@umich.edu          bool Valid;
3507708Sgblack@eecs.umich.edu          if ((((vaddr) >> pte->AddrShiftAmount) & 1) == 0) {
3516378Sgblack@eecs.umich.edu              // Check even bits
3526378Sgblack@eecs.umich.edu              Valid = pte->V0;
3536378Sgblack@eecs.umich.edu              EvenOdd = 0;
3545222Sksewell@umich.edu          } else {
3556378Sgblack@eecs.umich.edu              // Check odd bits
3566378Sgblack@eecs.umich.edu              Valid = pte->V1;
3576378Sgblack@eecs.umich.edu              EvenOdd = 1;
3585222Sksewell@umich.edu          }
3595222Sksewell@umich.edu
3606378Sgblack@eecs.umich.edu          if (Valid == false) {
3616378Sgblack@eecs.umich.edu              //Invalid entry
3625222Sksewell@umich.edu              ItbInvalidFault *Flt = new ItbInvalidFault();
3635222Sksewell@umich.edu              /* EntryHi VPN, ASID fields must be set */
3646379Sgblack@eecs.umich.edu              Flt->entryHiAsid = Asid;
3656379Sgblack@eecs.umich.edu              Flt->entryHiVPN2 = (VPN >> 2);
3666379Sgblack@eecs.umich.edu              Flt->entryHiVPN2X = (VPN & 0x3);
3675222Sksewell@umich.edu
3685222Sksewell@umich.edu              /* BadVAddr must be set */
3697708Sgblack@eecs.umich.edu              Flt->badVAddr = vaddr;
3705222Sksewell@umich.edu
3715222Sksewell@umich.edu              /* Context must be set */
3726379Sgblack@eecs.umich.edu              Flt->contextBadVPN2 = (VPN >> 2);
3735222Sksewell@umich.edu              return Flt;
3746378Sgblack@eecs.umich.edu          } else {
3756378Sgblack@eecs.umich.edu              // Ok, this is really a match, set paddr
3765222Sksewell@umich.edu              Addr PAddr;
3776378Sgblack@eecs.umich.edu              if (EvenOdd == 0) {
3785222Sksewell@umich.edu                PAddr = pte->PFN0;
3796378Sgblack@eecs.umich.edu              } else {
3805222Sksewell@umich.edu                PAddr = pte->PFN1;
3815222Sksewell@umich.edu              }
3826378Sgblack@eecs.umich.edu              PAddr >>= (pte->AddrShiftAmount - 12);
3835222Sksewell@umich.edu              PAddr <<= pte->AddrShiftAmount;
3847708Sgblack@eecs.umich.edu              PAddr |= (vaddr & pte->OffsetMask);
3855222Sksewell@umich.edu              req->setPaddr(PAddr);
3866378Sgblack@eecs.umich.edu            }
3876378Sgblack@eecs.umich.edu        } else {
3886378Sgblack@eecs.umich.edu            // Didn't find any match, return a TLB Refill Exception
3896383Sgblack@eecs.umich.edu            ItbRefillFault *Flt = new ItbRefillFault();
3906378Sgblack@eecs.umich.edu            /* EntryHi VPN, ASID fields must be set */
3916379Sgblack@eecs.umich.edu            Flt->entryHiAsid = Asid;
3926379Sgblack@eecs.umich.edu            Flt->entryHiVPN2 = (VPN >> 2);
3936379Sgblack@eecs.umich.edu            Flt->entryHiVPN2X = (VPN & 0x3);
3945222Sksewell@umich.edu
3956378Sgblack@eecs.umich.edu            /* BadVAddr must be set */
3967708Sgblack@eecs.umich.edu            Flt->badVAddr = vaddr;
3975222Sksewell@umich.edu
3986378Sgblack@eecs.umich.edu            /* Context must be set */
3996379Sgblack@eecs.umich.edu            Flt->contextBadVPN2 = (VPN >> 2);
4006378Sgblack@eecs.umich.edu            return Flt;
4015222Sksewell@umich.edu        }
4025222Sksewell@umich.edu    }
4036378Sgblack@eecs.umich.edu    return checkCacheability(req);
4045224Sksewell@umich.edu#endif
4055222Sksewell@umich.edu}
4065222Sksewell@umich.edu
4075222Sksewell@umich.eduFault
4086022Sgblack@eecs.umich.eduTLB::translateData(RequestPtr req, ThreadContext *tc, bool write)
4095222Sksewell@umich.edu{
4105224Sksewell@umich.edu#if !FULL_SYSTEM
4116038Sksewell@umich.edu    //@TODO: This should actually use TLB instead of going directly
4126038Sksewell@umich.edu    //       to the page table in syscall mode.
4136038Sksewell@umich.edu    /**
4146038Sksewell@umich.edu     * Check for alignment faults
4156038Sksewell@umich.edu     */
4166038Sksewell@umich.edu    if (req->getVaddr() & (req->getSize() - 1)) {
4176038Sksewell@umich.edu        DPRINTF(TLB, "Alignment Fault on %#x, size = %d", req->getVaddr(),
4186038Sksewell@umich.edu                req->getSize());
4196038Sksewell@umich.edu        return new AlignmentFault();
4206038Sksewell@umich.edu    }
4216038Sksewell@umich.edu
4226038Sksewell@umich.edu
4235224Sksewell@umich.edu    Process * p = tc->getProcessPtr();
4245224Sksewell@umich.edu
4255224Sksewell@umich.edu    Fault fault = p->pTable->translate(req);
4266378Sgblack@eecs.umich.edu    if (fault != NoFault)
4275224Sksewell@umich.edu        return fault;
4285224Sksewell@umich.edu
4295224Sksewell@umich.edu    return NoFault;
4305224Sksewell@umich.edu#else
4317708Sgblack@eecs.umich.edu    Addr vaddr = req->getVaddr();
4327708Sgblack@eecs.umich.edu
4337708Sgblack@eecs.umich.edu    bool misaligned = (req->getSize() - 1) & vaddr;
4347708Sgblack@eecs.umich.edu
4357708Sgblack@eecs.umich.edu    if (IsKSeg0(vaddr)) {
4366378Sgblack@eecs.umich.edu        // Address will not be translated through TLB, set response, and go!
4377708Sgblack@eecs.umich.edu        req->setPaddr(KSeg02Phys(vaddr));
4386383Sgblack@eecs.umich.edu        if (getOperatingMode(tc->readMiscReg(MISCREG_STATUS)) != mode_kernel ||
4397708Sgblack@eecs.umich.edu                misaligned) {
4406378Sgblack@eecs.umich.edu            StoreAddressErrorFault *Flt = new StoreAddressErrorFault();
4416378Sgblack@eecs.umich.edu            /* BadVAddr must be set */
4427708Sgblack@eecs.umich.edu            Flt->badVAddr = vaddr;
4436378Sgblack@eecs.umich.edu
4446378Sgblack@eecs.umich.edu            return Flt;
4456378Sgblack@eecs.umich.edu        }
4467708Sgblack@eecs.umich.edu    } else if(IsKSeg1(vaddr)) {
4475222Sksewell@umich.edu      // Address will not be translated through TLB, set response, and go!
4487708Sgblack@eecs.umich.edu      req->setPaddr(KSeg02Phys(vaddr));
4496378Sgblack@eecs.umich.edu    } else {
4506378Sgblack@eecs.umich.edu        /*
4516378Sgblack@eecs.umich.edu         * This is an optimization - smallPages is updated every time a TLB
4526378Sgblack@eecs.umich.edu         * operation is performed. That way, we don't need to look at
4536378Sgblack@eecs.umich.edu         * Config3 _ SP and PageGrain _ ESP every time we do a TLB lookup
4546378Sgblack@eecs.umich.edu         */
4557708Sgblack@eecs.umich.edu        Addr VPN = (vaddr >> 11) & 0xFFFFFFFC;
4566378Sgblack@eecs.umich.edu        if (smallPages == 1) {
4577708Sgblack@eecs.umich.edu            VPN = vaddr >> 11;
4586378Sgblack@eecs.umich.edu        }
4596378Sgblack@eecs.umich.edu        uint8_t Asid = req->getAsid();
4606378Sgblack@eecs.umich.edu        PTE *pte = lookup(VPN, Asid);
4617708Sgblack@eecs.umich.edu        if (misaligned) {
4626378Sgblack@eecs.umich.edu            // Unaligned address!
4636378Sgblack@eecs.umich.edu            StoreAddressErrorFault *Flt = new StoreAddressErrorFault();
4646378Sgblack@eecs.umich.edu            /* BadVAddr must be set */
4657708Sgblack@eecs.umich.edu            Flt->badVAddr = vaddr;
4666378Sgblack@eecs.umich.edu            return Flt;
4676378Sgblack@eecs.umich.edu        }
4686378Sgblack@eecs.umich.edu        if (pte != NULL) {
4696378Sgblack@eecs.umich.edu            // Ok, found something
4706378Sgblack@eecs.umich.edu            /* Check for valid bits */
4716378Sgblack@eecs.umich.edu            int EvenOdd;
4726378Sgblack@eecs.umich.edu            bool Valid;
4736378Sgblack@eecs.umich.edu            bool Dirty;
4747708Sgblack@eecs.umich.edu            if ((((vaddr >> pte->AddrShiftAmount) & 1)) == 0) {
4756378Sgblack@eecs.umich.edu                // Check even bits
4766378Sgblack@eecs.umich.edu                Valid = pte->V0;
4776378Sgblack@eecs.umich.edu                Dirty = pte->D0;
4786378Sgblack@eecs.umich.edu                EvenOdd = 0;
4796378Sgblack@eecs.umich.edu            } else {
4806378Sgblack@eecs.umich.edu                // Check odd bits
4816378Sgblack@eecs.umich.edu                Valid = pte->V1;
4826378Sgblack@eecs.umich.edu                Dirty = pte->D1;
4836378Sgblack@eecs.umich.edu                EvenOdd = 1;
4846378Sgblack@eecs.umich.edu            }
4855222Sksewell@umich.edu
4866378Sgblack@eecs.umich.edu            if (Valid == false) {
4876378Sgblack@eecs.umich.edu                //Invalid entry
4886378Sgblack@eecs.umich.edu                DtbInvalidFault *Flt = new DtbInvalidFault();
4896378Sgblack@eecs.umich.edu                /* EntryHi VPN, ASID fields must be set */
4906379Sgblack@eecs.umich.edu                Flt->entryHiAsid = Asid;
4916379Sgblack@eecs.umich.edu                Flt->entryHiVPN2 = (VPN>>2);
4926379Sgblack@eecs.umich.edu                Flt->entryHiVPN2X = (VPN & 0x3);
4935222Sksewell@umich.edu
4946378Sgblack@eecs.umich.edu                /* BadVAddr must be set */
4957708Sgblack@eecs.umich.edu                Flt->badVAddr = vaddr;
4965222Sksewell@umich.edu
4976378Sgblack@eecs.umich.edu                /* Context must be set */
4986379Sgblack@eecs.umich.edu                Flt->contextBadVPN2 = (VPN >> 2);
4995222Sksewell@umich.edu
5006378Sgblack@eecs.umich.edu                return Flt;
5016378Sgblack@eecs.umich.edu            } else {
5026378Sgblack@eecs.umich.edu                // Ok, this is really a match, set paddr
5036378Sgblack@eecs.umich.edu                if (!Dirty) {
5046378Sgblack@eecs.umich.edu                    TLBModifiedFault *Flt = new TLBModifiedFault();
5056378Sgblack@eecs.umich.edu                    /* EntryHi VPN, ASID fields must be set */
5066379Sgblack@eecs.umich.edu                    Flt->entryHiAsid = Asid;
5076379Sgblack@eecs.umich.edu                    Flt->entryHiVPN2 = (VPN >> 2);
5086379Sgblack@eecs.umich.edu                    Flt->entryHiVPN2X = (VPN & 0x3);
5095222Sksewell@umich.edu
5106378Sgblack@eecs.umich.edu                    /* BadVAddr must be set */
5117708Sgblack@eecs.umich.edu                    Flt->badVAddr = vaddr;
5125222Sksewell@umich.edu
5136378Sgblack@eecs.umich.edu                    /* Context must be set */
5146379Sgblack@eecs.umich.edu                    Flt->contextBadVPN2 = (VPN >> 2);
5156378Sgblack@eecs.umich.edu                    return Flt;
5166378Sgblack@eecs.umich.edu                }
5176378Sgblack@eecs.umich.edu                Addr PAddr;
5186378Sgblack@eecs.umich.edu                if (EvenOdd == 0) {
5196378Sgblack@eecs.umich.edu                    PAddr = pte->PFN0;
5206378Sgblack@eecs.umich.edu                } else {
5216378Sgblack@eecs.umich.edu                    PAddr = pte->PFN1;
5226378Sgblack@eecs.umich.edu                }
5236378Sgblack@eecs.umich.edu                PAddr >>= (pte->AddrShiftAmount - 12);
5246378Sgblack@eecs.umich.edu                PAddr <<= pte->AddrShiftAmount;
5257708Sgblack@eecs.umich.edu                PAddr |= (vaddr & pte->OffsetMask);
5266378Sgblack@eecs.umich.edu                req->setPaddr(PAddr);
5276378Sgblack@eecs.umich.edu            }
5286378Sgblack@eecs.umich.edu        } else {
5296378Sgblack@eecs.umich.edu            // Didn't find any match, return a TLB Refill Exception
5306378Sgblack@eecs.umich.edu            DtbRefillFault *Flt = new DtbRefillFault();
5316378Sgblack@eecs.umich.edu            /* EntryHi VPN, ASID fields must be set */
5326379Sgblack@eecs.umich.edu            Flt->entryHiAsid = Asid;
5336379Sgblack@eecs.umich.edu            Flt->entryHiVPN2 = (VPN >> 2);
5346379Sgblack@eecs.umich.edu            Flt->entryHiVPN2X = (VPN & 0x3);
5355222Sksewell@umich.edu
5366378Sgblack@eecs.umich.edu            /* BadVAddr must be set */
5377708Sgblack@eecs.umich.edu            Flt->badVAddr = vaddr;
5385222Sksewell@umich.edu
5396378Sgblack@eecs.umich.edu            /* Context must be set */
5406379Sgblack@eecs.umich.edu            Flt->contextBadVPN2 = (VPN >> 2);
5416378Sgblack@eecs.umich.edu            return Flt;
5425222Sksewell@umich.edu        }
5435222Sksewell@umich.edu    }
5445222Sksewell@umich.edu    return checkCacheability(req);
5455224Sksewell@umich.edu#endif
5465222Sksewell@umich.edu}
5475222Sksewell@umich.edu
5486022Sgblack@eecs.umich.eduFault
5496023Snate@binkert.orgTLB::translateAtomic(RequestPtr req, ThreadContext *tc, Mode mode)
5506022Sgblack@eecs.umich.edu{
5516023Snate@binkert.org    if (mode == Execute)
5526022Sgblack@eecs.umich.edu        return translateInst(req, tc);
5536022Sgblack@eecs.umich.edu    else
5546023Snate@binkert.org        return translateData(req, tc, mode == Write);
5556022Sgblack@eecs.umich.edu}
5566022Sgblack@eecs.umich.edu
5575894Sgblack@eecs.umich.eduvoid
5586022Sgblack@eecs.umich.eduTLB::translateTiming(RequestPtr req, ThreadContext *tc,
5596023Snate@binkert.org        Translation *translation, Mode mode)
5605894Sgblack@eecs.umich.edu{
5615894Sgblack@eecs.umich.edu    assert(translation);
5626023Snate@binkert.org    translation->finish(translateAtomic(req, tc, mode), req, tc, mode);
5635894Sgblack@eecs.umich.edu}
5645894Sgblack@eecs.umich.edu
5655222Sksewell@umich.edu
5665222Sksewell@umich.eduMipsISA::PTE &
5675222Sksewell@umich.eduTLB::index(bool advance)
5685222Sksewell@umich.edu{
5696378Sgblack@eecs.umich.edu    PTE *pte = &table[nlu];
5705222Sksewell@umich.edu
5715222Sksewell@umich.edu    if (advance)
5725222Sksewell@umich.edu        nextnlu();
5735222Sksewell@umich.edu
5745222Sksewell@umich.edu    return *pte;
5755222Sksewell@umich.edu}
5764997Sgblack@eecs.umich.edu
5776022Sgblack@eecs.umich.eduMipsISA::TLB *
5786022Sgblack@eecs.umich.eduMipsTLBParams::create()
5794997Sgblack@eecs.umich.edu{
5806378Sgblack@eecs.umich.edu    return new TLB(this);
5814997Sgblack@eecs.umich.edu}
582