diff options
-rw-r--r-- | src/arch/alpha/tlb.cc | 924 | ||||
-rw-r--r-- | src/arch/mips/mmaped_ipr.hh | 3 | ||||
-rw-r--r-- | src/arch/sparc/asi.cc | 4 | ||||
-rw-r--r-- | src/arch/sparc/miscregfile.cc | 58 | ||||
-rw-r--r-- | src/arch/sparc/miscregfile.hh | 2 | ||||
-rw-r--r-- | src/arch/sparc/tlb.cc | 224 | ||||
-rw-r--r-- | src/arch/sparc/tlb.hh | 11 | ||||
-rw-r--r-- | src/arch/sparc/tlb_map.hh | 11 | ||||
-rw-r--r-- | src/base/range_map.hh | 123 | ||||
-rw-r--r-- | src/cpu/exetrace.cc | 6 | ||||
-rw-r--r-- | src/dev/sparc/t1000.cc | 6 | ||||
-rw-r--r-- | src/mem/bus.cc | 70 | ||||
-rw-r--r-- | src/mem/bus.hh | 3 | ||||
-rw-r--r-- | src/unittest/rangemaptest.cc | 13 | ||||
-rw-r--r-- | src/unittest/rangemaptest2.cc | 78 |
15 files changed, 956 insertions, 580 deletions
diff --git a/src/arch/alpha/tlb.cc b/src/arch/alpha/tlb.cc index af69e45c0..c21bf94f5 100644 --- a/src/arch/alpha/tlb.cc +++ b/src/arch/alpha/tlb.cc @@ -48,589 +48,589 @@ using namespace EV5; namespace AlphaISA { - /////////////////////////////////////////////////////////////////////// - // - // Alpha TLB - // +/////////////////////////////////////////////////////////////////////// +// +// Alpha TLB +// #ifdef DEBUG - bool uncacheBit39 = false; - bool uncacheBit40 = false; +bool uncacheBit39 = false; +bool uncacheBit40 = false; #endif #define MODE2MASK(X) (1 << (X)) - TLB::TLB(const string &name, int s) - : SimObject(name), size(s), nlu(0) - { - table = new PTE[size]; - memset(table, 0, sizeof(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])); +} - TLB::~TLB() - { - if (table) - delete [] table; - } +TLB::~TLB() +{ + if (table) + delete [] table; +} - // 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; - } +// look up an entry in the TLB +PTE * +TLB::lookup(Addr vpn, uint8_t asn) const +{ + // assume not found... + PTE *retval = NULL; - ++i; + 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; } - } - DPRINTF(TLB, "lookup %#x, asn %#x -> %s ppn %#x\n", vpn, (int)asn, - retval ? "hit" : "miss", retval ? retval->ppn : 0); - return retval; + ++i; + } } + DPRINTF(TLB, "lookup %#x, asn %#x -> %s ppn %#x\n", vpn, (int)asn, + retval ? "hit" : "miss", retval ? retval->ppn : 0); + return retval; +} - 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. - */ +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. + */ #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 - 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) - panic("TLB entry not found in lookupTable"); +// 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); - ++i; - } + if (i == lookupTable.end()) + panic("TLB entry not found in lookupTable"); - DPRINTF(TLB, "remove @%d: %#x -> %#x\n", nlu, oldvpn, table[nlu].ppn); + int index; + while ((index = i->second) != nlu) { + if (table[index].tag != oldvpn) + panic("TLB entry not found in lookupTable"); - lookupTable.erase(i); + ++i; } - DPRINTF(TLB, "insert @%d: %#x -> %#x\n", nlu, vaddr.vpn(), pte.ppn); + DPRINTF(TLB, "remove @%d: %#x -> %#x\n", nlu, oldvpn, table[nlu].ppn); - table[nlu] = pte; - table[nlu].tag = vaddr.vpn(); - table[nlu].valid = true; - - lookupTable.insert(make_pair(vaddr.vpn(), nlu)); - nextnlu(); + lookupTable.erase(i); } - void - TLB::flushAll() - { - DPRINTF(TLB, "flushAll\n"); - memset(table, 0, sizeof(PTE[size])); - lookupTable.clear(); - nlu = 0; - } + DPRINTF(TLB, "insert @%d: %#x -> %#x\n", nlu, vaddr.vpn(), pte.ppn); - 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); + table[nlu] = pte; + table[nlu].tag = vaddr.vpn(); + table[nlu].valid = true; - // 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; + lookupTable.insert(make_pair(vaddr.vpn(), nlu)); + nextnlu(); +} - if (!pte->asma) { - DPRINTF(TLB, "flush @%d: %#x -> %#x\n", index, pte->tag, pte->ppn); - pte->valid = false; - lookupTable.erase(cur); - } +void +TLB::flushAll() +{ + DPRINTF(TLB, "flushAll\n"); + memset(table, 0, sizeof(PTE[size])); + lookupTable.clear(); + nlu = 0; +} + +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); + + // 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); } } +} - void - TLB::flushAddr(Addr addr, uint8_t asn) - { - 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; - 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); + while (i->first == vaddr.vpn()) { + int index = i->second; + PTE *pte = &table[index]; + assert(pte->valid); - // invalidate this entry - pte->valid = false; + if (vaddr.vpn() == pte->tag && (pte->asma || pte->asn == asn)) { + DPRINTF(TLB, "flushaddr @%d: %#x -> %#x\n", index, vaddr.vpn(), + pte->ppn); - lookupTable.erase(i); - } + // invalidate this entry + pte->valid = false; - ++i; + lookupTable.erase(i); } + + ++i; } +} - void - TLB::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 - TLB::unserialize(Checkpoint *cp, const string §ion) - { - UNSERIALIZE_SCALAR(size); - UNSERIALIZE_SCALAR(nlu); +void +TLB::unserialize(Checkpoint *cp, const string §ion) +{ + 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 - // - 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; - } +/////////////////////////////////////////////////////////////////////// +// +// Alpha ITB +// +ITB::ITB(const std::string &name, int size) + : TLB(name, size) +{} - Fault - ITB::translate(RequestPtr &req, ThreadContext *tc) const - { - if (PcPAL(req->getPC())) { - // strip off PAL PC marker (lsb is 1) - req->setPaddr((req->getVaddr() & ~3) & PAddrImplMask); - hits++; - return NoFault; - } +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->getPC())) { + // 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(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(IPR_ICM)) != - 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(IPR_DTB_ASN)); - PTE *pte = lookup(VAddr(req->getVaddr()).vpn(), - asn); - - if (!pte) { - misses++; - return new ItbPageFault(req->getVaddr()); - } - - req->setPaddr((pte->ppn << PageShift) + - (VAddr(req->getVaddr()).offset() - & ~3)); + } 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()); + } - // check permissions for this access - if (!(pte->xre & - (1 << ICM_CM(tc->readMiscReg(IPR_ICM))))) { - // instruction access fault - acv++; - return new ItbAcvFault(req->getVaddr()); - } + req->setPaddr((pte->ppn << PageShift) + + (VAddr(req->getVaddr()).offset() + & ~3)); - hits++; + // 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++; } + } - // check that the physical address is ok (catch bad physical addresses) - if (req->getPaddr() & ~PAddrImplMask) - return genMachineCheckFault(); + // check that the physical address is ok (catch bad physical addresses) + if (req->getPaddr() & ~PAddrImplMask) + return genMachineCheckFault(); - return checkCacheability(req); + return checkCacheability(req); - } +} - /////////////////////////////////////////////////////////////////////// - // - // 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; - } +/////////////////////////////////////////////////////////////////////// +// +// Alpha DTB +// + DTB::DTB(const std::string &name, int size) + : TLB(name, size) +{} - Fault - DTB::translate(RequestPtr &req, ThreadContext *tc, bool write) const - { - Addr pc = tc->readPC(); +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; +} - mode_type mode = - (mode_type)DTB_CM_CM(tc->readMiscReg(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) ? - (mode_type)ALT_MODE_AM( - tc->readMiscReg(IPR_ALT_MODE)) - : 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 (PcPAL(pc)) { + 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(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(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); - } + // 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(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)); + } + + 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 (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->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); } - - 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 (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++; } - // check that the physical address is ok (catch bad physical addresses) - if (req->getPaddr() & ~PAddrImplMask) - return genMachineCheckFault(); - - return checkCacheability(req); + if (write) + write_hits++; + else + read_hits++; } - PTE & - TLB::index(bool advance) - { - PTE *pte = &table[nlu]; + // check that the physical address is ok (catch bad physical addresses) + if (req->getPaddr() & ~PAddrImplMask) + return genMachineCheckFault(); - if (advance) - nextnlu(); + return checkCacheability(req); +} - return *pte; - } +PTE & +TLB::index(bool advance) +{ + PTE *pte = &table[nlu]; + + if (advance) + nextnlu(); - DEFINE_SIM_OBJECT_CLASS_NAME("AlphaTLB", TLB) + return *pte; +} - BEGIN_DECLARE_SIM_OBJECT_PARAMS(ITB) +DEFINE_SIM_OBJECT_CLASS_NAME("AlphaTLB", TLB) - Param<int> size; +BEGIN_DECLARE_SIM_OBJECT_PARAMS(ITB) - END_DECLARE_SIM_OBJECT_PARAMS(ITB) + Param<int> size; - BEGIN_INIT_SIM_OBJECT_PARAMS(ITB) +END_DECLARE_SIM_OBJECT_PARAMS(ITB) - INIT_PARAM_DFLT(size, "TLB size", 48) +BEGIN_INIT_SIM_OBJECT_PARAMS(ITB) - END_INIT_SIM_OBJECT_PARAMS(ITB) + INIT_PARAM_DFLT(size, "TLB size", 48) +END_INIT_SIM_OBJECT_PARAMS(ITB) - CREATE_SIM_OBJECT(ITB) - { - return new ITB(getInstanceName(), size); - } - REGISTER_SIM_OBJECT("AlphaITB", ITB) +CREATE_SIM_OBJECT(ITB) +{ + return new ITB(getInstanceName(), size); +} - BEGIN_DECLARE_SIM_OBJECT_PARAMS(DTB) +REGISTER_SIM_OBJECT("AlphaITB", ITB) - Param<int> size; +BEGIN_DECLARE_SIM_OBJECT_PARAMS(DTB) - END_DECLARE_SIM_OBJECT_PARAMS(DTB) + Param<int> size; - BEGIN_INIT_SIM_OBJECT_PARAMS(DTB) +END_DECLARE_SIM_OBJECT_PARAMS(DTB) - INIT_PARAM_DFLT(size, "TLB size", 64) +BEGIN_INIT_SIM_OBJECT_PARAMS(DTB) - END_INIT_SIM_OBJECT_PARAMS(DTB) + INIT_PARAM_DFLT(size, "TLB size", 64) +END_INIT_SIM_OBJECT_PARAMS(DTB) - CREATE_SIM_OBJECT(DTB) - { - return new DTB(getInstanceName(), size); - } - REGISTER_SIM_OBJECT("AlphaDTB", DTB) +CREATE_SIM_OBJECT(DTB) +{ + return new DTB(getInstanceName(), size); +} + +REGISTER_SIM_OBJECT("AlphaDTB", DTB) } diff --git a/src/arch/mips/mmaped_ipr.hh b/src/arch/mips/mmaped_ipr.hh index 041c76fdc..fa82a645c 100644 --- a/src/arch/mips/mmaped_ipr.hh +++ b/src/arch/mips/mmaped_ipr.hh @@ -37,8 +37,10 @@ * ISA-specific helper functions for memory mapped IPR accesses. */ +#include "base/misc.hh" #include "mem/packet.hh" +class ThreadContext; namespace MipsISA { @@ -48,7 +50,6 @@ handleIprRead(ThreadContext *xc, Packet *pkt) panic("No implementation for handleIprRead in MIPS\n"); } - inline Tick handleIprWrite(ThreadContext *xc, Packet *pkt) { diff --git a/src/arch/sparc/asi.cc b/src/arch/sparc/asi.cc index b307ade33..a9a778ff6 100644 --- a/src/arch/sparc/asi.cc +++ b/src/arch/sparc/asi.cc @@ -185,6 +185,7 @@ namespace SparcISA bool AsiIsTwin(ASI asi) { return + (asi == ASI_QUAD_LDD) || (asi == ASI_LDTX_AIUP) || (asi == ASI_LDTX_AIUS) || (asi == ASI_LDTX_REAL) || @@ -196,7 +197,8 @@ namespace SparcISA (asi == ASI_LDTX_P) || (asi == ASI_LDTX_S) || (asi == ASI_LDTX_PL) || - (asi == ASI_LDTX_SL); + (asi == ASI_LDTX_SL) || + (asi == ASI_LTX_L); } bool AsiIsPartialStore(ASI asi) diff --git a/src/arch/sparc/miscregfile.cc b/src/arch/sparc/miscregfile.cc index fd20a14c1..53559c072 100644 --- a/src/arch/sparc/miscregfile.cc +++ b/src/arch/sparc/miscregfile.cc @@ -129,6 +129,26 @@ void MiscRegFile::clear() MiscReg MiscRegFile::readReg(int miscReg) { switch (miscReg) { + case MISCREG_TLB_DATA: + /* Package up all the data for the tlb: + * 6666555555555544444444443333333333222222222211111111110000000000 + * 3210987654321098765432109876543210987654321098765432109876543210 + * secContext | priContext | |tl|partid| |||||^hpriv + * ||||^red + * |||^priv + * ||^am + * |^lsuim + * ^lsudm + */ + return bits((uint64_t)hpstate,2,2) | + bits((uint64_t)hpstate,5,5) << 1 | + bits((uint64_t)pstate,3,2) << 2 | + bits((uint64_t)lsuCtrlReg,3,2) << 4 | + bits((uint64_t)partId,7,0) << 8 | + bits((uint64_t)tl,2,0) << 16 | + (uint64_t)priContext << 32 | + (uint64_t)secContext << 48; + case MISCREG_Y: return y; case MISCREG_CCR: @@ -294,16 +314,17 @@ MiscReg MiscRegFile::readRegWithEffect(int miscReg, ThreadContext * tc) { switch (miscReg) { // tick and stick are aliased to each other in niagra - case MISCREG_TICK: + // well store the tick data in stick and the interrupt bit in tick case MISCREG_STICK: + case MISCREG_TICK: case MISCREG_PRIVTICK: // I'm not sure why legion ignores the lowest two bits, but we'll go // with it // change from curCycle() to instCount() until we're done with legion - DPRINTFN("Instruction Count when STICK read: %#X\n", - tc->getCpuPtr()->instCount()); - return mbits(tc->getCpuPtr()->instCount() - (tick & - mask(63)),62,2) | mbits(tick,63,63) ; + DPRINTFN("Instruction Count when TICK read: %#X stick=%#X\n", + tc->getCpuPtr()->instCount(), stick); + return mbits(tc->getCpuPtr()->instCount() + (int32_t)stick,62,2) | + mbits(tick,63,63); case MISCREG_FPRS: warn("FPRS register read and FPU stuff not really implemented\n"); return fprs; @@ -320,7 +341,6 @@ MiscReg MiscRegFile::readRegWithEffect(int miscReg, ThreadContext * tc) case MISCREG_SOFTINT: case MISCREG_TICK_CMPR: case MISCREG_STICK_CMPR: - case MISCREG_HPSTATE: case MISCREG_HINTP: case MISCREG_HTSTATE: case MISCREG_HTBA: @@ -336,9 +356,16 @@ MiscReg MiscRegFile::readRegWithEffect(int miscReg, ThreadContext * tc) case MISCREG_QUEUE_NRES_ERROR_HEAD: case MISCREG_QUEUE_NRES_ERROR_TAIL: #if FULL_SYSTEM + case MISCREG_HPSTATE: return readFSRegWithEffect(miscReg, tc); #else - panic("Accessing Fullsystem register is SE mode\n"); + case MISCREG_HPSTATE: + //HPSTATE is special because because sometimes in privilege checks for instructions + //it will read HPSTATE to make sure the priv. level is ok + //So, we'll just have to tell it it isn't, instead of panicing. + return 0; + + panic("Accessing Fullsystem register %s in SE mode\n",getMiscRegName(miscReg)); #endif } @@ -581,13 +608,14 @@ void MiscRegFile::setReg(int miscReg, const MiscReg &val) void MiscRegFile::setRegWithEffect(int miscReg, const MiscReg &val, ThreadContext * tc) { - const uint64_t Bit64 = (1ULL << 63); switch (miscReg) { case MISCREG_STICK: case MISCREG_TICK: - // change from curCycle() to instCount() until we're done with legion - tick = tc->getCpuPtr()->instCount() - val & ~Bit64; - tick |= val & Bit64; + // stick and tick are same thing on niagra + // use stick for offset and tick for holding intrrupt bit + stick = mbits(val,62,0) - tc->getCpuPtr()->instCount(); + tick = mbits(val,63,63); + DPRINTFN("Writing TICK=%#X\n", val); break; case MISCREG_FPRS: //Configure the fpu based on the fprs @@ -611,7 +639,6 @@ void MiscRegFile::setRegWithEffect(int miscReg, case MISCREG_SOFTINT: case MISCREG_TICK_CMPR: case MISCREG_STICK_CMPR: - case MISCREG_HPSTATE: case MISCREG_HINTP: case MISCREG_HTSTATE: case MISCREG_HTBA: @@ -627,10 +654,15 @@ void MiscRegFile::setRegWithEffect(int miscReg, case MISCREG_QUEUE_NRES_ERROR_HEAD: case MISCREG_QUEUE_NRES_ERROR_TAIL: #if FULL_SYSTEM + case MISCREG_HPSTATE: setFSRegWithEffect(miscReg, val, tc); return; #else - panic("Accessing Fullsystem register is SE mode\n"); + case MISCREG_HPSTATE: + //HPSTATE is special because normal trap processing saves HPSTATE when + //it goes into a trap, and restores it when it returns. + return; + panic("Accessing Fullsystem register %s to %#x in SE mode\n", getMiscRegName(miscReg), val); #endif } setReg(miscReg, val); diff --git a/src/arch/sparc/miscregfile.hh b/src/arch/sparc/miscregfile.hh index d09005795..c879fd357 100644 --- a/src/arch/sparc/miscregfile.hh +++ b/src/arch/sparc/miscregfile.hh @@ -137,6 +137,8 @@ namespace SparcISA MISCREG_QUEUE_NRES_ERROR_HEAD, MISCREG_QUEUE_NRES_ERROR_TAIL, + /* All the data for the TLB packed up in one register. */ + MISCREG_TLB_DATA, MISCREG_NUMMISCREGS }; diff --git a/src/arch/sparc/tlb.cc b/src/arch/sparc/tlb.cc index b0fc562ac..675287d18 100644 --- a/src/arch/sparc/tlb.cc +++ b/src/arch/sparc/tlb.cc @@ -45,7 +45,7 @@ namespace SparcISA { TLB::TLB(const std::string &name, int s) - : SimObject(name), size(s) + : SimObject(name), size(s), usedEntries(0), cacheValid(false) { // To make this work you'll have to change the hypervisor and OS if (size > 64) @@ -79,6 +79,8 @@ TLB::insert(Addr va, int partition_id, int context_id, bool real, TlbEntry *new_entry = NULL; int x; + cacheValid = false; + DPRINTF(TLB, "TLB: Inserting TLB Entry; va=%#x pa=%#x pid=%d cid=%d r=%d\n", va, PTE.paddr(), partition_id, context_id, (int)real); @@ -194,6 +196,8 @@ TLB::demapPage(Addr va, int partition_id, bool real, int context_id) TlbRange tr; MapIter i; + cacheValid = false; + // Assemble full address structure tr.va = va; tr.size = va + MachineBytes; @@ -217,6 +221,7 @@ void TLB::demapContext(int partition_id, int context_id) { int x; + cacheValid = false; for (x = 0; x < size; x++) { if (tlb[x].range.contextId == context_id && tlb[x].range.partitionId == partition_id) { @@ -234,6 +239,7 @@ void TLB::demapAll(int partition_id) { int x; + cacheValid = false; for (x = 0; x < size; x++) { if (!tlb[x].pte.locked() && tlb[x].range.partitionId == partition_id) { tlb[x].valid = false; @@ -250,6 +256,8 @@ void TLB::invalidateAll() { int x; + cacheValid = false; + for (x = 0; x < size; x++) { tlb[x].valid = false; } @@ -337,7 +345,7 @@ DTB::writeSfr(ThreadContext *tc, Addr a, bool write, ContextType ct, tc->setMiscRegWithEffect(MISCREG_MMU_DTLB_SFAR, a); } - void +void DTB::writeTagAccess(ThreadContext *tc, Addr va, int context) { TLB::writeTagAccess(tc, MISCREG_MMU_DTLB_TAG_ACCESS, va, context); @@ -348,26 +356,47 @@ DTB::writeTagAccess(ThreadContext *tc, Addr va, int context) Fault ITB::translate(RequestPtr &req, ThreadContext *tc) { - uint64_t hpstate = tc->readMiscReg(MISCREG_HPSTATE); - uint64_t pstate = tc->readMiscReg(MISCREG_PSTATE); - bool lsuIm = tc->readMiscReg(MISCREG_MMU_LSU_CTRL) >> 2 & 0x1; - uint64_t tl = tc->readMiscReg(MISCREG_TL); - uint64_t part_id = tc->readMiscReg(MISCREG_MMU_PART_ID); - bool addr_mask = pstate >> 3 & 0x1; - bool priv = pstate >> 2 & 0x1; + uint64_t tlbdata = tc->readMiscReg(MISCREG_TLB_DATA); + Addr vaddr = req->getVaddr(); - int context; - ContextType ct; - int asi; - bool real = false; TlbEntry *e; + assert(req->getAsi() == ASI_IMPLICIT); + DPRINTF(TLB, "TLB: ITB Request to translate va=%#x size=%d\n", vaddr, req->getSize()); - DPRINTF(TLB, "TLB: pstate: %#X hpstate: %#X lsudm: %#X part_id: %#X\n", - pstate, hpstate, lsuIm, part_id); - assert(req->getAsi() == ASI_IMPLICIT); + // Be fast if we can! + if (cacheValid && cacheState == tlbdata) { + if (cacheEntry) { + if (cacheEntry->range.va < vaddr + sizeof(MachInst) && + cacheEntry->range.va + cacheEntry->range.size >= vaddr) { + req->setPaddr(cacheEntry->pte.paddr() & ~(cacheEntry->pte.size()-1) | + vaddr & cacheEntry->pte.size()-1 ); + return NoFault; + } + } else { + req->setPaddr(vaddr & PAddrImplMask); + return NoFault; + } + } + + bool hpriv = bits(tlbdata,0,0); + bool red = bits(tlbdata,1,1); + bool priv = bits(tlbdata,2,2); + bool addr_mask = bits(tlbdata,3,3); + bool lsu_im = bits(tlbdata,4,4); + + int part_id = bits(tlbdata,15,8); + int tl = bits(tlbdata,18,16); + int pri_context = bits(tlbdata,47,32); + int context; + ContextType ct; + int asi; + bool real = false; + + DPRINTF(TLB, "TLB: priv:%d hpriv:%d red:%d lsuim:%d part_id: %#X\n", + priv, hpriv, red, lsu_im, part_id); if (tl > 0) { asi = ASI_N; @@ -376,16 +405,19 @@ ITB::translate(RequestPtr &req, ThreadContext *tc) } else { asi = ASI_P; ct = Primary; - context = tc->readMiscReg(MISCREG_MMU_P_CONTEXT); + context = pri_context; } - if ( hpstate >> 2 & 0x1 || hpstate >> 5 & 0x1 ) { - req->setPaddr(req->getVaddr() & PAddrImplMask); + if ( hpriv || red ) { + cacheValid = true; + cacheState = tlbdata; + cacheEntry = NULL; + req->setPaddr(vaddr & PAddrImplMask); return NoFault; } - // If the asi is unaligned trap - if (vaddr & req->getSize()-1) { + // If the access is unaligned trap + if (vaddr & 0x3) { writeSfsr(tc, false, ct, false, OtherFault, asi); return new MemAddressNotAligned; } @@ -398,8 +430,8 @@ ITB::translate(RequestPtr &req, ThreadContext *tc) return new InstructionAccessException; } - if (!lsuIm) { - e = lookup(req->getVaddr(), part_id, true); + if (!lsu_im) { + e = lookup(vaddr, part_id, true); real = true; context = 0; } else { @@ -421,9 +453,14 @@ ITB::translate(RequestPtr &req, ThreadContext *tc) return new InstructionAccessException; } + // cache translation date for next translation + cacheValid = true; + cacheState = tlbdata; + cacheEntry = e; + req->setPaddr(e->pte.paddr() & ~(e->pte.size()-1) | - req->getVaddr() & e->pte.size()-1 ); - DPRINTF(TLB, "TLB: %#X -> %#X\n", req->getVaddr(), req->getPaddr()); + vaddr & e->pte.size()-1 ); + DPRINTF(TLB, "TLB: %#X -> %#X\n", vaddr, req->getPaddr()); return NoFault; } @@ -433,33 +470,60 @@ Fault DTB::translate(RequestPtr &req, ThreadContext *tc, bool write) { /* @todo this could really use some profiling and fixing to make it faster! */ - uint64_t hpstate = tc->readMiscReg(MISCREG_HPSTATE); - uint64_t pstate = tc->readMiscReg(MISCREG_PSTATE); - bool lsuDm = tc->readMiscReg(MISCREG_MMU_LSU_CTRL) >> 3 & 0x1; - uint64_t tl = tc->readMiscReg(MISCREG_TL); - uint64_t part_id = tc->readMiscReg(MISCREG_MMU_PART_ID); - bool hpriv = hpstate >> 2 & 0x1; - bool red = hpstate >> 5 >> 0x1; - bool addr_mask = pstate >> 3 & 0x1; - bool priv = pstate >> 2 & 0x1; - bool implicit = false; - bool real = false; + uint64_t tlbdata = tc->readMiscReg(MISCREG_TLB_DATA); Addr vaddr = req->getVaddr(); Addr size = req->getSize(); - ContextType ct; - int context; ASI asi; - - TlbEntry *e; - asi = (ASI)req->getAsi(); + bool implicit = false; + bool hpriv = bits(tlbdata,0,0); + DPRINTF(TLB, "TLB: DTB Request to translate va=%#x size=%d asi=%#x\n", vaddr, size, asi); - DPRINTF(TLB, "TLB: pstate: %#X hpstate: %#X lsudm: %#X part_id: %#X\n", - pstate, hpstate, lsuDm, part_id); + if (asi == ASI_IMPLICIT) implicit = true; + if (hpriv && implicit) { + req->setPaddr(vaddr & PAddrImplMask); + return NoFault; + } + + // Be fast if we can! + if (cacheValid && cacheState == tlbdata) { + if (cacheEntry[0] && cacheAsi[0] == asi && cacheEntry[0]->range.va < vaddr + size && + cacheEntry[0]->range.va + cacheEntry[0]->range.size >= vaddr) { + req->setPaddr(cacheEntry[0]->pte.paddr() & ~(cacheEntry[0]->pte.size()-1) | + vaddr & cacheEntry[0]->pte.size()-1 ); + return NoFault; + } + if (cacheEntry[1] && cacheAsi[1] == asi && cacheEntry[1]->range.va < vaddr + size && + cacheEntry[1]->range.va + cacheEntry[1]->range.size >= vaddr) { + req->setPaddr(cacheEntry[1]->pte.paddr() & ~(cacheEntry[1]->pte.size()-1) | + vaddr & cacheEntry[1]->pte.size()-1 ); + return NoFault; + } + } + + bool red = bits(tlbdata,1,1); + bool priv = bits(tlbdata,2,2); + bool addr_mask = bits(tlbdata,3,3); + bool lsu_dm = bits(tlbdata,5,5); + + int part_id = bits(tlbdata,15,8); + int tl = bits(tlbdata,18,16); + int pri_context = bits(tlbdata,47,32); + int sec_context = bits(tlbdata,47,32); + + bool real = false; + ContextType ct = Primary; + int context = 0; + + TlbEntry *e; + + DPRINTF(TLB, "TLB: priv:%d hpriv:%d red:%d lsudm:%d part_id: %#X\n", + priv, hpriv, red, lsu_dm, part_id); + if (implicit) { if (tl > 0) { asi = ASI_N; @@ -468,7 +532,7 @@ DTB::translate(RequestPtr &req, ThreadContext *tc, bool write) } else { asi = ASI_P; ct = Primary; - context = tc->readMiscReg(MISCREG_MMU_P_CONTEXT); + context = pri_context; } } else if (!hpriv && !red) { if (tl > 0 || AsiIsNucleus(asi)) { @@ -476,9 +540,9 @@ DTB::translate(RequestPtr &req, ThreadContext *tc, bool write) context = 0; } else if (AsiIsSecondary(asi)) { ct = Secondary; - context = tc->readMiscReg(MISCREG_MMU_S_CONTEXT); + context = sec_context; } else { - context = tc->readMiscReg(MISCREG_MMU_P_CONTEXT); + context = pri_context; ct = Primary; //??? } @@ -496,7 +560,7 @@ DTB::translate(RequestPtr &req, ThreadContext *tc, bool write) } else if (hpriv) { if (asi == ASI_P) { ct = Primary; - context = tc->readMiscReg(MISCREG_MMU_P_CONTEXT); + context = pri_context; goto continueDtbFlow; } } @@ -508,6 +572,9 @@ DTB::translate(RequestPtr &req, ThreadContext *tc, bool write) panic("Block ASIs not supported\n"); if (AsiIsNoFault(asi)) panic("No Fault ASIs not supported\n"); + if (write && asi == ASI_LDTX_P) + // block init store (like write hint64) + goto continueDtbFlow; if (AsiIsTwin(asi)) panic("Twin ASIs not supported\n"); if (AsiIsPartialStore(asi)) @@ -544,17 +611,17 @@ continueDtbFlow: } - if ((!lsuDm && !hpriv) || AsiIsReal(asi)) { + if ((!lsu_dm && !hpriv) || AsiIsReal(asi)) { real = true; context = 0; }; if (hpriv && (implicit || (!AsiIsAsIfUser(asi) && !AsiIsReal(asi)))) { - req->setPaddr(req->getVaddr() & PAddrImplMask); + req->setPaddr(vaddr & PAddrImplMask); return NoFault; } - e = lookup(req->getVaddr(), part_id, real, context); + e = lookup(vaddr, part_id, real, context); if (e == NULL || !e->valid) { tc->setMiscReg(MISCREG_MMU_DTLB_TAG_ACCESS, @@ -587,9 +654,21 @@ continueDtbFlow: return new DataAccessException; } + // cache translation date for next translation + cacheValid = true; + cacheState = tlbdata; + if (cacheEntry[0] != e && cacheEntry[1] != e) { + cacheEntry[1] = cacheEntry[0]; + cacheEntry[0] = e; + cacheAsi[1] = cacheAsi[0]; + cacheAsi[0] = asi; + if (implicit) + cacheAsi[0] = (ASI)0; + } + req->setPaddr(e->pte.paddr() & ~(e->pte.size()-1) | - req->getVaddr() & e->pte.size()-1); - DPRINTF(TLB, "TLB: %#X -> %#X\n", req->getVaddr(), req->getPaddr()); + vaddr & e->pte.size()-1); + DPRINTF(TLB, "TLB: %#X -> %#X\n", vaddr, req->getPaddr()); return NoFault; /** Normal flow ends here. */ @@ -637,6 +716,8 @@ DTB::doMmuRegRead(ThreadContext *tc, Packet *pkt) { Addr va = pkt->getAddr(); ASI asi = (ASI)pkt->req->getAsi(); + uint64_t temp, data; + uint64_t tsbtemp, cnftemp; DPRINTF(IPR, "Memory Mapped IPR Read: asi=%#X a=%#x\n", (uint32_t)pkt->req->getAsi(), pkt->getAddr()); @@ -720,6 +801,10 @@ DTB::doMmuRegRead(ThreadContext *tc, Packet *pkt) break; case ASI_IMMU: switch (va) { + case 0x0: + temp = tc->readMiscRegWithEffect(MISCREG_MMU_ITLB_TAG_ACCESS); + pkt->set(bits(temp,63,22) | bits(temp,12,0) << 48); + break; case 0x30: pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_ITLB_TAG_ACCESS)); break; @@ -729,6 +814,10 @@ DTB::doMmuRegRead(ThreadContext *tc, Packet *pkt) break; case ASI_DMMU: switch (va) { + case 0x0: + temp = tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_TAG_ACCESS); + pkt->set(bits(temp,63,22) | bits(temp,12,0) << 48); + break; case 0x30: pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_TAG_ACCESS)); break; @@ -739,6 +828,37 @@ DTB::doMmuRegRead(ThreadContext *tc, Packet *pkt) goto doMmuReadError; } break; + case ASI_DMMU_TSB_PS0_PTR_REG: + temp = tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_TAG_ACCESS); + if (bits(temp,12,0) == 0) { + tsbtemp = tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_C0_TSB_PS0); + cnftemp = tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_C0_CONFIG); + } else { + tsbtemp = tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_CX_TSB_PS0); + cnftemp = tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_CX_CONFIG); + } + data = mbits(tsbtemp,63,13); + data |= temp >> (9 + bits(cnftemp,2,0) * 3) & + mbits((uint64_t)-1ll,12+bits(tsbtemp,3,0), 4); + pkt->set(data); + break; + case ASI_DMMU_TSB_PS1_PTR_REG: + temp = tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_TAG_ACCESS); + if (bits(temp,12,0) == 0) { + tsbtemp = tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_C0_TSB_PS1); + cnftemp = tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_C0_CONFIG); + } else { + tsbtemp = tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_CX_TSB_PS1); + cnftemp = tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_CX_CONFIG); + } + data = mbits(tsbtemp,63,13); + if (bits(tsbtemp,12,12)) + data |= ULL(1) << (13+bits(tsbtemp,3,0)); + data |= temp >> (9 + bits(cnftemp,2,0) * 3) & + mbits((uint64_t)-1ll,12+bits(tsbtemp,3,0), 4); + pkt->set(data); + break; + default: doMmuReadError: panic("need to impl DTB::doMmuRegRead() got asi=%#x, va=%#x\n", diff --git a/src/arch/sparc/tlb.hh b/src/arch/sparc/tlb.hh index 8a4ccd69f..f69b40ffb 100644 --- a/src/arch/sparc/tlb.hh +++ b/src/arch/sparc/tlb.hh @@ -31,6 +31,7 @@ #ifndef __ARCH_SPARC_TLB_HH__ #define __ARCH_SPARC_TLB_HH__ +#include "arch/sparc/asi.hh" #include "arch/sparc/tlb_map.hh" #include "base/misc.hh" #include "mem/request.hh" @@ -54,6 +55,9 @@ class TLB : public SimObject int size; int usedEntries; + uint64_t cacheState; + bool cacheValid; + enum FaultTypes { OtherFault = 0, PrivViolation = 0x1, @@ -131,6 +135,7 @@ class ITB : public TLB public: ITB(const std::string &name, int size) : TLB(name, size) { + cacheEntry = NULL; } Fault translate(RequestPtr &req, ThreadContext *tc); @@ -138,6 +143,7 @@ class ITB : public TLB void writeSfsr(ThreadContext *tc, bool write, ContextType ct, bool se, FaultTypes ft, int asi); void writeTagAccess(ThreadContext *tc, Addr va, int context); + TlbEntry *cacheEntry; friend class DTB; }; @@ -146,6 +152,8 @@ class DTB : public TLB public: DTB(const std::string &name, int size) : TLB(name, size) { + cacheEntry[0] = NULL; + cacheEntry[1] = NULL; } Fault translate(RequestPtr &req, ThreadContext *tc, bool write); @@ -157,7 +165,8 @@ class DTB : public TLB bool se, FaultTypes ft, int asi); void writeTagAccess(ThreadContext *tc, Addr va, int context); - + TlbEntry *cacheEntry[2]; + ASI cacheAsi[2]; }; } diff --git a/src/arch/sparc/tlb_map.hh b/src/arch/sparc/tlb_map.hh index 226ef23a1..688daf5b9 100644 --- a/src/arch/sparc/tlb_map.hh +++ b/src/arch/sparc/tlb_map.hh @@ -53,8 +53,15 @@ class TlbMap i = tree.upper_bound(r); if (i == tree.begin()) - // Nothing could match, so return end() - return tree.end(); + if (r.real == i->first.real && + r.partitionId == i->first.partitionId && + i->first.va < r.va + r.size && + i->first.va+i->first.size >= r.va && + (r.real || r.contextId == i->first.contextId)) + return i; + else + // Nothing could match, so return end() + return tree.end(); i--; diff --git a/src/base/range_map.hh b/src/base/range_map.hh index 17ecb9290..6d3450739 100644 --- a/src/base/range_map.hh +++ b/src/base/range_map.hh @@ -52,9 +52,13 @@ class range_map i = tree.upper_bound(r); - if (i == tree.begin()) - // Nothing could match, so return end() - return tree.end(); + if (i == tree.begin()) { + if (i->first.start <= r.end && i->first.end >= r.start) + return i; + else + // Nothing could match, so return end() + return tree.end(); + } i--; @@ -126,4 +130,117 @@ class range_map }; +template <class T,class V> +class range_multimap +{ + private: + typedef std::multimap<Range<T>,V> RangeMap; + RangeMap tree; + + public: + typedef typename RangeMap::iterator iterator; + + template <class U> + std::pair<iterator,iterator> find(const Range<U> &r) + { + iterator i; + iterator j; + + i = tree.lower_bound(r); + + if (i == tree.begin()) { + if (i->first.start <= r.end && i->first.end >= r.start) + return std::make_pair<iterator, iterator>(i,i); + else + // Nothing could match, so return end() + return std::make_pair<iterator, iterator>(tree.end(), tree.end()); + } + i--; + + if (i->first.start <= r.end && i->first.end >= r.start) { + // we have at least one match + j = i; + + i--; + while (i->first.start <= r.end && i->first.end >= + r.start) { + if (i == tree.begin()) + break; + i--; + } + if (i == tree.begin() && i->first.start <= r.end && i->first.end >= + r.start) + return std::make_pair<iterator, iterator>(i,j); + i++; + return std::make_pair<iterator, iterator>(i,j); + + } + + return std::make_pair<iterator, iterator>(tree.end(), tree.end()); + } + + template <class U> + bool intersect(const Range<U> &r) + { + std::pair<iterator,iterator> p; + p = find(r); + if (p.first != tree.end()) + return true; + return false; + } + + + template <class U,class W> + iterator insert(const Range<U> &r, const W d) + { + std::pair<iterator,iterator> p; + p = find(r); + if (p.first->first.start == r.start && p.first->first.end == r.end || + p.first == tree.end()) + return tree.insert(std::make_pair<Range<T>,V>(r, d)); + else + return tree.end(); + } + + size_t erase(T k) + { + return tree.erase(k); + } + + void erase(iterator p) + { + tree.erase(p); + } + + void erase(iterator p, iterator q) + { + tree.erase(p,q); + } + + void clear() + { + tree.erase(tree.begin(), tree.end()); + } + + iterator begin() + { + return tree.begin(); + } + + iterator end() + { + return tree.end(); + } + + size_t size() + { + return tree.size(); + } + + bool empty() + { + return tree.empty(); + } +}; + #endif //__BASE_RANGE_MAP_HH__ diff --git a/src/cpu/exetrace.cc b/src/cpu/exetrace.cc index 7c4c037ce..3fe40b4c1 100644 --- a/src/cpu/exetrace.cc +++ b/src/cpu/exetrace.cc @@ -57,7 +57,9 @@ using namespace std; using namespace TheISA; +#if THE_ISA == SPARC_ISA && FULL_SYSTEM static int diffcount = 0; +#endif namespace Trace { SharedData *shared_data = NULL; @@ -399,7 +401,7 @@ Trace::InstRecord::dump(ostream &outs) diffCcr || diffTl || diffGl || diffAsi || diffPil || diffCwp || diffCansave || diffCanrestore || diffOtherwin || diffCleanwin) - && !((staticInst->machInst & 0xE1F80000) == 0xE1F80000)) { + && !((staticInst->machInst & 0xC1F80000) == 0x81D00000)) { outs << "Differences found between M5 and Legion:"; if (diffPC) outs << " [PC]"; @@ -575,7 +577,7 @@ Trace::InstRecord::dump(ostream &outs) thread->getDTBPtr()->dumpAll(); diffcount++; - if (diffcount > 3) + if (diffcount > 2) fatal("Differences found between Legion and M5\n"); } diff --git a/src/dev/sparc/t1000.cc b/src/dev/sparc/t1000.cc index 5fc787084..4a8de77a5 100644 --- a/src/dev/sparc/t1000.cc +++ b/src/dev/sparc/t1000.cc @@ -62,13 +62,15 @@ T1000::intrFrequency() void T1000::postConsoleInt() { - panic("Need implementation\n"); + warn_once("Don't know what interrupt to post for console.\n"); + //panic("Need implementation\n"); } void T1000::clearConsoleInt() { - panic("Need implementation\n"); + warn_once("Don't know what interrupt to clear for console.\n"); + //panic("Need implementation\n"); } void diff --git a/src/mem/bus.cc b/src/mem/bus.cc index e9a870b80..bd721dd68 100644 --- a/src/mem/bus.cc +++ b/src/mem/bus.cc @@ -260,19 +260,12 @@ Bus::findPort(Addr addr, int id) { /* An interval tree would be a better way to do this. --ali. */ int dest_id = -1; - int i = 0; - bool found = false; AddrRangeIter iter; + range_map<Addr,int>::iterator i; - while (i < portList.size() && !found) - { - if (portList[i].range == addr) { - dest_id = portList[i].portId; - found = true; - DPRINTF(Bus, " found addr %#llx on device %d\n", addr, dest_id); - } - i++; - } + i = portMap.find(RangeSize(addr,1)); + if (i != portMap.end()) + dest_id = i->second; // Check if this matches the default range if (dest_id == -1) { @@ -463,13 +456,13 @@ Bus::recvStatusChange(Port::Status status, int id) assert((id < interfaces.size() && id >= 0) || id == defaultId); Port *port = interfaces[id]; - std::vector<DevMap>::iterator portIter; + range_map<Addr,int>::iterator portIter; std::vector<DevMap>::iterator snoopIter; // Clean out any previously existent ids - for (portIter = portList.begin(); portIter != portList.end(); ) { - if (portIter->portId == id) - portIter = portList.erase(portIter); + for (portIter = portMap.begin(); portIter != portMap.end(); ) { + if (portIter->second == id) + portMap.erase(portIter++); else portIter++; } @@ -495,16 +488,14 @@ Bus::recvStatusChange(Port::Status status, int id) } for(iter = ranges.begin(); iter != ranges.end(); iter++) { - DevMap dm; - dm.portId = id; - dm.range = *iter; - DPRINTF(BusAddrRanges, "Adding range %#llx - %#llx for id %d\n", - dm.range.start, dm.range.end, id); - portList.push_back(dm); + iter->start, iter->end, id); + if (portMap.insert(*iter, id) == portMap.end()) + panic("Two devices with same range\n"); + } } - DPRINTF(MMU, "port list has %d entries\n", portList.size()); + DPRINTF(MMU, "port list has %d entries\n", portMap.size()); // tell all our peers that our address range has changed. // Don't tell the device that caused this change, it already knows @@ -519,7 +510,8 @@ Bus::recvStatusChange(Port::Status status, int id) void Bus::addressRanges(AddrRangeList &resp, AddrRangeList &snoop, int id) { - std::vector<DevMap>::iterator portIter; + std::vector<DevMap>::iterator snoopIter; + range_map<Addr,int>::iterator portIter; AddrRangeIter dflt_iter; bool subset; @@ -534,37 +526,37 @@ Bus::addressRanges(AddrRangeList &resp, AddrRangeList &snoop, int id) DPRINTF(BusAddrRanges, " -- Dflt: %#llx : %#llx\n",dflt_iter->start, dflt_iter->end); } - for (portIter = portList.begin(); portIter != portList.end(); portIter++) { + for (portIter = portMap.begin(); portIter != portMap.end(); portIter++) { subset = false; for (dflt_iter = defaultRange.begin(); dflt_iter != defaultRange.end(); dflt_iter++) { - if ((portIter->range.start < dflt_iter->start && - portIter->range.end >= dflt_iter->start) || - (portIter->range.start < dflt_iter->end && - portIter->range.end >= dflt_iter->end)) + if ((portIter->first.start < dflt_iter->start && + portIter->first.end >= dflt_iter->start) || + (portIter->first.start < dflt_iter->end && + portIter->first.end >= dflt_iter->end)) fatal("Devices can not set ranges that itersect the default set\ but are not a subset of the default set.\n"); - if (portIter->range.start >= dflt_iter->start && - portIter->range.end <= dflt_iter->end) { + if (portIter->first.start >= dflt_iter->start && + portIter->first.end <= dflt_iter->end) { subset = true; DPRINTF(BusAddrRanges, " -- %#llx : %#llx is a SUBSET\n", - portIter->range.start, portIter->range.end); + portIter->first.start, portIter->first.end); } } - if (portIter->portId != id && !subset) { - resp.push_back(portIter->range); + if (portIter->second != id && !subset) { + resp.push_back(portIter->first); DPRINTF(BusAddrRanges, " -- %#llx : %#llx\n", - portIter->range.start, portIter->range.end); + portIter->first.start, portIter->first.end); } } - for (portIter = portSnoopList.begin(); - portIter != portSnoopList.end(); portIter++) + for (snoopIter = portSnoopList.begin(); + snoopIter != portSnoopList.end(); snoopIter++) { - if (portIter->portId != id) { - snoop.push_back(portIter->range); + if (snoopIter->portId != id) { + snoop.push_back(snoopIter->range); DPRINTF(BusAddrRanges, " -- Snoop: %#llx : %#llx\n", - portIter->range.start, portIter->range.end); + snoopIter->range.start, snoopIter->range.end); //@todo We need to properly insert snoop ranges //not overlapping the ranges (multiple) } diff --git a/src/mem/bus.hh b/src/mem/bus.hh index c472b6143..0ad4aad60 100644 --- a/src/mem/bus.hh +++ b/src/mem/bus.hh @@ -42,6 +42,7 @@ #include <inttypes.h> #include "base/range.hh" +#include "base/range_map.hh" #include "mem/mem_object.hh" #include "mem/packet.hh" #include "mem/port.hh" @@ -67,7 +68,7 @@ class Bus : public MemObject int portId; Range<Addr> range; }; - std::vector<DevMap> portList; + range_map<Addr, int> portMap; AddrRangeList defaultRange; std::vector<DevMap> portSnoopList; diff --git a/src/unittest/rangemaptest.cc b/src/unittest/rangemaptest.cc index 6fd99c927..983a41520 100644 --- a/src/unittest/rangemaptest.cc +++ b/src/unittest/rangemaptest.cc @@ -41,7 +41,7 @@ int main() range_map<Addr,int>::iterator i; - i = r.insert(RangeIn<Addr>(0,40),5); + i = r.insert(RangeIn<Addr>(10,40),5); assert(i != r.end()); i = r.insert(RangeIn<Addr>(60,90),3); assert(i != r.end()); @@ -52,6 +52,17 @@ int main() i = r.find(RangeIn(55,55)); assert(i == r.end()); + + i = r.insert(RangeIn<Addr>(0,12),1); + assert(i == r.end()); + + i = r.insert(RangeIn<Addr>(0,9),1); + assert(i != r.end()); + + i = r.find(RangeIn(20,30)); + assert(i != r.end()); + cout << i->first << " " << i->second << endl; + } diff --git a/src/unittest/rangemaptest2.cc b/src/unittest/rangemaptest2.cc new file mode 100644 index 000000000..b253dbe86 --- /dev/null +++ b/src/unittest/rangemaptest2.cc @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2006 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Ali Saidi + */ + +#include <iostream> +#include <cassert> +#include "sim/host.hh" +#include "base/range_map.hh" + +using namespace std; + +int main() +{ + range_multimap<Addr,int> r; + + range_multimap<Addr,int>::iterator i; + std::pair<range_multimap<Addr,int>::iterator,range_multimap<Addr,int>::iterator> + jk; + + i = r.insert(RangeIn<Addr>(10,40),5); + assert(i != r.end()); + i = r.insert(RangeIn<Addr>(10,40),6); + assert(i != r.end()); + i = r.insert(RangeIn<Addr>(60,90),3); + assert(i != r.end()); + + jk = r.find(RangeIn(20,30)); + assert(jk.first != r.end()); + cout << jk.first->first << " " << jk.first->second << endl; + cout << jk.second->first << " " << jk.second->second << endl; + + i = r.insert(RangeIn<Addr>(0,3),5); + assert(i != r.end()); + + for( i = r.begin(); i != r.end(); i++) + cout << i->first << " " << i->second << endl; + + jk = r.find(RangeIn(20,30)); + assert(jk.first != r.end()); + cout << jk.first->first << " " << jk.first->second << endl; + cout << jk.second->first << " " << jk.second->second << endl; + + +} + + + + + + + + |