tlb.cc
来自「M5,一个功能强大的多处理器系统模拟器.很多针对处理器架构,性能的研究都使用它作」· CC 代码 · 共 1,443 行 · 第 1/3 页
CC
1,443 行
/* * Copyright (c) 2001, 2002, 2003, 2004, 2005 * The Regents of The University of Michigan * All Rights Reserved * * This code is part of the M5 simulator. * * Permission is granted to use, copy, create derivative works and * redistribute this software and such derivative works for any * purpose, so long as the copyright notice above, this grant of * permission, and the disclaimer below appear in all copies made; and * so long as the name of The University of Michigan is not used in * any advertising or publicity pertaining to the use or distribution * of this software without specific, written prior authorization. * * THIS SOFTWARE IS PROVIDED AS IS, WITHOUT REPRESENTATION FROM THE * UNIVERSITY OF MICHIGAN AS TO ITS FITNESS FOR ANY PURPOSE, AND * WITHOUT WARRANTY BY THE UNIVERSITY OF MICHIGAN OF ANY KIND, EITHER * EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE. THE REGENTS OF THE UNIVERSITY OF MICHIGAN SHALL NOT BE * LIABLE FOR ANY DAMAGES, INCLUDING DIRECT, SPECIAL, INDIRECT, * INCIDENTAL, OR CONSEQUENTIAL DAMAGES, WITH RESPECT TO ANY CLAIM * ARISING OUT OF OR IN CONNECTION WITH THE USE OF THE SOFTWARE, EVEN * IF IT HAS BEEN OR IS HEREAFTER ADVISED OF THE POSSIBILITY OF SUCH * DAMAGES. * * Authors: Ali G. Saidi */#include <cstring>#include "arch/sparc/asi.hh"#include "arch/sparc/miscregfile.hh"#include "arch/sparc/tlb.hh"#include "base/bitfield.hh"#include "base/trace.hh"#include "cpu/thread_context.hh"#include "cpu/base.hh"#include "mem/packet_access.hh"#include "mem/request.hh"#include "sim/system.hh"/* @todo remove some of the magic constants. -- ali * */namespace SparcISA {TLB::TLB(const Params *p) : BaseTLB(p), size(p->size), usedEntries(0), lastReplaced(0), cacheValid(false){ // To make this work you'll have to change the hypervisor and OS if (size > 64) fatal("SPARC T1 TLB registers don't support more than 64 TLB entries."); tlb = new TlbEntry[size]; std::memset(tlb, 0, sizeof(TlbEntry) * size); for (int x = 0; x < size; x++) freeList.push_back(&tlb[x]); c0_tsb_ps0 = 0; c0_tsb_ps1 = 0; c0_config = 0; cx_tsb_ps0 = 0; cx_tsb_ps1 = 0; cx_config = 0; sfsr = 0; tag_access = 0;}voidTLB::clearUsedBits(){ MapIter i; for (i = lookupTable.begin(); i != lookupTable.end(); i++) { TlbEntry *t = i->second; if (!t->pte.locked()) { t->used = false; usedEntries--; } }}voidTLB::insert(Addr va, int partition_id, int context_id, bool real, const PageTableEntry& PTE, int entry){ MapIter i; TlbEntry *new_entry = NULL;// TlbRange tr; int x; cacheValid = false; va &= ~(PTE.size()-1); /* tr.va = va; tr.size = PTE.size() - 1; tr.contextId = context_id; tr.partitionId = partition_id; tr.real = real;*/ DPRINTF(TLB, "TLB: Inserting TLB Entry; va=%#x pa=%#x pid=%d cid=%d r=%d entryid=%d\n", va, PTE.paddr(), partition_id, context_id, (int)real, entry); // Demap any entry that conflicts for (x = 0; x < size; x++) { if (tlb[x].range.real == real && tlb[x].range.partitionId == partition_id && tlb[x].range.va < va + PTE.size() - 1 && tlb[x].range.va + tlb[x].range.size >= va && (real || tlb[x].range.contextId == context_id )) { if (tlb[x].valid) { freeList.push_front(&tlb[x]); DPRINTF(TLB, "TLB: Conflicting entry %#X , deleting it\n", x); tlb[x].valid = false; if (tlb[x].used) { tlb[x].used = false; usedEntries--; } lookupTable.erase(tlb[x].range); } } }/* i = lookupTable.find(tr); if (i != lookupTable.end()) { i->second->valid = false; if (i->second->used) { i->second->used = false; usedEntries--; } freeList.push_front(i->second); DPRINTF(TLB, "TLB: Found conflicting entry %#X , deleting it\n", i->second); lookupTable.erase(i); }*/ if (entry != -1) { assert(entry < size && entry >= 0); new_entry = &tlb[entry]; } else { if (!freeList.empty()) { new_entry = freeList.front(); } else { x = lastReplaced; do { ++x; if (x == size) x = 0; if (x == lastReplaced) goto insertAllLocked; } while (tlb[x].pte.locked()); lastReplaced = x; new_entry = &tlb[x]; } /* for (x = 0; x < size; x++) { if (!tlb[x].valid || !tlb[x].used) { new_entry = &tlb[x]; break; } }*/ }insertAllLocked: // Update the last ently if their all locked if (!new_entry) { new_entry = &tlb[size-1]; } freeList.remove(new_entry); if (new_entry->valid && new_entry->used) usedEntries--; if (new_entry->valid) lookupTable.erase(new_entry->range); assert(PTE.valid()); new_entry->range.va = va; new_entry->range.size = PTE.size() - 1; new_entry->range.partitionId = partition_id; new_entry->range.contextId = context_id; new_entry->range.real = real; new_entry->pte = PTE; new_entry->used = true;; new_entry->valid = true; usedEntries++; i = lookupTable.insert(new_entry->range, new_entry); assert(i != lookupTable.end()); // If all entries have there used bit set, clear it on them all, but the // one we just inserted if (usedEntries == size) { clearUsedBits(); new_entry->used = true; usedEntries++; }}TlbEntry*TLB::lookup(Addr va, int partition_id, bool real, int context_id, bool update_used){ MapIter i; TlbRange tr; TlbEntry *t; DPRINTF(TLB, "TLB: Looking up entry va=%#x pid=%d cid=%d r=%d\n", va, partition_id, context_id, real); // Assemble full address structure tr.va = va; tr.size = 1; tr.contextId = context_id; tr.partitionId = partition_id; tr.real = real; // Try to find the entry i = lookupTable.find(tr); if (i == lookupTable.end()) { DPRINTF(TLB, "TLB: No valid entry found\n"); return NULL; } // Mark the entries used bit and clear other used bits in needed t = i->second; DPRINTF(TLB, "TLB: Valid entry found pa: %#x size: %#x\n", t->pte.paddr(), t->pte.size()); // Update the used bits only if this is a real access (not a fake one from // virttophys() if (!t->used && update_used) { t->used = true; usedEntries++; if (usedEntries == size) { clearUsedBits(); t->used = true; usedEntries++; } } return t;}voidTLB::dumpAll(){ MapIter i; for (int x = 0; x < size; x++) { if (tlb[x].valid) { DPRINTFN("%4d: %#2x:%#2x %c %#4x %#8x %#8x %#16x\n", x, tlb[x].range.partitionId, tlb[x].range.contextId, tlb[x].range.real ? 'R' : ' ', tlb[x].range.size, tlb[x].range.va, tlb[x].pte.paddr(), tlb[x].pte()); } }}voidTLB::demapPage(Addr va, int partition_id, bool real, int context_id){ TlbRange tr; MapIter i; DPRINTF(IPR, "TLB: Demapping Page va=%#x pid=%#d cid=%d r=%d\n", va, partition_id, context_id, real); cacheValid = false; // Assemble full address structure tr.va = va; tr.size = 1; tr.contextId = context_id; tr.partitionId = partition_id; tr.real = real; // Demap any entry that conflicts i = lookupTable.find(tr); if (i != lookupTable.end()) { DPRINTF(IPR, "TLB: Demapped page\n"); i->second->valid = false; if (i->second->used) { i->second->used = false; usedEntries--; } freeList.push_front(i->second); lookupTable.erase(i); }}voidTLB::demapContext(int partition_id, int context_id){ int x; DPRINTF(IPR, "TLB: Demapping Context pid=%#d cid=%d\n", partition_id, context_id); cacheValid = false; for (x = 0; x < size; x++) { if (tlb[x].range.contextId == context_id && tlb[x].range.partitionId == partition_id) { if (tlb[x].valid == true) { freeList.push_front(&tlb[x]); } tlb[x].valid = false; if (tlb[x].used) { tlb[x].used = false; usedEntries--; } lookupTable.erase(tlb[x].range); } }}voidTLB::demapAll(int partition_id){ int x; DPRINTF(TLB, "TLB: Demapping All pid=%#d\n", partition_id); cacheValid = false; for (x = 0; x < size; x++) { if (tlb[x].valid && !tlb[x].pte.locked() && tlb[x].range.partitionId == partition_id) { freeList.push_front(&tlb[x]); tlb[x].valid = false; if (tlb[x].used) { tlb[x].used = false; usedEntries--; } lookupTable.erase(tlb[x].range); } }}voidTLB::invalidateAll(){ int x; cacheValid = false; lookupTable.clear(); for (x = 0; x < size; x++) { if (tlb[x].valid == true) freeList.push_back(&tlb[x]); tlb[x].valid = false; tlb[x].used = false; } usedEntries = 0;}uint64_tTLB::TteRead(int entry) { if (entry >= size) panic("entry: %d\n", entry); assert(entry < size); if (tlb[entry].valid) return tlb[entry].pte(); else return (uint64_t)-1ll;}uint64_tTLB::TagRead(int entry) { assert(entry < size); uint64_t tag; if (!tlb[entry].valid) return (uint64_t)-1ll; tag = tlb[entry].range.contextId; tag |= tlb[entry].range.va; tag |= (uint64_t)tlb[entry].range.partitionId << 61; tag |= tlb[entry].range.real ? ULL(1) << 60 : 0; tag |= (uint64_t)~tlb[entry].pte._size() << 56; return tag;}boolTLB::validVirtualAddress(Addr va, bool am){ if (am) return true; if (va >= StartVAddrHole && va <= EndVAddrHole) return false; return true;}voidTLB::writeSfsr(bool write, ContextType ct, bool se, FaultTypes ft, int asi){ if (sfsr & 0x1) sfsr = 0x3; else sfsr = 1; if (write) sfsr |= 1 << 2; sfsr |= ct << 4; if (se) sfsr |= 1 << 6; sfsr |= ft << 7; sfsr |= asi << 16;}voidTLB::writeTagAccess(Addr va, int context){ DPRINTF(TLB, "TLB: Writing Tag Access: va: %#X ctx: %#X value: %#X\n", va, context, mbits(va, 63,13) | mbits(context,12,0)); tag_access = mbits(va, 63,13) | mbits(context,12,0);}voidITB::writeSfsr(bool write, ContextType ct, bool se, FaultTypes ft, int asi){ DPRINTF(TLB, "TLB: ITB Fault: w=%d ct=%d ft=%d asi=%d\n", (int)write, ct, ft, asi); TLB::writeSfsr(write, ct, se, ft, asi);}voidDTB::writeSfsr(Addr a, bool write, ContextType ct, bool se, FaultTypes ft, int asi){ DPRINTF(TLB, "TLB: DTB Fault: A=%#x w=%d ct=%d ft=%d asi=%d\n", a, (int)write, ct, ft, asi); TLB::writeSfsr(write, ct, se, ft, asi); sfar = a;}FaultITB::translate(RequestPtr &req, ThreadContext *tc){ uint64_t tlbdata = tc->readMiscRegNoEffect(MISCREG_TLB_DATA); Addr vaddr = req->getVaddr(); TlbEntry *e; assert(req->getAsi() == ASI_IMPLICIT); DPRINTF(TLB, "TLB: ITB Request to translate va=%#x size=%d\n", vaddr, req->getSize()); // 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;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?