summaryrefslogtreecommitdiff
path: root/src/arch/alpha
diff options
context:
space:
mode:
authorGabe Black <gblack@eecs.umich.edu>2007-08-26 20:33:57 -0700
committerGabe Black <gblack@eecs.umich.edu>2007-08-26 20:33:57 -0700
commit9b49a78cfdc0bd6f8afdb0d066ea39778095d7ac (patch)
treeb4a977c8d7379ac552d245847825a73b61bf8c5b /src/arch/alpha
parent80d51650c8bce1503e5ce3877f3bfe21d3e57d45 (diff)
downloadgem5-9b49a78cfdc0bd6f8afdb0d066ea39778095d7ac.tar.xz
Address translation: Make the page table more flexible.
The page table now stores actual page table entries. It is still a templated class here, but this will be corrected in the near future. --HG-- extra : convert_revision : 804dcc6320414c2b3ab76a74a15295bd24e1d13d
Diffstat (limited to 'src/arch/alpha')
-rw-r--r--src/arch/alpha/ev5.cc55
-rw-r--r--src/arch/alpha/faults.cc48
-rw-r--r--src/arch/alpha/faults.hh5
-rw-r--r--src/arch/alpha/pagetable.cc6
-rw-r--r--src/arch/alpha/pagetable.hh9
-rw-r--r--src/arch/alpha/tlb.cc105
-rw-r--r--src/arch/alpha/tlb.hh34
7 files changed, 133 insertions, 129 deletions
diff --git a/src/arch/alpha/ev5.cc b/src/arch/alpha/ev5.cc
index 123506e40..5dc49623e 100644
--- a/src/arch/alpha/ev5.cc
+++ b/src/arch/alpha/ev5.cc
@@ -245,15 +245,16 @@ AlphaISA::MiscRegFile::readIpr(int idx, ThreadContext *tc)
case AlphaISA::IPR_DTB_PTE:
{
- AlphaISA::PTE &pte = tc->getDTBPtr()->index(!tc->misspeculating());
-
- retval |= ((uint64_t)pte.ppn & ULL(0x7ffffff)) << 32;
- retval |= ((uint64_t)pte.xre & ULL(0xf)) << 8;
- retval |= ((uint64_t)pte.xwe & ULL(0xf)) << 12;
- retval |= ((uint64_t)pte.fonr & ULL(0x1)) << 1;
- retval |= ((uint64_t)pte.fonw & ULL(0x1))<< 2;
- retval |= ((uint64_t)pte.asma & ULL(0x1)) << 4;
- retval |= ((uint64_t)pte.asn & ULL(0x7f)) << 57;
+ AlphaISA::TlbEntry &entry
+ = tc->getDTBPtr()->index(!tc->misspeculating());
+
+ retval |= ((uint64_t)entry.ppn & ULL(0x7ffffff)) << 32;
+ retval |= ((uint64_t)entry.xre & ULL(0xf)) << 8;
+ retval |= ((uint64_t)entry.xwe & ULL(0xf)) << 12;
+ retval |= ((uint64_t)entry.fonr & ULL(0x1)) << 1;
+ retval |= ((uint64_t)entry.fonw & ULL(0x1))<< 2;
+ retval |= ((uint64_t)entry.asma & ULL(0x1)) << 4;
+ retval |= ((uint64_t)entry.asn & ULL(0x7f)) << 57;
}
break;
@@ -480,7 +481,7 @@ AlphaISA::MiscRegFile::setIpr(int idx, uint64_t val, ThreadContext *tc)
break;
case AlphaISA::IPR_DTB_TAG: {
- struct AlphaISA::PTE pte;
+ struct AlphaISA::TlbEntry entry;
// FIXME: granularity hints NYI...
if (EV5::DTB_PTE_GH(ipr[AlphaISA::IPR_DTB_PTE]) != 0)
@@ -490,21 +491,21 @@ AlphaISA::MiscRegFile::setIpr(int idx, uint64_t val, ThreadContext *tc)
ipr[idx] = val;
// construct PTE for new entry
- pte.ppn = EV5::DTB_PTE_PPN(ipr[AlphaISA::IPR_DTB_PTE]);
- pte.xre = EV5::DTB_PTE_XRE(ipr[AlphaISA::IPR_DTB_PTE]);
- pte.xwe = EV5::DTB_PTE_XWE(ipr[AlphaISA::IPR_DTB_PTE]);
- pte.fonr = EV5::DTB_PTE_FONR(ipr[AlphaISA::IPR_DTB_PTE]);
- pte.fonw = EV5::DTB_PTE_FONW(ipr[AlphaISA::IPR_DTB_PTE]);
- pte.asma = EV5::DTB_PTE_ASMA(ipr[AlphaISA::IPR_DTB_PTE]);
- pte.asn = EV5::DTB_ASN_ASN(ipr[AlphaISA::IPR_DTB_ASN]);
+ entry.ppn = EV5::DTB_PTE_PPN(ipr[AlphaISA::IPR_DTB_PTE]);
+ entry.xre = EV5::DTB_PTE_XRE(ipr[AlphaISA::IPR_DTB_PTE]);
+ entry.xwe = EV5::DTB_PTE_XWE(ipr[AlphaISA::IPR_DTB_PTE]);
+ entry.fonr = EV5::DTB_PTE_FONR(ipr[AlphaISA::IPR_DTB_PTE]);
+ entry.fonw = EV5::DTB_PTE_FONW(ipr[AlphaISA::IPR_DTB_PTE]);
+ entry.asma = EV5::DTB_PTE_ASMA(ipr[AlphaISA::IPR_DTB_PTE]);
+ entry.asn = EV5::DTB_ASN_ASN(ipr[AlphaISA::IPR_DTB_ASN]);
// insert new TAG/PTE value into data TLB
- tc->getDTBPtr()->insert(val, pte);
+ tc->getDTBPtr()->insert(val, entry);
}
break;
case AlphaISA::IPR_ITB_PTE: {
- struct AlphaISA::PTE pte;
+ struct AlphaISA::TlbEntry entry;
// FIXME: granularity hints NYI...
if (EV5::ITB_PTE_GH(val) != 0)
@@ -514,16 +515,16 @@ AlphaISA::MiscRegFile::setIpr(int idx, uint64_t val, ThreadContext *tc)
ipr[idx] = val;
// construct PTE for new entry
- pte.ppn = EV5::ITB_PTE_PPN(val);
- pte.xre = EV5::ITB_PTE_XRE(val);
- pte.xwe = 0;
- pte.fonr = EV5::ITB_PTE_FONR(val);
- pte.fonw = EV5::ITB_PTE_FONW(val);
- pte.asma = EV5::ITB_PTE_ASMA(val);
- pte.asn = EV5::ITB_ASN_ASN(ipr[AlphaISA::IPR_ITB_ASN]);
+ entry.ppn = EV5::ITB_PTE_PPN(val);
+ entry.xre = EV5::ITB_PTE_XRE(val);
+ entry.xwe = 0;
+ entry.fonr = EV5::ITB_PTE_FONR(val);
+ entry.fonw = EV5::ITB_PTE_FONW(val);
+ entry.asma = EV5::ITB_PTE_ASMA(val);
+ entry.asn = EV5::ITB_ASN_ASN(ipr[AlphaISA::IPR_ITB_ASN]);
// insert new TAG/PTE value into data TLB
- tc->getITBPtr()->insert(ipr[AlphaISA::IPR_ITB_TAG], pte);
+ tc->getITBPtr()->insert(ipr[AlphaISA::IPR_ITB_TAG], entry);
}
break;
diff --git a/src/arch/alpha/faults.cc b/src/arch/alpha/faults.cc
index d81b55b33..7d4de902a 100644
--- a/src/arch/alpha/faults.cc
+++ b/src/arch/alpha/faults.cc
@@ -185,18 +185,18 @@ void ItbPageFault::invoke(ThreadContext * tc)
VAddr vaddr(pc);
VAddr paddr(physaddr);
- PTE pte;
- pte.tag = vaddr.vpn();
- pte.ppn = paddr.vpn();
- pte.xre = 15; //This can be read in all modes.
- pte.xwe = 1; //This can be written only in kernel mode.
- pte.asn = p->M5_pid; //Address space number.
- pte.asma = false; //Only match on this ASN.
- pte.fonr = false; //Don't fault on read.
- pte.fonw = false; //Don't fault on write.
- pte.valid = true; //This entry is valid.
-
- tc->getITBPtr()->insert(vaddr.page(), pte);
+ TlbEntry entry;
+ entry.tag = vaddr.vpn();
+ entry.ppn = paddr.vpn();
+ entry.xre = 15; //This can be read in all modes.
+ entry.xwe = 1; //This can be written only in kernel mode.
+ entry.asn = p->M5_pid; //Address space number.
+ entry.asma = false; //Only match on this ASN.
+ entry.fonr = false; //Don't fault on read.
+ entry.fonw = false; //Don't fault on write.
+ entry.valid = true; //This entry is valid.
+
+ tc->getITBPtr()->insert(vaddr.page(), entry);
}
}
@@ -214,18 +214,18 @@ void NDtbMissFault::invoke(ThreadContext * tc)
} else {
VAddr paddr(physaddr);
- PTE pte;
- pte.tag = vaddr.vpn();
- pte.ppn = paddr.vpn();
- pte.xre = 15; //This can be read in all modes.
- pte.xwe = 15; //This can be written in all modes.
- pte.asn = p->M5_pid; //Address space number.
- pte.asma = false; //Only match on this ASN.
- pte.fonr = false; //Don't fault on read.
- pte.fonw = false; //Don't fault on write.
- pte.valid = true; //This entry is valid.
-
- tc->getDTBPtr()->insert(vaddr.page(), pte);
+ TlbEntry entry;
+ entry.tag = vaddr.vpn();
+ entry.ppn = paddr.vpn();
+ entry.xre = 15; //This can be read in all modes.
+ entry.xwe = 15; //This can be written in all modes.
+ entry.asn = p->M5_pid; //Address space number.
+ entry.asma = false; //Only match on this ASN.
+ entry.fonr = false; //Don't fault on read.
+ entry.fonw = false; //Don't fault on write.
+ entry.valid = true; //This entry is valid.
+
+ tc->getDTBPtr()->insert(vaddr.page(), entry);
}
}
diff --git a/src/arch/alpha/faults.hh b/src/arch/alpha/faults.hh
index 49ba25966..74699b2b5 100644
--- a/src/arch/alpha/faults.hh
+++ b/src/arch/alpha/faults.hh
@@ -88,11 +88,6 @@ static inline Fault genMachineCheckFault()
return new MachineCheckFault;
}
-static inline Fault genAlignmentFault()
-{
- return new AlignmentFault;
-}
-
class ResetFault : public AlphaFault
{
private:
diff --git a/src/arch/alpha/pagetable.cc b/src/arch/alpha/pagetable.cc
index 0c26ccbe3..3f9537834 100644
--- a/src/arch/alpha/pagetable.cc
+++ b/src/arch/alpha/pagetable.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2006 The Regents of The University of Michigan
+ * Copyright (c) 2006-2007 The Regents of The University of Michigan
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -34,7 +34,7 @@
namespace AlphaISA
{
void
- PTE::serialize(std::ostream &os)
+ TlbEntry::serialize(std::ostream &os)
{
SERIALIZE_SCALAR(tag);
SERIALIZE_SCALAR(ppn);
@@ -48,7 +48,7 @@ namespace AlphaISA
}
void
- PTE::unserialize(Checkpoint *cp, const std::string &section)
+ TlbEntry::unserialize(Checkpoint *cp, const std::string &section)
{
UNSERIALIZE_SCALAR(tag);
UNSERIALIZE_SCALAR(ppn);
diff --git a/src/arch/alpha/pagetable.hh b/src/arch/alpha/pagetable.hh
index c7e1c8923..0b885bc36 100644
--- a/src/arch/alpha/pagetable.hh
+++ b/src/arch/alpha/pagetable.hh
@@ -89,9 +89,14 @@ namespace AlphaISA {
Addr paddr() const { return _pfn() << PageShift; }
};
- // ITB/DTB page table entry
- struct PTE
+ // ITB/DTB table entry
+ struct TlbEntry
{
+ //Construct an entry that maps to physical address addr.
+ TlbEntry(Addr addr)
+ {
+ }
+
Addr tag; // virtual page number tag
Addr ppn; // physical page number
uint8_t xre; // read permissions - VMEM_PERM_* mask
diff --git a/src/arch/alpha/tlb.cc b/src/arch/alpha/tlb.cc
index f701c423d..628d7ad6b 100644
--- a/src/arch/alpha/tlb.cc
+++ b/src/arch/alpha/tlb.cc
@@ -62,8 +62,8 @@ bool uncacheBit40 = false;
TLB::TLB(const string &name, int s)
: SimObject(name), size(s), nlu(0)
{
- table = new PTE[size];
- memset(table, 0, sizeof(PTE[size]));
+ table = new TlbEntry[size];
+ memset(table, 0, sizeof(TlbEntry[size]));
flushCache();
}
@@ -74,23 +74,23 @@ TLB::~TLB()
}
// look up an entry in the TLB
-PTE *
+TlbEntry *
TLB::lookup(Addr vpn, uint8_t asn)
{
// assume not found...
- PTE *retval = NULL;
-
- if (PTECache[0]) {
- if (vpn == PTECache[0]->tag &&
- (PTECache[0]->asma || PTECache[0]->asn == asn))
- retval = PTECache[0];
- else if (PTECache[1]) {
- if (vpn == PTECache[1]->tag &&
- (PTECache[1]->asma || PTECache[1]->asn == asn))
- retval = PTECache[1];
- else if (PTECache[2] && vpn == PTECache[2]->tag &&
- (PTECache[2]->asma || PTECache[2]->asn == asn))
- retval = PTECache[2];
+ TlbEntry *retval = NULL;
+
+ if (EntryCache[0]) {
+ if (vpn == EntryCache[0]->tag &&
+ (EntryCache[0]->asma || EntryCache[0]->asn == asn))
+ retval = EntryCache[0];
+ else if (EntryCache[1]) {
+ if (vpn == EntryCache[1]->tag &&
+ (EntryCache[1]->asma || EntryCache[1]->asn == asn))
+ retval = EntryCache[1];
+ else if (EntryCache[2] && vpn == EntryCache[2]->tag &&
+ (EntryCache[2]->asma || EntryCache[2]->asn == asn))
+ retval = EntryCache[2];
}
}
@@ -99,10 +99,10 @@ TLB::lookup(Addr vpn, uint8_t asn)
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 = updateCache(pte);
+ TlbEntry *entry = &table[index];
+ assert(entry->valid);
+ if (vpn == entry->tag && (entry->asma || entry->asn == asn)) {
+ retval = updateCache(entry);
break;
}
@@ -157,7 +157,7 @@ TLB::checkCacheability(RequestPtr &req)
// insert a new TLB entry
void
-TLB::insert(Addr addr, PTE &pte)
+TLB::insert(Addr addr, TlbEntry &entry)
{
flushCache();
VAddr vaddr = addr;
@@ -181,9 +181,9 @@ TLB::insert(Addr addr, PTE &pte)
lookupTable.erase(i);
}
- DPRINTF(TLB, "insert @%d: %#x -> %#x\n", nlu, vaddr.vpn(), pte.ppn);
+ DPRINTF(TLB, "insert @%d: %#x -> %#x\n", nlu, vaddr.vpn(), entry.ppn);
- table[nlu] = pte;
+ table[nlu] = entry;
table[nlu].tag = vaddr.vpn();
table[nlu].valid = true;
@@ -195,7 +195,7 @@ void
TLB::flushAll()
{
DPRINTF(TLB, "flushAll\n");
- memset(table, 0, sizeof(PTE[size]));
+ memset(table, 0, sizeof(TlbEntry[size]));
flushCache();
lookupTable.clear();
nlu = 0;
@@ -209,17 +209,17 @@ TLB::flushProcesses()
PageTable::iterator end = lookupTable.end();
while (i != end) {
int index = i->second;
- PTE *pte = &table[index];
- assert(pte->valid);
+ TlbEntry *entry = &table[index];
+ assert(entry->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;
+ if (!entry->asma) {
+ DPRINTF(TLB, "flush @%d: %#x -> %#x\n", index, entry->tag, entry->ppn);
+ entry->valid = false;
lookupTable.erase(cur);
}
}
@@ -237,15 +237,15 @@ TLB::flushAddr(Addr addr, uint8_t asn)
while (i != lookupTable.end() && i->first == vaddr.vpn()) {
int index = i->second;
- PTE *pte = &table[index];
- assert(pte->valid);
+ TlbEntry *entry = &table[index];
+ assert(entry->valid);
- if (vaddr.vpn() == pte->tag && (pte->asma || pte->asn == asn)) {
+ if (vaddr.vpn() == entry->tag && (entry->asma || entry->asn == asn)) {
DPRINTF(TLB, "flushaddr @%d: %#x -> %#x\n", index, vaddr.vpn(),
- pte->ppn);
+ entry->ppn);
// invalidate this entry
- pte->valid = false;
+ entry->valid = false;
lookupTable.erase(i++);
} else {
@@ -262,7 +262,7 @@ TLB::serialize(ostream &os)
SERIALIZE_SCALAR(nlu);
for (int i = 0; i < size; i++) {
- nameOut(os, csprintf("%s.PTE%d", name(), i));
+ nameOut(os, csprintf("%s.Entry%d", name(), i));
table[i].serialize(os);
}
}
@@ -274,7 +274,7 @@ TLB::unserialize(Checkpoint *cp, const string &section)
UNSERIALIZE_SCALAR(nlu);
for (int i = 0; i < size; i++) {
- table[i].unserialize(cp, csprintf("%s.PTE%d", section, i));
+ table[i].unserialize(cp, csprintf("%s.Entry%d", section, i));
if (table[i].valid) {
lookupTable.insert(make_pair(table[i].tag, i));
}
@@ -364,20 +364,20 @@ ITB::translate(RequestPtr &req, ThreadContext *tc)
} else {
// not a physical address: need to look up pte
int asn = DTB_ASN_ASN(tc->readMiscRegNoEffect(IPR_DTB_ASN));
- PTE *pte = lookup(VAddr(req->getVaddr()).vpn(),
+ TlbEntry *entry = lookup(VAddr(req->getVaddr()).vpn(),
asn);
- if (!pte) {
+ if (!entry) {
misses++;
return new ItbPageFault(req->getVaddr());
}
- req->setPaddr((pte->ppn << PageShift) +
+ req->setPaddr((entry->ppn << PageShift) +
(VAddr(req->getVaddr()).offset()
& ~3));
// check permissions for this access
- if (!(pte->xre &
+ if (!(entry->xre &
(1 << ICM_CM(tc->readMiscRegNoEffect(IPR_ICM))))) {
// instruction access fault
acv++;
@@ -548,10 +548,9 @@ DTB::translate(RequestPtr &req, ThreadContext *tc, bool write)
int asn = DTB_ASN_ASN(tc->readMiscRegNoEffect(IPR_DTB_ASN));
// not a physical address: need to look up pte
- PTE *pte = lookup(VAddr(req->getVaddr()).vpn(),
- asn);
+ TlbEntry *entry = lookup(VAddr(req->getVaddr()).vpn(), asn);
- if (!pte) {
+ if (!entry) {
// page fault
if (write) { write_misses++; } else { read_misses++; }
uint64_t flags = (write ? MM_STAT_WR_MASK : 0) |
@@ -563,32 +562,32 @@ DTB::translate(RequestPtr &req, ThreadContext *tc, bool write)
flags));
}
- req->setPaddr((pte->ppn << PageShift) +
+ req->setPaddr((entry->ppn << PageShift) +
VAddr(req->getVaddr()).offset());
if (write) {
- if (!(pte->xwe & MODE2MASK(mode))) {
+ if (!(entry->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);
+ (entry->fonw ? MM_STAT_FONW_MASK : 0);
return new DtbPageFault(req->getVaddr(), req->getFlags(), flags);
}
- if (pte->fonw) {
+ if (entry->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))) {
+ if (!(entry->xre & MODE2MASK(mode))) {
read_acv++;
uint64_t flags = MM_STAT_ACV_MASK |
- (pte->fonr ? MM_STAT_FONR_MASK : 0);
+ (entry->fonr ? MM_STAT_FONR_MASK : 0);
return new DtbAcvFault(req->getVaddr(), req->getFlags(), flags);
}
- if (pte->fonr) {
+ if (entry->fonr) {
read_acv++;
uint64_t flags = MM_STAT_FONR_MASK;
return new DtbPageFault(req->getVaddr(), req->getFlags(), flags);
@@ -609,15 +608,15 @@ DTB::translate(RequestPtr &req, ThreadContext *tc, bool write)
return checkCacheability(req);
}
-PTE &
+TlbEntry &
TLB::index(bool advance)
{
- PTE *pte = &table[nlu];
+ TlbEntry *entry = &table[nlu];
if (advance)
nextnlu();
- return *pte;
+ return *entry;
}
/* end namespace AlphaISA */ }
diff --git a/src/arch/alpha/tlb.hh b/src/arch/alpha/tlb.hh
index a4255f3c5..8df47dbec 100644
--- a/src/arch/alpha/tlb.hh
+++ b/src/arch/alpha/tlb.hh
@@ -48,20 +48,20 @@ class ThreadContext;
namespace AlphaISA
{
- class PTE;
+ class TlbEntry;
class TLB : public SimObject
{
protected:
typedef std::multimap<Addr, int> PageTable;
- PageTable lookupTable; // Quick lookup into page table
+ PageTable lookupTable; // Quick lookup into page table
- PTE *table; // the Page Table
- int size; // TLB Size
- int nlu; // not last used entry (for replacement)
+ TlbEntry *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);
+ TlbEntry *lookup(Addr vpn, uint8_t asn);
public:
TLB(const std::string &name, int size);
@@ -69,8 +69,8 @@ namespace AlphaISA
int getsize() const { return size; }
- PTE &index(bool advance = true);
- void insert(Addr vaddr, PTE &pte);
+ TlbEntry &index(bool advance = true);
+ void insert(Addr vaddr, TlbEntry &entry);
void flushAll();
void flushProcesses();
@@ -90,13 +90,17 @@ namespace AlphaISA
virtual void unserialize(Checkpoint *cp, const std::string &section);
// Most recently used page table entries
- PTE *PTECache[3];
- inline void flushCache() { memset(PTECache, 0, 3 * sizeof(PTE*)); }
- inline PTE* updateCache(PTE *pte) {
- PTECache[2] = PTECache[1];
- PTECache[1] = PTECache[0];
- PTECache[0] = pte;
- return pte;
+ TlbEntry *EntryCache[3];
+ inline void flushCache()
+ {
+ memset(EntryCache, 0, 3 * sizeof(TlbEntry*));
+ }
+
+ inline TlbEntry* updateCache(TlbEntry *entry) {
+ EntryCache[2] = EntryCache[1];
+ EntryCache[1] = EntryCache[0];
+ EntryCache[0] = entry;
+ return entry;
}
};