tlb.cc revision 860
12810SN/A/*
211893Snikos.nikoleris@arm.com * Copyright (c) 2003 The Regents of The University of Michigan
39796Sprakash.ramrakhyani@arm.com * All rights reserved.
49796Sprakash.ramrakhyani@arm.com *
59796Sprakash.ramrakhyani@arm.com * Redistribution and use in source and binary forms, with or without
69796Sprakash.ramrakhyani@arm.com * modification, are permitted provided that the following conditions are
79796Sprakash.ramrakhyani@arm.com * met: redistributions of source code must retain the above copyright
89796Sprakash.ramrakhyani@arm.com * notice, this list of conditions and the following disclaimer;
99796Sprakash.ramrakhyani@arm.com * redistributions in binary form must reproduce the above copyright
109796Sprakash.ramrakhyani@arm.com * notice, this list of conditions and the following disclaimer in the
119796Sprakash.ramrakhyani@arm.com * documentation and/or other materials provided with the distribution;
129796Sprakash.ramrakhyani@arm.com * neither the name of the copyright holders nor the names of its
139796Sprakash.ramrakhyani@arm.com * contributors may be used to endorse or promote products derived from
142810SN/A * this software without specific prior written permission.
152810SN/A *
162810SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
172810SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
182810SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
192810SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
202810SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
212810SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
222810SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
232810SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
242810SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
252810SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
262810SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
272810SN/A */
282810SN/A
292810SN/A#include <sstream>
302810SN/A#include <string>
312810SN/A#include <vector>
322810SN/A
332810SN/A#include "base/inifile.hh"
342810SN/A#include "base/str.hh"
352810SN/A#include "base/trace.hh"
362810SN/A#include "cpu/exec_context.hh"
372810SN/A#include "sim/builder.hh"
382810SN/A#include "targetarch/alpha_memory.hh"
392810SN/A#include "targetarch/ev5.hh"
402810SN/A
412810SN/Ausing namespace std;
422810SN/A
432810SN/A///////////////////////////////////////////////////////////////////////
442810SN/A//
452810SN/A//  Alpha TLB
462810SN/A//
472810SN/A#ifdef DEBUG
482810SN/Abool uncacheBit39 = false;
4911486Snikos.nikoleris@arm.combool uncacheBit40 = false;
5011486Snikos.nikoleris@arm.com#endif
518229Snate@binkert.org
525338Sstever@gmail.comAlphaTLB::AlphaTLB(const string &name, int s)
532810SN/A    : SimObject(name), size(s), nlu(0)
542810SN/A{
552810SN/A    table = new AlphaISA::PTE[size];
562810SN/A    memset(table, 0, sizeof(AlphaISA::PTE[size]));
579796Sprakash.ramrakhyani@arm.com}
5811893Snikos.nikoleris@arm.com
5911893Snikos.nikoleris@arm.comAlphaTLB::~AlphaTLB()
6011722Ssophiane.senni@gmail.com{
6111722Ssophiane.senni@gmail.com    if (table)
6211722Ssophiane.senni@gmail.com        delete [] table;
6311722Ssophiane.senni@gmail.com}
6412513Sodanrc@yahoo.com.br
6512513Sodanrc@yahoo.com.br// look up an entry in the TLB
6612629Sodanrc@yahoo.com.brAlphaISA::PTE *
6712629Sodanrc@yahoo.com.brAlphaTLB::lookup(Addr vpn, uint8_t asn) const
689796Sprakash.ramrakhyani@arm.com{
699796Sprakash.ramrakhyani@arm.com    DPRINTF(TLB, "lookup %#x\n", vpn);
709796Sprakash.ramrakhyani@arm.com
712810SN/A    PageTable::const_iterator i = lookupTable.find(vpn);
722810SN/A    if (i == lookupTable.end())
732810SN/A        return NULL;
7410360Sandreas.hansson@arm.com
752810SN/A    while (i->first == vpn) {
762810SN/A        int index = i->second;
772810SN/A        AlphaISA::PTE *pte = &table[index];
782810SN/A        assert(pte->valid);
7912636Sodanrc@yahoo.com.br        if (vpn == pte->tag && (pte->asma || pte->asn == asn))
8012636Sodanrc@yahoo.com.br            return pte;
8112636Sodanrc@yahoo.com.br
8212636Sodanrc@yahoo.com.br        ++i;
8312636Sodanrc@yahoo.com.br    }
8412636Sodanrc@yahoo.com.br
8512636Sodanrc@yahoo.com.br    // not found...
8612636Sodanrc@yahoo.com.br    return NULL;
8712636Sodanrc@yahoo.com.br}
8812636Sodanrc@yahoo.com.br
8912636Sodanrc@yahoo.com.br
9012636Sodanrc@yahoo.com.brvoid
9112636Sodanrc@yahoo.com.brAlphaTLB::checkCacheability(MemReqPtr &req)
9212636Sodanrc@yahoo.com.br{
9312636Sodanrc@yahoo.com.br    // in Alpha, cacheability is controlled by upper-level bits of the
9412636Sodanrc@yahoo.com.br    // physical address
9512636Sodanrc@yahoo.com.br
9612636Sodanrc@yahoo.com.br    /*
9712636Sodanrc@yahoo.com.br     * We support having the uncacheable bit in either bit 39 or bit 40.
9812636Sodanrc@yahoo.com.br     * The Turbolaser platform (and EV5) support having the bit in 39, but
9912636Sodanrc@yahoo.com.br     * Tsunami (which Linux assumes uses an EV6) generates accesses with
10012636Sodanrc@yahoo.com.br     * the bit in 40.  So we must check for both, but we have debug flags
10112636Sodanrc@yahoo.com.br     * to catch a weird case where both are used, which shouldn't happen.
10212636Sodanrc@yahoo.com.br     */
10312636Sodanrc@yahoo.com.br
10412636Sodanrc@yahoo.com.br    if (req->paddr & PA_UNCACHED_BIT_40 ||
10512636Sodanrc@yahoo.com.br        req->paddr & PA_UNCACHED_BIT_39) {
10612636Sodanrc@yahoo.com.br
10712636Sodanrc@yahoo.com.br#ifdef DEBUG
10812636Sodanrc@yahoo.com.br        if (req->paddr & PA_UNCACHED_BIT_40) {
10912636Sodanrc@yahoo.com.br            if(uncacheBit39)
11012636Sodanrc@yahoo.com.br                panic("Bit 40 access follows bit 39 access, PA=%x\n",
11112636Sodanrc@yahoo.com.br                      req->paddr);
11212636Sodanrc@yahoo.com.br
11312636Sodanrc@yahoo.com.br            uncacheBit40 = true;
11412636Sodanrc@yahoo.com.br        } else if (req->paddr & PA_UNCACHED_BIT_39) {
11512636Sodanrc@yahoo.com.br            if(uncacheBit40)
11612636Sodanrc@yahoo.com.br                panic("Bit 39 acceess follows bit 40 access, PA=%x\n",
11712636Sodanrc@yahoo.com.br                      req->paddr);
11812636Sodanrc@yahoo.com.br
11912636Sodanrc@yahoo.com.br            uncacheBit39 = true;
12012636Sodanrc@yahoo.com.br        }
12112636Sodanrc@yahoo.com.br#endif
12212636Sodanrc@yahoo.com.br
12312636Sodanrc@yahoo.com.br        // IPR memory space not implemented
12412636Sodanrc@yahoo.com.br        if (PA_IPR_SPACE(req->paddr))
12512636Sodanrc@yahoo.com.br            if (!req->xc->misspeculating())
12612636Sodanrc@yahoo.com.br                panic("IPR memory space not implemented! PA=%x\n",
1279796Sprakash.ramrakhyani@arm.com                      req->paddr);
1282810SN/A
12911522Sstephan.diestelhorst@arm.com        // mark request as uncacheable
13011522Sstephan.diestelhorst@arm.com        req->flags |= UNCACHEABLE;
1312810SN/A    }
13211522Sstephan.diestelhorst@arm.com}
1332810SN/A
1342810SN/A
1359796Sprakash.ramrakhyani@arm.com// insert a new TLB entry
1362810SN/Avoid
1372810SN/AAlphaTLB::insert(Addr vaddr, AlphaISA::PTE &pte)
1382810SN/A{
1392810SN/A    if (table[nlu].valid) {
1402810SN/A        Addr oldvpn = table[nlu].tag;
1419796Sprakash.ramrakhyani@arm.com        PageTable::iterator i = lookupTable.find(oldvpn);
1422810SN/A
1432810SN/A        if (i == lookupTable.end())
1442810SN/A            panic("TLB entry not found in lookupTable");
1452810SN/A
1469796Sprakash.ramrakhyani@arm.com        int index;
1472810SN/A        while ((index = i->second) != nlu) {
1482810SN/A            if (table[index].tag != oldvpn)
1492810SN/A                panic("TLB entry not found in lookupTable");
1502810SN/A
1519796Sprakash.ramrakhyani@arm.com            ++i;
1522810SN/A        }
1532810SN/A
1542810SN/A        DPRINTF(TLB, "remove @%d: %#x -> %#x\n", nlu, oldvpn, table[nlu].ppn);
1552810SN/A
1569796Sprakash.ramrakhyani@arm.com        lookupTable.erase(i);
1572810SN/A    }
1582810SN/A
1592810SN/A    Addr vpn = VA_VPN(vaddr);
1602810SN/A    DPRINTF(TLB, "insert @%d: %#x -> %#x\n", nlu, vpn, pte.ppn);
1612810SN/A
1622810SN/A    table[nlu] = pte;
1639796Sprakash.ramrakhyani@arm.com    table[nlu].tag = vpn;
1642810SN/A    table[nlu].valid = true;
1652810SN/A
1662810SN/A    lookupTable.insert(make_pair(vpn, nlu));
1676978SLisa.Hsu@amd.com    nextnlu();
1688833Sdam.sunwoo@arm.com}
1699796Sprakash.ramrakhyani@arm.com
1708833Sdam.sunwoo@arm.comvoid
1716978SLisa.Hsu@amd.comAlphaTLB::flushAll()
1726978SLisa.Hsu@amd.com{
1738833Sdam.sunwoo@arm.com    memset(table, 0, sizeof(AlphaISA::PTE[size]));
1748833Sdam.sunwoo@arm.com    lookupTable.clear();
1758833Sdam.sunwoo@arm.com    nlu = 0;
1766978SLisa.Hsu@amd.com}
1776978SLisa.Hsu@amd.com
1789796Sprakash.ramrakhyani@arm.comvoid
1796978SLisa.Hsu@amd.comAlphaTLB::flushProcesses()
1808833Sdam.sunwoo@arm.com{
1816978SLisa.Hsu@amd.com    PageTable::iterator i = lookupTable.begin();
1828833Sdam.sunwoo@arm.com    PageTable::iterator end = lookupTable.end();
1838833Sdam.sunwoo@arm.com    while (i != end) {
1848833Sdam.sunwoo@arm.com        int index = i->second;
1856978SLisa.Hsu@amd.com        AlphaISA::PTE *pte = &table[index];
1866978SLisa.Hsu@amd.com        assert(pte->valid);
1876978SLisa.Hsu@amd.com
18810024Sdam.sunwoo@arm.com        if (!pte->asma) {
18910024Sdam.sunwoo@arm.com            DPRINTF(TLB, "flush @%d: %#x -> %#x\n", index, pte->tag, pte->ppn);
19010024Sdam.sunwoo@arm.com            pte->valid = false;
19110024Sdam.sunwoo@arm.com            lookupTable.erase(i);
19210024Sdam.sunwoo@arm.com        }
19310024Sdam.sunwoo@arm.com
19410024Sdam.sunwoo@arm.com        ++i;
19510024Sdam.sunwoo@arm.com    }
19610024Sdam.sunwoo@arm.com}
19710024Sdam.sunwoo@arm.com
19810024Sdam.sunwoo@arm.comvoid
19910024Sdam.sunwoo@arm.comAlphaTLB::flushAddr(Addr vaddr, uint8_t asn)
20010024Sdam.sunwoo@arm.com{
20110024Sdam.sunwoo@arm.com    Addr vpn = VA_VPN(vaddr);
20210024Sdam.sunwoo@arm.com
20310024Sdam.sunwoo@arm.com    PageTable::iterator i = lookupTable.find(vpn);
20410024Sdam.sunwoo@arm.com    if (i == lookupTable.end())
20510024Sdam.sunwoo@arm.com        return;
20610024Sdam.sunwoo@arm.com
20710024Sdam.sunwoo@arm.com    while (i->first == vpn) {
20810024Sdam.sunwoo@arm.com        int index = i->second;
20910024Sdam.sunwoo@arm.com        AlphaISA::PTE *pte = &table[index];
21010025Stimothy.jones@arm.com        assert(pte->valid);
21110025Stimothy.jones@arm.com
21210025Stimothy.jones@arm.com        if (vpn == pte->tag && (pte->asma || pte->asn == asn)) {
21310025Stimothy.jones@arm.com            DPRINTF(TLB, "flushaddr @%d: %#x -> %#x\n", index, vpn, pte->ppn);
21410025Stimothy.jones@arm.com
21510025Stimothy.jones@arm.com            // invalidate this entry
21610025Stimothy.jones@arm.com            pte->valid = false;
21710025Stimothy.jones@arm.com
21810025Stimothy.jones@arm.com            lookupTable.erase(i);
21910025Stimothy.jones@arm.com        }
22010024Sdam.sunwoo@arm.com
2212810SN/A        ++i;
2222810SN/A    }
223}
224
225
226void
227AlphaTLB::serialize(ostream &os)
228{
229    SERIALIZE_SCALAR(size);
230    SERIALIZE_SCALAR(nlu);
231
232    for (int i = 0; i < size; i++) {
233        nameOut(os, csprintf("%s.PTE%d", name(), i));
234        table[i].serialize(os);
235    }
236}
237
238void
239AlphaTLB::unserialize(Checkpoint *cp, const string &section)
240{
241    UNSERIALIZE_SCALAR(size);
242    UNSERIALIZE_SCALAR(nlu);
243
244    for (int i = 0; i < size; i++) {
245        table[i].unserialize(cp, csprintf("%s.PTE%d", section, i));
246        if (table[i].valid) {
247            lookupTable.insert(make_pair(table[i].tag, i));
248        }
249    }
250}
251
252
253///////////////////////////////////////////////////////////////////////
254//
255//  Alpha ITB
256//
257AlphaITB::AlphaITB(const std::string &name, int size)
258    : AlphaTLB(name, size)
259{}
260
261
262void
263AlphaITB::regStats()
264{
265    hits
266        .name(name() + ".hits")
267        .desc("ITB hits");
268    misses
269        .name(name() + ".misses")
270        .desc("ITB misses");
271    acv
272        .name(name() + ".acv")
273        .desc("ITB acv");
274    accesses
275        .name(name() + ".accesses")
276        .desc("ITB accesses");
277
278    accesses = hits + misses;
279}
280
281void
282AlphaITB::fault(Addr pc, ExecContext *xc) const
283{
284    uint64_t *ipr = xc->regs.ipr;
285
286    if (!xc->misspeculating()) {
287        ipr[AlphaISA::IPR_ITB_TAG] = pc;
288        ipr[AlphaISA::IPR_IFAULT_VA_FORM] =
289            ipr[AlphaISA::IPR_IVPTBR] | (VA_VPN(pc) << 3);
290    }
291}
292
293
294Fault
295AlphaITB::translate(MemReqPtr &req) const
296{
297    InternalProcReg *ipr = req->xc->regs.ipr;
298
299    if (PC_PAL(req->vaddr)) {
300        // strip off PAL PC marker (lsb is 1)
301        req->paddr = (req->vaddr & ~3) & PA_IMPL_MASK;
302        hits++;
303        return No_Fault;
304    }
305
306    if (req->flags & PHYSICAL) {
307        req->paddr = req->vaddr;
308    } else {
309        // verify that this is a good virtual address
310        if (!validVirtualAddress(req->vaddr)) {
311            fault(req->vaddr, req->xc);
312            acv++;
313            return ITB_Acv_Fault;
314        }
315
316        // Check for "superpage" mapping: when SP<1> is set, and
317        // VA<42:41> == 2, VA<39:13> maps directly to PA<39:13>.
318        if ((MCSR_SP(ipr[AlphaISA::IPR_MCSR]) & 2) &&
319               VA_SPACE(req->vaddr) == 2) {
320
321            // only valid in kernel mode
322            if (ICM_CM(ipr[AlphaISA::IPR_ICM]) != AlphaISA::mode_kernel) {
323                fault(req->vaddr, req->xc);
324                acv++;
325                return ITB_Acv_Fault;
326            }
327
328            req->paddr = req->vaddr & PA_IMPL_MASK;
329
330            // sign extend the physical address properly
331            if (req->paddr & PA_UNCACHED_BIT_39 ||
332                req->paddr & PA_UNCACHED_BIT_40)
333                req->paddr |= 0xf0000000000ULL;
334            else
335                req->paddr &= 0xffffffffffULL;
336
337        } else {
338            // not a physical address: need to look up pte
339            AlphaISA::PTE *pte = lookup(VA_VPN(req->vaddr),
340                                 DTB_ASN_ASN(ipr[AlphaISA::IPR_DTB_ASN]));
341
342            if (!pte) {
343                fault(req->vaddr, req->xc);
344                misses++;
345                return ITB_Fault_Fault;
346            }
347
348            req->paddr = PA_PFN2PA(pte->ppn) + VA_POFS(req->vaddr & ~3);
349
350            // check permissions for this access
351            if (!(pte->xre & (1 << ICM_CM(ipr[AlphaISA::IPR_ICM])))) {
352                // instruction access fault
353                fault(req->vaddr, req->xc);
354                acv++;
355                return ITB_Acv_Fault;
356            }
357
358            hits++;
359        }
360    }
361
362    // check that the physical address is ok (catch bad physical addresses)
363    if (req->paddr & ~PA_IMPL_MASK)
364        return Machine_Check_Fault;
365
366    checkCacheability(req);
367
368    return No_Fault;
369}
370
371///////////////////////////////////////////////////////////////////////
372//
373//  Alpha DTB
374//
375AlphaDTB::AlphaDTB(const std::string &name, int size)
376    : AlphaTLB(name, size)
377{}
378
379void
380AlphaDTB::regStats()
381{
382    read_hits
383        .name(name() + ".read_hits")
384        .desc("DTB read hits")
385        ;
386
387    read_misses
388        .name(name() + ".read_misses")
389        .desc("DTB read misses")
390        ;
391
392    read_acv
393        .name(name() + ".read_acv")
394        .desc("DTB read access violations")
395        ;
396
397    read_accesses
398        .name(name() + ".read_accesses")
399        .desc("DTB read accesses")
400        ;
401
402    write_hits
403        .name(name() + ".write_hits")
404        .desc("DTB write hits")
405        ;
406
407    write_misses
408        .name(name() + ".write_misses")
409        .desc("DTB write misses")
410        ;
411
412    write_acv
413        .name(name() + ".write_acv")
414        .desc("DTB write access violations")
415        ;
416
417    write_accesses
418        .name(name() + ".write_accesses")
419        .desc("DTB write accesses")
420        ;
421
422    hits
423        .name(name() + ".hits")
424        .desc("DTB hits")
425        ;
426
427    misses
428        .name(name() + ".misses")
429        .desc("DTB misses")
430        ;
431
432    acv
433        .name(name() + ".acv")
434        .desc("DTB access violations")
435        ;
436
437    accesses
438        .name(name() + ".accesses")
439        .desc("DTB accesses")
440        ;
441
442    hits = read_hits + write_hits;
443    misses = read_misses + write_misses;
444    acv = read_acv + write_acv;
445    accesses = read_accesses + write_accesses;
446}
447
448void
449AlphaDTB::fault(Addr vaddr, uint64_t flags, ExecContext *xc) const
450{
451    uint64_t *ipr = xc->regs.ipr;
452
453    // set fault address and flags
454    if (!xc->misspeculating() && !xc->regs.intrlock) {
455        // set VA register with faulting address
456        ipr[AlphaISA::IPR_VA] = vaddr;
457
458        // set MM_STAT register flags
459        ipr[AlphaISA::IPR_MM_STAT] = (((xc->regs.opcode & 0x3f) << 11)
460                               | ((xc->regs.ra & 0x1f) << 6)
461                               | (flags & 0x3f));
462
463        // set VA_FORM register with faulting formatted address
464        ipr[AlphaISA::IPR_VA_FORM] =
465            ipr[AlphaISA::IPR_MVPTBR] | (VA_VPN(vaddr) << 3);
466
467        // lock these registers until the VA register is read
468        xc->regs.intrlock = true;
469    }
470}
471
472Fault
473AlphaDTB::translate(MemReqPtr &req, bool write) const
474{
475    RegFile *regs = &req->xc->regs;
476    Addr pc = regs->pc;
477    InternalProcReg *ipr = regs->ipr;
478
479    AlphaISA::mode_type mode =
480        (AlphaISA::mode_type)DTB_CM_CM(ipr[AlphaISA::IPR_DTB_CM]);
481
482    if (PC_PAL(pc)) {
483        mode = (req->flags & ALTMODE) ?
484            (AlphaISA::mode_type)ALT_MODE_AM(ipr[AlphaISA::IPR_ALT_MODE])
485            : AlphaISA::mode_kernel;
486    }
487
488    if (req->flags & PHYSICAL) {
489        req->paddr = req->vaddr;
490    } else {
491        // verify that this is a good virtual address
492        if (!validVirtualAddress(req->vaddr)) {
493            fault(req->vaddr,
494                  ((write ? MM_STAT_WR_MASK : 0) | MM_STAT_BAD_VA_MASK |
495                   MM_STAT_ACV_MASK),
496                  req->xc);
497
498            if (write) { write_acv++; } else { read_acv++; }
499            return DTB_Fault_Fault;
500        }
501
502        // Check for "superpage" mapping: when SP<1> is set, and
503        // VA<42:41> == 2, VA<39:13> maps directly to PA<39:13>.
504        if ((MCSR_SP(ipr[AlphaISA::IPR_MCSR]) & 2) &&
505            VA_SPACE(req->vaddr) == 2) {
506
507            // only valid in kernel mode
508            if (DTB_CM_CM(ipr[AlphaISA::IPR_DTB_CM]) !=
509                AlphaISA::mode_kernel) {
510                fault(req->vaddr,
511                      ((write ? MM_STAT_WR_MASK : 0) | MM_STAT_ACV_MASK),
512                      req->xc);
513                if (write) { write_acv++; } else { read_acv++; }
514                return DTB_Acv_Fault;
515            }
516
517            req->paddr = req->vaddr & PA_IMPL_MASK;
518
519            // sign extend the physical address properly
520            if (req->paddr & PA_UNCACHED_BIT_39 ||
521                req->paddr & PA_UNCACHED_BIT_40)
522                req->paddr |= 0xf0000000000ULL;
523            else
524                req->paddr &= 0xffffffffffULL;
525
526        } else {
527            if (write)
528                write_accesses++;
529            else
530                read_accesses++;
531
532            // not a physical address: need to look up pte
533            AlphaISA::PTE *pte = lookup(VA_VPN(req->vaddr),
534                                 DTB_ASN_ASN(ipr[AlphaISA::IPR_DTB_ASN]));
535
536            if (!pte) {
537                // page fault
538                fault(req->vaddr,
539                      ((write ? MM_STAT_WR_MASK : 0) | MM_STAT_DTB_MISS_MASK),
540                      req->xc);
541                if (write) { write_misses++; } else { read_misses++; }
542                return (req->flags & VPTE) ? Pdtb_Miss_Fault : Ndtb_Miss_Fault;
543            }
544
545            req->paddr = PA_PFN2PA(pte->ppn) | VA_POFS(req->vaddr);
546
547            if (write) {
548                if (!(pte->xwe & MODE2MASK(mode))) {
549                    // declare the instruction access fault
550                    fault(req->vaddr, MM_STAT_WR_MASK | MM_STAT_ACV_MASK |
551                          (pte->fonw ? MM_STAT_FONW_MASK : 0),
552                          req->xc);
553                    write_acv++;
554                    return DTB_Fault_Fault;
555                }
556                if (pte->fonw) {
557                    fault(req->vaddr, MM_STAT_WR_MASK | MM_STAT_FONW_MASK,
558                          req->xc);
559                    write_acv++;
560                    return DTB_Fault_Fault;
561                }
562            } else {
563                if (!(pte->xre & MODE2MASK(mode))) {
564                    fault(req->vaddr,
565                          MM_STAT_ACV_MASK |
566                          (pte->fonr ? MM_STAT_FONR_MASK : 0),
567                          req->xc);
568                    read_acv++;
569                    return DTB_Acv_Fault;
570                }
571                if (pte->fonr) {
572                    fault(req->vaddr, MM_STAT_FONR_MASK, req->xc);
573                    read_acv++;
574                    return DTB_Fault_Fault;
575                }
576            }
577        }
578
579        if (write)
580            write_hits++;
581        else
582            read_hits++;
583    }
584
585    // check that the physical address is ok (catch bad physical addresses)
586    if (req->paddr & ~PA_IMPL_MASK)
587        return Machine_Check_Fault;
588
589    checkCacheability(req);
590
591    return No_Fault;
592}
593
594AlphaISA::PTE &
595AlphaTLB::index(bool advance)
596{
597    AlphaISA::PTE *pte = &table[nlu];
598
599    if (advance)
600        nextnlu();
601
602    return *pte;
603}
604
605DEFINE_SIM_OBJECT_CLASS_NAME("AlphaTLB", AlphaTLB)
606
607BEGIN_DECLARE_SIM_OBJECT_PARAMS(AlphaITB)
608
609    Param<int> size;
610
611END_DECLARE_SIM_OBJECT_PARAMS(AlphaITB)
612
613BEGIN_INIT_SIM_OBJECT_PARAMS(AlphaITB)
614
615    INIT_PARAM_DFLT(size, "TLB size", 48)
616
617END_INIT_SIM_OBJECT_PARAMS(AlphaITB)
618
619
620CREATE_SIM_OBJECT(AlphaITB)
621{
622    return new AlphaITB(getInstanceName(), size);
623}
624
625REGISTER_SIM_OBJECT("AlphaITB", AlphaITB)
626
627BEGIN_DECLARE_SIM_OBJECT_PARAMS(AlphaDTB)
628
629    Param<int> size;
630
631END_DECLARE_SIM_OBJECT_PARAMS(AlphaDTB)
632
633BEGIN_INIT_SIM_OBJECT_PARAMS(AlphaDTB)
634
635    INIT_PARAM_DFLT(size, "TLB size", 64)
636
637END_INIT_SIM_OBJECT_PARAMS(AlphaDTB)
638
639
640CREATE_SIM_OBJECT(AlphaDTB)
641{
642    return new AlphaDTB(getInstanceName(), size);
643}
644
645REGISTER_SIM_OBJECT("AlphaDTB", AlphaDTB)
646
647