tlb.cc revision 6185:9925b3e83e06
12929Sktlim@umich.edu/*
211504Sandreas.sandberg@arm.com * Copyright (c) 2001-2005 The Regents of The University of Michigan
311504Sandreas.sandberg@arm.com * All rights reserved.
411504Sandreas.sandberg@arm.com *
511504Sandreas.sandberg@arm.com * Redistribution and use in source and binary forms, with or without
611504Sandreas.sandberg@arm.com * modification, are permitted provided that the following conditions are
711504Sandreas.sandberg@arm.com * met: redistributions of source code must retain the above copyright
811504Sandreas.sandberg@arm.com * notice, this list of conditions and the following disclaimer;
911504Sandreas.sandberg@arm.com * redistributions in binary form must reproduce the above copyright
1011504Sandreas.sandberg@arm.com * notice, this list of conditions and the following disclaimer in the
1111504Sandreas.sandberg@arm.com * documentation and/or other materials provided with the distribution;
1211504Sandreas.sandberg@arm.com * neither the name of the copyright holders nor the names of its
1311504Sandreas.sandberg@arm.com * contributors may be used to endorse or promote products derived from
1411504Sandreas.sandberg@arm.com * this software without specific prior written permission.
152932Sktlim@umich.edu *
162929Sktlim@umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
172929Sktlim@umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
182929Sktlim@umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
192929Sktlim@umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
202929Sktlim@umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
212929Sktlim@umich.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
222929Sktlim@umich.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
232929Sktlim@umich.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
242929Sktlim@umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
252929Sktlim@umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
262929Sktlim@umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
272929Sktlim@umich.edu *
282929Sktlim@umich.edu * Authors: Nathan Binkert
292929Sktlim@umich.edu *          Steve Reinhardt
302929Sktlim@umich.edu *          Andrew Schultz
312929Sktlim@umich.edu */
322929Sktlim@umich.edu
332929Sktlim@umich.edu#include <string>
342929Sktlim@umich.edu#include <vector>
352929Sktlim@umich.edu
362929Sktlim@umich.edu#include "arch/alpha/pagetable.hh"
372929Sktlim@umich.edu#include "arch/alpha/tlb.hh"
382929Sktlim@umich.edu#include "arch/alpha/faults.hh"
392929Sktlim@umich.edu#include "base/inifile.hh"
402932Sktlim@umich.edu#include "base/str.hh"
412932Sktlim@umich.edu#include "base/trace.hh"
422932Sktlim@umich.edu#include "cpu/thread_context.hh"
4311504Sandreas.sandberg@arm.com
442929Sktlim@umich.eduusing namespace std;
452929Sktlim@umich.edu
4611504Sandreas.sandberg@arm.comnamespace AlphaISA {
4711504Sandreas.sandberg@arm.com
4811504Sandreas.sandberg@arm.com///////////////////////////////////////////////////////////////////////
4911504Sandreas.sandberg@arm.com//
5011504Sandreas.sandberg@arm.com//  Alpha TLB
5111504Sandreas.sandberg@arm.com//
5211504Sandreas.sandberg@arm.com
532929Sktlim@umich.edu#ifdef DEBUG
542929Sktlim@umich.edubool uncacheBit39 = false;
552929Sktlim@umich.edubool uncacheBit40 = false;
568947Sandreas.hansson@arm.com#endif
578947Sandreas.hansson@arm.com
588947Sandreas.hansson@arm.com#define MODE2MASK(X) (1 << (X))
592929Sktlim@umich.edu
602929Sktlim@umich.eduTLB::TLB(const Params *p)
6111504Sandreas.sandberg@arm.com    : BaseTLB(p), size(p->size), nlu(0)
6211504Sandreas.sandberg@arm.com{
6311504Sandreas.sandberg@arm.com    table = new TlbEntry[size];
6411504Sandreas.sandberg@arm.com    memset(table, 0, sizeof(TlbEntry[size]));
6511504Sandreas.sandberg@arm.com    flushCache();
6611504Sandreas.sandberg@arm.com}
6711504Sandreas.sandberg@arm.com
682929Sktlim@umich.eduTLB::~TLB()
6911504Sandreas.sandberg@arm.com{
7011504Sandreas.sandberg@arm.com    if (table)
716007Ssteve.reinhardt@amd.com        delete [] table;
726007Ssteve.reinhardt@amd.com}
7311504Sandreas.sandberg@arm.com
742929Sktlim@umich.eduvoid
752929Sktlim@umich.eduTLB::regStats()
7611504Sandreas.sandberg@arm.com{
776007Ssteve.reinhardt@amd.com    fetch_hits
786007Ssteve.reinhardt@amd.com        .name(name() + ".fetch_hits")
799781Sandreas.hansson@arm.com        .desc("ITB hits");
806007Ssteve.reinhardt@amd.com    fetch_misses
8111504Sandreas.sandberg@arm.com        .name(name() + ".fetch_misses")
822929Sktlim@umich.edu        .desc("ITB misses");
832929Sktlim@umich.edu    fetch_acv
8411504Sandreas.sandberg@arm.com        .name(name() + ".fetch_acv")
8511504Sandreas.sandberg@arm.com        .desc("ITB acv");
8611504Sandreas.sandberg@arm.com    fetch_accesses
8711504Sandreas.sandberg@arm.com        .name(name() + ".fetch_accesses")
8811504Sandreas.sandberg@arm.com        .desc("ITB accesses");
896007Ssteve.reinhardt@amd.com
9011504Sandreas.sandberg@arm.com    fetch_accesses = fetch_hits + fetch_misses;
9111504Sandreas.sandberg@arm.com
9211504Sandreas.sandberg@arm.com    read_hits
9311504Sandreas.sandberg@arm.com        .name(name() + ".read_hits")
946007Ssteve.reinhardt@amd.com        .desc("DTB read hits")
9511504Sandreas.sandberg@arm.com        ;
9611504Sandreas.sandberg@arm.com
9711504Sandreas.sandberg@arm.com    read_misses
986007Ssteve.reinhardt@amd.com        .name(name() + ".read_misses")
992929Sktlim@umich.edu        .desc("DTB read misses")
1002929Sktlim@umich.edu        ;
1016007Ssteve.reinhardt@amd.com
1026007Ssteve.reinhardt@amd.com    read_acv
1032929Sktlim@umich.edu        .name(name() + ".read_acv")
1042929Sktlim@umich.edu        .desc("DTB read access violations")
1056007Ssteve.reinhardt@amd.com        ;
1062929Sktlim@umich.edu
1072929Sktlim@umich.edu    read_accesses
10811504Sandreas.sandberg@arm.com        .name(name() + ".read_accesses")
1098947Sandreas.hansson@arm.com        .desc("DTB read accesses")
11011504Sandreas.sandberg@arm.com        ;
11111504Sandreas.sandberg@arm.com
1128947Sandreas.hansson@arm.com    write_hits
11311504Sandreas.sandberg@arm.com        .name(name() + ".write_hits")
11411504Sandreas.sandberg@arm.com        .desc("DTB write hits")
1158947Sandreas.hansson@arm.com        ;
11611504Sandreas.sandberg@arm.com
11711504Sandreas.sandberg@arm.com    write_misses
11811504Sandreas.sandberg@arm.com        .name(name() + ".write_misses")
1198947Sandreas.hansson@arm.com        .desc("DTB write misses")
12011504Sandreas.sandberg@arm.com        ;
12111504Sandreas.sandberg@arm.com
12211504Sandreas.sandberg@arm.com    write_acv
12311504Sandreas.sandberg@arm.com        .name(name() + ".write_acv")
12411542Sandreas.sandberg@arm.com        .desc("DTB write access violations")
12511542Sandreas.sandberg@arm.com        ;
12611542Sandreas.sandberg@arm.com
12711542Sandreas.sandberg@arm.com    write_accesses
12811504Sandreas.sandberg@arm.com        .name(name() + ".write_accesses")
12911504Sandreas.sandberg@arm.com        .desc("DTB write accesses")
13011504Sandreas.sandberg@arm.com        ;
13111504Sandreas.sandberg@arm.com
13211542Sandreas.sandberg@arm.com    data_hits
13311504Sandreas.sandberg@arm.com        .name(name() + ".data_hits")
13411504Sandreas.sandberg@arm.com        .desc("DTB hits")
13511504Sandreas.sandberg@arm.com        ;
13611504Sandreas.sandberg@arm.com
13711504Sandreas.sandberg@arm.com    data_misses
13811504Sandreas.sandberg@arm.com        .name(name() + ".data_misses")
1392929Sktlim@umich.edu        .desc("DTB misses")
1402929Sktlim@umich.edu        ;
14111504Sandreas.sandberg@arm.com
1424937Sstever@gmail.com    data_acv
1432929Sktlim@umich.edu        .name(name() + ".data_acv")
14411504Sandreas.sandberg@arm.com        .desc("DTB access violations")
1452929Sktlim@umich.edu        ;
14611504Sandreas.sandberg@arm.com
14711504Sandreas.sandberg@arm.com    data_accesses
1482929Sktlim@umich.edu        .name(name() + ".data_accesses")
14911504Sandreas.sandberg@arm.com        .desc("DTB accesses")
15011504Sandreas.sandberg@arm.com        ;
1512929Sktlim@umich.edu
15211504Sandreas.sandberg@arm.com    data_hits = read_hits + write_hits;
15311504Sandreas.sandberg@arm.com    data_misses = read_misses + write_misses;
15411504Sandreas.sandberg@arm.com    data_acv = read_acv + write_acv;
15511504Sandreas.sandberg@arm.com    data_accesses = read_accesses + write_accesses;
15611504Sandreas.sandberg@arm.com}
15711504Sandreas.sandberg@arm.com
15811504Sandreas.sandberg@arm.com// look up an entry in the TLB
15911504Sandreas.sandberg@arm.comTlbEntry *
16011504Sandreas.sandberg@arm.comTLB::lookup(Addr vpn, uint8_t asn)
16111504Sandreas.sandberg@arm.com{
16211504Sandreas.sandberg@arm.com    // assume not found...
16311504Sandreas.sandberg@arm.com    TlbEntry *retval = NULL;
16411542Sandreas.sandberg@arm.com
16511504Sandreas.sandberg@arm.com    if (EntryCache[0]) {
16611504Sandreas.sandberg@arm.com        if (vpn == EntryCache[0]->tag &&
16711504Sandreas.sandberg@arm.com            (EntryCache[0]->asma || EntryCache[0]->asn == asn))
16811504Sandreas.sandberg@arm.com            retval = EntryCache[0];
16911504Sandreas.sandberg@arm.com        else if (EntryCache[1]) {
17011504Sandreas.sandberg@arm.com            if (vpn == EntryCache[1]->tag &&
17111504Sandreas.sandberg@arm.com                (EntryCache[1]->asma || EntryCache[1]->asn == asn))
17211542Sandreas.sandberg@arm.com                retval = EntryCache[1];
17311504Sandreas.sandberg@arm.com            else if (EntryCache[2] && vpn == EntryCache[2]->tag &&
17411504Sandreas.sandberg@arm.com                     (EntryCache[2]->asma || EntryCache[2]->asn == asn))
17511504Sandreas.sandberg@arm.com                retval = EntryCache[2];
17611504Sandreas.sandberg@arm.com        }
17711504Sandreas.sandberg@arm.com    }
17811504Sandreas.sandberg@arm.com
17911504Sandreas.sandberg@arm.com    if (retval == NULL) {
1802929Sktlim@umich.edu        PageTable::const_iterator i = lookupTable.find(vpn);
1812929Sktlim@umich.edu        if (i != lookupTable.end()) {
1822929Sktlim@umich.edu            while (i->first == vpn) {
18311504Sandreas.sandberg@arm.com                int index = i->second;
1842929Sktlim@umich.edu                TlbEntry *entry = &table[index];
1852929Sktlim@umich.edu                assert(entry->valid);
1862929Sktlim@umich.edu                if (vpn == entry->tag && (entry->asma || entry->asn == asn)) {
1872929Sktlim@umich.edu                    retval = updateCache(entry);
18811504Sandreas.sandberg@arm.com                    break;
1892997Sstever@eecs.umich.edu                }
1902929Sktlim@umich.edu
19111504Sandreas.sandberg@arm.com                ++i;
19211504Sandreas.sandberg@arm.com            }
19311504Sandreas.sandberg@arm.com        }
1942929Sktlim@umich.edu    }
19511504Sandreas.sandberg@arm.com
19611504Sandreas.sandberg@arm.com    DPRINTF(TLB, "lookup %#x, asn %#x -> %s ppn %#x\n", vpn, (int)asn,
1972929Sktlim@umich.edu            retval ? "hit" : "miss", retval ? retval->ppn : 0);
19811504Sandreas.sandberg@arm.com    return retval;
19911504Sandreas.sandberg@arm.com}
2002997Sstever@eecs.umich.edu
20111504Sandreas.sandberg@arm.comFault
20211504Sandreas.sandberg@arm.comTLB::checkCacheability(RequestPtr &req, bool itb)
20311504Sandreas.sandberg@arm.com{
20411504Sandreas.sandberg@arm.com    // in Alpha, cacheability is controlled by upper-level bits of the
2052997Sstever@eecs.umich.edu    // physical address
20611504Sandreas.sandberg@arm.com
20711504Sandreas.sandberg@arm.com    /*
20811504Sandreas.sandberg@arm.com     * We support having the uncacheable bit in either bit 39 or bit
20911504Sandreas.sandberg@arm.com     * 40.  The Turbolaser platform (and EV5) support having the bit
21011504Sandreas.sandberg@arm.com     * in 39, but Tsunami (which Linux assumes uses an EV6) generates
21111504Sandreas.sandberg@arm.com     * accesses with the bit in 40.  So we must check for both, but we
2122929Sktlim@umich.edu     * have debug flags to catch a weird case where both are used,
2132997Sstever@eecs.umich.edu     * which shouldn't happen.
2148120Sgblack@eecs.umich.edu     */
21511504Sandreas.sandberg@arm.com
2162997Sstever@eecs.umich.edu
21711504Sandreas.sandberg@arm.com    if (req->getPaddr() & PAddrUncachedBit43) {
2182929Sktlim@umich.edu        // IPR memory space not implemented
2192997Sstever@eecs.umich.edu        if (PAddrIprSpace(req->getPaddr())) {
2202929Sktlim@umich.edu            return new UnimpFault("IPR memory space not implemented!");
22111504Sandreas.sandberg@arm.com        } else {
22211504Sandreas.sandberg@arm.com            // mark request as uncacheable
2232929Sktlim@umich.edu            req->setFlags(Request::UNCACHEABLE);
22411504Sandreas.sandberg@arm.com
22511504Sandreas.sandberg@arm.com            // Clear bits 42:35 of the physical address (10-2 in
2263691Shsul@eecs.umich.edu            // Tsunami manual)
22711504Sandreas.sandberg@arm.com            req->setPaddr(req->getPaddr() & PAddrUncachedMask);
2283005Sstever@eecs.umich.edu        }
22911504Sandreas.sandberg@arm.com        // We shouldn't be able to read from an uncachable address in Alpha as
23011105Spower.jg@gmail.com        // we don't have a ROM and we don't want to try to fetch from a device
23111504Sandreas.sandberg@arm.com        // register as we destroy any data that is clear-on-read.
23211504Sandreas.sandberg@arm.com        if (req->isUncacheable() && itb)
23311504Sandreas.sandberg@arm.com            return new UnimpFault("CPU trying to fetch from uncached I/O");
2346166Ssteve.reinhardt@amd.com
23511504Sandreas.sandberg@arm.com    }
23611504Sandreas.sandberg@arm.com    return NoFault;
23711504Sandreas.sandberg@arm.com}
23811504Sandreas.sandberg@arm.com
23911504Sandreas.sandberg@arm.com
24011504Sandreas.sandberg@arm.com// insert a new TLB entry
24111504Sandreas.sandberg@arm.comvoid
24211504Sandreas.sandberg@arm.comTLB::insert(Addr addr, TlbEntry &entry)
24311504Sandreas.sandberg@arm.com{
24411504Sandreas.sandberg@arm.com    flushCache();
24511504Sandreas.sandberg@arm.com    VAddr vaddr = addr;
24611504Sandreas.sandberg@arm.com    if (table[nlu].valid) {
24711504Sandreas.sandberg@arm.com        Addr oldvpn = table[nlu].tag;
24811504Sandreas.sandberg@arm.com        PageTable::iterator i = lookupTable.find(oldvpn);
249
250        if (i == lookupTable.end())
251            panic("TLB entry not found in lookupTable");
252
253        int index;
254        while ((index = i->second) != nlu) {
255            if (table[index].tag != oldvpn)
256                panic("TLB entry not found in lookupTable");
257
258            ++i;
259        }
260
261        DPRINTF(TLB, "remove @%d: %#x -> %#x\n", nlu, oldvpn, table[nlu].ppn);
262
263        lookupTable.erase(i);
264    }
265
266    DPRINTF(TLB, "insert @%d: %#x -> %#x\n", nlu, vaddr.vpn(), entry.ppn);
267
268    table[nlu] = entry;
269    table[nlu].tag = vaddr.vpn();
270    table[nlu].valid = true;
271
272    lookupTable.insert(make_pair(vaddr.vpn(), nlu));
273    nextnlu();
274}
275
276void
277TLB::flushAll()
278{
279    DPRINTF(TLB, "flushAll\n");
280    memset(table, 0, sizeof(TlbEntry[size]));
281    flushCache();
282    lookupTable.clear();
283    nlu = 0;
284}
285
286void
287TLB::flushProcesses()
288{
289    flushCache();
290    PageTable::iterator i = lookupTable.begin();
291    PageTable::iterator end = lookupTable.end();
292    while (i != end) {
293        int index = i->second;
294        TlbEntry *entry = &table[index];
295        assert(entry->valid);
296
297        // we can't increment i after we erase it, so save a copy and
298        // increment it to get the next entry now
299        PageTable::iterator cur = i;
300        ++i;
301
302        if (!entry->asma) {
303            DPRINTF(TLB, "flush @%d: %#x -> %#x\n", index,
304                    entry->tag, entry->ppn);
305            entry->valid = false;
306            lookupTable.erase(cur);
307        }
308    }
309}
310
311void
312TLB::flushAddr(Addr addr, uint8_t asn)
313{
314    flushCache();
315    VAddr vaddr = addr;
316
317    PageTable::iterator i = lookupTable.find(vaddr.vpn());
318    if (i == lookupTable.end())
319        return;
320
321    while (i != lookupTable.end() && i->first == vaddr.vpn()) {
322        int index = i->second;
323        TlbEntry *entry = &table[index];
324        assert(entry->valid);
325
326        if (vaddr.vpn() == entry->tag && (entry->asma || entry->asn == asn)) {
327            DPRINTF(TLB, "flushaddr @%d: %#x -> %#x\n", index, vaddr.vpn(),
328                    entry->ppn);
329
330            // invalidate this entry
331            entry->valid = false;
332
333            lookupTable.erase(i++);
334        } else {
335            ++i;
336        }
337    }
338}
339
340
341void
342TLB::serialize(ostream &os)
343{
344    SERIALIZE_SCALAR(size);
345    SERIALIZE_SCALAR(nlu);
346
347    for (int i = 0; i < size; i++) {
348        nameOut(os, csprintf("%s.Entry%d", name(), i));
349        table[i].serialize(os);
350    }
351}
352
353void
354TLB::unserialize(Checkpoint *cp, const string &section)
355{
356    UNSERIALIZE_SCALAR(size);
357    UNSERIALIZE_SCALAR(nlu);
358
359    for (int i = 0; i < size; i++) {
360        table[i].unserialize(cp, csprintf("%s.Entry%d", section, i));
361        if (table[i].valid) {
362            lookupTable.insert(make_pair(table[i].tag, i));
363        }
364    }
365}
366
367Fault
368TLB::translateInst(RequestPtr req, ThreadContext *tc)
369{
370    //If this is a pal pc, then set PHYSICAL
371    if (FULL_SYSTEM && PcPAL(req->getPC()))
372        req->setFlags(Request::PHYSICAL);
373
374    if (PcPAL(req->getPC())) {
375        // strip off PAL PC marker (lsb is 1)
376        req->setPaddr((req->getVaddr() & ~3) & PAddrImplMask);
377        fetch_hits++;
378        return NoFault;
379    }
380
381    if (req->getFlags() & Request::PHYSICAL) {
382        req->setPaddr(req->getVaddr());
383    } else {
384        // verify that this is a good virtual address
385        if (!validVirtualAddress(req->getVaddr())) {
386            fetch_acv++;
387            return new ItbAcvFault(req->getVaddr());
388        }
389
390
391        // VA<42:41> == 2, VA<39:13> maps directly to PA<39:13> for EV5
392        // VA<47:41> == 0x7e, VA<40:13> maps directly to PA<40:13> for EV6
393        if (VAddrSpaceEV6(req->getVaddr()) == 0x7e) {
394            // only valid in kernel mode
395            if (ICM_CM(tc->readMiscRegNoEffect(IPR_ICM)) !=
396                mode_kernel) {
397                fetch_acv++;
398                return new ItbAcvFault(req->getVaddr());
399            }
400
401            req->setPaddr(req->getVaddr() & PAddrImplMask);
402
403            // sign extend the physical address properly
404            if (req->getPaddr() & PAddrUncachedBit40)
405                req->setPaddr(req->getPaddr() | ULL(0xf0000000000));
406            else
407                req->setPaddr(req->getPaddr() & ULL(0xffffffffff));
408        } else {
409            // not a physical address: need to look up pte
410            int asn = DTB_ASN_ASN(tc->readMiscRegNoEffect(IPR_DTB_ASN));
411            TlbEntry *entry = lookup(VAddr(req->getVaddr()).vpn(),
412                              asn);
413
414            if (!entry) {
415                fetch_misses++;
416                return new ItbPageFault(req->getVaddr());
417            }
418
419            req->setPaddr((entry->ppn << PageShift) +
420                          (VAddr(req->getVaddr()).offset()
421                           & ~3));
422
423            // check permissions for this access
424            if (!(entry->xre &
425                  (1 << ICM_CM(tc->readMiscRegNoEffect(IPR_ICM))))) {
426                // instruction access fault
427                fetch_acv++;
428                return new ItbAcvFault(req->getVaddr());
429            }
430
431            fetch_hits++;
432        }
433    }
434
435    // check that the physical address is ok (catch bad physical addresses)
436    if (req->getPaddr() & ~PAddrImplMask)
437        return genMachineCheckFault();
438
439    return checkCacheability(req, true);
440
441}
442
443Fault
444TLB::translateData(RequestPtr req, ThreadContext *tc, bool write)
445{
446    Addr pc = tc->readPC();
447
448    mode_type mode =
449        (mode_type)DTB_CM_CM(tc->readMiscRegNoEffect(IPR_DTB_CM));
450
451    /**
452     * Check for alignment faults
453     */
454    if (req->getVaddr() & (req->getSize() - 1)) {
455        DPRINTF(TLB, "Alignment Fault on %#x, size = %d\n", req->getVaddr(),
456                req->getSize());
457        uint64_t flags = write ? MM_STAT_WR_MASK : 0;
458        return new DtbAlignmentFault(req->getVaddr(), req->getFlags(), flags);
459    }
460
461    if (PcPAL(pc)) {
462        mode = (req->getFlags() & Request::ALTMODE) ?
463            (mode_type)ALT_MODE_AM(
464                tc->readMiscRegNoEffect(IPR_ALT_MODE))
465            : mode_kernel;
466    }
467
468    if (req->getFlags() & Request::PHYSICAL) {
469        req->setPaddr(req->getVaddr());
470    } else {
471        // verify that this is a good virtual address
472        if (!validVirtualAddress(req->getVaddr())) {
473            if (write) { write_acv++; } else { read_acv++; }
474            uint64_t flags = (write ? MM_STAT_WR_MASK : 0) |
475                MM_STAT_BAD_VA_MASK |
476                MM_STAT_ACV_MASK;
477            return new DtbPageFault(req->getVaddr(), req->getFlags(), flags);
478        }
479
480        // Check for "superpage" mapping
481        if (VAddrSpaceEV6(req->getVaddr()) == 0x7e) {
482            // only valid in kernel mode
483            if (DTB_CM_CM(tc->readMiscRegNoEffect(IPR_DTB_CM)) !=
484                mode_kernel) {
485                if (write) { write_acv++; } else { read_acv++; }
486                uint64_t flags = ((write ? MM_STAT_WR_MASK : 0) |
487                                  MM_STAT_ACV_MASK);
488
489                return new DtbAcvFault(req->getVaddr(), req->getFlags(),
490                                       flags);
491            }
492
493            req->setPaddr(req->getVaddr() & PAddrImplMask);
494
495            // sign extend the physical address properly
496            if (req->getPaddr() & PAddrUncachedBit40)
497                req->setPaddr(req->getPaddr() | ULL(0xf0000000000));
498            else
499                req->setPaddr(req->getPaddr() & ULL(0xffffffffff));
500        } else {
501            if (write)
502                write_accesses++;
503            else
504                read_accesses++;
505
506            int asn = DTB_ASN_ASN(tc->readMiscRegNoEffect(IPR_DTB_ASN));
507
508            // not a physical address: need to look up pte
509            TlbEntry *entry = lookup(VAddr(req->getVaddr()).vpn(), asn);
510
511            if (!entry) {
512                // page fault
513                if (write) { write_misses++; } else { read_misses++; }
514                uint64_t flags = (write ? MM_STAT_WR_MASK : 0) |
515                    MM_STAT_DTB_MISS_MASK;
516                return (req->getFlags() & Request::VPTE) ?
517                    (Fault)(new PDtbMissFault(req->getVaddr(), req->getFlags(),
518                                              flags)) :
519                    (Fault)(new NDtbMissFault(req->getVaddr(), req->getFlags(),
520                                              flags));
521            }
522
523            req->setPaddr((entry->ppn << PageShift) +
524                          VAddr(req->getVaddr()).offset());
525
526            if (write) {
527                if (!(entry->xwe & MODE2MASK(mode))) {
528                    // declare the instruction access fault
529                    write_acv++;
530                    uint64_t flags = MM_STAT_WR_MASK |
531                        MM_STAT_ACV_MASK |
532                        (entry->fonw ? MM_STAT_FONW_MASK : 0);
533                    return new DtbPageFault(req->getVaddr(), req->getFlags(),
534                                            flags);
535                }
536                if (entry->fonw) {
537                    write_acv++;
538                    uint64_t flags = MM_STAT_WR_MASK | MM_STAT_FONW_MASK;
539                    return new DtbPageFault(req->getVaddr(), req->getFlags(),
540                                            flags);
541                }
542            } else {
543                if (!(entry->xre & MODE2MASK(mode))) {
544                    read_acv++;
545                    uint64_t flags = MM_STAT_ACV_MASK |
546                        (entry->fonr ? MM_STAT_FONR_MASK : 0);
547                    return new DtbAcvFault(req->getVaddr(), req->getFlags(),
548                                           flags);
549                }
550                if (entry->fonr) {
551                    read_acv++;
552                    uint64_t flags = MM_STAT_FONR_MASK;
553                    return new DtbPageFault(req->getVaddr(), req->getFlags(),
554                                            flags);
555                }
556            }
557        }
558
559        if (write)
560            write_hits++;
561        else
562            read_hits++;
563    }
564
565    // check that the physical address is ok (catch bad physical addresses)
566    if (req->getPaddr() & ~PAddrImplMask)
567        return genMachineCheckFault();
568
569    return checkCacheability(req);
570}
571
572TlbEntry &
573TLB::index(bool advance)
574{
575    TlbEntry *entry = &table[nlu];
576
577    if (advance)
578        nextnlu();
579
580    return *entry;
581}
582
583Fault
584TLB::translateAtomic(RequestPtr req, ThreadContext *tc, Mode mode)
585{
586    if (mode == Execute)
587        return translateInst(req, tc);
588    else
589        return translateData(req, tc, mode == Write);
590}
591
592void
593TLB::translateTiming(RequestPtr req, ThreadContext *tc,
594        Translation *translation, Mode mode)
595{
596    assert(translation);
597    translation->finish(translateAtomic(req, tc, mode), req, tc, mode);
598}
599
600/* end namespace AlphaISA */ }
601
602AlphaISA::TLB *
603AlphaTLBParams::create()
604{
605    return new AlphaISA::TLB(this);
606}
607