summaryrefslogtreecommitdiff
path: root/src/arch/alpha/tlb.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/arch/alpha/tlb.cc')
-rw-r--r--src/arch/alpha/tlb.cc926
1 files changed, 464 insertions, 462 deletions
diff --git a/src/arch/alpha/tlb.cc b/src/arch/alpha/tlb.cc
index bab44c434..ae302e686 100644
--- a/src/arch/alpha/tlb.cc
+++ b/src/arch/alpha/tlb.cc
@@ -46,589 +46,591 @@
using namespace std;
using namespace EV5;
-///////////////////////////////////////////////////////////////////////
-//
-// Alpha TLB
-//
+namespace AlphaISA
+{
+ ///////////////////////////////////////////////////////////////////////
+ //
+ // Alpha TLB
+ //
#ifdef DEBUG
-bool uncacheBit39 = false;
-bool uncacheBit40 = false;
+ 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]));
-}
+ TLB::TLB(const string &name, int s)
+ : SimObject(name), size(s), nlu(0)
+ {
+ table = new PTE[size];
+ memset(table, 0, sizeof(PTE[size]));
+ }
-AlphaTLB::~AlphaTLB()
-{
- if (table)
- delete [] table;
-}
+ TLB::~TLB()
+ {
+ if (table)
+ delete [] table;
+ }
-// look up an entry in the TLB
-AlphaISA::PTE *
-AlphaTLB::lookup(Addr vpn, uint8_t asn) const
-{
- // assume not found...
- AlphaISA::PTE *retval = NULL;
+ // look up an entry in the TLB
+ PTE *
+ TLB::lookup(Addr vpn, uint8_t asn) const
+ {
+ // assume not found...
+ PTE *retval = NULL;
+
+ PageTable::const_iterator i = lookupTable.find(vpn);
+ if (i != lookupTable.end()) {
+ while (i->first == vpn) {
+ int index = i->second;
+ PTE *pte = &table[index];
+ assert(pte->valid);
+ if (vpn == pte->tag && (pte->asma || pte->asn == asn)) {
+ retval = pte;
+ break;
+ }
- PageTable::const_iterator i = lookupTable.find(vpn);
- 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;
}
- }
- DPRINTF(TLB, "lookup %#x, asn %#x -> %s ppn %#x\n", vpn, (int)asn,
- retval ? "hit" : "miss", retval ? retval->ppn : 0);
- return retval;
-}
+ DPRINTF(TLB, "lookup %#x, asn %#x -> %s ppn %#x\n", vpn, (int)asn,
+ retval ? "hit" : "miss", retval ? retval->ppn : 0);
+ return retval;
+ }
-Fault
-AlphaTLB::checkCacheability(RequestPtr &req)
-{
- // in Alpha, cacheability is controlled by upper-level bits of the
- // physical address
+ Fault
+ TLB::checkCacheability(RequestPtr &req)
+ {
+ // in Alpha, cacheability is controlled by upper-level bits of the
+ // physical address
- /*
- * 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.
- */
+ /*
+ * 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.
+ */
#if ALPHA_TLASER
- if (req->getPaddr() & PAddrUncachedBit39) {
+ if (req->getPaddr() & PAddrUncachedBit39) {
#else
- if (req->getPaddr() & PAddrUncachedBit43) {
+ if (req->getPaddr() & PAddrUncachedBit43) {
#endif
- // IPR memory space not implemented
- if (PAddrIprSpace(req->getPaddr())) {
- return new UnimpFault("IPR memory space not implemented!");
- } else {
- // mark request as uncacheable
- req->setFlags(req->getFlags() | UNCACHEABLE);
+ // IPR memory space not implemented
+ if (PAddrIprSpace(req->getPaddr())) {
+ return new UnimpFault("IPR memory space not implemented!");
+ } else {
+ // mark request as uncacheable
+ req->setFlags(req->getFlags() | UNCACHEABLE);
#if !ALPHA_TLASER
- // Clear bits 42:35 of the physical address (10-2 in Tsunami manual)
- req->setPaddr(req->getPaddr() & PAddrUncachedMask);
+ // Clear bits 42:35 of the physical address (10-2 in Tsunami manual)
+ req->setPaddr(req->getPaddr() & PAddrUncachedMask);
#endif
+ }
}
+ return NoFault;
}
- return NoFault;
-}
-// insert a new TLB entry
-void
-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);
+ // insert a new TLB entry
+ void
+ TLB::insert(Addr addr, PTE &pte)
+ {
+ VAddr vaddr = addr;
+ if (table[nlu].valid) {
+ Addr oldvpn = table[nlu].tag;
+ PageTable::iterator i = lookupTable.find(oldvpn);
- if (i == lookupTable.end())
- panic("TLB entry not found in lookupTable");
-
- int index;
- while ((index = i->second) != nlu) {
- if (table[index].tag != oldvpn)
+ if (i == lookupTable.end())
panic("TLB entry not found in lookupTable");
- ++i;
+ int index;
+ while ((index = i->second) != nlu) {
+ if (table[index].tag != oldvpn)
+ panic("TLB entry not found in lookupTable");
+
+ ++i;
+ }
+
+ DPRINTF(TLB, "remove @%d: %#x -> %#x\n", nlu, oldvpn, table[nlu].ppn);
+
+ lookupTable.erase(i);
}
- DPRINTF(TLB, "remove @%d: %#x -> %#x\n", nlu, oldvpn, table[nlu].ppn);
+ DPRINTF(TLB, "insert @%d: %#x -> %#x\n", nlu, vaddr.vpn(), pte.ppn);
- lookupTable.erase(i);
- }
+ table[nlu] = pte;
+ table[nlu].tag = vaddr.vpn();
+ table[nlu].valid = true;
- DPRINTF(TLB, "insert @%d: %#x -> %#x\n", nlu, vaddr.vpn(), pte.ppn);
+ lookupTable.insert(make_pair(vaddr.vpn(), nlu));
+ nextnlu();
+ }
- table[nlu] = pte;
- table[nlu].tag = vaddr.vpn();
- table[nlu].valid = true;
+ void
+ TLB::flushAll()
+ {
+ DPRINTF(TLB, "flushAll\n");
+ memset(table, 0, sizeof(PTE[size]));
+ lookupTable.clear();
+ nlu = 0;
+ }
- lookupTable.insert(make_pair(vaddr.vpn(), nlu));
- nextnlu();
-}
+ void
+ TLB::flushProcesses()
+ {
+ PageTable::iterator i = lookupTable.begin();
+ PageTable::iterator end = lookupTable.end();
+ while (i != end) {
+ int index = i->second;
+ PTE *pte = &table[index];
+ assert(pte->valid);
-void
-AlphaTLB::flushAll()
-{
- DPRINTF(TLB, "flushAll\n");
- memset(table, 0, sizeof(AlphaISA::PTE[size]));
- lookupTable.clear();
- nlu = 0;
-}
+ // we can't increment i after we erase it, so save a copy and
+ // increment it to get the next entry now
+ PageTable::iterator cur = i;
+ ++i;
-void
-AlphaTLB::flushProcesses()
-{
- PageTable::iterator i = lookupTable.begin();
- PageTable::iterator end = lookupTable.end();
- while (i != end) {
- int index = i->second;
- AlphaISA::PTE *pte = &table[index];
- assert(pte->valid);
-
- // we can't increment i after we erase it, so save a copy and
- // increment it to get the next entry now
- PageTable::iterator cur = i;
- ++i;
-
- if (!pte->asma) {
- DPRINTF(TLB, "flush @%d: %#x -> %#x\n", index, pte->tag, pte->ppn);
- pte->valid = false;
- lookupTable.erase(cur);
+ if (!pte->asma) {
+ DPRINTF(TLB, "flush @%d: %#x -> %#x\n", index, pte->tag, pte->ppn);
+ pte->valid = false;
+ lookupTable.erase(cur);
+ }
}
}
-}
-void
-AlphaTLB::flushAddr(Addr addr, uint8_t asn)
-{
- AlphaISA::VAddr vaddr = addr;
+ void
+ TLB::flushAddr(Addr addr, uint8_t asn)
+ {
+ VAddr vaddr = addr;
- PageTable::iterator i = lookupTable.find(vaddr.vpn());
- if (i == lookupTable.end())
- return;
+ PageTable::iterator i = lookupTable.find(vaddr.vpn());
+ if (i == lookupTable.end())
+ return;
- while (i->first == vaddr.vpn()) {
- int index = i->second;
- AlphaISA::PTE *pte = &table[index];
- assert(pte->valid);
+ while (i->first == vaddr.vpn()) {
+ int index = i->second;
+ PTE *pte = &table[index];
+ assert(pte->valid);
- if (vaddr.vpn() == pte->tag && (pte->asma || pte->asn == asn)) {
- DPRINTF(TLB, "flushaddr @%d: %#x -> %#x\n", index, vaddr.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;
+ // invalidate this entry
+ pte->valid = false;
- lookupTable.erase(i);
- }
+ lookupTable.erase(i);
+ }
- ++i;
+ ++i;
+ }
}
-}
-void
-AlphaTLB::serialize(ostream &os)
-{
- SERIALIZE_SCALAR(size);
- SERIALIZE_SCALAR(nlu);
+ void
+ TLB::serialize(ostream &os)
+ {
+ SERIALIZE_SCALAR(size);
+ SERIALIZE_SCALAR(nlu);
- for (int i = 0; i < size; i++) {
- nameOut(os, csprintf("%s.PTE%d", name(), i));
- table[i].serialize(os);
+ for (int i = 0; i < size; i++) {
+ nameOut(os, csprintf("%s.PTE%d", name(), i));
+ table[i].serialize(os);
+ }
}
-}
-void
-AlphaTLB::unserialize(Checkpoint *cp, const string &section)
-{
- UNSERIALIZE_SCALAR(size);
- UNSERIALIZE_SCALAR(nlu);
+ void
+ TLB::unserialize(Checkpoint *cp, const string &section)
+ {
+ UNSERIALIZE_SCALAR(size);
+ UNSERIALIZE_SCALAR(nlu);
- for (int i = 0; i < size; i++) {
- table[i].unserialize(cp, csprintf("%s.PTE%d", section, i));
- if (table[i].valid) {
- lookupTable.insert(make_pair(table[i].tag, i));
+ for (int i = 0; i < size; i++) {
+ 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)
-{}
-
-void
-AlphaITB::regStats()
-{
- hits
- .name(name() + ".hits")
- .desc("ITB hits");
- misses
- .name(name() + ".misses")
- .desc("ITB misses");
- acv
- .name(name() + ".acv")
- .desc("ITB acv");
- accesses
- .name(name() + ".accesses")
- .desc("ITB accesses");
-
- accesses = hits + misses;
-}
-
-
-Fault
-AlphaITB::translate(RequestPtr &req, ThreadContext *tc) const
-{
- if (AlphaISA::PcPAL(req->getVaddr())) {
- // strip off PAL PC marker (lsb is 1)
- req->setPaddr((req->getVaddr() & ~3) & PAddrImplMask);
- hits++;
- return NoFault;
+ ///////////////////////////////////////////////////////////////////////
+ //
+ // Alpha ITB
+ //
+ ITB::ITB(const std::string &name, int size)
+ : TLB(name, size)
+ {}
+
+
+ void
+ ITB::regStats()
+ {
+ hits
+ .name(name() + ".hits")
+ .desc("ITB hits");
+ misses
+ .name(name() + ".misses")
+ .desc("ITB misses");
+ acv
+ .name(name() + ".acv")
+ .desc("ITB acv");
+ accesses
+ .name(name() + ".accesses")
+ .desc("ITB accesses");
+
+ accesses = hits + misses;
}
- if (req->getFlags() & PHYSICAL) {
- req->setPaddr(req->getVaddr());
- } else {
- // verify that this is a good virtual address
- if (!validVirtualAddress(req->getVaddr())) {
- acv++;
- return new ItbAcvFault(req->getVaddr());
+
+ Fault
+ ITB::translate(RequestPtr &req, ThreadContext *tc) const
+ {
+ if (PcPAL(req->getVaddr())) {
+ // strip off PAL PC marker (lsb is 1)
+ req->setPaddr((req->getVaddr() & ~3) & PAddrImplMask);
+ hits++;
+ return NoFault;
}
+ if (req->getFlags() & PHYSICAL) {
+ req->setPaddr(req->getVaddr());
+ } else {
+ // verify that this is a good virtual address
+ if (!validVirtualAddress(req->getVaddr())) {
+ acv++;
+ return new ItbAcvFault(req->getVaddr());
+ }
+
- // 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
+ // 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
#if ALPHA_TLASER
- if ((MCSR_SP(tc->readMiscReg(AlphaISA::IPR_MCSR)) & 2) &&
- VAddrSpaceEV5(req->getVaddr()) == 2) {
+ if ((MCSR_SP(tc->readMiscReg(IPR_MCSR)) & 2) &&
+ VAddrSpaceEV5(req->getVaddr()) == 2) {
#else
- if (VAddrSpaceEV6(req->getVaddr()) == 0x7e) {
+ if (VAddrSpaceEV6(req->getVaddr()) == 0x7e) {
#endif
- // only valid in kernel mode
- if (ICM_CM(tc->readMiscReg(AlphaISA::IPR_ICM)) !=
- AlphaISA::mode_kernel) {
- acv++;
- return new ItbAcvFault(req->getVaddr());
- }
+ // only valid in kernel mode
+ if (ICM_CM(tc->readMiscReg(IPR_ICM)) !=
+ mode_kernel) {
+ acv++;
+ return new ItbAcvFault(req->getVaddr());
+ }
- req->setPaddr(req->getVaddr() & PAddrImplMask);
+ req->setPaddr(req->getVaddr() & PAddrImplMask);
#if !ALPHA_TLASER
- // sign extend the physical address properly
- if (req->getPaddr() & PAddrUncachedBit40)
- req->setPaddr(req->getPaddr() | ULL(0xf0000000000));
- else
- req->setPaddr(req->getPaddr() & ULL(0xffffffffff));
+ // sign extend the physical address properly
+ if (req->getPaddr() & PAddrUncachedBit40)
+ req->setPaddr(req->getPaddr() | ULL(0xf0000000000));
+ else
+ req->setPaddr(req->getPaddr() & ULL(0xffffffffff));
#endif
- } else {
- // not a physical address: need to look up pte
- int asn = DTB_ASN_ASN(tc->readMiscReg(AlphaISA::IPR_DTB_ASN));
- AlphaISA::PTE *pte = lookup(AlphaISA::VAddr(req->getVaddr()).vpn(),
- asn);
-
- if (!pte) {
- misses++;
- return new ItbPageFault(req->getVaddr());
- }
+ } else {
+ // not a physical address: need to look up pte
+ int asn = DTB_ASN_ASN(tc->readMiscReg(IPR_DTB_ASN));
+ PTE *pte = lookup(VAddr(req->getVaddr()).vpn(),
+ asn);
+
+ if (!pte) {
+ misses++;
+ return new ItbPageFault(req->getVaddr());
+ }
- req->setPaddr((pte->ppn << AlphaISA::PageShift) +
- (AlphaISA::VAddr(req->getVaddr()).offset()
- & ~3));
+ req->setPaddr((pte->ppn << PageShift) +
+ (VAddr(req->getVaddr()).offset()
+ & ~3));
- // check permissions for this access
- if (!(pte->xre &
- (1 << ICM_CM(tc->readMiscReg(AlphaISA::IPR_ICM))))) {
- // instruction access fault
- acv++;
- return new ItbAcvFault(req->getVaddr());
- }
+ // check permissions for this access
+ if (!(pte->xre &
+ (1 << ICM_CM(tc->readMiscReg(IPR_ICM))))) {
+ // instruction access fault
+ acv++;
+ return new ItbAcvFault(req->getVaddr());
+ }
- hits++;
+ hits++;
+ }
}
- }
-
- // check that the physical address is ok (catch bad physical addresses)
- if (req->getPaddr() & ~PAddrImplMask)
- return genMachineCheckFault();
- return checkCacheability(req);
-
-}
+ // check that the physical address is ok (catch bad physical addresses)
+ if (req->getPaddr() & ~PAddrImplMask)
+ return genMachineCheckFault();
-///////////////////////////////////////////////////////////////////////
-//
-// Alpha DTB
-//
-AlphaDTB::AlphaDTB(const std::string &name, int size)
- : AlphaTLB(name, size)
-{}
+ return checkCacheability(req);
-void
-AlphaDTB::regStats()
-{
- read_hits
- .name(name() + ".read_hits")
- .desc("DTB read hits")
- ;
-
- read_misses
- .name(name() + ".read_misses")
- .desc("DTB read misses")
- ;
-
- read_acv
- .name(name() + ".read_acv")
- .desc("DTB read access violations")
- ;
-
- read_accesses
- .name(name() + ".read_accesses")
- .desc("DTB read accesses")
- ;
-
- write_hits
- .name(name() + ".write_hits")
- .desc("DTB write hits")
- ;
-
- write_misses
- .name(name() + ".write_misses")
- .desc("DTB write misses")
- ;
-
- write_acv
- .name(name() + ".write_acv")
- .desc("DTB write access violations")
- ;
-
- write_accesses
- .name(name() + ".write_accesses")
- .desc("DTB write accesses")
- ;
-
- hits
- .name(name() + ".hits")
- .desc("DTB hits")
- ;
-
- misses
- .name(name() + ".misses")
- .desc("DTB misses")
- ;
-
- acv
- .name(name() + ".acv")
- .desc("DTB access violations")
- ;
-
- accesses
- .name(name() + ".accesses")
- .desc("DTB accesses")
- ;
-
- hits = read_hits + write_hits;
- misses = read_misses + write_misses;
- acv = read_acv + write_acv;
- accesses = read_accesses + write_accesses;
-}
+ }
-Fault
-AlphaDTB::translate(RequestPtr &req, ThreadContext *tc, bool write) const
-{
- Addr pc = tc->readPC();
+ ///////////////////////////////////////////////////////////////////////
+ //
+ // Alpha DTB
+ //
+ DTB::DTB(const std::string &name, int size)
+ : TLB(name, size)
+ {}
+
+ void
+ DTB::regStats()
+ {
+ read_hits
+ .name(name() + ".read_hits")
+ .desc("DTB read hits")
+ ;
+
+ read_misses
+ .name(name() + ".read_misses")
+ .desc("DTB read misses")
+ ;
+
+ read_acv
+ .name(name() + ".read_acv")
+ .desc("DTB read access violations")
+ ;
+
+ read_accesses
+ .name(name() + ".read_accesses")
+ .desc("DTB read accesses")
+ ;
+
+ write_hits
+ .name(name() + ".write_hits")
+ .desc("DTB write hits")
+ ;
+
+ write_misses
+ .name(name() + ".write_misses")
+ .desc("DTB write misses")
+ ;
+
+ write_acv
+ .name(name() + ".write_acv")
+ .desc("DTB write access violations")
+ ;
+
+ write_accesses
+ .name(name() + ".write_accesses")
+ .desc("DTB write accesses")
+ ;
+
+ hits
+ .name(name() + ".hits")
+ .desc("DTB hits")
+ ;
+
+ misses
+ .name(name() + ".misses")
+ .desc("DTB misses")
+ ;
+
+ acv
+ .name(name() + ".acv")
+ .desc("DTB access violations")
+ ;
+
+ accesses
+ .name(name() + ".accesses")
+ .desc("DTB accesses")
+ ;
+
+ hits = read_hits + write_hits;
+ misses = read_misses + write_misses;
+ acv = read_acv + write_acv;
+ accesses = read_accesses + write_accesses;
+ }
- AlphaISA::mode_type mode =
- (AlphaISA::mode_type)DTB_CM_CM(tc->readMiscReg(AlphaISA::IPR_DTB_CM));
+ Fault
+ DTB::translate(RequestPtr &req, ThreadContext *tc, bool write) const
+ {
+ Addr pc = tc->readPC();
+ mode_type mode =
+ (mode_type)DTB_CM_CM(tc->readMiscReg(IPR_DTB_CM));
- /**
- * Check for alignment faults
- */
- if (req->getVaddr() & (req->getSize() - 1)) {
- DPRINTF(TLB, "Alignment Fault on %#x, size = %d", req->getVaddr(),
- req->getSize());
- uint64_t flags = write ? MM_STAT_WR_MASK : 0;
- return new DtbAlignmentFault(req->getVaddr(), req->getFlags(), flags);
- }
- if (pc & 0x1) {
- mode = (req->getFlags() & ALTMODE) ?
- (AlphaISA::mode_type)ALT_MODE_AM(
- tc->readMiscReg(AlphaISA::IPR_ALT_MODE))
- : AlphaISA::mode_kernel;
- }
+ /**
+ * Check for alignment faults
+ */
+ if (req->getVaddr() & (req->getSize() - 1)) {
+ DPRINTF(TLB, "Alignment Fault on %#x, size = %d", req->getVaddr(),
+ req->getSize());
+ uint64_t flags = write ? MM_STAT_WR_MASK : 0;
+ return new DtbAlignmentFault(req->getVaddr(), req->getFlags(), flags);
+ }
- if (req->getFlags() & PHYSICAL) {
- req->setPaddr(req->getVaddr());
- } else {
- // verify that this is a good virtual address
- if (!validVirtualAddress(req->getVaddr())) {
- if (write) { write_acv++; } else { read_acv++; }
- uint64_t flags = (write ? MM_STAT_WR_MASK : 0) |
- MM_STAT_BAD_VA_MASK |
- MM_STAT_ACV_MASK;
- return new DtbPageFault(req->getVaddr(), req->getFlags(), flags);
+ if (pc & 0x1) {
+ mode = (req->getFlags() & ALTMODE) ?
+ (mode_type)ALT_MODE_AM(
+ tc->readMiscReg(IPR_ALT_MODE))
+ : mode_kernel;
}
- // Check for "superpage" mapping
+ if (req->getFlags() & PHYSICAL) {
+ req->setPaddr(req->getVaddr());
+ } else {
+ // verify that this is a good virtual address
+ if (!validVirtualAddress(req->getVaddr())) {
+ if (write) { write_acv++; } else { read_acv++; }
+ uint64_t flags = (write ? MM_STAT_WR_MASK : 0) |
+ MM_STAT_BAD_VA_MASK |
+ MM_STAT_ACV_MASK;
+ return new DtbPageFault(req->getVaddr(), req->getFlags(), flags);
+ }
+
+ // Check for "superpage" mapping
#if ALPHA_TLASER
- if ((MCSR_SP(tc->readMiscReg(AlphaISA::IPR_MCSR)) & 2) &&
- VAddrSpaceEV5(req->getVaddr()) == 2) {
+ if ((MCSR_SP(tc->readMiscReg(IPR_MCSR)) & 2) &&
+ VAddrSpaceEV5(req->getVaddr()) == 2) {
#else
- if (VAddrSpaceEV6(req->getVaddr()) == 0x7e) {
+ if (VAddrSpaceEV6(req->getVaddr()) == 0x7e) {
#endif
- // only valid in kernel mode
- if (DTB_CM_CM(tc->readMiscReg(AlphaISA::IPR_DTB_CM)) !=
- AlphaISA::mode_kernel) {
- if (write) { write_acv++; } else { read_acv++; }
- uint64_t flags = ((write ? MM_STAT_WR_MASK : 0) |
- MM_STAT_ACV_MASK);
- return new DtbAcvFault(req->getVaddr(), req->getFlags(), flags);
- }
+ // only valid in kernel mode
+ if (DTB_CM_CM(tc->readMiscReg(IPR_DTB_CM)) !=
+ mode_kernel) {
+ if (write) { write_acv++; } else { read_acv++; }
+ uint64_t flags = ((write ? MM_STAT_WR_MASK : 0) |
+ MM_STAT_ACV_MASK);
+ return new DtbAcvFault(req->getVaddr(), req->getFlags(), flags);
+ }
- req->setPaddr(req->getVaddr() & PAddrImplMask);
+ req->setPaddr(req->getVaddr() & PAddrImplMask);
#if !ALPHA_TLASER
- // sign extend the physical address properly
- if (req->getPaddr() & PAddrUncachedBit40)
- req->setPaddr(req->getPaddr() | ULL(0xf0000000000));
- else
- req->setPaddr(req->getPaddr() & ULL(0xffffffffff));
+ // sign extend the physical address properly
+ if (req->getPaddr() & PAddrUncachedBit40)
+ req->setPaddr(req->getPaddr() | ULL(0xf0000000000));
+ else
+ req->setPaddr(req->getPaddr() & ULL(0xffffffffff));
#endif
- } else {
- if (write)
- write_accesses++;
- else
- read_accesses++;
-
- int asn = DTB_ASN_ASN(tc->readMiscReg(AlphaISA::IPR_DTB_ASN));
-
- // not a physical address: need to look up pte
- AlphaISA::PTE *pte = lookup(AlphaISA::VAddr(req->getVaddr()).vpn(),
- asn);
-
- if (!pte) {
- // page fault
- if (write) { write_misses++; } else { read_misses++; }
- uint64_t flags = (write ? MM_STAT_WR_MASK : 0) |
- MM_STAT_DTB_MISS_MASK;
- return (req->getFlags() & VPTE) ?
- (Fault)(new PDtbMissFault(req->getVaddr(), req->getFlags(),
- flags)) :
- (Fault)(new NDtbMissFault(req->getVaddr(), req->getFlags(),
- flags));
- }
-
- req->setPaddr((pte->ppn << AlphaISA::PageShift) +
- AlphaISA::VAddr(req->getVaddr()).offset());
-
- if (write) {
- if (!(pte->xwe & MODE2MASK(mode))) {
- // declare the instruction access fault
- write_acv++;
- uint64_t flags = MM_STAT_WR_MASK |
- MM_STAT_ACV_MASK |
- (pte->fonw ? MM_STAT_FONW_MASK : 0);
- return new DtbPageFault(req->getVaddr(), req->getFlags(), flags);
- }
- if (pte->fonw) {
- write_acv++;
- uint64_t flags = MM_STAT_WR_MASK |
- MM_STAT_FONW_MASK;
- return new DtbPageFault(req->getVaddr(), req->getFlags(), flags);
- }
} else {
- if (!(pte->xre & MODE2MASK(mode))) {
- read_acv++;
- uint64_t flags = MM_STAT_ACV_MASK |
- (pte->fonr ? MM_STAT_FONR_MASK : 0);
- return new DtbAcvFault(req->getVaddr(), req->getFlags(), flags);
+ if (write)
+ write_accesses++;
+ else
+ read_accesses++;
+
+ int asn = DTB_ASN_ASN(tc->readMiscReg(IPR_DTB_ASN));
+
+ // not a physical address: need to look up pte
+ PTE *pte = lookup(VAddr(req->getVaddr()).vpn(),
+ asn);
+
+ if (!pte) {
+ // page fault
+ if (write) { write_misses++; } else { read_misses++; }
+ uint64_t flags = (write ? MM_STAT_WR_MASK : 0) |
+ MM_STAT_DTB_MISS_MASK;
+ return (req->getFlags() & VPTE) ?
+ (Fault)(new PDtbMissFault(req->getVaddr(), req->getFlags(),
+ flags)) :
+ (Fault)(new NDtbMissFault(req->getVaddr(), req->getFlags(),
+ flags));
}
- if (pte->fonr) {
- read_acv++;
- uint64_t flags = MM_STAT_FONR_MASK;
- return new DtbPageFault(req->getVaddr(), req->getFlags(), flags);
+
+ req->setPaddr((pte->ppn << PageShift) +
+ VAddr(req->getVaddr()).offset());
+
+ if (write) {
+ if (!(pte->xwe & MODE2MASK(mode))) {
+ // declare the instruction access fault
+ write_acv++;
+ uint64_t flags = MM_STAT_WR_MASK |
+ MM_STAT_ACV_MASK |
+ (pte->fonw ? MM_STAT_FONW_MASK : 0);
+ return new DtbPageFault(req->getVaddr(), req->getFlags(), flags);
+ }
+ if (pte->fonw) {
+ write_acv++;
+ uint64_t flags = MM_STAT_WR_MASK |
+ MM_STAT_FONW_MASK;
+ return new DtbPageFault(req->getVaddr(), req->getFlags(), flags);
+ }
+ } else {
+ if (!(pte->xre & MODE2MASK(mode))) {
+ read_acv++;
+ uint64_t flags = MM_STAT_ACV_MASK |
+ (pte->fonr ? MM_STAT_FONR_MASK : 0);
+ return new DtbAcvFault(req->getVaddr(), req->getFlags(), flags);
+ }
+ if (pte->fonr) {
+ read_acv++;
+ uint64_t flags = MM_STAT_FONR_MASK;
+ return new DtbPageFault(req->getVaddr(), req->getFlags(), flags);
+ }
}
}
+
+ if (write)
+ write_hits++;
+ else
+ read_hits++;
}
- if (write)
- write_hits++;
- else
- read_hits++;
+ // check that the physical address is ok (catch bad physical addresses)
+ if (req->getPaddr() & ~PAddrImplMask)
+ return genMachineCheckFault();
+
+ return checkCacheability(req);
}
- // check that the physical address is ok (catch bad physical addresses)
- if (req->getPaddr() & ~PAddrImplMask)
- return genMachineCheckFault();
+ PTE &
+ TLB::index(bool advance)
+ {
+ PTE *pte = &table[nlu];
- return checkCacheability(req);
-}
+ if (advance)
+ nextnlu();
-AlphaISA::PTE &
-AlphaTLB::index(bool advance)
-{
- AlphaISA::PTE *pte = &table[nlu];
+ return *pte;
+ }
- if (advance)
- nextnlu();
+ DEFINE_SIM_OBJECT_CLASS_NAME("AlphaTLB", TLB)
- return *pte;
-}
+ BEGIN_DECLARE_SIM_OBJECT_PARAMS(ITB)
-DEFINE_SIM_OBJECT_CLASS_NAME("AlphaTLB", AlphaTLB)
+ Param<int> size;
-BEGIN_DECLARE_SIM_OBJECT_PARAMS(AlphaITB)
+ END_DECLARE_SIM_OBJECT_PARAMS(ITB)
- Param<int> size;
+ BEGIN_INIT_SIM_OBJECT_PARAMS(ITB)
-END_DECLARE_SIM_OBJECT_PARAMS(AlphaITB)
+ INIT_PARAM_DFLT(size, "TLB size", 48)
-BEGIN_INIT_SIM_OBJECT_PARAMS(AlphaITB)
+ END_INIT_SIM_OBJECT_PARAMS(ITB)
- INIT_PARAM_DFLT(size, "TLB size", 48)
-
-END_INIT_SIM_OBJECT_PARAMS(AlphaITB)
+ CREATE_SIM_OBJECT(ITB)
+ {
+ return new ITB(getInstanceName(), size);
+ }
-CREATE_SIM_OBJECT(AlphaITB)
-{
- return new AlphaITB(getInstanceName(), size);
-}
+ REGISTER_SIM_OBJECT("AlphaITB", ITB)
-REGISTER_SIM_OBJECT("AlphaITB", AlphaITB)
+ BEGIN_DECLARE_SIM_OBJECT_PARAMS(DTB)
-BEGIN_DECLARE_SIM_OBJECT_PARAMS(AlphaDTB)
+ Param<int> size;
- Param<int> size;
+ END_DECLARE_SIM_OBJECT_PARAMS(DTB)
-END_DECLARE_SIM_OBJECT_PARAMS(AlphaDTB)
+ BEGIN_INIT_SIM_OBJECT_PARAMS(DTB)
-BEGIN_INIT_SIM_OBJECT_PARAMS(AlphaDTB)
+ INIT_PARAM_DFLT(size, "TLB size", 64)
- INIT_PARAM_DFLT(size, "TLB size", 64)
+ END_INIT_SIM_OBJECT_PARAMS(DTB)
-END_INIT_SIM_OBJECT_PARAMS(AlphaDTB)
+ CREATE_SIM_OBJECT(DTB)
+ {
+ return new DTB(getInstanceName(), size);
+ }
-CREATE_SIM_OBJECT(AlphaDTB)
-{
- return new AlphaDTB(getInstanceName(), size);
+ REGISTER_SIM_OBJECT("AlphaDTB", DTB)
}
-
-REGISTER_SIM_OBJECT("AlphaDTB", AlphaDTB)
-