tlb.cc revision 8232
12929Sktlim@umich.edu/*
211504Sandreas.sandberg@arm.com * Copyright (c) 2001-2005 The Regents of The University of Michigan
311504Sandreas.sandberg@arm.com * Copyright (c) 2007 MIPS Technologies, Inc.
411504Sandreas.sandberg@arm.com * All rights reserved.
511504Sandreas.sandberg@arm.com *
611504Sandreas.sandberg@arm.com * Redistribution and use in source and binary forms, with or without
711504Sandreas.sandberg@arm.com * modification, are permitted provided that the following conditions are
811504Sandreas.sandberg@arm.com * met: redistributions of source code must retain the above copyright
911504Sandreas.sandberg@arm.com * notice, this list of conditions and the following disclaimer;
1011504Sandreas.sandberg@arm.com * redistributions in binary form must reproduce the above copyright
1111504Sandreas.sandberg@arm.com * notice, this list of conditions and the following disclaimer in the
1211504Sandreas.sandberg@arm.com * documentation and/or other materials provided with the distribution;
1311504Sandreas.sandberg@arm.com * neither the name of the copyright holders nor the names of its
1411504Sandreas.sandberg@arm.com * contributors may be used to endorse or promote products derived from
152932Sktlim@umich.edu * this software without specific prior written permission.
162929Sktlim@umich.edu *
172929Sktlim@umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
182929Sktlim@umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
192929Sktlim@umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
202929Sktlim@umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
212929Sktlim@umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
222929Sktlim@umich.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
232929Sktlim@umich.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
242929Sktlim@umich.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
252929Sktlim@umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
262929Sktlim@umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
272929Sktlim@umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
282929Sktlim@umich.edu *
292929Sktlim@umich.edu * Authors: Nathan Binkert
302929Sktlim@umich.edu *          Steve Reinhardt
312929Sktlim@umich.edu *          Jaidev Patwardhan
322929Sktlim@umich.edu */
332929Sktlim@umich.edu
342929Sktlim@umich.edu#include <string>
352929Sktlim@umich.edu#include <vector>
362929Sktlim@umich.edu
372929Sktlim@umich.edu#include "arch/mips/faults.hh"
382929Sktlim@umich.edu#include "arch/mips/pagetable.hh"
392929Sktlim@umich.edu#include "arch/mips/pra_constants.hh"
402932Sktlim@umich.edu#include "arch/mips/tlb.hh"
412932Sktlim@umich.edu#include "arch/mips/utility.hh"
422932Sktlim@umich.edu#include "base/inifile.hh"
4311504Sandreas.sandberg@arm.com#include "base/str.hh"
442929Sktlim@umich.edu#include "base/trace.hh"
452929Sktlim@umich.edu#include "cpu/thread_context.hh"
4611504Sandreas.sandberg@arm.com#include "debug/MipsPRA.hh"
4711504Sandreas.sandberg@arm.com#include "debug/TLB.hh"
4811504Sandreas.sandberg@arm.com#include "mem/page_table.hh"
4911504Sandreas.sandberg@arm.com#include "params/MipsTLB.hh"
5011504Sandreas.sandberg@arm.com#include "sim/process.hh"
5111504Sandreas.sandberg@arm.com
5211504Sandreas.sandberg@arm.comusing namespace std;
532929Sktlim@umich.eduusing namespace MipsISA;
542929Sktlim@umich.edu
552929Sktlim@umich.edu///////////////////////////////////////////////////////////////////////
568947Sandreas.hansson@arm.com//
578947Sandreas.hansson@arm.com//  MIPS TLB
588947Sandreas.hansson@arm.com//
592929Sktlim@umich.edu
602929Sktlim@umich.edustatic inline mode_type
6111504Sandreas.sandberg@arm.comgetOperatingMode(MiscReg Stat)
6211504Sandreas.sandberg@arm.com{
6311504Sandreas.sandberg@arm.com    if ((Stat & 0x10000006) != 0 || (Stat & 0x18) ==0) {
6411504Sandreas.sandberg@arm.com        return mode_kernel;
6511504Sandreas.sandberg@arm.com    } else if ((Stat & 0x18) == 0x8) {
6611504Sandreas.sandberg@arm.com        return mode_supervisor;
6711504Sandreas.sandberg@arm.com    } else if ((Stat & 0x18) == 0x10) {
682929Sktlim@umich.edu        return mode_user;
6911504Sandreas.sandberg@arm.com    } else {
7011504Sandreas.sandberg@arm.com        return mode_number;
716007Ssteve.reinhardt@amd.com    }
726007Ssteve.reinhardt@amd.com}
7311504Sandreas.sandberg@arm.com
742929Sktlim@umich.edu
752929Sktlim@umich.eduTLB::TLB(const Params *p)
7611504Sandreas.sandberg@arm.com    : BaseTLB(p), size(p->size), nlu(0)
776007Ssteve.reinhardt@amd.com{
786007Ssteve.reinhardt@amd.com    table = new PTE[size];
799781Sandreas.hansson@arm.com    memset(table, 0, sizeof(PTE[size]));
806007Ssteve.reinhardt@amd.com    smallPages = 0;
8111504Sandreas.sandberg@arm.com}
822929Sktlim@umich.edu
832929Sktlim@umich.eduTLB::~TLB()
8411504Sandreas.sandberg@arm.com{
8511504Sandreas.sandberg@arm.com    if (table)
8611504Sandreas.sandberg@arm.com        delete [] table;
8711504Sandreas.sandberg@arm.com}
8811504Sandreas.sandberg@arm.com
896007Ssteve.reinhardt@amd.com// look up an entry in the TLB
9011504Sandreas.sandberg@arm.comMipsISA::PTE *
9111504Sandreas.sandberg@arm.comTLB::lookup(Addr vpn, uint8_t asn) const
9211504Sandreas.sandberg@arm.com{
9311504Sandreas.sandberg@arm.com    // assume not found...
946007Ssteve.reinhardt@amd.com    PTE *retval = NULL;
9511504Sandreas.sandberg@arm.com    PageTable::const_iterator i = lookupTable.find(vpn);
9611504Sandreas.sandberg@arm.com    if (i != lookupTable.end()) {
9711504Sandreas.sandberg@arm.com        while (i->first == vpn) {
986007Ssteve.reinhardt@amd.com            int index = i->second;
992929Sktlim@umich.edu            PTE *pte = &table[index];
1002929Sktlim@umich.edu
1016007Ssteve.reinhardt@amd.com            /* 1KB TLB Lookup code - from MIPS ARM Volume III - Rev. 2.50 */
1026007Ssteve.reinhardt@amd.com            Addr Mask = pte->Mask;
1032929Sktlim@umich.edu            Addr InvMask = ~Mask;
1042929Sktlim@umich.edu            Addr VPN  = pte->VPN;
1056007Ssteve.reinhardt@amd.com            if (((vpn & InvMask) == (VPN & InvMask)) &&
1062929Sktlim@umich.edu                    (pte->G  || (asn == pte->asid))) {
1072929Sktlim@umich.edu                // We have a VPN + ASID Match
10811504Sandreas.sandberg@arm.com                retval = pte;
1098947Sandreas.hansson@arm.com                break;
11011504Sandreas.sandberg@arm.com            }
11111504Sandreas.sandberg@arm.com            ++i;
1128947Sandreas.hansson@arm.com        }
11311504Sandreas.sandberg@arm.com    }
11411504Sandreas.sandberg@arm.com
1158947Sandreas.hansson@arm.com    DPRINTF(TLB, "lookup %#x, asn %#x -> %s ppn %#x\n", vpn, (int)asn,
11611504Sandreas.sandberg@arm.com            retval ? "hit" : "miss", retval ? retval->PFN1 : 0);
11711504Sandreas.sandberg@arm.com    return retval;
11811504Sandreas.sandberg@arm.com}
1198947Sandreas.hansson@arm.com
12011504Sandreas.sandberg@arm.comMipsISA::PTE*
12111504Sandreas.sandberg@arm.comTLB::getEntry(unsigned Index) const
12211504Sandreas.sandberg@arm.com{
12311504Sandreas.sandberg@arm.com    // Make sure that Index is valid
12411542Sandreas.sandberg@arm.com    assert(Index<size);
12511542Sandreas.sandberg@arm.com    return &table[Index];
12611542Sandreas.sandberg@arm.com}
12711542Sandreas.sandberg@arm.com
12811504Sandreas.sandberg@arm.comint
12911504Sandreas.sandberg@arm.comTLB::probeEntry(Addr vpn, uint8_t asn) const
13011504Sandreas.sandberg@arm.com{
13111504Sandreas.sandberg@arm.com    // assume not found...
13211542Sandreas.sandberg@arm.com    PTE *retval = NULL;
13311504Sandreas.sandberg@arm.com    int Ind = -1;
13411504Sandreas.sandberg@arm.com    PageTable::const_iterator i = lookupTable.find(vpn);
13511504Sandreas.sandberg@arm.com    if (i != lookupTable.end()) {
13611504Sandreas.sandberg@arm.com        while (i->first == vpn) {
13711504Sandreas.sandberg@arm.com            int index = i->second;
13811504Sandreas.sandberg@arm.com            PTE *pte = &table[index];
1392929Sktlim@umich.edu
1402929Sktlim@umich.edu            /* 1KB TLB Lookup code - from MIPS ARM Volume III - Rev. 2.50 */
14111504Sandreas.sandberg@arm.com            Addr Mask = pte->Mask;
1424937Sstever@gmail.com            Addr InvMask = ~Mask;
1432929Sktlim@umich.edu            Addr VPN = pte->VPN;
14411504Sandreas.sandberg@arm.com            if (((vpn & InvMask) == (VPN & InvMask)) &&
1452929Sktlim@umich.edu                    (pte->G  || (asn == pte->asid))) {
14611504Sandreas.sandberg@arm.com                // We have a VPN + ASID Match
14711504Sandreas.sandberg@arm.com                retval = pte;
1482929Sktlim@umich.edu                Ind = index;
14911504Sandreas.sandberg@arm.com                break;
15011504Sandreas.sandberg@arm.com            }
1512929Sktlim@umich.edu            ++i;
15211504Sandreas.sandberg@arm.com        }
15311504Sandreas.sandberg@arm.com    }
15411504Sandreas.sandberg@arm.com    DPRINTF(MipsPRA,"VPN: %x, asid: %d, Result of TLBP: %d\n",vpn,asn,Ind);
15511504Sandreas.sandberg@arm.com    return Ind;
15611504Sandreas.sandberg@arm.com}
15711504Sandreas.sandberg@arm.com
15811504Sandreas.sandberg@arm.cominline Fault
15911504Sandreas.sandberg@arm.comTLB::checkCacheability(RequestPtr &req)
16011504Sandreas.sandberg@arm.com{
16111504Sandreas.sandberg@arm.com    Addr VAddrUncacheable = 0xA0000000;
16211504Sandreas.sandberg@arm.com    // In MIPS, cacheability is controlled by certain bits of the virtual
16311504Sandreas.sandberg@arm.com    // address or by the TLB entry
16411542Sandreas.sandberg@arm.com    if ((req->getVaddr() & VAddrUncacheable) == VAddrUncacheable) {
16511504Sandreas.sandberg@arm.com        // mark request as uncacheable
16611504Sandreas.sandberg@arm.com        req->setFlags(Request::UNCACHEABLE);
16711504Sandreas.sandberg@arm.com    }
16811504Sandreas.sandberg@arm.com    return NoFault;
16911504Sandreas.sandberg@arm.com}
17011504Sandreas.sandberg@arm.com
17111504Sandreas.sandberg@arm.comvoid
17211542Sandreas.sandberg@arm.comTLB::insertAt(PTE &pte, unsigned Index, int _smallPages)
17311504Sandreas.sandberg@arm.com{
17411504Sandreas.sandberg@arm.com    smallPages = _smallPages;
17511504Sandreas.sandberg@arm.com    if (Index > size) {
17611504Sandreas.sandberg@arm.com        warn("Attempted to write at index (%d) beyond TLB size (%d)",
17711504Sandreas.sandberg@arm.com                Index, size);
17811504Sandreas.sandberg@arm.com    } else {
17911504Sandreas.sandberg@arm.com        // Update TLB
1802929Sktlim@umich.edu        DPRINTF(TLB, "TLB[%d]: %x %x %x %x\n",
1812929Sktlim@umich.edu                Index, pte.Mask << 11,
1822929Sktlim@umich.edu                ((pte.VPN << 11) | pte.asid),
18311504Sandreas.sandberg@arm.com                ((pte.PFN0 << 6) | (pte.C0 << 3) |
1842929Sktlim@umich.edu                 (pte.D0 << 2) | (pte.V0 <<1) | pte.G),
1852929Sktlim@umich.edu                ((pte.PFN1 <<6) | (pte.C1 << 3) |
1862929Sktlim@umich.edu                 (pte.D1 << 2) | (pte.V1 <<1) | pte.G));
1872929Sktlim@umich.edu        if (table[Index].V0 == true || table[Index].V1 == true) {
18811504Sandreas.sandberg@arm.com            // Previous entry is valid
1892997Sstever@eecs.umich.edu            PageTable::iterator i = lookupTable.find(table[Index].VPN);
1902929Sktlim@umich.edu            lookupTable.erase(i);
19111504Sandreas.sandberg@arm.com        }
19211504Sandreas.sandberg@arm.com        table[Index]=pte;
19311504Sandreas.sandberg@arm.com        // Update fast lookup table
1942929Sktlim@umich.edu        lookupTable.insert(make_pair(table[Index].VPN, Index));
19511504Sandreas.sandberg@arm.com    }
19611504Sandreas.sandberg@arm.com}
1972929Sktlim@umich.edu
19811504Sandreas.sandberg@arm.com// insert a new TLB entry
19911504Sandreas.sandberg@arm.comvoid
2002997Sstever@eecs.umich.eduTLB::insert(Addr addr, PTE &pte)
20111504Sandreas.sandberg@arm.com{
20211504Sandreas.sandberg@arm.com    fatal("TLB Insert not yet implemented\n");
20311504Sandreas.sandberg@arm.com}
20411504Sandreas.sandberg@arm.com
2052997Sstever@eecs.umich.eduvoid
20611504Sandreas.sandberg@arm.comTLB::flushAll()
20711504Sandreas.sandberg@arm.com{
20811504Sandreas.sandberg@arm.com    DPRINTF(TLB, "flushAll\n");
20911504Sandreas.sandberg@arm.com    memset(table, 0, sizeof(PTE[size]));
21011504Sandreas.sandberg@arm.com    lookupTable.clear();
21111504Sandreas.sandberg@arm.com    nlu = 0;
2122929Sktlim@umich.edu}
2132997Sstever@eecs.umich.edu
2148120Sgblack@eecs.umich.eduvoid
21511504Sandreas.sandberg@arm.comTLB::serialize(ostream &os)
2162997Sstever@eecs.umich.edu{
21711504Sandreas.sandberg@arm.com    SERIALIZE_SCALAR(size);
2182929Sktlim@umich.edu    SERIALIZE_SCALAR(nlu);
2192997Sstever@eecs.umich.edu
2202929Sktlim@umich.edu    for (int i = 0; i < size; i++) {
22111504Sandreas.sandberg@arm.com        nameOut(os, csprintf("%s.PTE%d", name(), i));
22211504Sandreas.sandberg@arm.com        table[i].serialize(os);
2232929Sktlim@umich.edu    }
22411504Sandreas.sandberg@arm.com}
22511504Sandreas.sandberg@arm.com
2263691Shsul@eecs.umich.eduvoid
22711504Sandreas.sandberg@arm.comTLB::unserialize(Checkpoint *cp, const string &section)
2283005Sstever@eecs.umich.edu{
22911504Sandreas.sandberg@arm.com    UNSERIALIZE_SCALAR(size);
23011105Spower.jg@gmail.com    UNSERIALIZE_SCALAR(nlu);
23111504Sandreas.sandberg@arm.com
23211504Sandreas.sandberg@arm.com    for (int i = 0; i < size; i++) {
23311504Sandreas.sandberg@arm.com        table[i].unserialize(cp, csprintf("%s.PTE%d", section, i));
2346166Ssteve.reinhardt@amd.com        if (table[i].V0 || table[i].V1) {
23511504Sandreas.sandberg@arm.com            lookupTable.insert(make_pair(table[i].VPN, i));
23611504Sandreas.sandberg@arm.com        }
23711504Sandreas.sandberg@arm.com    }
23811504Sandreas.sandberg@arm.com}
23911504Sandreas.sandberg@arm.com
24011504Sandreas.sandberg@arm.comvoid
24111504Sandreas.sandberg@arm.comTLB::regStats()
24211504Sandreas.sandberg@arm.com{
24311504Sandreas.sandberg@arm.com    read_hits
24411504Sandreas.sandberg@arm.com        .name(name() + ".read_hits")
24511504Sandreas.sandberg@arm.com        .desc("DTB read hits")
24611504Sandreas.sandberg@arm.com        ;
24711504Sandreas.sandberg@arm.com
24811504Sandreas.sandberg@arm.com    read_misses
249        .name(name() + ".read_misses")
250        .desc("DTB read misses")
251        ;
252
253
254    read_accesses
255        .name(name() + ".read_accesses")
256        .desc("DTB read accesses")
257        ;
258
259    write_hits
260        .name(name() + ".write_hits")
261        .desc("DTB write hits")
262        ;
263
264    write_misses
265        .name(name() + ".write_misses")
266        .desc("DTB write misses")
267        ;
268
269
270    write_accesses
271        .name(name() + ".write_accesses")
272        .desc("DTB write accesses")
273        ;
274
275    hits
276        .name(name() + ".hits")
277        .desc("DTB hits")
278        ;
279
280    misses
281        .name(name() + ".misses")
282        .desc("DTB misses")
283        ;
284
285    accesses
286        .name(name() + ".accesses")
287        .desc("DTB accesses")
288        ;
289
290    hits = read_hits + write_hits;
291    misses = read_misses + write_misses;
292    accesses = read_accesses + write_accesses;
293}
294
295Fault
296TLB::translateInst(RequestPtr req, ThreadContext *tc)
297{
298#if !FULL_SYSTEM
299    Process * p = tc->getProcessPtr();
300
301    Fault fault = p->pTable->translate(req);
302    if (fault != NoFault)
303        return fault;
304
305    return NoFault;
306#else
307    Addr vaddr = req->getVaddr();
308
309    bool misaligned = (req->getSize() - 1) & vaddr;
310
311    if (IsKSeg0(vaddr)) {
312        // Address will not be translated through TLB, set response, and go!
313        req->setPaddr(KSeg02Phys(vaddr));
314        if (getOperatingMode(tc->readMiscReg(MISCREG_STATUS)) != mode_kernel ||
315                misaligned) {
316            AddressErrorFault *Flt = new AddressErrorFault();
317            /* BadVAddr must be set */
318            Flt->badVAddr = vaddr;
319            return Flt;
320        }
321    } else if(IsKSeg1(vaddr)) {
322        // Address will not be translated through TLB, set response, and go!
323        req->setPaddr(KSeg02Phys(vaddr));
324    } else {
325      /*
326       * This is an optimization - smallPages is updated every time a TLB
327       * operation is performed. That way, we don't need to look at
328       * Config3 _ SP and PageGrain _ ESP every time we do a TLB lookup
329       */
330      Addr VPN;
331      if (smallPages == 1) {
332        VPN = (vaddr >> 11);
333      } else {
334        VPN = ((vaddr >> 11) & 0xFFFFFFFC);
335      }
336      uint8_t Asid = req->getAsid();
337      if (misaligned) {
338          // Unaligned address!
339          AddressErrorFault *Flt = new AddressErrorFault();
340          /* BadVAddr must be set */
341          Flt->badVAddr = vaddr;
342          return Flt;
343      }
344      PTE *pte = lookup(VPN,Asid);
345      if (pte != NULL) {
346          // Ok, found something
347          /* Check for valid bits */
348          int EvenOdd;
349          bool Valid;
350          if ((((vaddr) >> pte->AddrShiftAmount) & 1) == 0) {
351              // Check even bits
352              Valid = pte->V0;
353              EvenOdd = 0;
354          } else {
355              // Check odd bits
356              Valid = pte->V1;
357              EvenOdd = 1;
358          }
359
360          if (Valid == false) {
361              //Invalid entry
362              ItbInvalidFault *Flt = new ItbInvalidFault();
363              /* EntryHi VPN, ASID fields must be set */
364              Flt->entryHiAsid = Asid;
365              Flt->entryHiVPN2 = (VPN >> 2);
366              Flt->entryHiVPN2X = (VPN & 0x3);
367
368              /* BadVAddr must be set */
369              Flt->badVAddr = vaddr;
370
371              /* Context must be set */
372              Flt->contextBadVPN2 = (VPN >> 2);
373              return Flt;
374          } else {
375              // Ok, this is really a match, set paddr
376              Addr PAddr;
377              if (EvenOdd == 0) {
378                PAddr = pte->PFN0;
379              } else {
380                PAddr = pte->PFN1;
381              }
382              PAddr >>= (pte->AddrShiftAmount - 12);
383              PAddr <<= pte->AddrShiftAmount;
384              PAddr |= (vaddr & pte->OffsetMask);
385              req->setPaddr(PAddr);
386            }
387        } else {
388            // Didn't find any match, return a TLB Refill Exception
389            ItbRefillFault *Flt = new ItbRefillFault();
390            /* EntryHi VPN, ASID fields must be set */
391            Flt->entryHiAsid = Asid;
392            Flt->entryHiVPN2 = (VPN >> 2);
393            Flt->entryHiVPN2X = (VPN & 0x3);
394
395            /* BadVAddr must be set */
396            Flt->badVAddr = vaddr;
397
398            /* Context must be set */
399            Flt->contextBadVPN2 = (VPN >> 2);
400            return Flt;
401        }
402    }
403    return checkCacheability(req);
404#endif
405}
406
407Fault
408TLB::translateData(RequestPtr req, ThreadContext *tc, bool write)
409{
410#if !FULL_SYSTEM
411    //@TODO: This should actually use TLB instead of going directly
412    //       to the page table in syscall mode.
413    /**
414     * Check for alignment faults
415     */
416    if (req->getVaddr() & (req->getSize() - 1)) {
417        DPRINTF(TLB, "Alignment Fault on %#x, size = %d", req->getVaddr(),
418                req->getSize());
419        return new AlignmentFault();
420    }
421
422
423    Process * p = tc->getProcessPtr();
424
425    Fault fault = p->pTable->translate(req);
426    if (fault != NoFault)
427        return fault;
428
429    return NoFault;
430#else
431    Addr vaddr = req->getVaddr();
432
433    bool misaligned = (req->getSize() - 1) & vaddr;
434
435    if (IsKSeg0(vaddr)) {
436        // Address will not be translated through TLB, set response, and go!
437        req->setPaddr(KSeg02Phys(vaddr));
438        if (getOperatingMode(tc->readMiscReg(MISCREG_STATUS)) != mode_kernel ||
439                misaligned) {
440            StoreAddressErrorFault *Flt = new StoreAddressErrorFault();
441            /* BadVAddr must be set */
442            Flt->badVAddr = vaddr;
443
444            return Flt;
445        }
446    } else if(IsKSeg1(vaddr)) {
447      // Address will not be translated through TLB, set response, and go!
448      req->setPaddr(KSeg02Phys(vaddr));
449    } else {
450        /*
451         * This is an optimization - smallPages is updated every time a TLB
452         * operation is performed. That way, we don't need to look at
453         * Config3 _ SP and PageGrain _ ESP every time we do a TLB lookup
454         */
455        Addr VPN = (vaddr >> 11) & 0xFFFFFFFC;
456        if (smallPages == 1) {
457            VPN = vaddr >> 11;
458        }
459        uint8_t Asid = req->getAsid();
460        PTE *pte = lookup(VPN, Asid);
461        if (misaligned) {
462            // Unaligned address!
463            StoreAddressErrorFault *Flt = new StoreAddressErrorFault();
464            /* BadVAddr must be set */
465            Flt->badVAddr = vaddr;
466            return Flt;
467        }
468        if (pte != NULL) {
469            // Ok, found something
470            /* Check for valid bits */
471            int EvenOdd;
472            bool Valid;
473            bool Dirty;
474            if ((((vaddr >> pte->AddrShiftAmount) & 1)) == 0) {
475                // Check even bits
476                Valid = pte->V0;
477                Dirty = pte->D0;
478                EvenOdd = 0;
479            } else {
480                // Check odd bits
481                Valid = pte->V1;
482                Dirty = pte->D1;
483                EvenOdd = 1;
484            }
485
486            if (Valid == false) {
487                //Invalid entry
488                DtbInvalidFault *Flt = new DtbInvalidFault();
489                /* EntryHi VPN, ASID fields must be set */
490                Flt->entryHiAsid = Asid;
491                Flt->entryHiVPN2 = (VPN>>2);
492                Flt->entryHiVPN2X = (VPN & 0x3);
493
494                /* BadVAddr must be set */
495                Flt->badVAddr = vaddr;
496
497                /* Context must be set */
498                Flt->contextBadVPN2 = (VPN >> 2);
499
500                return Flt;
501            } else {
502                // Ok, this is really a match, set paddr
503                if (!Dirty) {
504                    TLBModifiedFault *Flt = new TLBModifiedFault();
505                    /* EntryHi VPN, ASID fields must be set */
506                    Flt->entryHiAsid = Asid;
507                    Flt->entryHiVPN2 = (VPN >> 2);
508                    Flt->entryHiVPN2X = (VPN & 0x3);
509
510                    /* BadVAddr must be set */
511                    Flt->badVAddr = vaddr;
512
513                    /* Context must be set */
514                    Flt->contextBadVPN2 = (VPN >> 2);
515                    return Flt;
516                }
517                Addr PAddr;
518                if (EvenOdd == 0) {
519                    PAddr = pte->PFN0;
520                } else {
521                    PAddr = pte->PFN1;
522                }
523                PAddr >>= (pte->AddrShiftAmount - 12);
524                PAddr <<= pte->AddrShiftAmount;
525                PAddr |= (vaddr & pte->OffsetMask);
526                req->setPaddr(PAddr);
527            }
528        } else {
529            // Didn't find any match, return a TLB Refill Exception
530            DtbRefillFault *Flt = new DtbRefillFault();
531            /* EntryHi VPN, ASID fields must be set */
532            Flt->entryHiAsid = Asid;
533            Flt->entryHiVPN2 = (VPN >> 2);
534            Flt->entryHiVPN2X = (VPN & 0x3);
535
536            /* BadVAddr must be set */
537            Flt->badVAddr = vaddr;
538
539            /* Context must be set */
540            Flt->contextBadVPN2 = (VPN >> 2);
541            return Flt;
542        }
543    }
544    return checkCacheability(req);
545#endif
546}
547
548Fault
549TLB::translateAtomic(RequestPtr req, ThreadContext *tc, Mode mode)
550{
551    if (mode == Execute)
552        return translateInst(req, tc);
553    else
554        return translateData(req, tc, mode == Write);
555}
556
557void
558TLB::translateTiming(RequestPtr req, ThreadContext *tc,
559        Translation *translation, Mode mode)
560{
561    assert(translation);
562    translation->finish(translateAtomic(req, tc, mode), req, tc, mode);
563}
564
565
566MipsISA::PTE &
567TLB::index(bool advance)
568{
569    PTE *pte = &table[nlu];
570
571    if (advance)
572        nextnlu();
573
574    return *pte;
575}
576
577MipsISA::TLB *
578MipsTLBParams::create()
579{
580    return new TLB(this);
581}
582