tlb.cc revision 679
14997Sgblack@eecs.umich.edu/*
25417Sgblack@eecs.umich.edu * Copyright (c) 2003 The Regents of The University of Michigan
34997Sgblack@eecs.umich.edu * All rights reserved.
44997Sgblack@eecs.umich.edu *
54997Sgblack@eecs.umich.edu * Redistribution and use in source and binary forms, with or without
64997Sgblack@eecs.umich.edu * modification, are permitted provided that the following conditions are
74997Sgblack@eecs.umich.edu * met: redistributions of source code must retain the above copyright
84997Sgblack@eecs.umich.edu * notice, this list of conditions and the following disclaimer;
94997Sgblack@eecs.umich.edu * redistributions in binary form must reproduce the above copyright
104997Sgblack@eecs.umich.edu * notice, this list of conditions and the following disclaimer in the
114997Sgblack@eecs.umich.edu * documentation and/or other materials provided with the distribution;
124997Sgblack@eecs.umich.edu * neither the name of the copyright holders nor the names of its
134997Sgblack@eecs.umich.edu * contributors may be used to endorse or promote products derived from
144997Sgblack@eecs.umich.edu * this software without specific prior written permission.
154997Sgblack@eecs.umich.edu *
164997Sgblack@eecs.umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
174997Sgblack@eecs.umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
184997Sgblack@eecs.umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
194997Sgblack@eecs.umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
204997Sgblack@eecs.umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
214997Sgblack@eecs.umich.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
224997Sgblack@eecs.umich.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
234997Sgblack@eecs.umich.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
244997Sgblack@eecs.umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
254997Sgblack@eecs.umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
264997Sgblack@eecs.umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
274997Sgblack@eecs.umich.edu */
284997Sgblack@eecs.umich.edu
294997Sgblack@eecs.umich.edu#include <sstream>
304997Sgblack@eecs.umich.edu#include <string>
314997Sgblack@eecs.umich.edu#include <vector>
324997Sgblack@eecs.umich.edu
334997Sgblack@eecs.umich.edu#include "base/inifile.hh"
344997Sgblack@eecs.umich.edu#include "base/str.hh"
354997Sgblack@eecs.umich.edu#include "base/trace.hh"
364997Sgblack@eecs.umich.edu#include "cpu/exec_context.hh"
374997Sgblack@eecs.umich.edu#include "sim/builder.hh"
384997Sgblack@eecs.umich.edu#include "targetarch/alpha_memory.hh"
394997Sgblack@eecs.umich.edu#include "targetarch/ev5.hh"
404997Sgblack@eecs.umich.edu
414997Sgblack@eecs.umich.eduusing namespace std;
424997Sgblack@eecs.umich.edu
434997Sgblack@eecs.umich.edu///////////////////////////////////////////////////////////////////////
444997Sgblack@eecs.umich.edu//
454997Sgblack@eecs.umich.edu//  Alpha TLB
464997Sgblack@eecs.umich.edu//
474997Sgblack@eecs.umich.eduAlphaTLB::AlphaTLB(const string &name, int s)
484997Sgblack@eecs.umich.edu    : SimObject(name), size(s), nlu(0)
494997Sgblack@eecs.umich.edu{
504997Sgblack@eecs.umich.edu    table = new AlphaISA::PTE[size];
514997Sgblack@eecs.umich.edu    memset(table, 0, sizeof(AlphaISA::PTE[size]));
524997Sgblack@eecs.umich.edu}
534997Sgblack@eecs.umich.edu
544997Sgblack@eecs.umich.eduAlphaTLB::~AlphaTLB()
554997Sgblack@eecs.umich.edu{
564997Sgblack@eecs.umich.edu    if (table)
574997Sgblack@eecs.umich.edu        delete [] table;
584997Sgblack@eecs.umich.edu}
594997Sgblack@eecs.umich.edu
605086Sgblack@eecs.umich.edu// look up an entry in the TLB
615086Sgblack@eecs.umich.eduAlphaISA::PTE *
625912Sgblack@eecs.umich.eduAlphaTLB::lookup(Addr vpn, uint8_t asn) const
636313Sgblack@eecs.umich.edu{
645124Sgblack@eecs.umich.edu    DPRINTF(TLB, "lookup %#x\n", vpn);
655086Sgblack@eecs.umich.edu
665149Sgblack@eecs.umich.edu    PageTable::const_iterator i = lookupTable.find(vpn);
675086Sgblack@eecs.umich.edu    if (i == lookupTable.end())
685086Sgblack@eecs.umich.edu        return NULL;
695237Sgblack@eecs.umich.edu
705086Sgblack@eecs.umich.edu    while (i->first == vpn) {
715086Sgblack@eecs.umich.edu        int index = i->second;
725086Sgblack@eecs.umich.edu        AlphaISA::PTE *pte = &table[index];
735086Sgblack@eecs.umich.edu        assert(pte->valid);
745245Sgblack@eecs.umich.edu        if (vpn == pte->tag && (pte->asma || pte->asn == asn))
755245Sgblack@eecs.umich.edu            return pte;
765245Sgblack@eecs.umich.edu
775895Sgblack@eecs.umich.edu        ++i;
785895Sgblack@eecs.umich.edu    }
795895Sgblack@eecs.umich.edu
805245Sgblack@eecs.umich.edu    // not found...
815086Sgblack@eecs.umich.edu    return NULL;
825086Sgblack@eecs.umich.edu}
835086Sgblack@eecs.umich.edu
845358Sgblack@eecs.umich.edu
855124Sgblack@eecs.umich.eduvoid
865124Sgblack@eecs.umich.eduAlphaTLB::checkCacheability(MemReqPtr &req)
875124Sgblack@eecs.umich.edu{
885124Sgblack@eecs.umich.edu    // in Alpha, cacheability is controlled by upper-level bits of the
895124Sgblack@eecs.umich.edu    // physical address
905124Sgblack@eecs.umich.edu    if (req->paddr & PA_UNCACHED_BIT) {
915124Sgblack@eecs.umich.edu        if (PA_IPR_SPACE(req->paddr)) {
925237Sgblack@eecs.umich.edu            // IPR memory space not implemented
935245Sgblack@eecs.umich.edu            if (!req->xc->misspeculating()) {
945245Sgblack@eecs.umich.edu                switch (req->paddr) {
955245Sgblack@eecs.umich.edu                  case ULL(0xFFFFF00188):
965236Sgblack@eecs.umich.edu                    req->data = 0;
975236Sgblack@eecs.umich.edu                    break;
985895Sgblack@eecs.umich.edu
995124Sgblack@eecs.umich.edu                  default:
1005124Sgblack@eecs.umich.edu                    panic("IPR memory space not implemented! PA=%x\n",
1015124Sgblack@eecs.umich.edu                          req->paddr);
1025124Sgblack@eecs.umich.edu                }
1035124Sgblack@eecs.umich.edu            }
1045124Sgblack@eecs.umich.edu        } else {
1055124Sgblack@eecs.umich.edu            // mark request as uncacheable
1065124Sgblack@eecs.umich.edu            req->flags |= UNCACHEABLE;
1075124Sgblack@eecs.umich.edu        }
1085124Sgblack@eecs.umich.edu    }
1095124Sgblack@eecs.umich.edu}
1105124Sgblack@eecs.umich.edu
1115124Sgblack@eecs.umich.edu
1125124Sgblack@eecs.umich.edu// insert a new TLB entry
1135124Sgblack@eecs.umich.eduvoid
1145895Sgblack@eecs.umich.eduAlphaTLB::insert(Addr vaddr, AlphaISA::PTE &pte)
1155124Sgblack@eecs.umich.edu{
1165124Sgblack@eecs.umich.edu    if (table[nlu].valid) {
1175360Sgblack@eecs.umich.edu        Addr oldvpn = table[nlu].tag;
1185360Sgblack@eecs.umich.edu        PageTable::iterator i = lookupTable.find(oldvpn);
1195124Sgblack@eecs.umich.edu
1205124Sgblack@eecs.umich.edu        if (i == lookupTable.end())
1215124Sgblack@eecs.umich.edu            panic("TLB entry not found in lookupTable");
1225124Sgblack@eecs.umich.edu
1235124Sgblack@eecs.umich.edu        int index;
1245124Sgblack@eecs.umich.edu        while ((index = i->second) != nlu) {
1255124Sgblack@eecs.umich.edu            if (table[index].tag != oldvpn)
1265124Sgblack@eecs.umich.edu                panic("TLB entry not found in lookupTable");
1275360Sgblack@eecs.umich.edu
1285124Sgblack@eecs.umich.edu            ++i;
1295360Sgblack@eecs.umich.edu        }
1305124Sgblack@eecs.umich.edu
1315360Sgblack@eecs.umich.edu        DPRINTF(TLB, "remove @%d: %#x -> %#x\n", nlu, oldvpn, table[nlu].ppn);
1325124Sgblack@eecs.umich.edu
1335124Sgblack@eecs.umich.edu        lookupTable.erase(i);
1345360Sgblack@eecs.umich.edu    }
1355360Sgblack@eecs.umich.edu
1365360Sgblack@eecs.umich.edu    Addr vpn = VA_VPN(vaddr);
1375360Sgblack@eecs.umich.edu    DPRINTF(TLB, "insert @%d: %#x -> %#x\n", nlu, vpn, pte.ppn);
1385360Sgblack@eecs.umich.edu
1395360Sgblack@eecs.umich.edu    table[nlu] = pte;
1405360Sgblack@eecs.umich.edu    table[nlu].tag = vpn;
1415360Sgblack@eecs.umich.edu    table[nlu].valid = true;
1425360Sgblack@eecs.umich.edu
1435360Sgblack@eecs.umich.edu    lookupTable.insert(make_pair(vpn, nlu));
1445360Sgblack@eecs.umich.edu    nextnlu();
1455124Sgblack@eecs.umich.edu}
1465124Sgblack@eecs.umich.edu
1475124Sgblack@eecs.umich.eduvoid
1485124Sgblack@eecs.umich.eduAlphaTLB::flushAll()
1495124Sgblack@eecs.umich.edu{
1505242Sgblack@eecs.umich.edu    memset(table, 0, sizeof(AlphaISA::PTE[size]));
1515242Sgblack@eecs.umich.edu    lookupTable.clear();
1525242Sgblack@eecs.umich.edu    nlu = 0;
1535242Sgblack@eecs.umich.edu}
1545242Sgblack@eecs.umich.edu
1555242Sgblack@eecs.umich.eduvoid
1565124Sgblack@eecs.umich.eduAlphaTLB::flushProcesses()
1575124Sgblack@eecs.umich.edu{
1585124Sgblack@eecs.umich.edu    PageTable::iterator i = lookupTable.begin();
1595357Sgblack@eecs.umich.edu    PageTable::iterator end = lookupTable.end();
1605357Sgblack@eecs.umich.edu    while (i != end) {
1615357Sgblack@eecs.umich.edu        int index = i->second;
1625357Sgblack@eecs.umich.edu        AlphaISA::PTE *pte = &table[index];
1635357Sgblack@eecs.umich.edu        assert(pte->valid);
1645357Sgblack@eecs.umich.edu
1655124Sgblack@eecs.umich.edu        if (!pte->asma) {
1665124Sgblack@eecs.umich.edu            DPRINTF(TLB, "flush @%d: %#x -> %#x\n", index, pte->tag, pte->ppn);
1675242Sgblack@eecs.umich.edu            pte->valid = false;
1685242Sgblack@eecs.umich.edu            lookupTable.erase(i);
1695242Sgblack@eecs.umich.edu        }
1705242Sgblack@eecs.umich.edu
1715242Sgblack@eecs.umich.edu        ++i;
1725242Sgblack@eecs.umich.edu    }
1735242Sgblack@eecs.umich.edu}
1745242Sgblack@eecs.umich.edu
1755242Sgblack@eecs.umich.eduvoid
1765242Sgblack@eecs.umich.eduAlphaTLB::flushAddr(Addr vaddr, uint8_t asn)
1775124Sgblack@eecs.umich.edu{
1785124Sgblack@eecs.umich.edu    Addr vpn = VA_VPN(vaddr);
1795124Sgblack@eecs.umich.edu
1805358Sgblack@eecs.umich.edu    PageTable::iterator i = lookupTable.find(vpn);
1815086Sgblack@eecs.umich.edu    if (i == lookupTable.end())
1825359Sgblack@eecs.umich.edu        return;
1835359Sgblack@eecs.umich.edu
1845359Sgblack@eecs.umich.edu    while (i->first == vpn) {
1855359Sgblack@eecs.umich.edu        int index = i->second;
1865359Sgblack@eecs.umich.edu        AlphaISA::PTE *pte = &table[index];
1875086Sgblack@eecs.umich.edu        assert(pte->valid);
1885086Sgblack@eecs.umich.edu
1895086Sgblack@eecs.umich.edu        if (vpn == pte->tag && (pte->asma || pte->asn == asn)) {
1906141Sgblack@eecs.umich.edu            DPRINTF(TLB, "flushaddr @%d: %#x -> %#x\n", index, vpn, pte->ppn);
1916141Sgblack@eecs.umich.edu
1926141Sgblack@eecs.umich.edu            // invalidate this entry
1936141Sgblack@eecs.umich.edu            pte->valid = false;
1946141Sgblack@eecs.umich.edu
1956141Sgblack@eecs.umich.edu            lookupTable.erase(i);
1966141Sgblack@eecs.umich.edu        }
1976141Sgblack@eecs.umich.edu
1986141Sgblack@eecs.umich.edu        ++i;
1996141Sgblack@eecs.umich.edu    }
2006141Sgblack@eecs.umich.edu}
2016141Sgblack@eecs.umich.edu
2026141Sgblack@eecs.umich.edu
2036141Sgblack@eecs.umich.eduvoid
2046141Sgblack@eecs.umich.eduAlphaTLB::serialize(ostream &os)
2056141Sgblack@eecs.umich.edu{
2066141Sgblack@eecs.umich.edu    SERIALIZE_SCALAR(size);
2076141Sgblack@eecs.umich.edu    SERIALIZE_SCALAR(nlu);
2086141Sgblack@eecs.umich.edu
2096141Sgblack@eecs.umich.edu    for (int i = 0; i < size; i++) {
2106141Sgblack@eecs.umich.edu        nameOut(os, csprintf("%s.PTE%d", name(), i));
2116141Sgblack@eecs.umich.edu        table[i].serialize(os);
2126141Sgblack@eecs.umich.edu    }
2136141Sgblack@eecs.umich.edu}
2146141Sgblack@eecs.umich.edu
2156141Sgblack@eecs.umich.eduvoid
2166141Sgblack@eecs.umich.eduAlphaTLB::unserialize(Checkpoint *cp, const string &section)
2176141Sgblack@eecs.umich.edu{
2186141Sgblack@eecs.umich.edu    UNSERIALIZE_SCALAR(size);
2196141Sgblack@eecs.umich.edu    UNSERIALIZE_SCALAR(nlu);
2206141Sgblack@eecs.umich.edu
2216141Sgblack@eecs.umich.edu    for (int i = 0; i < size; i++) {
2226141Sgblack@eecs.umich.edu        table[i].unserialize(cp, csprintf("%s.PTE%d", section, i));
2236141Sgblack@eecs.umich.edu        if (table[i].valid) {
2246141Sgblack@eecs.umich.edu            lookupTable.insert(make_pair(table[i].tag, i));
2256141Sgblack@eecs.umich.edu        }
2266141Sgblack@eecs.umich.edu    }
2276141Sgblack@eecs.umich.edu}
2286141Sgblack@eecs.umich.edu
2296141Sgblack@eecs.umich.edu
2306141Sgblack@eecs.umich.edu///////////////////////////////////////////////////////////////////////
2316141Sgblack@eecs.umich.edu//
2326141Sgblack@eecs.umich.edu//  Alpha ITB
2336141Sgblack@eecs.umich.edu//
2346141Sgblack@eecs.umich.eduAlphaITB::AlphaITB(const std::string &name, int size)
2356141Sgblack@eecs.umich.edu    : AlphaTLB(name, size)
2366141Sgblack@eecs.umich.edu{}
2376141Sgblack@eecs.umich.edu
2386141Sgblack@eecs.umich.edu
2396141Sgblack@eecs.umich.eduvoid
2406141Sgblack@eecs.umich.eduAlphaITB::regStats()
2416141Sgblack@eecs.umich.edu{
2426141Sgblack@eecs.umich.edu    hits
2436141Sgblack@eecs.umich.edu        .name(name() + ".hits")
2446141Sgblack@eecs.umich.edu        .desc("ITB hits");
2456141Sgblack@eecs.umich.edu    misses
2466141Sgblack@eecs.umich.edu        .name(name() + ".misses")
2476141Sgblack@eecs.umich.edu        .desc("ITB misses");
2486141Sgblack@eecs.umich.edu    acv
2496141Sgblack@eecs.umich.edu        .name(name() + ".acv")
2506141Sgblack@eecs.umich.edu        .desc("ITB acv");
2516141Sgblack@eecs.umich.edu    accesses
2526141Sgblack@eecs.umich.edu        .name(name() + ".accesses")
2536141Sgblack@eecs.umich.edu        .desc("ITB accesses");
2546141Sgblack@eecs.umich.edu
2556141Sgblack@eecs.umich.edu    accesses = hits + misses;
2566141Sgblack@eecs.umich.edu}
2576141Sgblack@eecs.umich.edu
2586141Sgblack@eecs.umich.eduvoid
2596141Sgblack@eecs.umich.eduAlphaITB::fault(Addr pc, ExecContext *xc) const
2606141Sgblack@eecs.umich.edu{
2616141Sgblack@eecs.umich.edu    uint64_t *ipr = xc->regs.ipr;
2626141Sgblack@eecs.umich.edu
2636141Sgblack@eecs.umich.edu    if (!xc->misspeculating()) {
2646141Sgblack@eecs.umich.edu        ipr[AlphaISA::IPR_ITB_TAG] = pc;
2656141Sgblack@eecs.umich.edu        ipr[AlphaISA::IPR_IFAULT_VA_FORM] =
2666141Sgblack@eecs.umich.edu            ipr[AlphaISA::IPR_IVPTBR] | (VA_VPN(pc) << 3);
2676141Sgblack@eecs.umich.edu    }
2686141Sgblack@eecs.umich.edu}
2696141Sgblack@eecs.umich.edu
2706141Sgblack@eecs.umich.edu
2716141Sgblack@eecs.umich.eduFault
2726141Sgblack@eecs.umich.eduAlphaITB::translate(MemReqPtr &req) const
2736141Sgblack@eecs.umich.edu{
2746141Sgblack@eecs.umich.edu    InternalProcReg *ipr = req->xc->regs.ipr;
2756141Sgblack@eecs.umich.edu
2766141Sgblack@eecs.umich.edu    if (PC_PAL(req->vaddr)) {
2776141Sgblack@eecs.umich.edu        // strip off PAL PC marker (lsb is 1)
2786141Sgblack@eecs.umich.edu        req->paddr = (req->vaddr & ~3) & PA_IMPL_MASK;
2796141Sgblack@eecs.umich.edu        hits++;
2806141Sgblack@eecs.umich.edu        return No_Fault;
2816141Sgblack@eecs.umich.edu    }
2826141Sgblack@eecs.umich.edu
2836141Sgblack@eecs.umich.edu    if (req->flags & PHYSICAL) {
2846141Sgblack@eecs.umich.edu        req->paddr = req->vaddr;
2856141Sgblack@eecs.umich.edu    } else {
2866141Sgblack@eecs.umich.edu        // verify that this is a good virtual address
2876141Sgblack@eecs.umich.edu        if (!validVirtualAddress(req->vaddr)) {
2886141Sgblack@eecs.umich.edu            fault(req->vaddr, req->xc);
2896141Sgblack@eecs.umich.edu            acv++;
2906141Sgblack@eecs.umich.edu            return ITB_Acv_Fault;
2916141Sgblack@eecs.umich.edu        }
2926141Sgblack@eecs.umich.edu
2936141Sgblack@eecs.umich.edu        // Check for "superpage" mapping: when SP<1> is set, and
2946141Sgblack@eecs.umich.edu        // VA<42:41> == 2, VA<39:13> maps directly to PA<39:13>.
2956141Sgblack@eecs.umich.edu        if ((MCSR_SP(ipr[AlphaISA::IPR_MCSR]) & 2) &&
2966141Sgblack@eecs.umich.edu               VA_SPACE(req->vaddr) == 2) {
2976141Sgblack@eecs.umich.edu
2986141Sgblack@eecs.umich.edu            // only valid in kernel mode
2996141Sgblack@eecs.umich.edu            if (ICM_CM(ipr[AlphaISA::IPR_ICM]) != AlphaISA::mode_kernel) {
3006141Sgblack@eecs.umich.edu                fault(req->vaddr, req->xc);
3016141Sgblack@eecs.umich.edu                acv++;
3026141Sgblack@eecs.umich.edu                return ITB_Acv_Fault;
3036141Sgblack@eecs.umich.edu            }
3046141Sgblack@eecs.umich.edu
3056141Sgblack@eecs.umich.edu            req->paddr = req->vaddr & PA_IMPL_MASK;
3066141Sgblack@eecs.umich.edu        } else {
3076141Sgblack@eecs.umich.edu            // not a physical address: need to look up pte
3086141Sgblack@eecs.umich.edu            AlphaISA::PTE *pte = lookup(VA_VPN(req->vaddr),
3096141Sgblack@eecs.umich.edu                                 DTB_ASN_ASN(ipr[AlphaISA::IPR_DTB_ASN]));
3106141Sgblack@eecs.umich.edu
3116141Sgblack@eecs.umich.edu            if (!pte) {
3126141Sgblack@eecs.umich.edu                fault(req->vaddr, req->xc);
3136141Sgblack@eecs.umich.edu                misses++;
3146141Sgblack@eecs.umich.edu                return ITB_Fault_Fault;
3156141Sgblack@eecs.umich.edu            }
3166141Sgblack@eecs.umich.edu
3176141Sgblack@eecs.umich.edu            req->paddr = PA_PFN2PA(pte->ppn) + VA_POFS(req->vaddr & ~3);
3186141Sgblack@eecs.umich.edu
3196141Sgblack@eecs.umich.edu            // check permissions for this access
3206141Sgblack@eecs.umich.edu            if (!(pte->xre & (1 << ICM_CM(ipr[AlphaISA::IPR_ICM])))) {
3216141Sgblack@eecs.umich.edu                // instruction access fault
3226141Sgblack@eecs.umich.edu                fault(req->vaddr, req->xc);
3236141Sgblack@eecs.umich.edu                acv++;
3246141Sgblack@eecs.umich.edu                return ITB_Acv_Fault;
3256141Sgblack@eecs.umich.edu            }
3266141Sgblack@eecs.umich.edu
3276141Sgblack@eecs.umich.edu            hits++;
3286141Sgblack@eecs.umich.edu        }
3296141Sgblack@eecs.umich.edu    }
3306141Sgblack@eecs.umich.edu
3316141Sgblack@eecs.umich.edu    // check that the physical address is ok (catch bad physical addresses)
3326141Sgblack@eecs.umich.edu    if (req->paddr & ~PA_IMPL_MASK)
3336141Sgblack@eecs.umich.edu        return Machine_Check_Fault;
3346141Sgblack@eecs.umich.edu
3356141Sgblack@eecs.umich.edu    checkCacheability(req);
3366141Sgblack@eecs.umich.edu
3376141Sgblack@eecs.umich.edu    return No_Fault;
3386141Sgblack@eecs.umich.edu}
3396141Sgblack@eecs.umich.edu
3406141Sgblack@eecs.umich.edu///////////////////////////////////////////////////////////////////////
3416141Sgblack@eecs.umich.edu//
3426141Sgblack@eecs.umich.edu//  Alpha DTB
3436141Sgblack@eecs.umich.edu//
3446141Sgblack@eecs.umich.eduAlphaDTB::AlphaDTB(const std::string &name, int size)
3456141Sgblack@eecs.umich.edu    : AlphaTLB(name, size)
3466141Sgblack@eecs.umich.edu{}
3476141Sgblack@eecs.umich.edu
3486141Sgblack@eecs.umich.eduvoid
3496141Sgblack@eecs.umich.eduAlphaDTB::regStats()
3506141Sgblack@eecs.umich.edu{
3516141Sgblack@eecs.umich.edu    read_hits
3526141Sgblack@eecs.umich.edu        .name(name() + ".read_hits")
3536141Sgblack@eecs.umich.edu        .desc("DTB read hits")
3546141Sgblack@eecs.umich.edu        ;
3556141Sgblack@eecs.umich.edu
3566141Sgblack@eecs.umich.edu    read_misses
3576141Sgblack@eecs.umich.edu        .name(name() + ".read_misses")
3586141Sgblack@eecs.umich.edu        .desc("DTB read misses")
3596141Sgblack@eecs.umich.edu        ;
3606141Sgblack@eecs.umich.edu
3616141Sgblack@eecs.umich.edu    read_acv
3626141Sgblack@eecs.umich.edu        .name(name() + ".read_acv")
3636141Sgblack@eecs.umich.edu        .desc("DTB read access violations")
3646141Sgblack@eecs.umich.edu        ;
3656141Sgblack@eecs.umich.edu
3666141Sgblack@eecs.umich.edu    read_accesses
3676141Sgblack@eecs.umich.edu        .name(name() + ".read_accesses")
3686141Sgblack@eecs.umich.edu        .desc("DTB read accesses")
3696141Sgblack@eecs.umich.edu        ;
3706141Sgblack@eecs.umich.edu
3716141Sgblack@eecs.umich.edu    write_hits
3726141Sgblack@eecs.umich.edu        .name(name() + ".write_hits")
3736141Sgblack@eecs.umich.edu        .desc("DTB write hits")
3746141Sgblack@eecs.umich.edu        ;
3756141Sgblack@eecs.umich.edu
3766141Sgblack@eecs.umich.edu    write_misses
3776141Sgblack@eecs.umich.edu        .name(name() + ".write_misses")
3786141Sgblack@eecs.umich.edu        .desc("DTB write misses")
3796141Sgblack@eecs.umich.edu        ;
3806141Sgblack@eecs.umich.edu
3816141Sgblack@eecs.umich.edu    write_acv
3826141Sgblack@eecs.umich.edu        .name(name() + ".write_acv")
3836141Sgblack@eecs.umich.edu        .desc("DTB write access violations")
3846141Sgblack@eecs.umich.edu        ;
3856141Sgblack@eecs.umich.edu
3866141Sgblack@eecs.umich.edu    write_accesses
3876141Sgblack@eecs.umich.edu        .name(name() + ".write_accesses")
3886141Sgblack@eecs.umich.edu        .desc("DTB write accesses")
3896141Sgblack@eecs.umich.edu        ;
3906141Sgblack@eecs.umich.edu
3916141Sgblack@eecs.umich.edu    hits
3926141Sgblack@eecs.umich.edu        .name(name() + ".hits")
3936141Sgblack@eecs.umich.edu        .desc("DTB hits")
3946141Sgblack@eecs.umich.edu        ;
3956141Sgblack@eecs.umich.edu
3966141Sgblack@eecs.umich.edu    misses
3976141Sgblack@eecs.umich.edu        .name(name() + ".misses")
3986141Sgblack@eecs.umich.edu        .desc("DTB misses")
3996141Sgblack@eecs.umich.edu        ;
4006141Sgblack@eecs.umich.edu
4016141Sgblack@eecs.umich.edu    acv
4026141Sgblack@eecs.umich.edu        .name(name() + ".acv")
4036141Sgblack@eecs.umich.edu        .desc("DTB access violations")
4046141Sgblack@eecs.umich.edu        ;
4056141Sgblack@eecs.umich.edu
4066141Sgblack@eecs.umich.edu    accesses
4076141Sgblack@eecs.umich.edu        .name(name() + ".accesses")
4086141Sgblack@eecs.umich.edu        .desc("DTB accesses")
4096141Sgblack@eecs.umich.edu        ;
4106141Sgblack@eecs.umich.edu
4116141Sgblack@eecs.umich.edu    hits = read_hits + write_hits;
4126141Sgblack@eecs.umich.edu    misses = read_misses + write_misses;
4136141Sgblack@eecs.umich.edu    acv = read_acv + write_acv;
4146141Sgblack@eecs.umich.edu    accesses = read_accesses + write_accesses;
4156141Sgblack@eecs.umich.edu}
4166141Sgblack@eecs.umich.edu
4176141Sgblack@eecs.umich.eduvoid
4186141Sgblack@eecs.umich.eduAlphaDTB::fault(Addr vaddr, uint64_t flags, ExecContext *xc) const
4196141Sgblack@eecs.umich.edu{
4206141Sgblack@eecs.umich.edu    uint64_t *ipr = xc->regs.ipr;
4216141Sgblack@eecs.umich.edu
4226141Sgblack@eecs.umich.edu    // set fault address and flags
4236141Sgblack@eecs.umich.edu    if (!xc->misspeculating() && !xc->regs.intrlock) {
4246141Sgblack@eecs.umich.edu        // set VA register with faulting address
4256141Sgblack@eecs.umich.edu        ipr[AlphaISA::IPR_VA] = vaddr;
4266141Sgblack@eecs.umich.edu
4276141Sgblack@eecs.umich.edu        // set MM_STAT register flags
4286141Sgblack@eecs.umich.edu        ipr[AlphaISA::IPR_MM_STAT] = (((xc->regs.opcode & 0x3f) << 11)
4296141Sgblack@eecs.umich.edu                               | ((xc->regs.ra & 0x1f) << 6)
4306141Sgblack@eecs.umich.edu                               | (flags & 0x3f));
4316141Sgblack@eecs.umich.edu
4326141Sgblack@eecs.umich.edu        // set VA_FORM register with faulting formatted address
4336141Sgblack@eecs.umich.edu        ipr[AlphaISA::IPR_VA_FORM] =
4346141Sgblack@eecs.umich.edu            ipr[AlphaISA::IPR_MVPTBR] | (VA_VPN(vaddr) << 3);
4356141Sgblack@eecs.umich.edu
4366141Sgblack@eecs.umich.edu        // lock these registers until the VA register is read
4376141Sgblack@eecs.umich.edu        xc->regs.intrlock = true;
4386141Sgblack@eecs.umich.edu    }
4396141Sgblack@eecs.umich.edu}
4406141Sgblack@eecs.umich.edu
4416141Sgblack@eecs.umich.eduFault
4426141Sgblack@eecs.umich.eduAlphaDTB::translate(MemReqPtr &req, bool write) const
4436141Sgblack@eecs.umich.edu{
4446141Sgblack@eecs.umich.edu    RegFile *regs = &req->xc->regs;
4456141Sgblack@eecs.umich.edu    Addr pc = regs->pc;
4466141Sgblack@eecs.umich.edu    InternalProcReg *ipr = regs->ipr;
4476141Sgblack@eecs.umich.edu
4486141Sgblack@eecs.umich.edu    AlphaISA::mode_type mode =
4496141Sgblack@eecs.umich.edu        (AlphaISA::mode_type)DTB_CM_CM(ipr[AlphaISA::IPR_DTB_CM]);
4506141Sgblack@eecs.umich.edu
4516141Sgblack@eecs.umich.edu    if (PC_PAL(pc)) {
4526141Sgblack@eecs.umich.edu        mode = (req->flags & ALTMODE) ?
4536141Sgblack@eecs.umich.edu            (AlphaISA::mode_type)ALT_MODE_AM(ipr[AlphaISA::IPR_ALT_MODE])
4546141Sgblack@eecs.umich.edu            : AlphaISA::mode_kernel;
4556141Sgblack@eecs.umich.edu    }
4566141Sgblack@eecs.umich.edu
4576141Sgblack@eecs.umich.edu    if (req->flags & PHYSICAL) {
4586141Sgblack@eecs.umich.edu        req->paddr = req->vaddr;
4596141Sgblack@eecs.umich.edu    } else {
4606141Sgblack@eecs.umich.edu        // verify that this is a good virtual address
4616141Sgblack@eecs.umich.edu        if (!validVirtualAddress(req->vaddr)) {
4626141Sgblack@eecs.umich.edu            fault(req->vaddr,
4636141Sgblack@eecs.umich.edu                  ((write ? MM_STAT_WR_MASK : 0) | MM_STAT_BAD_VA_MASK |
4646141Sgblack@eecs.umich.edu                   MM_STAT_ACV_MASK),
4656141Sgblack@eecs.umich.edu                  req->xc);
4666141Sgblack@eecs.umich.edu
4676141Sgblack@eecs.umich.edu            if (write) { write_acv++; } else { read_acv++; }
4686141Sgblack@eecs.umich.edu            return DTB_Fault_Fault;
4696141Sgblack@eecs.umich.edu        }
4706141Sgblack@eecs.umich.edu
4716141Sgblack@eecs.umich.edu        // Check for "superpage" mapping: when SP<1> is set, and
4726141Sgblack@eecs.umich.edu        // VA<42:41> == 2, VA<39:13> maps directly to PA<39:13>.
4736141Sgblack@eecs.umich.edu        if ((MCSR_SP(ipr[AlphaISA::IPR_MCSR]) & 2) &&
4746141Sgblack@eecs.umich.edu            VA_SPACE(req->vaddr) == 2) {
4756141Sgblack@eecs.umich.edu
4766141Sgblack@eecs.umich.edu            // only valid in kernel mode
4776141Sgblack@eecs.umich.edu            if (DTB_CM_CM(ipr[AlphaISA::IPR_DTB_CM]) !=
4786141Sgblack@eecs.umich.edu                AlphaISA::mode_kernel) {
4796141Sgblack@eecs.umich.edu                fault(req->vaddr,
4806141Sgblack@eecs.umich.edu                      ((write ? MM_STAT_WR_MASK : 0) | MM_STAT_ACV_MASK),
4816141Sgblack@eecs.umich.edu                      req->xc);
4826141Sgblack@eecs.umich.edu                if (write) { write_acv++; } else { read_acv++; }
4836141Sgblack@eecs.umich.edu                return DTB_Acv_Fault;
4846141Sgblack@eecs.umich.edu            }
4856141Sgblack@eecs.umich.edu
4866141Sgblack@eecs.umich.edu            req->paddr = req->vaddr & PA_IMPL_MASK;
4876141Sgblack@eecs.umich.edu        } else {
4886141Sgblack@eecs.umich.edu            if (write)
4896141Sgblack@eecs.umich.edu                write_accesses++;
4906141Sgblack@eecs.umich.edu            else
4916141Sgblack@eecs.umich.edu                read_accesses++;
4926141Sgblack@eecs.umich.edu
4936141Sgblack@eecs.umich.edu            // not a physical address: need to look up pte
4946141Sgblack@eecs.umich.edu            AlphaISA::PTE *pte = lookup(VA_VPN(req->vaddr),
4956141Sgblack@eecs.umich.edu                                 DTB_ASN_ASN(ipr[AlphaISA::IPR_DTB_ASN]));
4966141Sgblack@eecs.umich.edu
4976141Sgblack@eecs.umich.edu            if (!pte) {
4986141Sgblack@eecs.umich.edu                // page fault
4996141Sgblack@eecs.umich.edu                fault(req->vaddr,
5006141Sgblack@eecs.umich.edu                      ((write ? MM_STAT_WR_MASK : 0) | MM_STAT_DTB_MISS_MASK),
5016141Sgblack@eecs.umich.edu                      req->xc);
5026141Sgblack@eecs.umich.edu                if (write) { write_misses++; } else { read_misses++; }
5036141Sgblack@eecs.umich.edu                return (req->flags & VPTE) ? Pdtb_Miss_Fault : Ndtb_Miss_Fault;
5046141Sgblack@eecs.umich.edu            }
5056141Sgblack@eecs.umich.edu
5066141Sgblack@eecs.umich.edu            req->paddr = PA_PFN2PA(pte->ppn) | VA_POFS(req->vaddr);
5076141Sgblack@eecs.umich.edu
5086141Sgblack@eecs.umich.edu            if (write) {
5096141Sgblack@eecs.umich.edu                if (!(pte->xwe & MODE2MASK(mode))) {
5106141Sgblack@eecs.umich.edu                    // declare the instruction access fault
5116141Sgblack@eecs.umich.edu                    fault(req->vaddr, MM_STAT_WR_MASK | MM_STAT_ACV_MASK |
5126141Sgblack@eecs.umich.edu                          (pte->fonw ? MM_STAT_FONW_MASK : 0),
5136141Sgblack@eecs.umich.edu                          req->xc);
5146141Sgblack@eecs.umich.edu                    write_acv++;
5156141Sgblack@eecs.umich.edu                    return DTB_Fault_Fault;
5166141Sgblack@eecs.umich.edu                }
5176141Sgblack@eecs.umich.edu                if (pte->fonw) {
5186141Sgblack@eecs.umich.edu                    fault(req->vaddr, MM_STAT_WR_MASK | MM_STAT_FONW_MASK,
5196141Sgblack@eecs.umich.edu                          req->xc);
5206141Sgblack@eecs.umich.edu                    write_acv++;
5216141Sgblack@eecs.umich.edu                    return DTB_Fault_Fault;
5226141Sgblack@eecs.umich.edu                }
5236141Sgblack@eecs.umich.edu            } else {
5246141Sgblack@eecs.umich.edu                if (!(pte->xre & MODE2MASK(mode))) {
5256141Sgblack@eecs.umich.edu                    fault(req->vaddr,
5266141Sgblack@eecs.umich.edu                          MM_STAT_ACV_MASK |
5276141Sgblack@eecs.umich.edu                          (pte->fonr ? MM_STAT_FONR_MASK : 0),
5286141Sgblack@eecs.umich.edu                          req->xc);
5296141Sgblack@eecs.umich.edu                    read_acv++;
5306141Sgblack@eecs.umich.edu                    return DTB_Acv_Fault;
5316141Sgblack@eecs.umich.edu                }
5326141Sgblack@eecs.umich.edu                if (pte->fonr) {
5336141Sgblack@eecs.umich.edu                    fault(req->vaddr, MM_STAT_FONR_MASK, req->xc);
5346141Sgblack@eecs.umich.edu                    read_acv++;
5356141Sgblack@eecs.umich.edu                    return DTB_Fault_Fault;
5366141Sgblack@eecs.umich.edu                }
5376141Sgblack@eecs.umich.edu            }
5386141Sgblack@eecs.umich.edu        }
5396141Sgblack@eecs.umich.edu
5406141Sgblack@eecs.umich.edu        if (write)
5416141Sgblack@eecs.umich.edu            write_hits++;
5426141Sgblack@eecs.umich.edu        else
5436141Sgblack@eecs.umich.edu            read_hits++;
5446141Sgblack@eecs.umich.edu    }
5456141Sgblack@eecs.umich.edu
5466141Sgblack@eecs.umich.edu    // check that the physical address is ok (catch bad physical addresses)
5476141Sgblack@eecs.umich.edu    if (req->paddr & ~PA_IMPL_MASK)
5486141Sgblack@eecs.umich.edu        return Machine_Check_Fault;
5496023Snate@binkert.org
5506023Snate@binkert.org    checkCacheability(req);
5515086Sgblack@eecs.umich.edu
5526141Sgblack@eecs.umich.edu    return No_Fault;
5536141Sgblack@eecs.umich.edu}
5546141Sgblack@eecs.umich.edu
5556141Sgblack@eecs.umich.eduAlphaISA::PTE &
5566141Sgblack@eecs.umich.eduAlphaTLB::index(bool advance)
5576141Sgblack@eecs.umich.edu{
5586141Sgblack@eecs.umich.edu    AlphaISA::PTE *pte = &table[nlu];
5596141Sgblack@eecs.umich.edu
5606141Sgblack@eecs.umich.edu    if (advance)
5616141Sgblack@eecs.umich.edu        nextnlu();
5625895Sgblack@eecs.umich.edu
5635124Sgblack@eecs.umich.edu    return *pte;
5645140Sgblack@eecs.umich.edu}
5655140Sgblack@eecs.umich.edu
5666141Sgblack@eecs.umich.eduDEFINE_SIM_OBJECT_CLASS_NAME("AlphaTLB", AlphaTLB)
5675140Sgblack@eecs.umich.edu
5685140Sgblack@eecs.umich.eduBEGIN_DECLARE_SIM_OBJECT_PARAMS(AlphaITB)
5696141Sgblack@eecs.umich.edu
5705237Sgblack@eecs.umich.edu    Param<int> size;
5715140Sgblack@eecs.umich.edu
5726141Sgblack@eecs.umich.eduEND_DECLARE_SIM_OBJECT_PARAMS(AlphaITB)
5735237Sgblack@eecs.umich.edu
5745431Sgblack@eecs.umich.eduBEGIN_INIT_SIM_OBJECT_PARAMS(AlphaITB)
5756059Sgblack@eecs.umich.edu
5766141Sgblack@eecs.umich.edu    INIT_PARAM_DFLT(size, "TLB size", 48)
5776059Sgblack@eecs.umich.edu
5785431Sgblack@eecs.umich.eduEND_INIT_SIM_OBJECT_PARAMS(AlphaITB)
5795433Sgblack@eecs.umich.edu
5805965Sgblack@eecs.umich.edu
5815433Sgblack@eecs.umich.eduCREATE_SIM_OBJECT(AlphaITB)
5826099Sgblack@eecs.umich.edu{
5835433Sgblack@eecs.umich.edu    return new AlphaITB(getInstanceName(), size);
5846023Snate@binkert.org}
5855433Sgblack@eecs.umich.edu
5865433Sgblack@eecs.umich.eduREGISTER_SIM_OBJECT("AlphaITB", AlphaITB)
5875965Sgblack@eecs.umich.edu
5885433Sgblack@eecs.umich.eduBEGIN_DECLARE_SIM_OBJECT_PARAMS(AlphaDTB)
5895140Sgblack@eecs.umich.edu
5905140Sgblack@eecs.umich.edu    Param<int> size;
5915965Sgblack@eecs.umich.edu
5925965Sgblack@eecs.umich.eduEND_DECLARE_SIM_OBJECT_PARAMS(AlphaDTB)
5935965Sgblack@eecs.umich.edu
5945965Sgblack@eecs.umich.eduBEGIN_INIT_SIM_OBJECT_PARAMS(AlphaDTB)
5956141Sgblack@eecs.umich.edu
5965980Snate@binkert.org    INIT_PARAM_DFLT(size, "TLB size", 64)
5975980Snate@binkert.org
5985965Sgblack@eecs.umich.eduEND_INIT_SIM_OBJECT_PARAMS(AlphaDTB)
5995965Sgblack@eecs.umich.edu
6005965Sgblack@eecs.umich.edu
6015433Sgblack@eecs.umich.eduCREATE_SIM_OBJECT(AlphaDTB)
6025237Sgblack@eecs.umich.edu{
6035965Sgblack@eecs.umich.edu    return new AlphaDTB(getInstanceName(), size);
6045965Sgblack@eecs.umich.edu}
6055965Sgblack@eecs.umich.edu
6065140Sgblack@eecs.umich.eduREGISTER_SIM_OBJECT("AlphaDTB", AlphaDTB)
6075965Sgblack@eecs.umich.edu
6085965Sgblack@eecs.umich.edu