/*
- * Copyright (c) 2003 The Regents of The University of Michigan
+ * Copyright (c) 2001-2004 The Regents of The University of Michigan
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
#include <string>
#include <vector>
-#include "alpha_memory.hh"
-#include "ev5.hh"
-#include "exec_context.hh"
-#include "trace.hh"
-#include "inifile.hh"
-#include "str.hh"
+#include "arch/alpha/alpha_memory.hh"
+#include "base/inifile.hh"
+#include "base/str.hh"
+#include "base/trace.hh"
+#include "cpu/exec_context.hh"
+#include "sim/builder.hh"
using namespace std;
+using namespace EV5;
///////////////////////////////////////////////////////////////////////
//
// Alpha TLB
//
-AlphaTlb::AlphaTlb(const string &name, int s)
+#ifdef DEBUG
+bool uncacheBit39 = false;
+bool uncacheBit40 = false;
+#endif
+
+#define MODE2MASK(X) (1 << (X))
+
+AlphaTLB::AlphaTLB(const string &name, int s)
: SimObject(name), size(s), nlu(0)
{
table = new AlphaISA::PTE[size];
memset(table, 0, sizeof(AlphaISA::PTE[size]));
}
-AlphaTlb::~AlphaTlb()
+AlphaTLB::~AlphaTLB()
{
if (table)
delete [] table;
// look up an entry in the TLB
AlphaISA::PTE *
-AlphaTlb::lookup(Addr vpn, uint8_t asn) const
+AlphaTLB::lookup(Addr vpn, uint8_t asn) const
{
- DPRINTF(TLB, "lookup %#x\n", vpn);
+ // assume not found...
+ AlphaISA::PTE *retval = NULL;
PageTable::const_iterator i = lookupTable.find(vpn);
- if (i == lookupTable.end())
- return NULL;
-
- while (i->first == vpn) {
- int index = i->second;
- AlphaISA::PTE *pte = &table[index];
- assert(pte->valid);
- if (vpn == pte->tag && (pte->asma || pte->asn == asn))
- return pte;
+ if (i != lookupTable.end()) {
+ while (i->first == vpn) {
+ int index = i->second;
+ AlphaISA::PTE *pte = &table[index];
+ assert(pte->valid);
+ if (vpn == pte->tag && (pte->asma || pte->asn == asn)) {
+ retval = pte;
+ break;
+ }
- ++i;
+ ++i;
+ }
}
- // not found...
- return NULL;
+ DPRINTF(TLB, "lookup %#x, asn %#x -> %s ppn %#x\n", vpn, (int)asn,
+ retval ? "hit" : "miss", retval ? retval->ppn : 0);
+ return retval;
}
void
-AlphaTlb::checkCacheability(MemReqPtr req)
+AlphaTLB::checkCacheability(MemReqPtr &req)
{
// in Alpha, cacheability is controlled by upper-level bits of the
// physical address
- if (req->paddr & PA_UNCACHED_BIT) {
- if (PA_IPR_SPACE(req->paddr)) {
- // IPR memory space not implemented
- if (!req->xc->misspeculating())
- panic("IPR memory space not implemented! PA=%x\n", req->paddr);
+
+ /*
+ * We support having the uncacheable bit in either bit 39 or bit 40.
+ * The Turbolaser platform (and EV5) support having the bit in 39, but
+ * Tsunami (which Linux assumes uses an EV6) generates accesses with
+ * the bit in 40. So we must check for both, but we have debug flags
+ * to catch a weird case where both are used, which shouldn't happen.
+ */
+
+
+#ifdef ALPHA_TLASER
+ if (req->paddr & PAddrUncachedBit39) {
+#else
+ if (req->paddr & PAddrUncachedBit43) {
+#endif
+ // IPR memory space not implemented
+ if (PAddrIprSpace(req->paddr)) {
+ if (!req->xc->misspeculating()) {
+ switch (req->paddr) {
+ case ULL(0xFFFFF00188):
+ req->data = 0;
+ break;
+
+ default:
+ panic("IPR memory space not implemented! PA=%x\n",
+ req->paddr);
+ }
+ }
} else {
// mark request as uncacheable
req->flags |= UNCACHEABLE;
+
+#ifndef ALPHA_TLASER
+ // Clear bits 42:35 of the physical address (10-2 in Tsunami manual)
+ req->paddr &= PAddrUncachedMask;
+#endif
}
}
}
// insert a new TLB entry
void
-AlphaTlb::insert(Addr vaddr, AlphaISA::PTE &pte)
+AlphaTLB::insert(Addr addr, AlphaISA::PTE &pte)
{
+ AlphaISA::VAddr vaddr = addr;
if (table[nlu].valid) {
Addr oldvpn = table[nlu].tag;
PageTable::iterator i = lookupTable.find(oldvpn);
lookupTable.erase(i);
}
- Addr vpn = VA_VPN(vaddr);
- DPRINTF(TLB, "insert @%d: %#x -> %#x\n", nlu, vpn, pte.ppn);
+ DPRINTF(TLB, "insert @%d: %#x -> %#x\n", nlu, vaddr.vpn(), pte.ppn);
table[nlu] = pte;
- table[nlu].tag = vpn;
+ table[nlu].tag = vaddr.vpn();
table[nlu].valid = true;
- lookupTable.insert(make_pair(vpn, nlu));
+ lookupTable.insert(make_pair(vaddr.vpn(), nlu));
nextnlu();
}
void
-AlphaTlb::flushAll()
+AlphaTLB::flushAll()
{
memset(table, 0, sizeof(AlphaISA::PTE[size]));
lookupTable.clear();
}
void
-AlphaTlb::flushProcesses()
+AlphaTLB::flushProcesses()
{
PageTable::iterator i = lookupTable.begin();
PageTable::iterator end = lookupTable.end();
}
void
-AlphaTlb::flushAddr(Addr vaddr, uint8_t asn)
+AlphaTLB::flushAddr(Addr addr, uint8_t asn)
{
- Addr vpn = VA_VPN(vaddr);
+ AlphaISA::VAddr vaddr = addr;
- PageTable::iterator i = lookupTable.find(vpn);
+ PageTable::iterator i = lookupTable.find(vaddr.vpn());
if (i == lookupTable.end())
return;
- while (i->first == vpn) {
+ while (i->first == vaddr.vpn()) {
int index = i->second;
AlphaISA::PTE *pte = &table[index];
assert(pte->valid);
- if (vpn == pte->tag && (pte->asma || pte->asn == asn)) {
- DPRINTF(TLB, "flushaddr @%d: %#x -> %#x\n", index, vpn, pte->ppn);
+ if (vaddr.vpn() == pte->tag && (pte->asma || pte->asn == asn)) {
+ DPRINTF(TLB, "flushaddr @%d: %#x -> %#x\n", index, vaddr.vpn(),
+ pte->ppn);
// invalidate this entry
pte->valid = false;
void
-AlphaTlb::serialize()
+AlphaTLB::serialize(ostream &os)
{
- nameOut();
-
- paramOut("size", size);
- paramOut("nlu", nlu);
+ SERIALIZE_SCALAR(size);
+ SERIALIZE_SCALAR(nlu);
- stringstream buf;
for (int i = 0; i < size; i++) {
- buf.str("");
- ccprintf(buf, "pte%02d.valid", i);
- paramOut(buf.str(), table[i].valid);
-
- buf.str("");
- ccprintf(buf, "pte%02d.tag", i);
- paramOut(buf.str(), table[i].tag);
-
- buf.str("");
- ccprintf(buf, "pte%02d.ppn", i);
- paramOut(buf.str(), table[i].ppn);
-
- buf.str("");
- ccprintf(buf, "pte%02d.xre", i);
- paramOut(buf.str(), table[i].xre);
-
- buf.str("");
- ccprintf(buf, "pte%02d.xwe", i);
- paramOut(buf.str(), table[i].xwe);
-
- buf.str("");
- ccprintf(buf, "pte%02d.fonr", i);
- paramOut(buf.str(), table[i].fonr);
-
- buf.str("");
- ccprintf(buf, "pte%02d.fonw", i);
- paramOut(buf.str(), table[i].fonw);
-
- buf.str("");
- ccprintf(buf, "pte%02d.asma", i);
- paramOut(buf.str(), table[i].asma);
-
- buf.str("");
- ccprintf(buf, "pte%02d.asn", i);
- paramOut(buf.str(), table[i].asn);
+ nameOut(os, csprintf("%s.PTE%d", name(), i));
+ table[i].serialize(os);
}
}
void
-AlphaTlb::unserialize(IniFile &db, const string &category, ConfigNode *node)
+AlphaTLB::unserialize(Checkpoint *cp, const string §ion)
{
- string data;
- stringstream buf;
-
- db.findDefault(category,"size",data);
- to_number(data,size);
- db.findDefault(category,"nlu",data);
- to_number(data,nlu);
+ UNSERIALIZE_SCALAR(size);
+ UNSERIALIZE_SCALAR(nlu);
for (int i = 0; i < size; i++) {
- buf.str("");
- ccprintf(buf, "pte%02d.valid", i);
- db.findDefault(category, buf.str(), data);
- to_number(data, table[i].valid);
-
- buf.str("");
- ccprintf(buf, "pte%02d.tag", i);
- db.findDefault(category, buf.str(), data);
- to_number(data, table[i].tag);
-
- buf.str("");
- ccprintf(buf, "pte%02d.ppn", i);
- db.findDefault(category, buf.str(), data);
- to_number(data, table[i].ppn);
-
- buf.str("");
- ccprintf(buf, "pte%02d.xre", i);
- db.findDefault(category, buf.str(), data);
- to_number(data, table[i].xre);
-
- buf.str("");
- ccprintf(buf, "pte%02d.xwe", i);
- db.findDefault(category, buf.str(), data);
- to_number(data, table[i].xwe);
-
- buf.str("");
- ccprintf(buf, "pte%02d.fonr", i);
- db.findDefault(category, buf.str(), data);
- to_number(data, table[i].fonr);
-
- buf.str("");
- ccprintf(buf, "pte%02d.fonw", i);
- db.findDefault(category, buf.str(), data);
- to_number(data, table[i].fonw);
-
- buf.str("");
- ccprintf(buf, "pte%02d.asma", i);
- db.findDefault(category, buf.str(), data);
- to_number(data, table[i].asma);
-
- buf.str("");
- ccprintf(buf, "pte%02d.asn", i);
- db.findDefault(category, buf.str(), data);
- to_number(data, table[i].asn);
+ table[i].unserialize(cp, csprintf("%s.PTE%d", section, i));
+ if (table[i].valid) {
+ lookupTable.insert(make_pair(table[i].tag, i));
+ }
}
}
//
// Alpha ITB
//
-AlphaItb::AlphaItb(const std::string &name, int size)
- : AlphaTlb(name, size)
+AlphaITB::AlphaITB(const std::string &name, int size)
+ : AlphaTLB(name, size)
{}
void
-AlphaItb::regStats()
+AlphaITB::regStats()
{
hits
.name(name() + ".hits")
}
void
-AlphaItb::fault(Addr pc, ExecContext *xc) const
+AlphaITB::fault(Addr pc, ExecContext *xc) const
{
uint64_t *ipr = xc->regs.ipr;
if (!xc->misspeculating()) {
ipr[AlphaISA::IPR_ITB_TAG] = pc;
ipr[AlphaISA::IPR_IFAULT_VA_FORM] =
- ipr[AlphaISA::IPR_IVPTBR] | (VA_VPN(pc) << 3);
+ ipr[AlphaISA::IPR_IVPTBR] | (AlphaISA::VAddr(pc).vpn() << 3);
}
}
Fault
-AlphaItb::translate(MemReqPtr req) const
+AlphaITB::translate(MemReqPtr &req) const
{
InternalProcReg *ipr = req->xc->regs.ipr;
- if (PC_PAL(req->vaddr)) {
+ if (AlphaISA::PcPAL(req->vaddr)) {
// strip off PAL PC marker (lsb is 1)
- req->paddr = (req->vaddr & ~3) & PA_IMPL_MASK;
+ req->paddr = (req->vaddr & ~3) & PAddrImplMask;
hits++;
return No_Fault;
}
- // verify that this is a good virtual address
- if (!validVirtualAddress(req->vaddr)) {
- fault(req->vaddr, req->xc);
- acv++;
- return Itb_Acv_Fault;
- }
-
- // Check for "superpage" mapping: when SP<1> is set, and
- // VA<42:41> == 2, VA<39:13> maps directly to PA<39:13>.
- if ((MCSR_SP(ipr[AlphaISA::IPR_MCSR]) & 2) &&
- VA_SPACE(req->vaddr) == 2) {
- // only valid in kernel mode
- if (ICM_CM(ipr[AlphaISA::IPR_ICM]) != AlphaISA::mode_kernel) {
+ if (req->flags & PHYSICAL) {
+ req->paddr = req->vaddr;
+ } else {
+ // verify that this is a good virtual address
+ if (!validVirtualAddress(req->vaddr)) {
fault(req->vaddr, req->xc);
acv++;
- return Itb_Acv_Fault;
+ return ITB_Acv_Fault;
}
- req->flags |= PHYSICAL;
- }
- if (req->flags & PHYSICAL) {
- req->paddr = req->vaddr & PA_IMPL_MASK;
- } else {
- // not a physical address: need to look up pte
+ // VA<42:41> == 2, VA<39:13> maps directly to PA<39:13> for EV5
+ // VA<47:41> == 0x7e, VA<40:13> maps directly to PA<40:13> for EV6
+#ifdef ALPHA_TLASER
+ if ((MCSR_SP(ipr[AlphaISA::IPR_MCSR]) & 2) &&
+ VAddrSpaceEV5(req->vaddr) == 2) {
+#else
+ if (VAddrSpaceEV6(req->vaddr) == 0x7e) {
+#endif
+ // only valid in kernel mode
+ if (ICM_CM(ipr[AlphaISA::IPR_ICM]) !=
+ AlphaISA::mode_kernel) {
+ fault(req->vaddr, req->xc);
+ acv++;
+ return ITB_Acv_Fault;
+ }
- AlphaISA::PTE *pte = lookup(VA_VPN(req->vaddr),
- DTB_ASN_ASN(ipr[AlphaISA::IPR_DTB_ASN]));
+ req->paddr = req->vaddr & PAddrImplMask;
- if (!pte) {
- fault(req->vaddr, req->xc);
- misses++;
- return Itb_Fault_Fault;
- }
+#ifndef ALPHA_TLASER
+ // sign extend the physical address properly
+ if (req->paddr & PAddrUncachedBit40)
+ req->paddr |= ULL(0xf0000000000);
+ else
+ req->paddr &= ULL(0xffffffffff);
+#endif
+
+ } else {
+ // not a physical address: need to look up pte
+ AlphaISA::PTE *pte = lookup(AlphaISA::VAddr(req->vaddr).vpn(),
+ DTB_ASN_ASN(ipr[AlphaISA::IPR_DTB_ASN]));
+
+ if (!pte) {
+ fault(req->vaddr, req->xc);
+ misses++;
+ return ITB_Fault_Fault;
+ }
- req->paddr = PA_PFN2PA(pte->ppn) + VA_POFS(req->vaddr & ~3);
+ req->paddr = (pte->ppn << AlphaISA::PageShift) +
+ (AlphaISA::VAddr(req->vaddr).offset() & ~3);
- // check permissions for this access
- if (!(pte->xre & (1 << ICM_CM(ipr[AlphaISA::IPR_ICM])))) {
- // instruction access fault
- fault(req->vaddr, req->xc);
- acv++;
- return Itb_Acv_Fault;
+ // check permissions for this access
+ if (!(pte->xre & (1 << ICM_CM(ipr[AlphaISA::IPR_ICM])))) {
+ // instruction access fault
+ fault(req->vaddr, req->xc);
+ acv++;
+ return ITB_Acv_Fault;
+ }
+
+ hits++;
}
}
+ // check that the physical address is ok (catch bad physical addresses)
+ if (req->paddr & ~PAddrImplMask)
+ return Machine_Check_Fault;
+
checkCacheability(req);
- hits++;
return No_Fault;
}
//
// Alpha DTB
//
-AlphaDtb::AlphaDtb(const std::string &name, int size)
- : AlphaTlb(name, size)
+AlphaDTB::AlphaDTB(const std::string &name, int size)
+ : AlphaTLB(name, size)
{}
void
-AlphaDtb::regStats()
+AlphaDTB::regStats()
{
read_hits
.name(name() + ".read_hits")
}
void
-AlphaDtb::fault(Addr vaddr, uint64_t flags, ExecContext *xc) const
+AlphaDTB::fault(MemReqPtr &req, uint64_t flags) const
{
+ ExecContext *xc = req->xc;
+ AlphaISA::VAddr vaddr = req->vaddr;
uint64_t *ipr = xc->regs.ipr;
- // set fault address and flags
- if (!xc->misspeculating() && !xc->regs.intrlock) {
+ // Set fault address and flags. Even though we're modeling an
+ // EV5, we use the EV6 technique of not latching fault registers
+ // on VPTE loads (instead of locking the registers until IPR_VA is
+ // read, like the EV5). The EV6 approach is cleaner and seems to
+ // work with EV5 PAL code, but not the other way around.
+ if (!xc->misspeculating()
+ && !(req->flags & VPTE) && !(req->flags & NO_FAULT)) {
// set VA register with faulting address
- ipr[AlphaISA::IPR_VA] = vaddr;
+ ipr[AlphaISA::IPR_VA] = req->vaddr;
// set MM_STAT register flags
- ipr[AlphaISA::IPR_MM_STAT] = (((xc->regs.opcode & 0x3f) << 11)
- | ((xc->regs.ra & 0x1f) << 6)
- | (flags & 0x3f));
+ ipr[AlphaISA::IPR_MM_STAT] =
+ (((Opcode(xc->getInst()) & 0x3f) << 11)
+ | ((Ra(xc->getInst()) & 0x1f) << 6)
+ | (flags & 0x3f));
// set VA_FORM register with faulting formatted address
ipr[AlphaISA::IPR_VA_FORM] =
- ipr[AlphaISA::IPR_MVPTBR] | (VA_VPN(vaddr) << 3);
-
- // lock these registers until the VA register is read
- xc->regs.intrlock = true;
+ ipr[AlphaISA::IPR_MVPTBR] | (vaddr.vpn() << 3);
}
}
Fault
-AlphaDtb::translate(MemReqPtr req, bool write) const
+AlphaDTB::translate(MemReqPtr &req, bool write) const
{
RegFile *regs = &req->xc->regs;
Addr pc = regs->pc;
InternalProcReg *ipr = regs->ipr;
- if (write)
- write_accesses++;
- else
- read_accesses++;
+ AlphaISA::mode_type mode =
+ (AlphaISA::mode_type)DTB_CM_CM(ipr[AlphaISA::IPR_DTB_CM]);
- AlphaISA::md_mode_type mode =
- (AlphaISA::md_mode_type)DTB_CM_CM(ipr[AlphaISA::IPR_DTB_CM]);
- if (PC_PAL(pc)) {
- mode = (req->flags & ALTMODE) ? (AlphaISA::md_mode_type)
- (ALT_MODE_AM(ipr[AlphaISA::IPR_ALT_MODE]))
- : AlphaISA::mode_kernel;
+ /**
+ * Check for alignment faults
+ */
+ if (req->vaddr & (req->size - 1)) {
+ fault(req, write ? MM_STAT_WR_MASK : 0);
+ DPRINTF(TLB, "Alignment Fault on %#x, size = %d", req->vaddr,
+ req->size);
+ return Alignment_Fault;
}
- // verify that this is a good virtual address
- if (!validVirtualAddress(req->vaddr)) {
- fault(req->vaddr,
- ((write ? MM_STAT_WR_MASK : 0) | MM_STAT_BAD_VA_MASK |
- MM_STAT_ACV_MASK),
- req->xc);
-
- if (write) { write_acv++; } else { read_acv++; }
- return Dtb_Fault_Fault;
+ if (pc & 0x1) {
+ mode = (req->flags & ALTMODE) ?
+ (AlphaISA::mode_type)ALT_MODE_AM(ipr[AlphaISA::IPR_ALT_MODE])
+ : AlphaISA::mode_kernel;
}
- // Check for "superpage" mapping: when SP<1> is set, and
- // VA<42:41> == 2, VA<39:13> maps directly to PA<39:13>.
- if ((MCSR_SP(ipr[AlphaISA::IPR_MCSR]) & 2) && VA_SPACE(req->vaddr) == 2) {
- // only valid in kernel mode
- if (DTB_CM_CM(ipr[AlphaISA::IPR_DTB_CM]) != AlphaISA::mode_kernel) {
- fault(req->vaddr,
- ((write ? MM_STAT_WR_MASK : 0) | MM_STAT_ACV_MASK),
- req->xc);
+ if (req->flags & PHYSICAL) {
+ req->paddr = req->vaddr;
+ } else {
+ // verify that this is a good virtual address
+ if (!validVirtualAddress(req->vaddr)) {
+ fault(req, (write ? MM_STAT_WR_MASK : 0) |
+ MM_STAT_BAD_VA_MASK |
+ MM_STAT_ACV_MASK);
+
if (write) { write_acv++; } else { read_acv++; }
- return Dtb_Acv_Fault;
+ return DTB_Fault_Fault;
}
- req->flags |= PHYSICAL;
- }
+ // Check for "superpage" mapping
+#ifdef ALPHA_TLASER
+ if ((MCSR_SP(ipr[AlphaISA::IPR_MCSR]) & 2) &&
+ VAddrSpaceEV5(req->vaddr) == 2) {
+#else
+ if (VAddrSpaceEV6(req->vaddr) == 0x7e) {
+#endif
+
+ // only valid in kernel mode
+ if (DTB_CM_CM(ipr[AlphaISA::IPR_DTB_CM]) !=
+ AlphaISA::mode_kernel) {
+ fault(req, ((write ? MM_STAT_WR_MASK : 0) |
+ MM_STAT_ACV_MASK));
+ if (write) { write_acv++; } else { read_acv++; }
+ return DTB_Acv_Fault;
+ }
- if (req->flags & PHYSICAL) {
- req->paddr = req->vaddr & PA_IMPL_MASK;
- } else {
- // not a physical address: need to look up pte
-
- AlphaISA::PTE *pte = lookup(VA_VPN(req->vaddr),
- DTB_ASN_ASN(ipr[AlphaISA::IPR_DTB_ASN]));
-
- if (!pte) {
- // page fault
- fault(req->vaddr,
- ((write ? MM_STAT_WR_MASK : 0) | MM_STAT_DTB_MISS_MASK),
- req->xc);
- if (write) { write_misses++; } else { read_misses++; }
- return (req->flags & VPTE) ? Pdtb_Miss_Fault : Ndtb_Miss_Fault;
- }
+ req->paddr = req->vaddr & PAddrImplMask;
- req->paddr = PA_PFN2PA(pte->ppn) | VA_POFS(req->vaddr);
+#ifndef ALPHA_TLASER
+ // sign extend the physical address properly
+ if (req->paddr & PAddrUncachedBit40)
+ req->paddr |= ULL(0xf0000000000);
+ else
+ req->paddr &= ULL(0xffffffffff);
+#endif
- if (write) {
- if (!(pte->xwe & MODE2MASK(mode))) {
- // declare the instruction access fault
- fault(req->vaddr, MM_STAT_WR_MASK | MM_STAT_ACV_MASK |
- (pte->fonw ? MM_STAT_FONW_MASK : 0),
- req->xc);
- write_acv++;
- return Dtb_Fault_Fault;
- }
- if (pte->fonw) {
- fault(req->vaddr, MM_STAT_WR_MASK | MM_STAT_FONW_MASK,
- req->xc);
- write_acv++;
- return Dtb_Fault_Fault;
- }
} else {
- if (!(pte->xre & MODE2MASK(mode))) {
- fault(req->vaddr,
- MM_STAT_ACV_MASK | (pte->fonr ? MM_STAT_FONR_MASK : 0),
- req->xc);
- read_acv++;
- return Dtb_Acv_Fault;
+ if (write)
+ write_accesses++;
+ else
+ read_accesses++;
+
+ // not a physical address: need to look up pte
+ AlphaISA::PTE *pte = lookup(AlphaISA::VAddr(req->vaddr).vpn(),
+ DTB_ASN_ASN(ipr[AlphaISA::IPR_DTB_ASN]));
+
+ if (!pte) {
+ // page fault
+ fault(req, (write ? MM_STAT_WR_MASK : 0) |
+ MM_STAT_DTB_MISS_MASK);
+ if (write) { write_misses++; } else { read_misses++; }
+ return (req->flags & VPTE) ? Pdtb_Miss_Fault : Ndtb_Miss_Fault;
}
- if (pte->fonr) {
- fault(req->vaddr, MM_STAT_FONR_MASK, req->xc);
- read_acv++;
- return Dtb_Fault_Fault;
+
+ req->paddr = (pte->ppn << AlphaISA::PageShift) +
+ AlphaISA::VAddr(req->vaddr).offset();
+
+ if (write) {
+ if (!(pte->xwe & MODE2MASK(mode))) {
+ // declare the instruction access fault
+ fault(req, MM_STAT_WR_MASK |
+ MM_STAT_ACV_MASK |
+ (pte->fonw ? MM_STAT_FONW_MASK : 0));
+ write_acv++;
+ return DTB_Fault_Fault;
+ }
+ if (pte->fonw) {
+ fault(req, MM_STAT_WR_MASK |
+ MM_STAT_FONW_MASK);
+ write_acv++;
+ return DTB_Fault_Fault;
+ }
+ } else {
+ if (!(pte->xre & MODE2MASK(mode))) {
+ fault(req, MM_STAT_ACV_MASK |
+ (pte->fonr ? MM_STAT_FONR_MASK : 0));
+ read_acv++;
+ return DTB_Acv_Fault;
+ }
+ if (pte->fonr) {
+ fault(req, MM_STAT_FONR_MASK);
+ read_acv++;
+ return DTB_Fault_Fault;
+ }
}
}
+
+ if (write)
+ write_hits++;
+ else
+ read_hits++;
}
- checkCacheability(req);
+ // check that the physical address is ok (catch bad physical addresses)
+ if (req->paddr & ~PAddrImplMask)
+ return Machine_Check_Fault;
- if (write)
- write_hits++;
- else
- read_hits++;
+ checkCacheability(req);
return No_Fault;
}
AlphaISA::PTE &
-AlphaTlb::index()
+AlphaTLB::index(bool advance)
{
AlphaISA::PTE *pte = &table[nlu];
- nextnlu();
+
+ if (advance)
+ nextnlu();
return *pte;
}
-BEGIN_DECLARE_SIM_OBJECT_PARAMS(AlphaItb)
+DEFINE_SIM_OBJECT_CLASS_NAME("AlphaTLB", AlphaTLB)
+
+BEGIN_DECLARE_SIM_OBJECT_PARAMS(AlphaITB)
Param<int> size;
-END_DECLARE_SIM_OBJECT_PARAMS(AlphaItb)
+END_DECLARE_SIM_OBJECT_PARAMS(AlphaITB)
-BEGIN_INIT_SIM_OBJECT_PARAMS(AlphaItb)
+BEGIN_INIT_SIM_OBJECT_PARAMS(AlphaITB)
INIT_PARAM_DFLT(size, "TLB size", 48)
-END_INIT_SIM_OBJECT_PARAMS(AlphaItb)
+END_INIT_SIM_OBJECT_PARAMS(AlphaITB)
-CREATE_SIM_OBJECT(AlphaItb)
+CREATE_SIM_OBJECT(AlphaITB)
{
- return new AlphaItb(getInstanceName(), size);
+ return new AlphaITB(getInstanceName(), size);
}
-REGISTER_SIM_OBJECT("AlphaITB", AlphaItb)
+REGISTER_SIM_OBJECT("AlphaITB", AlphaITB)
-BEGIN_DECLARE_SIM_OBJECT_PARAMS(AlphaDtb)
+BEGIN_DECLARE_SIM_OBJECT_PARAMS(AlphaDTB)
Param<int> size;
-END_DECLARE_SIM_OBJECT_PARAMS(AlphaDtb)
+END_DECLARE_SIM_OBJECT_PARAMS(AlphaDTB)
-BEGIN_INIT_SIM_OBJECT_PARAMS(AlphaDtb)
+BEGIN_INIT_SIM_OBJECT_PARAMS(AlphaDTB)
INIT_PARAM_DFLT(size, "TLB size", 64)
-END_INIT_SIM_OBJECT_PARAMS(AlphaDtb)
+END_INIT_SIM_OBJECT_PARAMS(AlphaDTB)
-CREATE_SIM_OBJECT(AlphaDtb)
+CREATE_SIM_OBJECT(AlphaDTB)
{
- return new AlphaDtb(getInstanceName(), size);
+ return new AlphaDTB(getInstanceName(), size);
}
-REGISTER_SIM_OBJECT("AlphaDTB", AlphaDtb)
+REGISTER_SIM_OBJECT("AlphaDTB", AlphaDTB)
+