diff --git a/src/arch/x86/tlb.hh b/src/arch/x86/tlb.hh --- a/src/arch/x86/tlb.hh +++ b/src/arch/x86/tlb.hh @@ -74,9 +74,11 @@ typedef X86TLBParams Params; TLB(const Params *p); + void setNumThreads(uint32_t numThreads); + void takeOverFrom(BaseTLB *otlb) {} - TlbEntry *lookup(Addr va, bool update_lru = true); + TlbEntry *lookup(Addr va, ThreadID tid, bool update_lru = true); void setConfigAddress(uint32_t addr); @@ -91,7 +93,7 @@ void flushAll(); - void flushNonGlobal(); + void flushNonGlobal(ThreadID tid); void demapPage(Addr va, uint64_t asn); @@ -99,10 +101,10 @@ uint32_t size; TlbEntry * tlb; + EntryList freeList; + /* a vector of Trie trees for each hardware thread */ + std::vector trie; - EntryList freeList; - - TlbEntryTrie trie; uint64_t lruSeq; Fault translateInt(RequestPtr req, ThreadContext *tc); @@ -145,7 +147,7 @@ Fault finalizePhysical(RequestPtr req, ThreadContext *tc, Mode mode) const; - TlbEntry * insert(Addr vpn, TlbEntry &entry); + TlbEntry * insert(Addr vpn, ThreadID tid, TlbEntry &entry); // Checkpointing virtual void serialize(std::ostream &os); diff --git a/src/arch/x86/tlb.cc b/src/arch/x86/tlb.cc --- a/src/arch/x86/tlb.cc +++ b/src/arch/x86/tlb.cc @@ -77,6 +77,14 @@ walker = p->walker; walker->setTLB(this); + + trie.resize(1); +} + +void +TLB::setNumThreads(uint32_t numThreads) +{ + this->trie.resize(numThreads); } void @@ -92,16 +100,16 @@ } assert(tlb[lru].trieHandle); - trie.remove(tlb[lru].trieHandle); + trie[tlb[lru].hwTID].remove(tlb[lru].trieHandle); tlb[lru].trieHandle = NULL; freeList.push_back(&tlb[lru]); } TlbEntry * -TLB::insert(Addr vpn, TlbEntry &entry) +TLB::insert(Addr vpn, ThreadID tid, TlbEntry &entry) { // If somebody beat us to it, just use that existing entry. - TlbEntry *newEntry = trie.lookup(vpn); + TlbEntry *newEntry = trie[tid].lookup(vpn); if (newEntry) { assert(newEntry->vaddr == vpn); return newEntry; @@ -117,14 +125,14 @@ newEntry->lruSeq = nextSeq(); newEntry->vaddr = vpn; newEntry->trieHandle = - trie.insert(vpn, TlbEntryTrie::MaxBits - entry.logBytes, newEntry); + trie[tid].insert(vpn, TlbEntryTrie::MaxBits - entry.logBytes, newEntry); return newEntry; } TlbEntry * -TLB::lookup(Addr va, bool update_lru) +TLB::lookup(Addr va, ThreadID tid, bool update_lru) { - TlbEntry *entry = trie.lookup(va); + TlbEntry *entry = trie[tid].lookup(va); if (entry && update_lru) entry->lruSeq = nextSeq(); return entry; @@ -136,7 +144,7 @@ DPRINTF(TLB, "Invalidating all entries.\n"); for (unsigned i = 0; i < size; i++) { if (tlb[i].trieHandle) { - trie.remove(tlb[i].trieHandle); + trie[tlb[i].hwTID].remove(tlb[i].trieHandle); tlb[i].trieHandle = NULL; freeList.push_back(&tlb[i]); } @@ -150,12 +158,12 @@ } void -TLB::flushNonGlobal() +TLB::flushNonGlobal(ThreadID tid) { DPRINTF(TLB, "Invalidating all non global entries.\n"); for (unsigned i = 0; i < size; i++) { - if (tlb[i].trieHandle && !tlb[i].global) { - trie.remove(tlb[i].trieHandle); + if (tlb[i].trieHandle && !tlb[i].global && (tlb[i].hwTID == tid)) { + trie[tlb[i].hwTID].remove(tlb[i].trieHandle); tlb[i].trieHandle = NULL; freeList.push_back(&tlb[i]); } @@ -165,11 +173,13 @@ void TLB::demapPage(Addr va, uint64_t asn) { - TlbEntry *entry = trie.lookup(va); - if (entry) { - trie.remove(entry->trieHandle); - entry->trieHandle = NULL; - freeList.push_back(entry); + for (int tid = 0; tid < trie.size(); tid++) { + TlbEntry *entry = trie[tid].lookup(va); + if (entry) { + trie[tid].remove(entry->trieHandle); + entry->trieHandle = NULL; + freeList.push_back(entry); + } } } @@ -337,7 +347,7 @@ if (m5Reg.paging) { DPRINTF(TLB, "Paging enabled.\n"); // The vaddr already has the segment base applied. - TlbEntry *entry = lookup(vaddr); + TlbEntry *entry = lookup(vaddr, tc->threadId()); if (!entry) { if (FullSystem) { Fault fault = walker->start(tc, translation, req, mode); @@ -346,7 +356,7 @@ delayedResponse = true; return fault; } - entry = lookup(vaddr); + entry = lookup(vaddr, tc->threadId()); assert(entry); } else { DPRINTF(TLB, "Handling a TLB miss for " @@ -370,7 +380,7 @@ Addr alignedVaddr = p->pTable->pageAlign(vaddr); DPRINTF(TLB, "Mapping %#x to %#x\n", alignedVaddr, newEntry.pageStart()); - entry = insert(alignedVaddr, newEntry); + entry = insert(alignedVaddr, tc->threadId(), newEntry); } DPRINTF(TLB, "Miss was serviced.\n"); } @@ -486,7 +496,7 @@ freeList.pop_front(); newEntry->unserialize(cp, csprintf("%s.Entry%d", name(), x)); - newEntry->trieHandle = trie.insert(newEntry->vaddr, + newEntry->trieHandle = trie[newEntry->hwTID].insert(newEntry->vaddr, TlbEntryTrie::MaxBits - newEntry->logBytes, newEntry); } } diff --git a/src/cpu/o3/cpu.cc b/src/cpu/o3/cpu.cc --- a/src/cpu/o3/cpu.cc +++ b/src/cpu/o3/cpu.cc @@ -408,6 +408,10 @@ for (ThreadID tid = 0; tid < this->numThreads; tid++) this->thread[tid]->setFuncExeInst(0); + + // initialising TLBs + this->itb->setNumThreads(numThreads); + this->dtb->setNumThreads(numThreads); } template # Node ID f4565ce598ddb34c3f2abc157e9beff7aea831f0 # Parent 9c783a1367cd3c5aa617e9d246f0bfa037b1c289 diff --git a/src/arch/generic/tlb.hh b/src/arch/generic/tlb.hh --- a/src/arch/generic/tlb.hh +++ b/src/arch/generic/tlb.hh @@ -64,6 +64,11 @@ virtual void demapPage(Addr vaddr, uint64_t asn) = 0; /** + * Set the number of threads in case of multiple hardware threads + */ + virtual void setNumThreads(uint32_t numThreads) {}; + + /** * Remove all entries from the TLB */ virtual void flushAll() = 0; diff --git a/src/arch/x86/isa.cc b/src/arch/x86/isa.cc --- a/src/arch/x86/isa.cc +++ b/src/arch/x86/isa.cc @@ -208,8 +208,8 @@ case MISCREG_CR2: break; case MISCREG_CR3: - tc->getITBPtr()->flushNonGlobal(); - tc->getDTBPtr()->flushNonGlobal(); + tc->getITBPtr()->flushNonGlobal(tc->threadId()); + tc->getDTBPtr()->flushNonGlobal(tc->threadId()); break; case MISCREG_CR4: { diff --git a/src/arch/x86/pagetable.hh b/src/arch/x86/pagetable.hh --- a/src/arch/x86/pagetable.hh +++ b/src/arch/x86/pagetable.hh @@ -106,6 +106,8 @@ Addr vaddr; // The size of the page this represents, in address bits. unsigned logBytes; + // Hardware thread ID for SMT processor + ThreadID hwTID; // Read permission is always available, assuming it isn't blocked by // other mechanisms. diff --git a/src/arch/x86/pagetable.cc b/src/arch/x86/pagetable.cc --- a/src/arch/x86/pagetable.cc +++ b/src/arch/x86/pagetable.cc @@ -47,9 +47,9 @@ TlbEntry::TlbEntry(Addr asn, Addr _vaddr, Addr _paddr, bool uncacheable, bool read_only) : - paddr(_paddr), vaddr(_vaddr), logBytes(PageShift), writable(!read_only), - user(true), uncacheable(uncacheable), global(false), patBit(0), - noExec(false) + paddr(_paddr), vaddr(_vaddr), logBytes(PageShift), hwTID(asn), + writable(!read_only), user(true), uncacheable(uncacheable), global(false), + patBit(0), noExec(false) {} void diff --git a/src/arch/x86/pagetable_walker.cc b/src/arch/x86/pagetable_walker.cc --- a/src/arch/x86/pagetable_walker.cc +++ b/src/arch/x86/pagetable_walker.cc @@ -506,7 +506,7 @@ if (doEndWalk) { if (doTLBInsert) if (!functional) - walker->tlb->insert(entry.vaddr, entry); + walker->tlb->insert(entry.vaddr, tc->threadId(), entry); endWalk(); } else { PacketPtr oldRead = read;