summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/arch/alpha/tlb.cc926
-rw-r--r--src/arch/alpha/tlb.hh158
-rw-r--r--src/cpu/simple/atomic.cc4
-rw-r--r--src/cpu/simple/base.hh11
-rw-r--r--src/cpu/simple/timing.cc4
-rw-r--r--src/cpu/simple_thread.cc2
-rw-r--r--src/cpu/simple_thread.hh10
-rw-r--r--src/cpu/thread_context.hh17
8 files changed, 573 insertions, 559 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)
-
diff --git a/src/arch/alpha/tlb.hh b/src/arch/alpha/tlb.hh
index 955460649..ea5ba5539 100644
--- a/src/arch/alpha/tlb.hh
+++ b/src/arch/alpha/tlb.hh
@@ -36,6 +36,7 @@
#include "arch/alpha/ev5.hh"
#include "arch/alpha/isa_traits.hh"
+#include "arch/alpha/pagetable.hh"
#include "arch/alpha/utility.hh"
#include "arch/alpha/vtophys.hh"
#include "base/statistics.hh"
@@ -45,82 +46,87 @@
class ThreadContext;
-class AlphaTLB : public SimObject
+namespace AlphaISA
{
- protected:
- typedef std::multimap<Addr, int> PageTable;
- PageTable lookupTable; // Quick lookup into page table
-
- AlphaISA::PTE *table; // the Page Table
- int size; // TLB Size
- int nlu; // not last used entry (for replacement)
-
- void nextnlu() { if (++nlu >= size) nlu = 0; }
- AlphaISA::PTE *lookup(Addr vpn, uint8_t asn) const;
-
- public:
- AlphaTLB(const std::string &name, int size);
- virtual ~AlphaTLB();
-
- int getsize() const { return size; }
-
- AlphaISA::PTE &index(bool advance = true);
- void insert(Addr vaddr, AlphaISA::PTE &pte);
-
- void flushAll();
- void flushProcesses();
- void flushAddr(Addr addr, uint8_t asn);
-
- // static helper functions... really EV5 VM traits
- static bool validVirtualAddress(Addr vaddr) {
- // unimplemented bits must be all 0 or all 1
- Addr unimplBits = vaddr & EV5::VAddrUnImplMask;
- return (unimplBits == 0) || (unimplBits == EV5::VAddrUnImplMask);
- }
-
- static Fault checkCacheability(RequestPtr &req);
-
- // Checkpointing
- virtual void serialize(std::ostream &os);
- virtual void unserialize(Checkpoint *cp, const std::string &section);
-};
-
-class AlphaITB : public AlphaTLB
-{
- protected:
- mutable Stats::Scalar<> hits;
- mutable Stats::Scalar<> misses;
- mutable Stats::Scalar<> acv;
- mutable Stats::Formula accesses;
-
- public:
- AlphaITB(const std::string &name, int size);
- virtual void regStats();
-
- Fault translate(RequestPtr &req, ThreadContext *tc) const;
-};
-
-class AlphaDTB : public AlphaTLB
-{
- protected:
- mutable Stats::Scalar<> read_hits;
- mutable Stats::Scalar<> read_misses;
- mutable Stats::Scalar<> read_acv;
- mutable Stats::Scalar<> read_accesses;
- mutable Stats::Scalar<> write_hits;
- mutable Stats::Scalar<> write_misses;
- mutable Stats::Scalar<> write_acv;
- mutable Stats::Scalar<> write_accesses;
- Stats::Formula hits;
- Stats::Formula misses;
- Stats::Formula acv;
- Stats::Formula accesses;
-
- public:
- AlphaDTB(const std::string &name, int size);
- virtual void regStats();
-
- Fault translate(RequestPtr &req, ThreadContext *tc, bool write) const;
-};
+ class PTE;
+
+ class TLB : public SimObject
+ {
+ protected:
+ typedef std::multimap<Addr, int> PageTable;
+ PageTable lookupTable; // Quick lookup into page table
+
+ PTE *table; // the Page Table
+ int size; // TLB Size
+ int nlu; // not last used entry (for replacement)
+
+ void nextnlu() { if (++nlu >= size) nlu = 0; }
+ PTE *lookup(Addr vpn, uint8_t asn) const;
+
+ public:
+ TLB(const std::string &name, int size);
+ virtual ~TLB();
+
+ int getsize() const { return size; }
+
+ PTE &index(bool advance = true);
+ void insert(Addr vaddr, PTE &pte);
+
+ void flushAll();
+ void flushProcesses();
+ void flushAddr(Addr addr, uint8_t asn);
+
+ // static helper functions... really EV5 VM traits
+ static bool validVirtualAddress(Addr vaddr) {
+ // unimplemented bits must be all 0 or all 1
+ Addr unimplBits = vaddr & EV5::VAddrUnImplMask;
+ return (unimplBits == 0) || (unimplBits == EV5::VAddrUnImplMask);
+ }
+
+ static Fault checkCacheability(RequestPtr &req);
+
+ // Checkpointing
+ virtual void serialize(std::ostream &os);
+ virtual void unserialize(Checkpoint *cp, const std::string &section);
+ };
+
+ class ITB : public TLB
+ {
+ protected:
+ mutable Stats::Scalar<> hits;
+ mutable Stats::Scalar<> misses;
+ mutable Stats::Scalar<> acv;
+ mutable Stats::Formula accesses;
+
+ public:
+ ITB(const std::string &name, int size);
+ virtual void regStats();
+
+ Fault translate(RequestPtr &req, ThreadContext *tc) const;
+ };
+
+ class DTB : public TLB
+ {
+ protected:
+ mutable Stats::Scalar<> read_hits;
+ mutable Stats::Scalar<> read_misses;
+ mutable Stats::Scalar<> read_acv;
+ mutable Stats::Scalar<> read_accesses;
+ mutable Stats::Scalar<> write_hits;
+ mutable Stats::Scalar<> write_misses;
+ mutable Stats::Scalar<> write_acv;
+ mutable Stats::Scalar<> write_accesses;
+ Stats::Formula hits;
+ Stats::Formula misses;
+ Stats::Formula acv;
+ Stats::Formula accesses;
+
+ public:
+ DTB(const std::string &name, int size);
+ virtual void regStats();
+
+ Fault translate(RequestPtr &req, ThreadContext *tc, bool write) const;
+ };
+}
#endif // __ALPHA_MEMORY_HH__
diff --git a/src/cpu/simple/atomic.cc b/src/cpu/simple/atomic.cc
index 11e4d2acb..1e12aadef 100644
--- a/src/cpu/simple/atomic.cc
+++ b/src/cpu/simple/atomic.cc
@@ -513,8 +513,8 @@ BEGIN_DECLARE_SIM_OBJECT_PARAMS(AtomicSimpleCPU)
Param<int> cpu_id;
#if FULL_SYSTEM
- SimObjectParam<AlphaITB *> itb;
- SimObjectParam<AlphaDTB *> dtb;
+ SimObjectParam<TheISA::ITB *> itb;
+ SimObjectParam<TheISA::DTB *> dtb;
Param<Tick> profile;
#else
SimObjectParam<Process *> workload;
diff --git a/src/cpu/simple/base.hh b/src/cpu/simple/base.hh
index af6b6f835..1a9fc5127 100644
--- a/src/cpu/simple/base.hh
+++ b/src/cpu/simple/base.hh
@@ -47,8 +47,11 @@
// forward declarations
#if FULL_SYSTEM
class Processor;
-class AlphaITB;
-class AlphaDTB;
+namespace TheISA
+{
+ class ITB;
+ class DTB;
+}
class MemObject;
class RemoteGDB;
@@ -97,8 +100,8 @@ class BaseSimpleCPU : public BaseCPU
{
MemObject *mem;
#if FULL_SYSTEM
- AlphaITB *itb;
- AlphaDTB *dtb;
+ TheISA::ITB *itb;
+ TheISA::DTB *dtb;
#else
Process *process;
#endif
diff --git a/src/cpu/simple/timing.cc b/src/cpu/simple/timing.cc
index fe6775ea4..438417882 100644
--- a/src/cpu/simple/timing.cc
+++ b/src/cpu/simple/timing.cc
@@ -665,8 +665,8 @@ BEGIN_DECLARE_SIM_OBJECT_PARAMS(TimingSimpleCPU)
Param<int> cpu_id;
#if FULL_SYSTEM
- SimObjectParam<AlphaITB *> itb;
- SimObjectParam<AlphaDTB *> dtb;
+ SimObjectParam<TheISA::ITB *> itb;
+ SimObjectParam<TheISA::DTB *> dtb;
Param<Tick> profile;
#else
SimObjectParam<Process *> workload;
diff --git a/src/cpu/simple_thread.cc b/src/cpu/simple_thread.cc
index 4fc47c982..95018ff8c 100644
--- a/src/cpu/simple_thread.cc
+++ b/src/cpu/simple_thread.cc
@@ -60,7 +60,7 @@ using namespace std;
// constructor
#if FULL_SYSTEM
SimpleThread::SimpleThread(BaseCPU *_cpu, int _thread_num, System *_sys,
- AlphaITB *_itb, AlphaDTB *_dtb,
+ TheISA::ITB *_itb, TheISA::DTB *_dtb,
bool use_kernel_stats)
: ThreadState(-1, _thread_num), cpu(_cpu), system(_sys), itb(_itb),
dtb(_dtb)
diff --git a/src/cpu/simple_thread.hh b/src/cpu/simple_thread.hh
index fe22e6c43..10ec8faaa 100644
--- a/src/cpu/simple_thread.hh
+++ b/src/cpu/simple_thread.hh
@@ -107,14 +107,14 @@ class SimpleThread : public ThreadState
System *system;
#if FULL_SYSTEM
- AlphaITB *itb;
- AlphaDTB *dtb;
+ TheISA::ITB *itb;
+ TheISA::DTB *dtb;
#endif
// constructor: initialize SimpleThread from given process structure
#if FULL_SYSTEM
SimpleThread(BaseCPU *_cpu, int _thread_num, System *_system,
- AlphaITB *_itb, AlphaDTB *_dtb,
+ TheISA::ITB *_itb, TheISA::DTB *_dtb,
bool use_kernel_stats = true);
#else
SimpleThread(BaseCPU *_cpu, int _thread_num, Process *_process, int _asid,
@@ -201,9 +201,9 @@ class SimpleThread : public ThreadState
#if FULL_SYSTEM
System *getSystemPtr() { return system; }
- AlphaITB *getITBPtr() { return itb; }
+ TheISA::ITB *getITBPtr() { return itb; }
- AlphaDTB *getDTBPtr() { return dtb; }
+ TheISA::DTB *getDTBPtr() { return dtb; }
FunctionalPort *getPhysPort() { return physPort; }
diff --git a/src/cpu/thread_context.hh b/src/cpu/thread_context.hh
index 73046097d..448d67d02 100644
--- a/src/cpu/thread_context.hh
+++ b/src/cpu/thread_context.hh
@@ -31,9 +31,9 @@
#ifndef __CPU_THREAD_CONTEXT_HH__
#define __CPU_THREAD_CONTEXT_HH__
-#include "arch/types.hh"
#include "arch/regfile.hh"
#include "arch/syscallreturn.hh"
+#include "arch/types.hh"
#include "config/full_system.hh"
#include "mem/request.hh"
#include "sim/faults.hh"
@@ -43,8 +43,11 @@
// @todo: Figure out a more architecture independent way to obtain the ITB and
// DTB pointers.
-class AlphaDTB;
-class AlphaITB;
+namespace TheISA
+{
+ class DTB;
+ class ITB;
+}
class BaseCPU;
class EndQuiesceEvent;
class Event;
@@ -117,9 +120,9 @@ class ThreadContext
#if FULL_SYSTEM
virtual System *getSystemPtr() = 0;
- virtual AlphaITB *getITBPtr() = 0;
+ virtual TheISA::ITB *getITBPtr() = 0;
- virtual AlphaDTB * getDTBPtr() = 0;
+ virtual TheISA::DTB *getDTBPtr() = 0;
virtual Kernel::Statistics *getKernelStats() = 0;
@@ -292,9 +295,9 @@ class ProxyThreadContext : public ThreadContext
#if FULL_SYSTEM
System *getSystemPtr() { return actualTC->getSystemPtr(); }
- AlphaITB *getITBPtr() { return actualTC->getITBPtr(); }
+ TheISA::ITB *getITBPtr() { return actualTC->getITBPtr(); }
- AlphaDTB *getDTBPtr() { return actualTC->getDTBPtr(); }
+ TheISA::DTB *getDTBPtr() { return actualTC->getDTBPtr(); }
Kernel::Statistics *getKernelStats() { return actualTC->getKernelStats(); }