diff options
author | Gabe Black <gblack@eecs.umich.edu> | 2007-08-26 20:33:57 -0700 |
---|---|---|
committer | Gabe Black <gblack@eecs.umich.edu> | 2007-08-26 20:33:57 -0700 |
commit | 9b49a78cfdc0bd6f8afdb0d066ea39778095d7ac (patch) | |
tree | b4a977c8d7379ac552d245847825a73b61bf8c5b /src/arch/alpha | |
parent | 80d51650c8bce1503e5ce3877f3bfe21d3e57d45 (diff) | |
download | gem5-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.cc | 55 | ||||
-rw-r--r-- | src/arch/alpha/faults.cc | 48 | ||||
-rw-r--r-- | src/arch/alpha/faults.hh | 5 | ||||
-rw-r--r-- | src/arch/alpha/pagetable.cc | 6 | ||||
-rw-r--r-- | src/arch/alpha/pagetable.hh | 9 | ||||
-rw-r--r-- | src/arch/alpha/tlb.cc | 105 | ||||
-rw-r--r-- | src/arch/alpha/tlb.hh | 34 |
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 §ion) + TlbEntry::unserialize(Checkpoint *cp, const std::string §ion) { 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 §ion) 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 §ion); // 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; } }; |