tlb.cc revision 533
17118Sgblack@eecs.umich.edu/*
27118Sgblack@eecs.umich.edu * Copyright (c) 2003 The Regents of The University of Michigan
37118Sgblack@eecs.umich.edu * All rights reserved.
47118Sgblack@eecs.umich.edu *
57118Sgblack@eecs.umich.edu * Redistribution and use in source and binary forms, with or without
67118Sgblack@eecs.umich.edu * modification, are permitted provided that the following conditions are
77118Sgblack@eecs.umich.edu * met: redistributions of source code must retain the above copyright
87118Sgblack@eecs.umich.edu * notice, this list of conditions and the following disclaimer;
97118Sgblack@eecs.umich.edu * redistributions in binary form must reproduce the above copyright
107118Sgblack@eecs.umich.edu * notice, this list of conditions and the following disclaimer in the
117118Sgblack@eecs.umich.edu * documentation and/or other materials provided with the distribution;
127118Sgblack@eecs.umich.edu * neither the name of the copyright holders nor the names of its
137118Sgblack@eecs.umich.edu * contributors may be used to endorse or promote products derived from
147118Sgblack@eecs.umich.edu * this software without specific prior written permission.
156253Sgblack@eecs.umich.edu *
166253Sgblack@eecs.umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
176253Sgblack@eecs.umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
186253Sgblack@eecs.umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
196253Sgblack@eecs.umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
206253Sgblack@eecs.umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
216253Sgblack@eecs.umich.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
226253Sgblack@eecs.umich.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
236253Sgblack@eecs.umich.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
246253Sgblack@eecs.umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
256253Sgblack@eecs.umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
266253Sgblack@eecs.umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
276253Sgblack@eecs.umich.edu */
286253Sgblack@eecs.umich.edu
296253Sgblack@eecs.umich.edu#include <sstream>
306253Sgblack@eecs.umich.edu#include <string>
316253Sgblack@eecs.umich.edu#include <vector>
326253Sgblack@eecs.umich.edu
336253Sgblack@eecs.umich.edu#include "base/inifile.hh"
346253Sgblack@eecs.umich.edu#include "base/str.hh"
356253Sgblack@eecs.umich.edu#include "base/trace.hh"
366253Sgblack@eecs.umich.edu#include "cpu/exec_context.hh"
376253Sgblack@eecs.umich.edu#include "sim/builder.hh"
386253Sgblack@eecs.umich.edu#include "targetarch/alpha_memory.hh"
396253Sgblack@eecs.umich.edu#include "targetarch/ev5.hh"
406253Sgblack@eecs.umich.edu
416253Sgblack@eecs.umich.eduusing namespace std;
426253Sgblack@eecs.umich.edu
436253Sgblack@eecs.umich.edu///////////////////////////////////////////////////////////////////////
446253Sgblack@eecs.umich.edu//
456253Sgblack@eecs.umich.edu//  Alpha TLB
466253Sgblack@eecs.umich.edu//
476253Sgblack@eecs.umich.eduAlphaTlb::AlphaTlb(const string &name, int s)
486253Sgblack@eecs.umich.edu    : SimObject(name), size(s), nlu(0)
497118Sgblack@eecs.umich.edu{
507118Sgblack@eecs.umich.edu    table = new AlphaISA::PTE[size];
517118Sgblack@eecs.umich.edu    memset(table, 0, sizeof(AlphaISA::PTE[size]));
527118Sgblack@eecs.umich.edu}
537118Sgblack@eecs.umich.edu
547118Sgblack@eecs.umich.eduAlphaTlb::~AlphaTlb()
557118Sgblack@eecs.umich.edu{
567118Sgblack@eecs.umich.edu    if (table)
577118Sgblack@eecs.umich.edu        delete [] table;
587118Sgblack@eecs.umich.edu}
597118Sgblack@eecs.umich.edu
607118Sgblack@eecs.umich.edu// look up an entry in the TLB
617118Sgblack@eecs.umich.eduAlphaISA::PTE *
627118Sgblack@eecs.umich.eduAlphaTlb::lookup(Addr vpn, uint8_t asn) const
637118Sgblack@eecs.umich.edu{
647118Sgblack@eecs.umich.edu    DPRINTF(TLB, "lookup %#x\n", vpn);
657118Sgblack@eecs.umich.edu
667118Sgblack@eecs.umich.edu    PageTable::const_iterator i = lookupTable.find(vpn);
677118Sgblack@eecs.umich.edu    if (i == lookupTable.end())
687118Sgblack@eecs.umich.edu        return NULL;
697118Sgblack@eecs.umich.edu
707118Sgblack@eecs.umich.edu    while (i->first == vpn) {
717118Sgblack@eecs.umich.edu        int index = i->second;
727118Sgblack@eecs.umich.edu        AlphaISA::PTE *pte = &table[index];
737118Sgblack@eecs.umich.edu        assert(pte->valid);
747118Sgblack@eecs.umich.edu        if (vpn == pte->tag && (pte->asma || pte->asn == asn))
757118Sgblack@eecs.umich.edu            return pte;
767118Sgblack@eecs.umich.edu
777118Sgblack@eecs.umich.edu        ++i;
787118Sgblack@eecs.umich.edu    }
797118Sgblack@eecs.umich.edu
807118Sgblack@eecs.umich.edu    // not found...
817118Sgblack@eecs.umich.edu    return NULL;
827118Sgblack@eecs.umich.edu}
837118Sgblack@eecs.umich.edu
847118Sgblack@eecs.umich.edu
857118Sgblack@eecs.umich.eduvoid
867118Sgblack@eecs.umich.eduAlphaTlb::checkCacheability(MemReqPtr &req)
877118Sgblack@eecs.umich.edu{
887118Sgblack@eecs.umich.edu    // in Alpha, cacheability is controlled by upper-level bits of the
897118Sgblack@eecs.umich.edu    // physical address
907118Sgblack@eecs.umich.edu    if (req->paddr & PA_UNCACHED_BIT) {
917118Sgblack@eecs.umich.edu        if (PA_IPR_SPACE(req->paddr)) {
927118Sgblack@eecs.umich.edu            // IPR memory space not implemented
937118Sgblack@eecs.umich.edu            if (!req->xc->misspeculating()) {
947118Sgblack@eecs.umich.edu                switch (req->paddr) {
957118Sgblack@eecs.umich.edu                  case 0xFFFFF00188:
967118Sgblack@eecs.umich.edu                    req->data = 0;
977118Sgblack@eecs.umich.edu                    break;
987118Sgblack@eecs.umich.edu
997118Sgblack@eecs.umich.edu                  default:
1007118Sgblack@eecs.umich.edu                    panic("IPR memory space not implemented! PA=%x\n",
1017118Sgblack@eecs.umich.edu                          req->paddr);
1027118Sgblack@eecs.umich.edu                }
1037118Sgblack@eecs.umich.edu            }
1047118Sgblack@eecs.umich.edu        } else {
1057118Sgblack@eecs.umich.edu            // mark request as uncacheable
1067118Sgblack@eecs.umich.edu            req->flags |= UNCACHEABLE;
1077118Sgblack@eecs.umich.edu        }
1087118Sgblack@eecs.umich.edu    }
1097118Sgblack@eecs.umich.edu}
1107118Sgblack@eecs.umich.edu
1117118Sgblack@eecs.umich.edu
1127118Sgblack@eecs.umich.edu// insert a new TLB entry
1137118Sgblack@eecs.umich.eduvoid
1147118Sgblack@eecs.umich.eduAlphaTlb::insert(Addr vaddr, AlphaISA::PTE &pte)
1157118Sgblack@eecs.umich.edu{
1167118Sgblack@eecs.umich.edu    if (table[nlu].valid) {
1177118Sgblack@eecs.umich.edu        Addr oldvpn = table[nlu].tag;
1187118Sgblack@eecs.umich.edu        PageTable::iterator i = lookupTable.find(oldvpn);
1197118Sgblack@eecs.umich.edu
1207118Sgblack@eecs.umich.edu        if (i == lookupTable.end())
1217118Sgblack@eecs.umich.edu            panic("TLB entry not found in lookupTable");
1227118Sgblack@eecs.umich.edu
1237118Sgblack@eecs.umich.edu        int index;
1247118Sgblack@eecs.umich.edu        while ((index = i->second) != nlu) {
1257118Sgblack@eecs.umich.edu            if (table[index].tag != oldvpn)
1267118Sgblack@eecs.umich.edu                panic("TLB entry not found in lookupTable");
1277118Sgblack@eecs.umich.edu
1287118Sgblack@eecs.umich.edu            ++i;
1297118Sgblack@eecs.umich.edu        }
1307118Sgblack@eecs.umich.edu
1317118Sgblack@eecs.umich.edu        DPRINTF(TLB, "remove @%d: %#x -> %#x\n", nlu, oldvpn, table[nlu].ppn);
1327118Sgblack@eecs.umich.edu
1337118Sgblack@eecs.umich.edu        lookupTable.erase(i);
1347118Sgblack@eecs.umich.edu    }
1357118Sgblack@eecs.umich.edu
1367118Sgblack@eecs.umich.edu    Addr vpn = VA_VPN(vaddr);
1377118Sgblack@eecs.umich.edu    DPRINTF(TLB, "insert @%d: %#x -> %#x\n", nlu, vpn, pte.ppn);
1387118Sgblack@eecs.umich.edu
1397118Sgblack@eecs.umich.edu    table[nlu] = pte;
1407118Sgblack@eecs.umich.edu    table[nlu].tag = vpn;
1417118Sgblack@eecs.umich.edu    table[nlu].valid = true;
1427118Sgblack@eecs.umich.edu
1437118Sgblack@eecs.umich.edu    lookupTable.insert(make_pair(vpn, nlu));
1447118Sgblack@eecs.umich.edu    nextnlu();
1457118Sgblack@eecs.umich.edu}
1467118Sgblack@eecs.umich.edu
1477118Sgblack@eecs.umich.eduvoid
1487118Sgblack@eecs.umich.eduAlphaTlb::flushAll()
1497118Sgblack@eecs.umich.edu{
1507118Sgblack@eecs.umich.edu    memset(table, 0, sizeof(AlphaISA::PTE[size]));
1517118Sgblack@eecs.umich.edu    lookupTable.clear();
1527118Sgblack@eecs.umich.edu    nlu = 0;
1537118Sgblack@eecs.umich.edu}
1547118Sgblack@eecs.umich.edu
1557118Sgblack@eecs.umich.eduvoid
1567118Sgblack@eecs.umich.eduAlphaTlb::flushProcesses()
1577118Sgblack@eecs.umich.edu{
1587118Sgblack@eecs.umich.edu    PageTable::iterator i = lookupTable.begin();
1597118Sgblack@eecs.umich.edu    PageTable::iterator end = lookupTable.end();
1607118Sgblack@eecs.umich.edu    while (i != end) {
1617118Sgblack@eecs.umich.edu        int index = i->second;
1627118Sgblack@eecs.umich.edu        AlphaISA::PTE *pte = &table[index];
1637118Sgblack@eecs.umich.edu        assert(pte->valid);
1647118Sgblack@eecs.umich.edu
1657118Sgblack@eecs.umich.edu        if (!pte->asma) {
1667118Sgblack@eecs.umich.edu            DPRINTF(TLB, "flush @%d: %#x -> %#x\n", index, pte->tag, pte->ppn);
1677118Sgblack@eecs.umich.edu            pte->valid = false;
1687118Sgblack@eecs.umich.edu            lookupTable.erase(i);
1697118Sgblack@eecs.umich.edu        }
1707118Sgblack@eecs.umich.edu
1717118Sgblack@eecs.umich.edu        ++i;
1727118Sgblack@eecs.umich.edu    }
1737118Sgblack@eecs.umich.edu}
1747118Sgblack@eecs.umich.edu
1757118Sgblack@eecs.umich.eduvoid
1767118Sgblack@eecs.umich.eduAlphaTlb::flushAddr(Addr vaddr, uint8_t asn)
1777118Sgblack@eecs.umich.edu{
1787118Sgblack@eecs.umich.edu    Addr vpn = VA_VPN(vaddr);
1797118Sgblack@eecs.umich.edu
1807118Sgblack@eecs.umich.edu    PageTable::iterator i = lookupTable.find(vpn);
1817118Sgblack@eecs.umich.edu    if (i == lookupTable.end())
1827118Sgblack@eecs.umich.edu        return;
1837118Sgblack@eecs.umich.edu
1847118Sgblack@eecs.umich.edu    while (i->first == vpn) {
1857118Sgblack@eecs.umich.edu        int index = i->second;
1867118Sgblack@eecs.umich.edu        AlphaISA::PTE *pte = &table[index];
1877118Sgblack@eecs.umich.edu        assert(pte->valid);
1887118Sgblack@eecs.umich.edu
1897118Sgblack@eecs.umich.edu        if (vpn == pte->tag && (pte->asma || pte->asn == asn)) {
1907118Sgblack@eecs.umich.edu            DPRINTF(TLB, "flushaddr @%d: %#x -> %#x\n", index, vpn, pte->ppn);
1917118Sgblack@eecs.umich.edu
1927118Sgblack@eecs.umich.edu            // invalidate this entry
1937118Sgblack@eecs.umich.edu            pte->valid = false;
1947118Sgblack@eecs.umich.edu
1957118Sgblack@eecs.umich.edu            lookupTable.erase(i);
1967118Sgblack@eecs.umich.edu        }
1977118Sgblack@eecs.umich.edu
1987118Sgblack@eecs.umich.edu        ++i;
1997118Sgblack@eecs.umich.edu    }
2007118Sgblack@eecs.umich.edu}
2017118Sgblack@eecs.umich.edu
2027118Sgblack@eecs.umich.edu
2037118Sgblack@eecs.umich.eduvoid
2047118Sgblack@eecs.umich.eduAlphaTlb::serialize(ostream &os)
2057118Sgblack@eecs.umich.edu{
2067118Sgblack@eecs.umich.edu    SERIALIZE_SCALAR(size);
2077118Sgblack@eecs.umich.edu    SERIALIZE_SCALAR(nlu);
2087118Sgblack@eecs.umich.edu
2097118Sgblack@eecs.umich.edu    for (int i = 0; i < size; i++) {
2107118Sgblack@eecs.umich.edu        nameOut(os, csprintf("%s.PTE%d", name(), i));
2117118Sgblack@eecs.umich.edu        table[i].serialize(os);
2127118Sgblack@eecs.umich.edu    }
2137118Sgblack@eecs.umich.edu}
2147118Sgblack@eecs.umich.edu
2157118Sgblack@eecs.umich.eduvoid
2167118Sgblack@eecs.umich.eduAlphaTlb::unserialize(Checkpoint *cp, const string &section)
2177118Sgblack@eecs.umich.edu{
2187118Sgblack@eecs.umich.edu    UNSERIALIZE_SCALAR(size);
2197118Sgblack@eecs.umich.edu    UNSERIALIZE_SCALAR(nlu);
2207118Sgblack@eecs.umich.edu
2217118Sgblack@eecs.umich.edu    for (int i = 0; i < size; i++) {
2227118Sgblack@eecs.umich.edu        table[i].unserialize(cp, csprintf("%s.PTE%d", section, i));
2237118Sgblack@eecs.umich.edu        if (table[i].valid) {
2247118Sgblack@eecs.umich.edu            lookupTable.insert(make_pair(table[i].tag, i));
2257118Sgblack@eecs.umich.edu        }
2267118Sgblack@eecs.umich.edu    }
2277118Sgblack@eecs.umich.edu}
2287118Sgblack@eecs.umich.edu
2297118Sgblack@eecs.umich.edu
2307118Sgblack@eecs.umich.edu///////////////////////////////////////////////////////////////////////
2317118Sgblack@eecs.umich.edu//
2327118Sgblack@eecs.umich.edu//  Alpha ITB
2336253Sgblack@eecs.umich.edu//
2346253Sgblack@eecs.umich.eduAlphaItb::AlphaItb(const std::string &name, int size)
2356253Sgblack@eecs.umich.edu    : AlphaTlb(name, size)
2366253Sgblack@eecs.umich.edu{}
2376253Sgblack@eecs.umich.edu
2386253Sgblack@eecs.umich.edu
2396253Sgblack@eecs.umich.eduvoid
2406253Sgblack@eecs.umich.eduAlphaItb::regStats()
2416253Sgblack@eecs.umich.edu{
2426253Sgblack@eecs.umich.edu    hits
2436253Sgblack@eecs.umich.edu        .name(name() + ".hits")
2446253Sgblack@eecs.umich.edu        .desc("ITB hits");
2456253Sgblack@eecs.umich.edu    misses
2466253Sgblack@eecs.umich.edu        .name(name() + ".misses")
2476253Sgblack@eecs.umich.edu        .desc("ITB misses");
2486253Sgblack@eecs.umich.edu    acv
2496253Sgblack@eecs.umich.edu        .name(name() + ".acv")
2506253Sgblack@eecs.umich.edu        .desc("ITB acv");
2516253Sgblack@eecs.umich.edu    accesses
2526305Sgblack@eecs.umich.edu        .name(name() + ".accesses")
2536253Sgblack@eecs.umich.edu        .desc("ITB accesses");
2546253Sgblack@eecs.umich.edu
2556253Sgblack@eecs.umich.edu    accesses = hits + misses;
2566253Sgblack@eecs.umich.edu}
2576253Sgblack@eecs.umich.edu
2586253Sgblack@eecs.umich.eduvoid
2596253Sgblack@eecs.umich.eduAlphaItb::fault(Addr pc, ExecContext *xc) const
2606253Sgblack@eecs.umich.edu{
2616253Sgblack@eecs.umich.edu    uint64_t *ipr = xc->regs.ipr;
2626253Sgblack@eecs.umich.edu
2636253Sgblack@eecs.umich.edu    if (!xc->misspeculating()) {
2646253Sgblack@eecs.umich.edu        ipr[AlphaISA::IPR_ITB_TAG] = pc;
2656307Sgblack@eecs.umich.edu        ipr[AlphaISA::IPR_IFAULT_VA_FORM] =
2666307Sgblack@eecs.umich.edu            ipr[AlphaISA::IPR_IVPTBR] | (VA_VPN(pc) << 3);
2676307Sgblack@eecs.umich.edu    }
2686307Sgblack@eecs.umich.edu}
2696253Sgblack@eecs.umich.edu
2706253Sgblack@eecs.umich.edu
2716307Sgblack@eecs.umich.eduFault
2726253Sgblack@eecs.umich.eduAlphaItb::translate(MemReqPtr &req) const
2736253Sgblack@eecs.umich.edu{
2746253Sgblack@eecs.umich.edu    InternalProcReg *ipr = req->xc->regs.ipr;
2756307Sgblack@eecs.umich.edu
2766305Sgblack@eecs.umich.edu    if (PC_PAL(req->vaddr)) {
2776253Sgblack@eecs.umich.edu        // strip off PAL PC marker (lsb is 1)
2786253Sgblack@eecs.umich.edu        req->paddr = (req->vaddr & ~3) & PA_IMPL_MASK;
2796253Sgblack@eecs.umich.edu        hits++;
2806307Sgblack@eecs.umich.edu        return No_Fault;
2816307Sgblack@eecs.umich.edu    }
2826307Sgblack@eecs.umich.edu
2836307Sgblack@eecs.umich.edu    // verify that this is a good virtual address
2846307Sgblack@eecs.umich.edu    if (!validVirtualAddress(req->vaddr)) {
2856307Sgblack@eecs.umich.edu        fault(req->vaddr, req->xc);
2866307Sgblack@eecs.umich.edu        acv++;
2876307Sgblack@eecs.umich.edu        return Itb_Acv_Fault;
2886307Sgblack@eecs.umich.edu    }
2896307Sgblack@eecs.umich.edu
2906307Sgblack@eecs.umich.edu    // Check for "superpage" mapping: when SP<1> is set, and
2916307Sgblack@eecs.umich.edu    // VA<42:41> == 2, VA<39:13> maps directly to PA<39:13>.
2926307Sgblack@eecs.umich.edu    if ((MCSR_SP(ipr[AlphaISA::IPR_MCSR]) & 2) &&
2936307Sgblack@eecs.umich.edu        VA_SPACE(req->vaddr) == 2) {
2946307Sgblack@eecs.umich.edu        // only valid in kernel mode
2956307Sgblack@eecs.umich.edu        if (ICM_CM(ipr[AlphaISA::IPR_ICM]) != AlphaISA::mode_kernel) {
2966307Sgblack@eecs.umich.edu            fault(req->vaddr, req->xc);
2976307Sgblack@eecs.umich.edu            acv++;
2986307Sgblack@eecs.umich.edu            return Itb_Acv_Fault;
2996307Sgblack@eecs.umich.edu        }
3006307Sgblack@eecs.umich.edu
3016307Sgblack@eecs.umich.edu        req->flags |= PHYSICAL;
3026307Sgblack@eecs.umich.edu    }
3036307Sgblack@eecs.umich.edu
3046307Sgblack@eecs.umich.edu    if (req->flags & PHYSICAL) {
3056307Sgblack@eecs.umich.edu        req->paddr = req->vaddr & PA_IMPL_MASK;
3066307Sgblack@eecs.umich.edu    } else {
3076307Sgblack@eecs.umich.edu        // not a physical address: need to look up pte
3086307Sgblack@eecs.umich.edu
3096307Sgblack@eecs.umich.edu        AlphaISA::PTE *pte = lookup(VA_VPN(req->vaddr),
3106307Sgblack@eecs.umich.edu                                DTB_ASN_ASN(ipr[AlphaISA::IPR_DTB_ASN]));
3116307Sgblack@eecs.umich.edu
3126307Sgblack@eecs.umich.edu        if (!pte) {
3136307Sgblack@eecs.umich.edu            fault(req->vaddr, req->xc);
3146307Sgblack@eecs.umich.edu            misses++;
3156307Sgblack@eecs.umich.edu            return Itb_Fault_Fault;
3166307Sgblack@eecs.umich.edu        }
3176307Sgblack@eecs.umich.edu
3186307Sgblack@eecs.umich.edu        req->paddr = PA_PFN2PA(pte->ppn) + VA_POFS(req->vaddr & ~3);
3196307Sgblack@eecs.umich.edu
3206307Sgblack@eecs.umich.edu        // check permissions for this access
3216307Sgblack@eecs.umich.edu        if (!(pte->xre & (1 << ICM_CM(ipr[AlphaISA::IPR_ICM])))) {
3226307Sgblack@eecs.umich.edu            // instruction access fault
3236307Sgblack@eecs.umich.edu            fault(req->vaddr, req->xc);
3246307Sgblack@eecs.umich.edu            acv++;
3256307Sgblack@eecs.umich.edu            return Itb_Acv_Fault;
3266307Sgblack@eecs.umich.edu        }
3276307Sgblack@eecs.umich.edu    }
3286307Sgblack@eecs.umich.edu
3296307Sgblack@eecs.umich.edu    checkCacheability(req);
3306307Sgblack@eecs.umich.edu
3316307Sgblack@eecs.umich.edu    hits++;
3326307Sgblack@eecs.umich.edu    return No_Fault;
3336307Sgblack@eecs.umich.edu}
3346253Sgblack@eecs.umich.edu
3356253Sgblack@eecs.umich.edu///////////////////////////////////////////////////////////////////////
3366253Sgblack@eecs.umich.edu//
3376253Sgblack@eecs.umich.edu//  Alpha DTB
338//
339AlphaDtb::AlphaDtb(const std::string &name, int size)
340    : AlphaTlb(name, size)
341{}
342
343void
344AlphaDtb::regStats()
345{
346    read_hits
347        .name(name() + ".read_hits")
348        .desc("DTB read hits")
349        ;
350
351    read_misses
352        .name(name() + ".read_misses")
353        .desc("DTB read misses")
354        ;
355
356    read_acv
357        .name(name() + ".read_acv")
358        .desc("DTB read access violations")
359        ;
360
361    read_accesses
362        .name(name() + ".read_accesses")
363        .desc("DTB read accesses")
364        ;
365
366    write_hits
367        .name(name() + ".write_hits")
368        .desc("DTB write hits")
369        ;
370
371    write_misses
372        .name(name() + ".write_misses")
373        .desc("DTB write misses")
374        ;
375
376    write_acv
377        .name(name() + ".write_acv")
378        .desc("DTB write access violations")
379        ;
380
381    write_accesses
382        .name(name() + ".write_accesses")
383        .desc("DTB write accesses")
384        ;
385
386    hits
387        .name(name() + ".hits")
388        .desc("DTB hits")
389        ;
390
391    misses
392        .name(name() + ".misses")
393        .desc("DTB misses")
394        ;
395
396    acv
397        .name(name() + ".acv")
398        .desc("DTB access violations")
399        ;
400
401    accesses
402        .name(name() + ".accesses")
403        .desc("DTB accesses")
404        ;
405
406    hits = read_hits + write_hits;
407    misses = read_misses + write_misses;
408    acv = read_acv + write_acv;
409    accesses = read_accesses + write_accesses;
410}
411
412void
413AlphaDtb::fault(Addr vaddr, uint64_t flags, ExecContext *xc) const
414{
415    uint64_t *ipr = xc->regs.ipr;
416
417    // set fault address and flags
418    if (!xc->misspeculating() && !xc->regs.intrlock) {
419        // set VA register with faulting address
420        ipr[AlphaISA::IPR_VA] = vaddr;
421
422        // set MM_STAT register flags
423        ipr[AlphaISA::IPR_MM_STAT] = (((xc->regs.opcode & 0x3f) << 11)
424                               | ((xc->regs.ra & 0x1f) << 6)
425                               | (flags & 0x3f));
426
427        // set VA_FORM register with faulting formatted address
428        ipr[AlphaISA::IPR_VA_FORM] =
429            ipr[AlphaISA::IPR_MVPTBR] | (VA_VPN(vaddr) << 3);
430
431        // lock these registers until the VA register is read
432        xc->regs.intrlock = true;
433    }
434}
435
436Fault
437AlphaDtb::translate(MemReqPtr &req, bool write) const
438{
439    RegFile *regs = &req->xc->regs;
440    Addr pc = regs->pc;
441    InternalProcReg *ipr = regs->ipr;
442
443    if (write)
444        write_accesses++;
445    else
446        read_accesses++;
447
448    AlphaISA::mode_type mode =
449        (AlphaISA::mode_type)DTB_CM_CM(ipr[AlphaISA::IPR_DTB_CM]);
450
451    if (PC_PAL(pc)) {
452        mode = (req->flags & ALTMODE) ?
453            (AlphaISA::mode_type)ALT_MODE_AM(ipr[AlphaISA::IPR_ALT_MODE])
454            : AlphaISA::mode_kernel;
455    }
456
457    // verify that this is a good virtual address
458    if (!validVirtualAddress(req->vaddr)) {
459        fault(req->vaddr,
460              ((write ? MM_STAT_WR_MASK : 0) | MM_STAT_BAD_VA_MASK |
461               MM_STAT_ACV_MASK),
462              req->xc);
463
464        if (write) { write_acv++; } else { read_acv++; }
465        return Dtb_Fault_Fault;
466    }
467
468    // Check for "superpage" mapping: when SP<1> is set, and
469    // VA<42:41> == 2, VA<39:13> maps directly to PA<39:13>.
470    if ((MCSR_SP(ipr[AlphaISA::IPR_MCSR]) & 2) && VA_SPACE(req->vaddr) == 2) {
471        // only valid in kernel mode
472        if (DTB_CM_CM(ipr[AlphaISA::IPR_DTB_CM]) != AlphaISA::mode_kernel) {
473            fault(req->vaddr,
474                  ((write ? MM_STAT_WR_MASK : 0) | MM_STAT_ACV_MASK),
475                  req->xc);
476            if (write) { write_acv++; } else { read_acv++; }
477            return Dtb_Acv_Fault;
478        }
479
480        req->flags |= PHYSICAL;
481    }
482
483    if (req->flags & PHYSICAL) {
484        req->paddr = req->vaddr & PA_IMPL_MASK;
485    } else {
486        // not a physical address: need to look up pte
487
488        AlphaISA::PTE *pte = lookup(VA_VPN(req->vaddr),
489                                DTB_ASN_ASN(ipr[AlphaISA::IPR_DTB_ASN]));
490
491        if (!pte) {
492            // page fault
493            fault(req->vaddr,
494                  ((write ? MM_STAT_WR_MASK : 0) | MM_STAT_DTB_MISS_MASK),
495                  req->xc);
496            if (write) { write_misses++; } else { read_misses++; }
497            return (req->flags & VPTE) ? Pdtb_Miss_Fault : Ndtb_Miss_Fault;
498        }
499
500        req->paddr = PA_PFN2PA(pte->ppn) | VA_POFS(req->vaddr);
501
502        if (write) {
503            if (!(pte->xwe & MODE2MASK(mode))) {
504                // declare the instruction access fault
505                fault(req->vaddr, MM_STAT_WR_MASK | MM_STAT_ACV_MASK |
506                      (pte->fonw ? MM_STAT_FONW_MASK : 0),
507                      req->xc);
508                write_acv++;
509                return Dtb_Fault_Fault;
510            }
511            if (pte->fonw) {
512                fault(req->vaddr, MM_STAT_WR_MASK | MM_STAT_FONW_MASK,
513                      req->xc);
514                write_acv++;
515                return Dtb_Fault_Fault;
516            }
517        } else {
518            if (!(pte->xre & MODE2MASK(mode))) {
519                fault(req->vaddr,
520                      MM_STAT_ACV_MASK | (pte->fonr ? MM_STAT_FONR_MASK : 0),
521                      req->xc);
522                read_acv++;
523                return Dtb_Acv_Fault;
524            }
525            if (pte->fonr) {
526                fault(req->vaddr, MM_STAT_FONR_MASK, req->xc);
527                read_acv++;
528                return Dtb_Fault_Fault;
529            }
530        }
531    }
532
533    checkCacheability(req);
534
535    if (write)
536        write_hits++;
537    else
538        read_hits++;
539
540    return No_Fault;
541}
542
543AlphaISA::PTE &
544AlphaTlb::index()
545{
546    AlphaISA::PTE *pte = &table[nlu];
547    nextnlu();
548
549    return *pte;
550}
551
552BEGIN_DECLARE_SIM_OBJECT_PARAMS(AlphaItb)
553
554    Param<int> size;
555
556END_DECLARE_SIM_OBJECT_PARAMS(AlphaItb)
557
558BEGIN_INIT_SIM_OBJECT_PARAMS(AlphaItb)
559
560    INIT_PARAM_DFLT(size, "TLB size", 48)
561
562END_INIT_SIM_OBJECT_PARAMS(AlphaItb)
563
564
565CREATE_SIM_OBJECT(AlphaItb)
566{
567    return new AlphaItb(getInstanceName(), size);
568}
569
570REGISTER_SIM_OBJECT("AlphaITB", AlphaItb)
571
572BEGIN_DECLARE_SIM_OBJECT_PARAMS(AlphaDtb)
573
574    Param<int> size;
575
576END_DECLARE_SIM_OBJECT_PARAMS(AlphaDtb)
577
578BEGIN_INIT_SIM_OBJECT_PARAMS(AlphaDtb)
579
580    INIT_PARAM_DFLT(size, "TLB size", 64)
581
582END_INIT_SIM_OBJECT_PARAMS(AlphaDtb)
583
584
585CREATE_SIM_OBJECT(AlphaDtb)
586{
587    return new AlphaDtb(getInstanceName(), size);
588}
589
590REGISTER_SIM_OBJECT("AlphaDTB", AlphaDtb)
591
592