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