tlb.cc revision 2166
1955SN/A/*
2955SN/A * Copyright (c) 2001-2005 The Regents of The University of Michigan
39812Sandreas.hansson@arm.com * All rights reserved.
49812Sandreas.hansson@arm.com *
59812Sandreas.hansson@arm.com * Redistribution and use in source and binary forms, with or without
69812Sandreas.hansson@arm.com * modification, are permitted provided that the following conditions are
79812Sandreas.hansson@arm.com * met: redistributions of source code must retain the above copyright
89812Sandreas.hansson@arm.com * notice, this list of conditions and the following disclaimer;
99812Sandreas.hansson@arm.com * redistributions in binary form must reproduce the above copyright
109812Sandreas.hansson@arm.com * notice, this list of conditions and the following disclaimer in the
119812Sandreas.hansson@arm.com * documentation and/or other materials provided with the distribution;
129812Sandreas.hansson@arm.com * neither the name of the copyright holders nor the names of its
139812Sandreas.hansson@arm.com * contributors may be used to endorse or promote products derived from
149812Sandreas.hansson@arm.com * this software without specific prior written permission.
157816Ssteve.reinhardt@amd.com *
165871Snate@binkert.org * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
171762SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18955SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19955SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20955SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21955SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22955SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23955SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24955SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25955SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26955SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27955SN/A */
28955SN/A
29955SN/A#include <sstream>
30955SN/A#include <string>
31955SN/A#include <vector>
32955SN/A
33955SN/A#include "arch/alpha/alpha_memory.hh"
34955SN/A#include "base/inifile.hh"
35955SN/A#include "base/str.hh"
36955SN/A#include "base/trace.hh"
37955SN/A#include "config/alpha_tlaser.hh"
38955SN/A#include "cpu/exec_context.hh"
39955SN/A#include "sim/builder.hh"
40955SN/A
41955SN/Ausing namespace std;
422665Ssaidi@eecs.umich.eduusing namespace EV5;
432665Ssaidi@eecs.umich.edu
445863Snate@binkert.org///////////////////////////////////////////////////////////////////////
45955SN/A//
46955SN/A//  Alpha TLB
47955SN/A//
48955SN/A#ifdef DEBUG
49955SN/Abool uncacheBit39 = false;
508878Ssteve.reinhardt@amd.combool uncacheBit40 = false;
512632Sstever@eecs.umich.edu#endif
528878Ssteve.reinhardt@amd.com
532632Sstever@eecs.umich.edu#define MODE2MASK(X)			(1 << (X))
54955SN/A
558878Ssteve.reinhardt@amd.comAlphaTLB::AlphaTLB(const string &name, int s)
562632Sstever@eecs.umich.edu    : SimObject(name), size(s), nlu(0)
572761Sstever@eecs.umich.edu{
582632Sstever@eecs.umich.edu    table = new AlphaISA::PTE[size];
592632Sstever@eecs.umich.edu    memset(table, 0, sizeof(AlphaISA::PTE[size]));
602632Sstever@eecs.umich.edu}
612761Sstever@eecs.umich.edu
622761Sstever@eecs.umich.eduAlphaTLB::~AlphaTLB()
632761Sstever@eecs.umich.edu{
648878Ssteve.reinhardt@amd.com    if (table)
658878Ssteve.reinhardt@amd.com        delete [] table;
662761Sstever@eecs.umich.edu}
672761Sstever@eecs.umich.edu
682761Sstever@eecs.umich.edu// look up an entry in the TLB
692761Sstever@eecs.umich.eduAlphaISA::PTE *
702761Sstever@eecs.umich.eduAlphaTLB::lookup(Addr vpn, uint8_t asn) const
718878Ssteve.reinhardt@amd.com{
728878Ssteve.reinhardt@amd.com    // assume not found...
732632Sstever@eecs.umich.edu    AlphaISA::PTE *retval = NULL;
742632Sstever@eecs.umich.edu
758878Ssteve.reinhardt@amd.com    PageTable::const_iterator i = lookupTable.find(vpn);
768878Ssteve.reinhardt@amd.com    if (i != lookupTable.end()) {
772632Sstever@eecs.umich.edu        while (i->first == vpn) {
78955SN/A            int index = i->second;
79955SN/A            AlphaISA::PTE *pte = &table[index];
80955SN/A            assert(pte->valid);
815863Snate@binkert.org            if (vpn == pte->tag && (pte->asma || pte->asn == asn)) {
825863Snate@binkert.org                retval = pte;
835863Snate@binkert.org                break;
845863Snate@binkert.org            }
855863Snate@binkert.org
865863Snate@binkert.org            ++i;
875863Snate@binkert.org        }
885863Snate@binkert.org    }
895863Snate@binkert.org
905863Snate@binkert.org    DPRINTF(TLB, "lookup %#x, asn %#x -> %s ppn %#x\n", vpn, (int)asn,
915863Snate@binkert.org            retval ? "hit" : "miss", retval ? retval->ppn : 0);
928878Ssteve.reinhardt@amd.com    return retval;
935863Snate@binkert.org}
945863Snate@binkert.org
955863Snate@binkert.org
969812Sandreas.hansson@arm.comvoid
979812Sandreas.hansson@arm.comAlphaTLB::checkCacheability(MemReqPtr &req)
985863Snate@binkert.org{
999812Sandreas.hansson@arm.com    // in Alpha, cacheability is controlled by upper-level bits of the
1005863Snate@binkert.org    // physical address
1015863Snate@binkert.org
1025863Snate@binkert.org    /*
1039812Sandreas.hansson@arm.com     * We support having the uncacheable bit in either bit 39 or bit 40.
1049812Sandreas.hansson@arm.com     * The Turbolaser platform (and EV5) support having the bit in 39, but
1055863Snate@binkert.org     * Tsunami (which Linux assumes uses an EV6) generates accesses with
1065863Snate@binkert.org     * the bit in 40.  So we must check for both, but we have debug flags
1078878Ssteve.reinhardt@amd.com     * to catch a weird case where both are used, which shouldn't happen.
1085863Snate@binkert.org     */
1095863Snate@binkert.org
1105863Snate@binkert.org
1116654Snate@binkert.org#if ALPHA_TLASER
11210196SCurtis.Dunham@arm.com    if (req->paddr & PAddrUncachedBit39) {
113955SN/A#else
1145396Ssaidi@eecs.umich.edu    if (req->paddr & PAddrUncachedBit43) {
1155863Snate@binkert.org#endif
1165863Snate@binkert.org        // IPR memory space not implemented
1174202Sbinkertn@umich.edu        if (PAddrIprSpace(req->paddr)) {
1185863Snate@binkert.org            if (!req->xc->misspeculating()) {
1195863Snate@binkert.org                switch (req->paddr) {
1205863Snate@binkert.org                  case ULL(0xFFFFF00188):
1215863Snate@binkert.org                    req->data = 0;
122955SN/A                    break;
1236654Snate@binkert.org
1245273Sstever@gmail.com                  default:
1255871Snate@binkert.org                    panic("IPR memory space not implemented! PA=%x\n",
1265273Sstever@gmail.com                          req->paddr);
1276655Snate@binkert.org                }
1288878Ssteve.reinhardt@amd.com            }
1296655Snate@binkert.org        } else {
1306655Snate@binkert.org            // mark request as uncacheable
1319219Spower.jg@gmail.com            req->flags |= UNCACHEABLE;
1326655Snate@binkert.org
1335871Snate@binkert.org#if !ALPHA_TLASER
1346654Snate@binkert.org            // Clear bits 42:35 of the physical address (10-2 in Tsunami manual)
1358947Sandreas.hansson@arm.com            req->paddr &= PAddrUncachedMask;
1365396Ssaidi@eecs.umich.edu#endif
1378120Sgblack@eecs.umich.edu        }
1388120Sgblack@eecs.umich.edu    }
1398120Sgblack@eecs.umich.edu}
1408120Sgblack@eecs.umich.edu
1418120Sgblack@eecs.umich.edu
1428120Sgblack@eecs.umich.edu// insert a new TLB entry
1438120Sgblack@eecs.umich.eduvoid
1448120Sgblack@eecs.umich.eduAlphaTLB::insert(Addr addr, AlphaISA::PTE &pte)
1458879Ssteve.reinhardt@amd.com{
1468879Ssteve.reinhardt@amd.com    AlphaISA::VAddr vaddr = addr;
1478879Ssteve.reinhardt@amd.com    if (table[nlu].valid) {
1488879Ssteve.reinhardt@amd.com        Addr oldvpn = table[nlu].tag;
1498879Ssteve.reinhardt@amd.com        PageTable::iterator i = lookupTable.find(oldvpn);
1508879Ssteve.reinhardt@amd.com
1518879Ssteve.reinhardt@amd.com        if (i == lookupTable.end())
1528879Ssteve.reinhardt@amd.com            panic("TLB entry not found in lookupTable");
1538879Ssteve.reinhardt@amd.com
1548879Ssteve.reinhardt@amd.com        int index;
1558879Ssteve.reinhardt@amd.com        while ((index = i->second) != nlu) {
1568879Ssteve.reinhardt@amd.com            if (table[index].tag != oldvpn)
1578879Ssteve.reinhardt@amd.com                panic("TLB entry not found in lookupTable");
1588120Sgblack@eecs.umich.edu
1598120Sgblack@eecs.umich.edu            ++i;
1608120Sgblack@eecs.umich.edu        }
1618120Sgblack@eecs.umich.edu
1628120Sgblack@eecs.umich.edu        DPRINTF(TLB, "remove @%d: %#x -> %#x\n", nlu, oldvpn, table[nlu].ppn);
1638120Sgblack@eecs.umich.edu
1648120Sgblack@eecs.umich.edu        lookupTable.erase(i);
1658120Sgblack@eecs.umich.edu    }
1668120Sgblack@eecs.umich.edu
1678120Sgblack@eecs.umich.edu    DPRINTF(TLB, "insert @%d: %#x -> %#x\n", nlu, vaddr.vpn(), pte.ppn);
1688120Sgblack@eecs.umich.edu
1698120Sgblack@eecs.umich.edu    table[nlu] = pte;
1708120Sgblack@eecs.umich.edu    table[nlu].tag = vaddr.vpn();
1718120Sgblack@eecs.umich.edu    table[nlu].valid = true;
1728879Ssteve.reinhardt@amd.com
1738879Ssteve.reinhardt@amd.com    lookupTable.insert(make_pair(vaddr.vpn(), nlu));
1748879Ssteve.reinhardt@amd.com    nextnlu();
1758879Ssteve.reinhardt@amd.com}
17610458Sandreas.hansson@arm.com
17710458Sandreas.hansson@arm.comvoid
17810458Sandreas.hansson@arm.comAlphaTLB::flushAll()
1798879Ssteve.reinhardt@amd.com{
1808879Ssteve.reinhardt@amd.com    DPRINTF(TLB, "flushAll\n");
1818879Ssteve.reinhardt@amd.com    memset(table, 0, sizeof(AlphaISA::PTE[size]));
1828879Ssteve.reinhardt@amd.com    lookupTable.clear();
1839227Sandreas.hansson@arm.com    nlu = 0;
1849227Sandreas.hansson@arm.com}
1858879Ssteve.reinhardt@amd.com
1868879Ssteve.reinhardt@amd.comvoid
1878879Ssteve.reinhardt@amd.comAlphaTLB::flushProcesses()
1888879Ssteve.reinhardt@amd.com{
18910453SAndrew.Bardsley@arm.com    PageTable::iterator i = lookupTable.begin();
19010453SAndrew.Bardsley@arm.com    PageTable::iterator end = lookupTable.end();
19110453SAndrew.Bardsley@arm.com    while (i != end) {
19210456SCurtis.Dunham@arm.com        int index = i->second;
19310456SCurtis.Dunham@arm.com        AlphaISA::PTE *pte = &table[index];
19410456SCurtis.Dunham@arm.com        assert(pte->valid);
19510457Sandreas.hansson@arm.com
19610457Sandreas.hansson@arm.com        // we can't increment i after we erase it, so save a copy and
1978120Sgblack@eecs.umich.edu        // increment it to get the next entry now
1988947Sandreas.hansson@arm.com        PageTable::iterator cur = i;
1997816Ssteve.reinhardt@amd.com        ++i;
2005871Snate@binkert.org
2015871Snate@binkert.org        if (!pte->asma) {
2026121Snate@binkert.org            DPRINTF(TLB, "flush @%d: %#x -> %#x\n", index, pte->tag, pte->ppn);
2035871Snate@binkert.org            pte->valid = false;
2045871Snate@binkert.org            lookupTable.erase(cur);
2059926Sstan.czerniawski@arm.com        }
2069926Sstan.czerniawski@arm.com    }
2079119Sandreas.hansson@arm.com}
20810068Sandreas.hansson@arm.com
20910068Sandreas.hansson@arm.comvoid
210955SN/AAlphaTLB::flushAddr(Addr addr, uint8_t asn)
2119416SAndreas.Sandberg@ARM.com{
2129416SAndreas.Sandberg@ARM.com    AlphaISA::VAddr vaddr = addr;
2139416SAndreas.Sandberg@ARM.com
2149416SAndreas.Sandberg@ARM.com    PageTable::iterator i = lookupTable.find(vaddr.vpn());
2159416SAndreas.Sandberg@ARM.com    if (i == lookupTable.end())
2169416SAndreas.Sandberg@ARM.com        return;
2179416SAndreas.Sandberg@ARM.com
2185871Snate@binkert.org    while (i->first == vaddr.vpn()) {
21910584Sandreas.hansson@arm.com        int index = i->second;
2209416SAndreas.Sandberg@ARM.com        AlphaISA::PTE *pte = &table[index];
2219416SAndreas.Sandberg@ARM.com        assert(pte->valid);
2225871Snate@binkert.org
223955SN/A        if (vaddr.vpn() == pte->tag && (pte->asma || pte->asn == asn)) {
22410671Sandreas.hansson@arm.com            DPRINTF(TLB, "flushaddr @%d: %#x -> %#x\n", index, vaddr.vpn(),
22510671Sandreas.hansson@arm.com                    pte->ppn);
22610671Sandreas.hansson@arm.com
22710671Sandreas.hansson@arm.com            // invalidate this entry
2288881Smarc.orr@gmail.com            pte->valid = false;
2296121Snate@binkert.org
2306121Snate@binkert.org            lookupTable.erase(i);
2311533SN/A        }
2329239Sandreas.hansson@arm.com
2339239Sandreas.hansson@arm.com        ++i;
2349239Sandreas.hansson@arm.com    }
2359239Sandreas.hansson@arm.com}
2369239Sandreas.hansson@arm.com
2379239Sandreas.hansson@arm.com
2389239Sandreas.hansson@arm.comvoid
2399239Sandreas.hansson@arm.comAlphaTLB::serialize(ostream &os)
2409239Sandreas.hansson@arm.com{
2419239Sandreas.hansson@arm.com    SERIALIZE_SCALAR(size);
2429239Sandreas.hansson@arm.com    SERIALIZE_SCALAR(nlu);
2439239Sandreas.hansson@arm.com
2446655Snate@binkert.org    for (int i = 0; i < size; i++) {
2456655Snate@binkert.org        nameOut(os, csprintf("%s.PTE%d", name(), i));
2466655Snate@binkert.org        table[i].serialize(os);
2476655Snate@binkert.org    }
2485871Snate@binkert.org}
2495871Snate@binkert.org
2505863Snate@binkert.orgvoid
2515871Snate@binkert.orgAlphaTLB::unserialize(Checkpoint *cp, const string &section)
2528878Ssteve.reinhardt@amd.com{
2535871Snate@binkert.org    UNSERIALIZE_SCALAR(size);
2545871Snate@binkert.org    UNSERIALIZE_SCALAR(nlu);
2555871Snate@binkert.org
2565863Snate@binkert.org    for (int i = 0; i < size; i++) {
2576121Snate@binkert.org        table[i].unserialize(cp, csprintf("%s.PTE%d", section, i));
2585863Snate@binkert.org        if (table[i].valid) {
2595871Snate@binkert.org            lookupTable.insert(make_pair(table[i].tag, i));
2608336Ssteve.reinhardt@amd.com        }
2618336Ssteve.reinhardt@amd.com    }
2628336Ssteve.reinhardt@amd.com}
2638336Ssteve.reinhardt@amd.com
2644678Snate@binkert.org
2658336Ssteve.reinhardt@amd.com///////////////////////////////////////////////////////////////////////
2668336Ssteve.reinhardt@amd.com//
2678336Ssteve.reinhardt@amd.com//  Alpha ITB
2684678Snate@binkert.org//
2694678Snate@binkert.orgAlphaITB::AlphaITB(const std::string &name, int size)
2704678Snate@binkert.org    : AlphaTLB(name, size)
2714678Snate@binkert.org{}
2727827Snate@binkert.org
2737827Snate@binkert.org
2748336Ssteve.reinhardt@amd.comvoid
2754678Snate@binkert.orgAlphaITB::regStats()
2768336Ssteve.reinhardt@amd.com{
2778336Ssteve.reinhardt@amd.com    hits
2788336Ssteve.reinhardt@amd.com        .name(name() + ".hits")
2798336Ssteve.reinhardt@amd.com        .desc("ITB hits");
2808336Ssteve.reinhardt@amd.com    misses
2818336Ssteve.reinhardt@amd.com        .name(name() + ".misses")
2825871Snate@binkert.org        .desc("ITB misses");
2835871Snate@binkert.org    acv
2848336Ssteve.reinhardt@amd.com        .name(name() + ".acv")
2858336Ssteve.reinhardt@amd.com        .desc("ITB acv");
2868336Ssteve.reinhardt@amd.com    accesses
2878336Ssteve.reinhardt@amd.com        .name(name() + ".accesses")
2888336Ssteve.reinhardt@amd.com        .desc("ITB accesses");
2895871Snate@binkert.org
2908336Ssteve.reinhardt@amd.com    accesses = hits + misses;
2918336Ssteve.reinhardt@amd.com}
2928336Ssteve.reinhardt@amd.com
2938336Ssteve.reinhardt@amd.comvoid
2948336Ssteve.reinhardt@amd.comAlphaITB::fault(Addr pc, ExecContext *xc) const
2954678Snate@binkert.org{
2965871Snate@binkert.org    uint64_t *ipr = xc->regs.ipr;
2974678Snate@binkert.org
2988336Ssteve.reinhardt@amd.com    if (!xc->misspeculating()) {
2998336Ssteve.reinhardt@amd.com        ipr[AlphaISA::IPR_ITB_TAG] = pc;
3008336Ssteve.reinhardt@amd.com        ipr[AlphaISA::IPR_IFAULT_VA_FORM] =
3018336Ssteve.reinhardt@amd.com            ipr[AlphaISA::IPR_IVPTBR] | (AlphaISA::VAddr(pc).vpn() << 3);
3028336Ssteve.reinhardt@amd.com    }
3038336Ssteve.reinhardt@amd.com}
3048336Ssteve.reinhardt@amd.com
3058336Ssteve.reinhardt@amd.com
3068336Ssteve.reinhardt@amd.comFault
3078336Ssteve.reinhardt@amd.comAlphaITB::translate(MemReqPtr &req) const
3088336Ssteve.reinhardt@amd.com{
3098336Ssteve.reinhardt@amd.com    InternalProcReg *ipr = req->xc->regs.ipr;
3108336Ssteve.reinhardt@amd.com
3118336Ssteve.reinhardt@amd.com    if (AlphaISA::PcPAL(req->vaddr)) {
3128336Ssteve.reinhardt@amd.com        // strip off PAL PC marker (lsb is 1)
3138336Ssteve.reinhardt@amd.com        req->paddr = (req->vaddr & ~3) & PAddrImplMask;
3148336Ssteve.reinhardt@amd.com        hits++;
3155871Snate@binkert.org        return NoFault;
3166121Snate@binkert.org    }
317955SN/A
318955SN/A    if (req->flags & PHYSICAL) {
3192632Sstever@eecs.umich.edu        req->paddr = req->vaddr;
3202632Sstever@eecs.umich.edu    } else {
321955SN/A        // verify that this is a good virtual address
322955SN/A        if (!validVirtualAddress(req->vaddr)) {
323955SN/A            fault(req->vaddr, req->xc);
324955SN/A            acv++;
3258878Ssteve.reinhardt@amd.com            return new ItbAcvFault;
326955SN/A        }
3272632Sstever@eecs.umich.edu
3282632Sstever@eecs.umich.edu
3292632Sstever@eecs.umich.edu        // VA<42:41> == 2, VA<39:13> maps directly to PA<39:13> for EV5
3302632Sstever@eecs.umich.edu        // VA<47:41> == 0x7e, VA<40:13> maps directly to PA<40:13> for EV6
3312632Sstever@eecs.umich.edu#if ALPHA_TLASER
3322632Sstever@eecs.umich.edu        if ((MCSR_SP(ipr[AlphaISA::IPR_MCSR]) & 2) &&
3332632Sstever@eecs.umich.edu            VAddrSpaceEV5(req->vaddr) == 2) {
3348268Ssteve.reinhardt@amd.com#else
3358268Ssteve.reinhardt@amd.com        if (VAddrSpaceEV6(req->vaddr) == 0x7e) {
3368268Ssteve.reinhardt@amd.com#endif
3378268Ssteve.reinhardt@amd.com            // only valid in kernel mode
3388268Ssteve.reinhardt@amd.com            if (ICM_CM(ipr[AlphaISA::IPR_ICM]) !=
3398268Ssteve.reinhardt@amd.com                AlphaISA::mode_kernel) {
3408268Ssteve.reinhardt@amd.com                fault(req->vaddr, req->xc);
3412632Sstever@eecs.umich.edu                acv++;
3422632Sstever@eecs.umich.edu                return new ItbAcvFault;
3432632Sstever@eecs.umich.edu            }
3442632Sstever@eecs.umich.edu
3458268Ssteve.reinhardt@amd.com            req->paddr = req->vaddr & PAddrImplMask;
3462632Sstever@eecs.umich.edu
3478268Ssteve.reinhardt@amd.com#if !ALPHA_TLASER
3488268Ssteve.reinhardt@amd.com            // sign extend the physical address properly
3498268Ssteve.reinhardt@amd.com            if (req->paddr & PAddrUncachedBit40)
3508268Ssteve.reinhardt@amd.com                req->paddr |= ULL(0xf0000000000);
3513718Sstever@eecs.umich.edu            else
3522634Sstever@eecs.umich.edu                req->paddr &= ULL(0xffffffffff);
3532634Sstever@eecs.umich.edu#endif
3545863Snate@binkert.org
3552638Sstever@eecs.umich.edu        } else {
3568268Ssteve.reinhardt@amd.com            // not a physical address: need to look up pte
3572632Sstever@eecs.umich.edu            AlphaISA::PTE *pte = lookup(AlphaISA::VAddr(req->vaddr).vpn(),
3582632Sstever@eecs.umich.edu                                        DTB_ASN_ASN(ipr[AlphaISA::IPR_DTB_ASN]));
3592632Sstever@eecs.umich.edu
3602632Sstever@eecs.umich.edu            if (!pte) {
3612632Sstever@eecs.umich.edu                fault(req->vaddr, req->xc);
3621858SN/A                misses++;
3633716Sstever@eecs.umich.edu                return new ItbPageFault;
3642638Sstever@eecs.umich.edu            }
3652638Sstever@eecs.umich.edu
3662638Sstever@eecs.umich.edu            req->paddr = (pte->ppn << AlphaISA::PageShift) +
3672638Sstever@eecs.umich.edu                (AlphaISA::VAddr(req->vaddr).offset() & ~3);
3682638Sstever@eecs.umich.edu
3692638Sstever@eecs.umich.edu            // check permissions for this access
3702638Sstever@eecs.umich.edu            if (!(pte->xre & (1 << ICM_CM(ipr[AlphaISA::IPR_ICM])))) {
3715863Snate@binkert.org                // instruction access fault
3725863Snate@binkert.org                fault(req->vaddr, req->xc);
3735863Snate@binkert.org                acv++;
374955SN/A                return new ItbAcvFault;
3755341Sstever@gmail.com            }
3765341Sstever@gmail.com
3775863Snate@binkert.org            hits++;
3787756SAli.Saidi@ARM.com        }
3795341Sstever@gmail.com    }
3806121Snate@binkert.org
3814494Ssaidi@eecs.umich.edu    // check that the physical address is ok (catch bad physical addresses)
3826121Snate@binkert.org    if (req->paddr & ~PAddrImplMask)
3831105SN/A        return genMachineCheckFault();
3842667Sstever@eecs.umich.edu
3852667Sstever@eecs.umich.edu    checkCacheability(req);
3862667Sstever@eecs.umich.edu
3872667Sstever@eecs.umich.edu    return NoFault;
3886121Snate@binkert.org}
3892667Sstever@eecs.umich.edu
3905341Sstever@gmail.com///////////////////////////////////////////////////////////////////////
3915863Snate@binkert.org//
3925341Sstever@gmail.com//  Alpha DTB
3935341Sstever@gmail.com//
3945341Sstever@gmail.comAlphaDTB::AlphaDTB(const std::string &name, int size)
3958120Sgblack@eecs.umich.edu    : AlphaTLB(name, size)
3965341Sstever@gmail.com{}
3978120Sgblack@eecs.umich.edu
3985341Sstever@gmail.comvoid
3998120Sgblack@eecs.umich.eduAlphaDTB::regStats()
4006121Snate@binkert.org{
4016121Snate@binkert.org    read_hits
4028980Ssteve.reinhardt@amd.com        .name(name() + ".read_hits")
4039396Sandreas.hansson@arm.com        .desc("DTB read hits")
4045397Ssaidi@eecs.umich.edu        ;
4055397Ssaidi@eecs.umich.edu
4067727SAli.Saidi@ARM.com    read_misses
4078268Ssteve.reinhardt@amd.com        .name(name() + ".read_misses")
4086168Snate@binkert.org        .desc("DTB read misses")
4095341Sstever@gmail.com        ;
4108120Sgblack@eecs.umich.edu
4118120Sgblack@eecs.umich.edu    read_acv
4128120Sgblack@eecs.umich.edu        .name(name() + ".read_acv")
4136814Sgblack@eecs.umich.edu        .desc("DTB read access violations")
4145863Snate@binkert.org        ;
4158120Sgblack@eecs.umich.edu
4165341Sstever@gmail.com    read_accesses
4175863Snate@binkert.org        .name(name() + ".read_accesses")
4188268Ssteve.reinhardt@amd.com        .desc("DTB read accesses")
4196121Snate@binkert.org        ;
4206121Snate@binkert.org
4218268Ssteve.reinhardt@amd.com    write_hits
4225742Snate@binkert.org        .name(name() + ".write_hits")
4235742Snate@binkert.org        .desc("DTB write hits")
4245341Sstever@gmail.com        ;
4255742Snate@binkert.org
4265742Snate@binkert.org    write_misses
4275341Sstever@gmail.com        .name(name() + ".write_misses")
4286017Snate@binkert.org        .desc("DTB write misses")
4296121Snate@binkert.org        ;
4306017Snate@binkert.org
4317816Ssteve.reinhardt@amd.com    write_acv
4327756SAli.Saidi@ARM.com        .name(name() + ".write_acv")
4337756SAli.Saidi@ARM.com        .desc("DTB write access violations")
4347756SAli.Saidi@ARM.com        ;
4357756SAli.Saidi@ARM.com
4367756SAli.Saidi@ARM.com    write_accesses
4377756SAli.Saidi@ARM.com        .name(name() + ".write_accesses")
4387756SAli.Saidi@ARM.com        .desc("DTB write accesses")
4397756SAli.Saidi@ARM.com        ;
4407816Ssteve.reinhardt@amd.com
4417816Ssteve.reinhardt@amd.com    hits
4427816Ssteve.reinhardt@amd.com        .name(name() + ".hits")
4437816Ssteve.reinhardt@amd.com        .desc("DTB hits")
4447816Ssteve.reinhardt@amd.com        ;
4457816Ssteve.reinhardt@amd.com
4467816Ssteve.reinhardt@amd.com    misses
4477816Ssteve.reinhardt@amd.com        .name(name() + ".misses")
4487816Ssteve.reinhardt@amd.com        .desc("DTB misses")
4497816Ssteve.reinhardt@amd.com        ;
4507756SAli.Saidi@ARM.com
4517816Ssteve.reinhardt@amd.com    acv
4527816Ssteve.reinhardt@amd.com        .name(name() + ".acv")
4537816Ssteve.reinhardt@amd.com        .desc("DTB access violations")
4547816Ssteve.reinhardt@amd.com        ;
4557816Ssteve.reinhardt@amd.com
4567816Ssteve.reinhardt@amd.com    accesses
4577816Ssteve.reinhardt@amd.com        .name(name() + ".accesses")
4587816Ssteve.reinhardt@amd.com        .desc("DTB accesses")
4597816Ssteve.reinhardt@amd.com        ;
4607816Ssteve.reinhardt@amd.com
4617816Ssteve.reinhardt@amd.com    hits = read_hits + write_hits;
4627816Ssteve.reinhardt@amd.com    misses = read_misses + write_misses;
4637816Ssteve.reinhardt@amd.com    acv = read_acv + write_acv;
4647816Ssteve.reinhardt@amd.com    accesses = read_accesses + write_accesses;
4657816Ssteve.reinhardt@amd.com}
4667816Ssteve.reinhardt@amd.com
4677816Ssteve.reinhardt@amd.comvoid
4687816Ssteve.reinhardt@amd.comAlphaDTB::fault(MemReqPtr &req, uint64_t flags) const
4697816Ssteve.reinhardt@amd.com{
4707816Ssteve.reinhardt@amd.com    ExecContext *xc = req->xc;
4717816Ssteve.reinhardt@amd.com    AlphaISA::VAddr vaddr = req->vaddr;
4727816Ssteve.reinhardt@amd.com    uint64_t *ipr = xc->regs.ipr;
4737816Ssteve.reinhardt@amd.com
4747816Ssteve.reinhardt@amd.com    // Set fault address and flags.  Even though we're modeling an
4757816Ssteve.reinhardt@amd.com    // EV5, we use the EV6 technique of not latching fault registers
4767816Ssteve.reinhardt@amd.com    // on VPTE loads (instead of locking the registers until IPR_VA is
4777816Ssteve.reinhardt@amd.com    // read, like the EV5).  The EV6 approach is cleaner and seems to
4787816Ssteve.reinhardt@amd.com    // work with EV5 PAL code, but not the other way around.
4797816Ssteve.reinhardt@amd.com    if (!xc->misspeculating()
4807816Ssteve.reinhardt@amd.com        && !(req->flags & VPTE) && !(req->flags & NO_FAULT)) {
4817816Ssteve.reinhardt@amd.com        // set VA register with faulting address
4827816Ssteve.reinhardt@amd.com        ipr[AlphaISA::IPR_VA] = req->vaddr;
4837816Ssteve.reinhardt@amd.com
4847816Ssteve.reinhardt@amd.com        // set MM_STAT register flags
4857816Ssteve.reinhardt@amd.com        ipr[AlphaISA::IPR_MM_STAT] =
4867816Ssteve.reinhardt@amd.com            (((Opcode(xc->getInst()) & 0x3f) << 11)
4877816Ssteve.reinhardt@amd.com             | ((Ra(xc->getInst()) & 0x1f) << 6)
4887816Ssteve.reinhardt@amd.com             | (flags & 0x3f));
4897816Ssteve.reinhardt@amd.com
4907816Ssteve.reinhardt@amd.com        // set VA_FORM register with faulting formatted address
4917816Ssteve.reinhardt@amd.com        ipr[AlphaISA::IPR_VA_FORM] =
4927816Ssteve.reinhardt@amd.com            ipr[AlphaISA::IPR_MVPTBR] | (vaddr.vpn() << 3);
4937816Ssteve.reinhardt@amd.com    }
4947816Ssteve.reinhardt@amd.com}
4957816Ssteve.reinhardt@amd.com
4967816Ssteve.reinhardt@amd.comFault
4977816Ssteve.reinhardt@amd.comAlphaDTB::translate(MemReqPtr &req, bool write) const
4987816Ssteve.reinhardt@amd.com{
4997816Ssteve.reinhardt@amd.com    RegFile *regs = &req->xc->regs;
5007816Ssteve.reinhardt@amd.com    Addr pc = regs->pc;
5017816Ssteve.reinhardt@amd.com    InternalProcReg *ipr = regs->ipr;
5027816Ssteve.reinhardt@amd.com
5037816Ssteve.reinhardt@amd.com    AlphaISA::mode_type mode =
5047816Ssteve.reinhardt@amd.com        (AlphaISA::mode_type)DTB_CM_CM(ipr[AlphaISA::IPR_DTB_CM]);
5057816Ssteve.reinhardt@amd.com
5067816Ssteve.reinhardt@amd.com
5077816Ssteve.reinhardt@amd.com    /**
5087816Ssteve.reinhardt@amd.com     * Check for alignment faults
5097816Ssteve.reinhardt@amd.com     */
5107816Ssteve.reinhardt@amd.com    if (req->vaddr & (req->size - 1)) {
5117816Ssteve.reinhardt@amd.com        fault(req, write ? MM_STAT_WR_MASK : 0);
5128947Sandreas.hansson@arm.com        DPRINTF(TLB, "Alignment Fault on %#x, size = %d", req->vaddr,
5138947Sandreas.hansson@arm.com                req->size);
5147756SAli.Saidi@ARM.com        return genAlignmentFault();
5158120Sgblack@eecs.umich.edu    }
5167756SAli.Saidi@ARM.com
5177756SAli.Saidi@ARM.com    if (pc & 0x1) {
5187756SAli.Saidi@ARM.com        mode = (req->flags & ALTMODE) ?
5197756SAli.Saidi@ARM.com            (AlphaISA::mode_type)ALT_MODE_AM(ipr[AlphaISA::IPR_ALT_MODE])
5207816Ssteve.reinhardt@amd.com            : AlphaISA::mode_kernel;
5217816Ssteve.reinhardt@amd.com    }
5227816Ssteve.reinhardt@amd.com
5237816Ssteve.reinhardt@amd.com    if (req->flags & PHYSICAL) {
5247816Ssteve.reinhardt@amd.com        req->paddr = req->vaddr;
5257816Ssteve.reinhardt@amd.com    } else {
5267816Ssteve.reinhardt@amd.com        // verify that this is a good virtual address
5277816Ssteve.reinhardt@amd.com        if (!validVirtualAddress(req->vaddr)) {
5287816Ssteve.reinhardt@amd.com            fault(req, (write ? MM_STAT_WR_MASK : 0) |
5297816Ssteve.reinhardt@amd.com                  MM_STAT_BAD_VA_MASK |
5307756SAli.Saidi@ARM.com                  MM_STAT_ACV_MASK);
5317756SAli.Saidi@ARM.com
5329227Sandreas.hansson@arm.com            if (write) { write_acv++; } else { read_acv++; }
5339227Sandreas.hansson@arm.com            return new DtbPageFault;
5349227Sandreas.hansson@arm.com        }
5359227Sandreas.hansson@arm.com
5369590Sandreas@sandberg.pp.se        // Check for "superpage" mapping
5379590Sandreas@sandberg.pp.se#if ALPHA_TLASER
5389590Sandreas@sandberg.pp.se        if ((MCSR_SP(ipr[AlphaISA::IPR_MCSR]) & 2) &&
5399590Sandreas@sandberg.pp.se            VAddrSpaceEV5(req->vaddr) == 2) {
5409590Sandreas@sandberg.pp.se#else
5419590Sandreas@sandberg.pp.se        if (VAddrSpaceEV6(req->vaddr) == 0x7e) {
5426654Snate@binkert.org#endif
5436654Snate@binkert.org
5445871Snate@binkert.org            // only valid in kernel mode
5456121Snate@binkert.org            if (DTB_CM_CM(ipr[AlphaISA::IPR_DTB_CM]) !=
5468946Sandreas.hansson@arm.com                AlphaISA::mode_kernel) {
5479419Sandreas.hansson@arm.com                fault(req, ((write ? MM_STAT_WR_MASK : 0) |
5483940Ssaidi@eecs.umich.edu                            MM_STAT_ACV_MASK));
5493918Ssaidi@eecs.umich.edu                if (write) { write_acv++; } else { read_acv++; }
5503918Ssaidi@eecs.umich.edu                return new DtbAcvFault;
5511858SN/A            }
5529556Sandreas.hansson@arm.com
5539556Sandreas.hansson@arm.com            req->paddr = req->vaddr & PAddrImplMask;
5549556Sandreas.hansson@arm.com
5559556Sandreas.hansson@arm.com#if !ALPHA_TLASER
5569556Sandreas.hansson@arm.com            // sign extend the physical address properly
5579556Sandreas.hansson@arm.com            if (req->paddr & PAddrUncachedBit40)
5589556Sandreas.hansson@arm.com                req->paddr |= ULL(0xf0000000000);
5599556Sandreas.hansson@arm.com            else
5609556Sandreas.hansson@arm.com                req->paddr &= ULL(0xffffffffff);
5619556Sandreas.hansson@arm.com#endif
5629556Sandreas.hansson@arm.com
5639556Sandreas.hansson@arm.com        } else {
5649556Sandreas.hansson@arm.com            if (write)
5659556Sandreas.hansson@arm.com                write_accesses++;
5669556Sandreas.hansson@arm.com            else
5679556Sandreas.hansson@arm.com                read_accesses++;
5689556Sandreas.hansson@arm.com
5699556Sandreas.hansson@arm.com            // not a physical address: need to look up pte
5709556Sandreas.hansson@arm.com            AlphaISA::PTE *pte = lookup(AlphaISA::VAddr(req->vaddr).vpn(),
5719556Sandreas.hansson@arm.com                                        DTB_ASN_ASN(ipr[AlphaISA::IPR_DTB_ASN]));
5729556Sandreas.hansson@arm.com
5739556Sandreas.hansson@arm.com            if (!pte) {
5749556Sandreas.hansson@arm.com                // page fault
5759556Sandreas.hansson@arm.com                fault(req, (write ? MM_STAT_WR_MASK : 0) |
5769556Sandreas.hansson@arm.com                      MM_STAT_DTB_MISS_MASK);
5779556Sandreas.hansson@arm.com                if (write) { write_misses++; } else { read_misses++; }
5789556Sandreas.hansson@arm.com                return (req->flags & VPTE) ?
5799556Sandreas.hansson@arm.com                    (Fault)(new PDtbMissFault) :
5809556Sandreas.hansson@arm.com                    (Fault)(new NDtbMissFault);
5819556Sandreas.hansson@arm.com            }
5829556Sandreas.hansson@arm.com
5839556Sandreas.hansson@arm.com            req->paddr = (pte->ppn << AlphaISA::PageShift) +
5846121Snate@binkert.org                AlphaISA::VAddr(req->vaddr).offset();
58510238Sandreas.hansson@arm.com
58610238Sandreas.hansson@arm.com            if (write) {
58710238Sandreas.hansson@arm.com                if (!(pte->xwe & MODE2MASK(mode))) {
58810238Sandreas.hansson@arm.com                    // declare the instruction access fault
5899420Sandreas.hansson@arm.com                    fault(req, MM_STAT_WR_MASK |
59010238Sandreas.hansson@arm.com                          MM_STAT_ACV_MASK |
59110238Sandreas.hansson@arm.com                          (pte->fonw ? MM_STAT_FONW_MASK : 0));
5929420Sandreas.hansson@arm.com                    write_acv++;
5939420Sandreas.hansson@arm.com                    return new DtbPageFault;
5949420Sandreas.hansson@arm.com                }
5959420Sandreas.hansson@arm.com                if (pte->fonw) {
5969420Sandreas.hansson@arm.com                    fault(req, MM_STAT_WR_MASK |
59710264Sandreas.hansson@arm.com                          MM_STAT_FONW_MASK);
59810264Sandreas.hansson@arm.com                    write_acv++;
59910264Sandreas.hansson@arm.com                    return new DtbPageFault;
60010264Sandreas.hansson@arm.com                }
60110264Sandreas.hansson@arm.com            } else {
60210264Sandreas.hansson@arm.com                if (!(pte->xre & MODE2MASK(mode))) {
60310264Sandreas.hansson@arm.com                    fault(req, MM_STAT_ACV_MASK |
60410264Sandreas.hansson@arm.com                          (pte->fonr ? MM_STAT_FONR_MASK : 0));
60510264Sandreas.hansson@arm.com                    read_acv++;
60610264Sandreas.hansson@arm.com                    return new DtbAcvFault;
60710264Sandreas.hansson@arm.com                }
60810264Sandreas.hansson@arm.com                if (pte->fonr) {
60910264Sandreas.hansson@arm.com                    fault(req, MM_STAT_FONR_MASK);
61010264Sandreas.hansson@arm.com                    read_acv++;
61110264Sandreas.hansson@arm.com                    return new DtbPageFault;
61210264Sandreas.hansson@arm.com                }
61310457Sandreas.hansson@arm.com            }
61410457Sandreas.hansson@arm.com        }
61510457Sandreas.hansson@arm.com
61610457Sandreas.hansson@arm.com        if (write)
61710457Sandreas.hansson@arm.com            write_hits++;
61810457Sandreas.hansson@arm.com        else
61910457Sandreas.hansson@arm.com            read_hits++;
62010457Sandreas.hansson@arm.com    }
62110457Sandreas.hansson@arm.com
62210238Sandreas.hansson@arm.com    // check that the physical address is ok (catch bad physical addresses)
62310238Sandreas.hansson@arm.com    if (req->paddr & ~PAddrImplMask)
62410238Sandreas.hansson@arm.com        return genMachineCheckFault();
62510238Sandreas.hansson@arm.com
62610238Sandreas.hansson@arm.com    checkCacheability(req);
62710238Sandreas.hansson@arm.com
62810416Sandreas.hansson@arm.com    return NoFault;
62910238Sandreas.hansson@arm.com}
6309227Sandreas.hansson@arm.com
63110238Sandreas.hansson@arm.comAlphaISA::PTE &
63210416Sandreas.hansson@arm.comAlphaTLB::index(bool advance)
63310416Sandreas.hansson@arm.com{
6349227Sandreas.hansson@arm.com    AlphaISA::PTE *pte = &table[nlu];
6359590Sandreas@sandberg.pp.se
6369590Sandreas@sandberg.pp.se    if (advance)
6379590Sandreas@sandberg.pp.se        nextnlu();
6388737Skoansin.tan@gmail.com
63910238Sandreas.hansson@arm.com    return *pte;
64010238Sandreas.hansson@arm.com}
6419420Sandreas.hansson@arm.com
6428737Skoansin.tan@gmail.comDEFINE_SIM_OBJECT_CLASS_NAME("AlphaTLB", AlphaTLB)
64310106SMitch.Hayenga@arm.com
6448737Skoansin.tan@gmail.comBEGIN_DECLARE_SIM_OBJECT_PARAMS(AlphaITB)
6458737Skoansin.tan@gmail.com
64610238Sandreas.hansson@arm.com    Param<int> size;
64710238Sandreas.hansson@arm.com
6488737Skoansin.tan@gmail.comEND_DECLARE_SIM_OBJECT_PARAMS(AlphaITB)
6498737Skoansin.tan@gmail.com
6508737Skoansin.tan@gmail.comBEGIN_INIT_SIM_OBJECT_PARAMS(AlphaITB)
6518737Skoansin.tan@gmail.com
6528737Skoansin.tan@gmail.com    INIT_PARAM_DFLT(size, "TLB size", 48)
6538737Skoansin.tan@gmail.com
6549556Sandreas.hansson@arm.comEND_INIT_SIM_OBJECT_PARAMS(AlphaITB)
6559556Sandreas.hansson@arm.com
6569556Sandreas.hansson@arm.com
6579556Sandreas.hansson@arm.comCREATE_SIM_OBJECT(AlphaITB)
6589556Sandreas.hansson@arm.com{
6599556Sandreas.hansson@arm.com    return new AlphaITB(getInstanceName(), size);
6609556Sandreas.hansson@arm.com}
6619556Sandreas.hansson@arm.com
66210278SAndreas.Sandberg@ARM.comREGISTER_SIM_OBJECT("AlphaITB", AlphaITB)
66310278SAndreas.Sandberg@ARM.com
66410278SAndreas.Sandberg@ARM.comBEGIN_DECLARE_SIM_OBJECT_PARAMS(AlphaDTB)
66510278SAndreas.Sandberg@ARM.com
66610278SAndreas.Sandberg@ARM.com    Param<int> size;
66710278SAndreas.Sandberg@ARM.com
6689556Sandreas.hansson@arm.comEND_DECLARE_SIM_OBJECT_PARAMS(AlphaDTB)
6699590Sandreas@sandberg.pp.se
6709590Sandreas@sandberg.pp.seBEGIN_INIT_SIM_OBJECT_PARAMS(AlphaDTB)
6719420Sandreas.hansson@arm.com
6729846Sandreas.hansson@arm.com    INIT_PARAM_DFLT(size, "TLB size", 64)
6739846Sandreas.hansson@arm.com
6749846Sandreas.hansson@arm.comEND_INIT_SIM_OBJECT_PARAMS(AlphaDTB)
6759846Sandreas.hansson@arm.com
6768946Sandreas.hansson@arm.com
6773918Ssaidi@eecs.umich.eduCREATE_SIM_OBJECT(AlphaDTB)
6789068SAli.Saidi@ARM.com{
6799068SAli.Saidi@ARM.com    return new AlphaDTB(getInstanceName(), size);
6809068SAli.Saidi@ARM.com}
6819068SAli.Saidi@ARM.com
6829068SAli.Saidi@ARM.comREGISTER_SIM_OBJECT("AlphaDTB", AlphaDTB)
6839068SAli.Saidi@ARM.com
6849068SAli.Saidi@ARM.com