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 &section)
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