tlb.cc revision 1052
12SN/A/*
28707Sandreas.hansson@arm.com * Copyright (c) 2001-2004 The Regents of The University of Michigan
38707Sandreas.hansson@arm.com * All rights reserved.
48707Sandreas.hansson@arm.com *
58707Sandreas.hansson@arm.com * Redistribution and use in source and binary forms, with or without
68707Sandreas.hansson@arm.com * modification, are permitted provided that the following conditions are
78707Sandreas.hansson@arm.com * met: redistributions of source code must retain the above copyright
88707Sandreas.hansson@arm.com * notice, this list of conditions and the following disclaimer;
98707Sandreas.hansson@arm.com * redistributions in binary form must reproduce the above copyright
108707Sandreas.hansson@arm.com * notice, this list of conditions and the following disclaimer in the
118707Sandreas.hansson@arm.com * documentation and/or other materials provided with the distribution;
128707Sandreas.hansson@arm.com * neither the name of the copyright holders nor the names of its
138707Sandreas.hansson@arm.com * contributors may be used to endorse or promote products derived from
141762SN/A * this software without specific prior written permission.
157897Shestness@cs.utexas.edu *
162SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
172SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
182SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
192SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
202SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
212SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
222SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
232SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
242SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
252SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
262SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
272SN/A */
282SN/A
292SN/A#include <sstream>
302SN/A#include <string>
312SN/A#include <vector>
322SN/A
332SN/A#include "base/inifile.hh"
342SN/A#include "base/str.hh"
352SN/A#include "base/trace.hh"
362SN/A#include "cpu/exec_context.hh"
372SN/A#include "sim/builder.hh"
382SN/A#include "targetarch/alpha_memory.hh"
392SN/A#include "targetarch/ev5.hh"
402665Ssaidi@eecs.umich.edu
412665Ssaidi@eecs.umich.eduusing namespace std;
422665Ssaidi@eecs.umich.edu
437897Shestness@cs.utexas.edu///////////////////////////////////////////////////////////////////////
442SN/A//
452SN/A//  Alpha TLB
461388SN/A//
478229Snate@binkert.org#ifdef DEBUG
482SN/Abool uncacheBit39 = false;
492SN/Abool uncacheBit40 = false;
507781SAli.Saidi@ARM.com#endif
518229Snate@binkert.org
521191SN/AAlphaTLB::AlphaTLB(const string &name, int s)
531191SN/A    : SimObject(name), size(s), nlu(0)
541388SN/A{
555529Snate@binkert.org    table = new AlphaISA::PTE[size];
561717SN/A    memset(table, 0, sizeof(AlphaISA::PTE[size]));
572651Ssaidi@eecs.umich.edu}
588229Snate@binkert.org
592680Sktlim@umich.eduAlphaTLB::~AlphaTLB()
608232Snate@binkert.org{
615529Snate@binkert.org    if (table)
622190SN/A        delete [] table;
6356SN/A}
648229Snate@binkert.org
652190SN/A// look up an entry in the TLB
662SN/AAlphaISA::PTE *
672359SN/AAlphaTLB::lookup(Addr vpn, uint8_t asn) const
682359SN/A{
692359SN/A    DPRINTF(TLB, "lookup %#x, asn %#x\n", vpn, (int)asn);
702SN/A
712SN/A    PageTable::const_iterator i = lookupTable.find(vpn);
722SN/A    if (i == lookupTable.end())
732SN/A        return NULL;
742SN/A
752SN/A    while (i->first == vpn) {
762SN/A        int index = i->second;
772SN/A        AlphaISA::PTE *pte = &table[index];
782SN/A        assert(pte->valid);
795606Snate@binkert.org        if (vpn == pte->tag && (pte->asma || pte->asn == asn))
806144Sksewell@umich.edu            return pte;
816144Sksewell@umich.edu
823126Sktlim@umich.edu        ++i;
836144Sksewell@umich.edu    }
847823Ssteve.reinhardt@amd.com
853126Sktlim@umich.edu    // not found...
863126Sktlim@umich.edu    return NULL;
872356SN/A}
882356SN/A
892356SN/A
902367SN/Avoid
912356SN/AAlphaTLB::checkCacheability(MemReqPtr &req)
926144Sksewell@umich.edu{
932367SN/A    // in Alpha, cacheability is controlled by upper-level bits of the
946144Sksewell@umich.edu    // physical address
956144Sksewell@umich.edu
966144Sksewell@umich.edu    /*
972356SN/A     * We support having the uncacheable bit in either bit 39 or bit 40.
982367SN/A     * The Turbolaser platform (and EV5) support having the bit in 39, but
996144Sksewell@umich.edu     * Tsunami (which Linux assumes uses an EV6) generates accesses with
1007823Ssteve.reinhardt@amd.com     * the bit in 40.  So we must check for both, but we have debug flags
1016144Sksewell@umich.edu     * to catch a weird case where both are used, which shouldn't happen.
1022367SN/A     */
1032356SN/A
1046144Sksewell@umich.edu
1056144Sksewell@umich.edu#ifdef ALPHA_TLASER
1067823Ssteve.reinhardt@amd.com    if (req->paddr & PA_UNCACHED_BIT_39) {
1072356SN/A#else
1082356SN/A    if (req->paddr & PA_UNCACHED_BIT_43) {
1092356SN/A#endif
1105336Shines@cs.fsu.edu        // IPR memory space not implemented
1112356SN/A        if (PA_IPR_SPACE(req->paddr)) {
1124873Sstever@eecs.umich.edu            if (!req->xc->misspeculating()) {
1132356SN/A                switch (req->paddr) {
1142356SN/A                  case ULL(0xFFFFF00188):
1151858SN/A                    req->data = 0;
1161400SN/A                    break;
1175712Shsul@eecs.umich.edu
1185712Shsul@eecs.umich.edu                  default:
1196221Snate@binkert.org                    panic("IPR memory space not implemented! PA=%x\n",
1203661Srdreslin@umich.edu                          req->paddr);
1212SN/A                }
1221400SN/A            }
1235712Shsul@eecs.umich.edu        } else {
1246221Snate@binkert.org            // mark request as uncacheable
1253661Srdreslin@umich.edu            req->flags |= UNCACHEABLE;
1262SN/A
1272SN/A#ifndef ALPHA_TLASER
1287823Ssteve.reinhardt@amd.com            // Clear bits 42:35 of the physical address (10-2 in Tsunami manual)
1291062SN/A            req->paddr &= PA_UNCACHED_MASK;
1305712Shsul@eecs.umich.edu#endif
1315712Shsul@eecs.umich.edu        }
1325712Shsul@eecs.umich.edu    }
1335712Shsul@eecs.umich.edu}
1345712Shsul@eecs.umich.edu
1352SN/A
1362SN/A// insert a new TLB entry
1372SN/Avoid
1385712Shsul@eecs.umich.eduAlphaTLB::insert(Addr vaddr, AlphaISA::PTE &pte)
1395712Shsul@eecs.umich.edu{
1406221Snate@binkert.org    if (table[nlu].valid) {
1416221Snate@binkert.org        Addr oldvpn = table[nlu].tag;
1422SN/A        PageTable::iterator i = lookupTable.find(oldvpn);
1432SN/A
1446221Snate@binkert.org        if (i == lookupTable.end())
1456221Snate@binkert.org            panic("TLB entry not found in lookupTable");
1466221Snate@binkert.org
1476221Snate@binkert.org        int index;
1482SN/A        while ((index = i->second) != nlu) {
1492SN/A            if (table[index].tag != oldvpn)
1502SN/A                panic("TLB entry not found in lookupTable");
1512SN/A
1525606Snate@binkert.org            ++i;
1535606Snate@binkert.org        }
1546221Snate@binkert.org
1555606Snate@binkert.org        DPRINTF(TLB, "remove @%d: %#x -> %#x\n", nlu, oldvpn, table[nlu].ppn);
1566221Snate@binkert.org
1575606Snate@binkert.org        lookupTable.erase(i);
1585606Snate@binkert.org    }
1592SN/A
1601400SN/A    Addr vpn = VA_VPN(vaddr);
1615606Snate@binkert.org    DPRINTF(TLB, "insert @%d: %#x -> %#x\n", nlu, vpn, pte.ppn);
1625606Snate@binkert.org
1632SN/A    table[nlu] = pte;
1642SN/A    table[nlu].tag = vpn;
1652SN/A    table[nlu].valid = true;
1662SN/A
1676221Snate@binkert.org    lookupTable.insert(make_pair(vpn, nlu));
1686221Snate@binkert.org    nextnlu();
1695606Snate@binkert.org}
1706670Shsul@eecs.umich.edu
1715606Snate@binkert.orgvoid
1722SN/AAlphaTLB::flushAll()
1732SN/A{
174124SN/A    memset(table, 0, sizeof(AlphaISA::PTE[size]));
1756221Snate@binkert.org    lookupTable.clear();
1766221Snate@binkert.org    nlu = 0;
1776221Snate@binkert.org}
178124SN/A
179124SN/Avoid
180124SN/AAlphaTLB::flushProcesses()
181124SN/A{
1825606Snate@binkert.org    PageTable::iterator i = lookupTable.begin();
1835606Snate@binkert.org    PageTable::iterator end = lookupTable.end();
1846221Snate@binkert.org    while (i != end) {
1855606Snate@binkert.org        int index = i->second;
1866221Snate@binkert.org        AlphaISA::PTE *pte = &table[index];
1875606Snate@binkert.org        assert(pte->valid);
1885606Snate@binkert.org
189124SN/A        if (!pte->asma) {
1901400SN/A            DPRINTF(TLB, "flush @%d: %#x -> %#x\n", index, pte->tag, pte->ppn);
1915606Snate@binkert.org            pte->valid = false;
192124SN/A            lookupTable.erase(i);
193124SN/A        }
194124SN/A
195124SN/A        ++i;
1966221Snate@binkert.org    }
1976221Snate@binkert.org}
1985606Snate@binkert.org
1996221Snate@binkert.orgvoid
2005606Snate@binkert.orgAlphaTLB::flushAddr(Addr vaddr, uint8_t asn)
201124SN/A{
202124SN/A    Addr vpn = VA_VPN(vaddr);
2031191SN/A
2045529Snate@binkert.org    PageTable::iterator i = lookupTable.find(vpn);
2058634Schris.emmons@arm.com    if (i == lookupTable.end())
2068634Schris.emmons@arm.com        return;
2078634Schris.emmons@arm.com
2088634Schris.emmons@arm.com    while (i->first == vpn) {
2098634Schris.emmons@arm.com        int index = i->second;
2101191SN/A        AlphaISA::PTE *pte = &table[index];
2115529Snate@binkert.org        assert(pte->valid);
2121191SN/A
2135529Snate@binkert.org        if (vpn == pte->tag && (pte->asma || pte->asn == asn)) {
2141191SN/A            DPRINTF(TLB, "flushaddr @%d: %#x -> %#x\n", index, vpn, pte->ppn);
2151191SN/A
2165606Snate@binkert.org            // invalidate this entry
2175606Snate@binkert.org            pte->valid = false;
2185606Snate@binkert.org
2191191SN/A            lookupTable.erase(i);
2201191SN/A        }
2211917SN/A
2225810Sgblack@eecs.umich.edu        ++i;
2235810Sgblack@eecs.umich.edu    }
2241917SN/A}
2255529Snate@binkert.org
2265529Snate@binkert.org
2271917SN/Avoid
2285529Snate@binkert.orgAlphaTLB::serialize(ostream &os)
2291917SN/A{
2301191SN/A    SERIALIZE_SCALAR(size);
2311191SN/A    SERIALIZE_SCALAR(nlu);
2321191SN/A
2331191SN/A    for (int i = 0; i < size; i++) {
2341191SN/A        nameOut(os, csprintf("%s.PTE%d", name(), i));
2351191SN/A        table[i].serialize(os);
2361191SN/A    }
2371191SN/A}
2381191SN/A
2391191SN/Avoid
2401191SN/AAlphaTLB::unserialize(Checkpoint *cp, const string &section)
2411129SN/A{
2421129SN/A    UNSERIALIZE_SCALAR(size);
2431129SN/A    UNSERIALIZE_SCALAR(nlu);
2445529Snate@binkert.org
2452680Sktlim@umich.edu    for (int i = 0; i < size; i++) {
2461129SN/A        table[i].unserialize(cp, csprintf("%s.PTE%d", section, i));
247180SN/A        if (table[i].valid) {
2482SN/A            lookupTable.insert(make_pair(table[i].tag, i));
2491917SN/A        }
2501917SN/A    }
2511917SN/A}
2525529Snate@binkert.org
2537823Ssteve.reinhardt@amd.com
2541917SN/A///////////////////////////////////////////////////////////////////////
2552356SN/A//
2565529Snate@binkert.org//  Alpha ITB
2575606Snate@binkert.org//
2586144Sksewell@umich.eduAlphaITB::AlphaITB(const std::string &name, int size)
2598607Sgblack@eecs.umich.edu    : AlphaTLB(name, size)
2602356SN/A{}
2611917SN/A
2621917SN/A
2631917SN/Avoid
2641917SN/AAlphaITB::regStats()
2652SN/A{
2662SN/A    hits
267729SN/A        .name(name() + ".hits")
268707SN/A        .desc("ITB hits");
269707SN/A    misses
270707SN/A        .name(name() + ".misses")
271707SN/A        .desc("ITB misses");
272707SN/A    acv
273707SN/A        .name(name() + ".acv")
2747914SBrad.Beckmann@amd.com        .desc("ITB acv");
2757914SBrad.Beckmann@amd.com    accesses
2767914SBrad.Beckmann@amd.com        .name(name() + ".accesses")
2777914SBrad.Beckmann@amd.com        .desc("ITB accesses");
2787914SBrad.Beckmann@amd.com
2797914SBrad.Beckmann@amd.com    accesses = hits + misses;
2807914SBrad.Beckmann@amd.com}
2817914SBrad.Beckmann@amd.com
2827914SBrad.Beckmann@amd.comvoid
2837914SBrad.Beckmann@amd.comAlphaITB::fault(Addr pc, ExecContext *xc) const
2842680Sktlim@umich.edu{
2852SN/A    uint64_t *ipr = xc->regs.ipr;
2862SN/A
2872SN/A    if (!xc->misspeculating()) {
2882SN/A        ipr[AlphaISA::IPR_ITB_TAG] = pc;
2892680Sktlim@umich.edu        ipr[AlphaISA::IPR_IFAULT_VA_FORM] =
2902SN/A            ipr[AlphaISA::IPR_IVPTBR] | (VA_VPN(pc) << 3);
2912SN/A    }
2922680Sktlim@umich.edu}
2932190SN/A
2942190SN/A
2952190SN/AFault
2962SN/AAlphaITB::translate(MemReqPtr &req) const
2972SN/A{
2983495Sktlim@umich.edu    InternalProcReg *ipr = req->xc->regs.ipr;
2993495Sktlim@umich.edu
3003495Sktlim@umich.edu    if (PC_PAL(req->vaddr)) {
3017823Ssteve.reinhardt@amd.com        // strip off PAL PC marker (lsb is 1)
3023495Sktlim@umich.edu        req->paddr = (req->vaddr & ~3) & PA_IMPL_MASK;
3033661Srdreslin@umich.edu        hits++;
3043495Sktlim@umich.edu        return No_Fault;
3053495Sktlim@umich.edu    }
3063495Sktlim@umich.edu
3073495Sktlim@umich.edu    if (req->flags & PHYSICAL) {
3083495Sktlim@umich.edu        req->paddr = req->vaddr;
3093495Sktlim@umich.edu    } else {
3103495Sktlim@umich.edu        // verify that this is a good virtual address
3114599Sacolyte@umich.edu        if (!validVirtualAddress(req->vaddr)) {
3124599Sacolyte@umich.edu            fault(req->vaddr, req->xc);
3133661Srdreslin@umich.edu            acv++;
3143495Sktlim@umich.edu            return ITB_Acv_Fault;
3157823Ssteve.reinhardt@amd.com        }
3163495Sktlim@umich.edu
3173495Sktlim@umich.edu
318180SN/A        // VA<42:41> == 2, VA<39:13> maps directly to PA<39:13> for EV5
319180SN/A        // VA<47:41> == 0x7e, VA<40:13> maps directly to PA<40:13> for EV6
3202680Sktlim@umich.edu#ifdef ALPHA_TLASER
321180SN/A        if ((MCSR_SP(ipr[AlphaISA::IPR_MCSR]) & 2) &&
3226221Snate@binkert.org               VA_SPACE_EV5(req->vaddr) == 2) {
3236221Snate@binkert.org#else
3246221Snate@binkert.org        if (VA_SPACE_EV6(req->vaddr) == 0x7e) {
3252378SN/A#endif
3265718Shsul@eecs.umich.edu
3275718Shsul@eecs.umich.edu
3285718Shsul@eecs.umich.edu            // only valid in kernel mode
3295718Shsul@eecs.umich.edu            if (ICM_CM(ipr[AlphaISA::IPR_ICM]) != AlphaISA::mode_kernel) {
3305718Shsul@eecs.umich.edu                fault(req->vaddr, req->xc);
3315718Shsul@eecs.umich.edu                acv++;
3325718Shsul@eecs.umich.edu                return ITB_Acv_Fault;
3336221Snate@binkert.org            }
3345718Shsul@eecs.umich.edu
3355718Shsul@eecs.umich.edu            req->paddr = req->vaddr & PA_IMPL_MASK;
3365718Shsul@eecs.umich.edu
3375713Shsul@eecs.umich.edu#ifndef ALPHA_TLASER
3385714Shsul@eecs.umich.edu            // sign extend the physical address properly
339180SN/A            if (req->paddr & PA_UNCACHED_BIT_40)
340180SN/A                req->paddr |= ULL(0xf0000000000);
341180SN/A            else
342180SN/A                req->paddr &= ULL(0xffffffffff);
343180SN/A#endif
3444000Ssaidi@eecs.umich.edu
3454000Ssaidi@eecs.umich.edu        } else {
3464000Ssaidi@eecs.umich.edu            // not a physical address: need to look up pte
3476221Snate@binkert.org            AlphaISA::PTE *pte = lookup(VA_VPN(req->vaddr),
3486221Snate@binkert.org                                 DTB_ASN_ASN(ipr[AlphaISA::IPR_DTB_ASN]));
3496221Snate@binkert.org
3506221Snate@binkert.org            if (!pte) {
3514000Ssaidi@eecs.umich.edu                fault(req->vaddr, req->xc);
3524000Ssaidi@eecs.umich.edu                misses++;
3534000Ssaidi@eecs.umich.edu                return ITB_Fault_Fault;
3544000Ssaidi@eecs.umich.edu            }
355180SN/A
3562798Sktlim@umich.edu            req->paddr = PA_PFN2PA(pte->ppn) + VA_POFS(req->vaddr & ~3);
357180SN/A
3582359SN/A            // check permissions for this access
3592359SN/A            if (!(pte->xre & (1 << ICM_CM(ipr[AlphaISA::IPR_ICM])))) {
3602359SN/A                // instruction access fault
3615606Snate@binkert.org                fault(req->vaddr, req->xc);
3622359SN/A                acv++;
363180SN/A                return ITB_Acv_Fault;
364180SN/A            }
365180SN/A
3664192Sktlim@umich.edu            hits++;
367180SN/A        }
3682680Sktlim@umich.edu    }
369180SN/A
3705712Shsul@eecs.umich.edu    // check that the physical address is ok (catch bad physical addresses)
3715712Shsul@eecs.umich.edu    if (req->paddr & ~PA_IMPL_MASK)
3726221Snate@binkert.org        return Machine_Check_Fault;
3736221Snate@binkert.org
3742680Sktlim@umich.edu    checkCacheability(req);
3752680Sktlim@umich.edu
376180SN/A    return No_Fault;
3772680Sktlim@umich.edu}
3782651Ssaidi@eecs.umich.edu
3792680Sktlim@umich.edu///////////////////////////////////////////////////////////////////////
3802651Ssaidi@eecs.umich.edu//
3815714Shsul@eecs.umich.edu//  Alpha DTB
3825715Shsul@eecs.umich.edu//
3835714Shsul@eecs.umich.eduAlphaDTB::AlphaDTB(const std::string &name, int size)
3842359SN/A    : AlphaTLB(name, size)
3855875Ssteve.reinhardt@amd.com{}
3865875Ssteve.reinhardt@amd.com
3875875Ssteve.reinhardt@amd.comvoid
3885875Ssteve.reinhardt@amd.comAlphaDTB::regStats()
3895217Ssaidi@eecs.umich.edu{
3905875Ssteve.reinhardt@amd.com    read_hits
3917781SAli.Saidi@ARM.com        .name(name() + ".read_hits")
3927781SAli.Saidi@ARM.com        .desc("DTB read hits")
3937781SAli.Saidi@ARM.com        ;
3947781SAli.Saidi@ARM.com
3957781SAli.Saidi@ARM.com    read_misses
3967781SAli.Saidi@ARM.com        .name(name() + ".read_misses")
3977781SAli.Saidi@ARM.com        .desc("DTB read misses")
3987781SAli.Saidi@ARM.com        ;
3997781SAli.Saidi@ARM.com
4007781SAli.Saidi@ARM.com    read_acv
4017781SAli.Saidi@ARM.com        .name(name() + ".read_acv")
4027781SAli.Saidi@ARM.com        .desc("DTB read access violations")
4037781SAli.Saidi@ARM.com        ;
4047781SAli.Saidi@ARM.com
4057781SAli.Saidi@ARM.com    read_accesses
4067781SAli.Saidi@ARM.com        .name(name() + ".read_accesses")
4077781SAli.Saidi@ARM.com        .desc("DTB read accesses")
4087781SAli.Saidi@ARM.com        ;
4097781SAli.Saidi@ARM.com
4107781SAli.Saidi@ARM.com    write_hits
411180SN/A        .name(name() + ".write_hits")
412605SN/A        .desc("DTB write hits")
4131858SN/A        ;
4143520Sgblack@eecs.umich.edu
4155810Sgblack@eecs.umich.edu    write_misses
4162254SN/A        .name(name() + ".write_misses")
4176221Snate@binkert.org        .desc("DTB write misses")
4182680Sktlim@umich.edu        ;
4192254SN/A
4204947Snate@binkert.org    write_acv
4217823Ssteve.reinhardt@amd.com        .name(name() + ".write_acv")
422612SN/A        .desc("DTB write access violations")
4234192Sktlim@umich.edu        ;
4244192Sktlim@umich.edu
4254192Sktlim@umich.edu    write_accesses
4264192Sktlim@umich.edu        .name(name() + ".write_accesses")
4275476Snate@binkert.org        .desc("DTB write accesses")
4285476Snate@binkert.org        ;
4294192Sktlim@umich.edu
4305476Snate@binkert.org    hits
4314192Sktlim@umich.edu        .name(name() + ".hits")
4324192Sktlim@umich.edu        .desc("DTB hits")
4335476Snate@binkert.org        ;
4345476Snate@binkert.org
4354192Sktlim@umich.edu    misses
4365476Snate@binkert.org        .name(name() + ".misses")
4374192Sktlim@umich.edu        .desc("DTB misses")
438180SN/A        ;
439180SN/A
440180SN/A    acv
4411858SN/A        .name(name() + ".acv")
4425536Srstrong@hp.com        .desc("DTB access violations")
4435606Snate@binkert.org        ;
4441917SN/A
4451917SN/A    accesses
4461917SN/A        .name(name() + ".accesses")
4471917SN/A        .desc("DTB accesses")
4481917SN/A        ;
4496221Snate@binkert.org
4506221Snate@binkert.org    hits = read_hits + write_hits;
4512680Sktlim@umich.edu    misses = read_misses + write_misses;
4522680Sktlim@umich.edu    acv = read_acv + write_acv;
4531917SN/A    accesses = read_accesses + write_accesses;
4542254SN/A}
4557823Ssteve.reinhardt@amd.com
4561917SN/Avoid
4571917SN/AAlphaDTB::fault(MemReqPtr &req, uint64_t flags) const
4582SN/A{
459921SN/A    ExecContext *xc = req->xc;
460921SN/A    Addr vaddr = req->vaddr;
4614000Ssaidi@eecs.umich.edu    uint64_t *ipr = xc->regs.ipr;
4625647Sgblack@eecs.umich.edu
463921SN/A    // Set fault address and flags.  Even though we're modeling an
464921SN/A    // EV5, we use the EV6 technique of not latching fault registers
465921SN/A    // on VPTE loads (instead of locking the registers until IPR_VA is
466921SN/A    // read, like the EV5).  The EV6 approach is cleaner and seems to
467921SN/A    // work with EV5 PAL code, but not the other way around.
4684000Ssaidi@eecs.umich.edu    if (!xc->misspeculating()
4695647Sgblack@eecs.umich.edu        && !(req->flags & VPTE) && !(req->flags & NO_FAULT)) {
470921SN/A        // set VA register with faulting address
471921SN/A        ipr[AlphaISA::IPR_VA] = vaddr;
4722SN/A
4732SN/A        // set MM_STAT register flags
4741191SN/A        ipr[AlphaISA::IPR_MM_STAT] = (((OPCODE(xc->getInst()) & 0x3f) << 11)
4751191SN/A                               | ((RA(xc->getInst()) & 0x1f) << 6)
4761191SN/A                               | (flags & 0x3f));
4771191SN/A
4781191SN/A        // set VA_FORM register with faulting formatted address
4791191SN/A        ipr[AlphaISA::IPR_VA_FORM] =
4801191SN/A            ipr[AlphaISA::IPR_MVPTBR] | (VA_VPN(vaddr) << 3);
4811191SN/A    }
4821191SN/A}
4831191SN/A
4841191SN/AFault
4851191SN/AAlphaDTB::translate(MemReqPtr &req, bool write) const
4861191SN/A{
4871191SN/A    RegFile *regs = &req->xc->regs;
4881191SN/A    Addr pc = regs->pc;
4891191SN/A    InternalProcReg *ipr = regs->ipr;
4901191SN/A
4911191SN/A    AlphaISA::mode_type mode =
4921191SN/A        (AlphaISA::mode_type)DTB_CM_CM(ipr[AlphaISA::IPR_DTB_CM]);
4931191SN/A
4941191SN/A
4951191SN/A    /* @todo this should actually be in there but for whatever reason
4967823Ssteve.reinhardt@amd.com     * Its not working at present.
4977823Ssteve.reinhardt@amd.com     */
4981191SN/A    if (req->vaddr & (req->size - 1)) {
4991191SN/A        return Alignment_Fault;
5008707Sandreas.hansson@arm.com    }
5018707Sandreas.hansson@arm.com
5028707Sandreas.hansson@arm.com    if (PC_PAL(pc)) {
5038707Sandreas.hansson@arm.com        mode = (req->flags & ALTMODE) ?
5048707Sandreas.hansson@arm.com            (AlphaISA::mode_type)ALT_MODE_AM(ipr[AlphaISA::IPR_ALT_MODE])
5058707Sandreas.hansson@arm.com            : AlphaISA::mode_kernel;
5068707Sandreas.hansson@arm.com    }
5078707Sandreas.hansson@arm.com
5088707Sandreas.hansson@arm.com    if (req->flags & PHYSICAL) {
5098707Sandreas.hansson@arm.com        req->paddr = req->vaddr;
5108707Sandreas.hansson@arm.com    } else {
5118707Sandreas.hansson@arm.com        // verify that this is a good virtual address
5128707Sandreas.hansson@arm.com        if (!validVirtualAddress(req->vaddr)) {
5138707Sandreas.hansson@arm.com            fault(req, ((write ? MM_STAT_WR_MASK : 0) | MM_STAT_BAD_VA_MASK |
5148707Sandreas.hansson@arm.com                        MM_STAT_ACV_MASK));
5158707Sandreas.hansson@arm.com
5168707Sandreas.hansson@arm.com            if (write) { write_acv++; } else { read_acv++; }
5178707Sandreas.hansson@arm.com            return DTB_Fault_Fault;
5188707Sandreas.hansson@arm.com        }
5198707Sandreas.hansson@arm.com
5208707Sandreas.hansson@arm.com        // Check for "superpage" mapping
5218707Sandreas.hansson@arm.com#ifdef ALPHA_TLASER
5228707Sandreas.hansson@arm.com        if ((MCSR_SP(ipr[AlphaISA::IPR_MCSR]) & 2) &&
5238707Sandreas.hansson@arm.com               VA_SPACE_EV5(req->vaddr) == 2) {
5248707Sandreas.hansson@arm.com#else
5258707Sandreas.hansson@arm.com        if (VA_SPACE_EV6(req->vaddr) == 0x7e) {
5268707Sandreas.hansson@arm.com#endif
5278707Sandreas.hansson@arm.com
5288707Sandreas.hansson@arm.com            // only valid in kernel mode
5298707Sandreas.hansson@arm.com            if (DTB_CM_CM(ipr[AlphaISA::IPR_DTB_CM]) !=
5308711Sandreas.hansson@arm.com                AlphaISA::mode_kernel) {
5318707Sandreas.hansson@arm.com                fault(req, ((write ? MM_STAT_WR_MASK : 0) | MM_STAT_ACV_MASK));
5328707Sandreas.hansson@arm.com                if (write) { write_acv++; } else { read_acv++; }
533                return DTB_Acv_Fault;
534            }
535
536            req->paddr = req->vaddr & PA_IMPL_MASK;
537
538#ifndef ALPHA_TLASER
539            // sign extend the physical address properly
540            if (req->paddr & PA_UNCACHED_BIT_40)
541                req->paddr |= ULL(0xf0000000000);
542            else
543                req->paddr &= ULL(0xffffffffff);
544#endif
545
546        } else {
547            if (write)
548                write_accesses++;
549            else
550                read_accesses++;
551
552            // not a physical address: need to look up pte
553            AlphaISA::PTE *pte = lookup(VA_VPN(req->vaddr),
554                                 DTB_ASN_ASN(ipr[AlphaISA::IPR_DTB_ASN]));
555
556            if (!pte) {
557                // page fault
558                fault(req,
559                      (write ? MM_STAT_WR_MASK : 0) | MM_STAT_DTB_MISS_MASK);
560                if (write) { write_misses++; } else { read_misses++; }
561                return (req->flags & VPTE) ? Pdtb_Miss_Fault : Ndtb_Miss_Fault;
562            }
563
564            req->paddr = PA_PFN2PA(pte->ppn) | VA_POFS(req->vaddr);
565
566            if (write) {
567                if (!(pte->xwe & MODE2MASK(mode))) {
568                    // declare the instruction access fault
569                    fault(req, (MM_STAT_WR_MASK | MM_STAT_ACV_MASK |
570                                (pte->fonw ? MM_STAT_FONW_MASK : 0)));
571                    write_acv++;
572                    return DTB_Fault_Fault;
573                }
574                if (pte->fonw) {
575                    fault(req, MM_STAT_WR_MASK | MM_STAT_FONW_MASK);
576                    write_acv++;
577                    return DTB_Fault_Fault;
578                }
579            } else {
580                if (!(pte->xre & MODE2MASK(mode))) {
581                    fault(req, (MM_STAT_ACV_MASK |
582                                (pte->fonr ? MM_STAT_FONR_MASK : 0)));
583                    read_acv++;
584                    return DTB_Acv_Fault;
585                }
586                if (pte->fonr) {
587                    fault(req, MM_STAT_FONR_MASK);
588                    read_acv++;
589                    return DTB_Fault_Fault;
590                }
591            }
592        }
593
594        if (write)
595            write_hits++;
596        else
597            read_hits++;
598    }
599
600    // check that the physical address is ok (catch bad physical addresses)
601    if (req->paddr & ~PA_IMPL_MASK)
602        return Machine_Check_Fault;
603
604    checkCacheability(req);
605
606    return No_Fault;
607}
608
609AlphaISA::PTE &
610AlphaTLB::index(bool advance)
611{
612    AlphaISA::PTE *pte = &table[nlu];
613
614    if (advance)
615        nextnlu();
616
617    return *pte;
618}
619
620DEFINE_SIM_OBJECT_CLASS_NAME("AlphaTLB", AlphaTLB)
621
622BEGIN_DECLARE_SIM_OBJECT_PARAMS(AlphaITB)
623
624    Param<int> size;
625
626END_DECLARE_SIM_OBJECT_PARAMS(AlphaITB)
627
628BEGIN_INIT_SIM_OBJECT_PARAMS(AlphaITB)
629
630    INIT_PARAM_DFLT(size, "TLB size", 48)
631
632END_INIT_SIM_OBJECT_PARAMS(AlphaITB)
633
634
635CREATE_SIM_OBJECT(AlphaITB)
636{
637    return new AlphaITB(getInstanceName(), size);
638}
639
640REGISTER_SIM_OBJECT("AlphaITB", AlphaITB)
641
642BEGIN_DECLARE_SIM_OBJECT_PARAMS(AlphaDTB)
643
644    Param<int> size;
645
646END_DECLARE_SIM_OBJECT_PARAMS(AlphaDTB)
647
648BEGIN_INIT_SIM_OBJECT_PARAMS(AlphaDTB)
649
650    INIT_PARAM_DFLT(size, "TLB size", 64)
651
652END_INIT_SIM_OBJECT_PARAMS(AlphaDTB)
653
654
655CREATE_SIM_OBJECT(AlphaDTB)
656{
657    return new AlphaDTB(getInstanceName(), size);
658}
659
660REGISTER_SIM_OBJECT("AlphaDTB", AlphaDTB)
661
662