tlb.cc revision 4070
12968SN/A/* 22968SN/A * Copyright (c) 2001-2005 The Regents of The University of Michigan 310409Sandreas.hansson@arm.com * All rights reserved. 411502SCurtis.Dunham@arm.com * 511502SCurtis.Dunham@arm.com * Redistribution and use in source and binary forms, with or without 68721SN/A * modification, are permitted provided that the following conditions are 711530Sandreas.sandberg@arm.com * met: redistributions of source code must retain the above copyright 811530Sandreas.sandberg@arm.com * notice, this list of conditions and the following disclaimer; 911530Sandreas.sandberg@arm.com * redistributions in binary form must reproduce the above copyright 1011530Sandreas.sandberg@arm.com * notice, this list of conditions and the following disclaimer in the 1111530Sandreas.sandberg@arm.com * documentation and/or other materials provided with the distribution; 1211336Sandreas.hansson@arm.com * neither the name of the copyright holders nor the names of its 1311336Sandreas.hansson@arm.com * contributors may be used to endorse or promote products derived from 1410036SAli.Saidi@ARM.com * this software without specific prior written permission. 1510036SAli.Saidi@ARM.com * 1611530Sandreas.sandberg@arm.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 1711201Sandreas.hansson@arm.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 1811201Sandreas.hansson@arm.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 1911336Sandreas.hansson@arm.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 2011201Sandreas.hansson@arm.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 2110352Sandreas.hansson@arm.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 2211336Sandreas.hansson@arm.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2311201Sandreas.hansson@arm.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2411336Sandreas.hansson@arm.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2511336Sandreas.hansson@arm.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 2611336Sandreas.hansson@arm.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2711336Sandreas.hansson@arm.com * 2811201Sandreas.hansson@arm.com * Authors: Ali Saidi 2911201Sandreas.hansson@arm.com */ 3011336Sandreas.hansson@arm.com 3111201Sandreas.hansson@arm.com#include <cstring> 3210352Sandreas.hansson@arm.com 3311336Sandreas.hansson@arm.com#include "arch/sparc/asi.hh" 3411336Sandreas.hansson@arm.com#include "arch/sparc/miscregfile.hh" 3511336Sandreas.hansson@arm.com#include "arch/sparc/tlb.hh" 3611201Sandreas.hansson@arm.com#include "base/bitfield.hh" 3711336Sandreas.hansson@arm.com#include "base/trace.hh" 3811336Sandreas.hansson@arm.com#include "cpu/thread_context.hh" 3911201Sandreas.hansson@arm.com#include "cpu/base.hh" 4010409Sandreas.hansson@arm.com#include "mem/packet_access.hh" 4111336Sandreas.hansson@arm.com#include "mem/request.hh" 4211201Sandreas.hansson@arm.com#include "sim/builder.hh" 4311336Sandreas.hansson@arm.com 4411336Sandreas.hansson@arm.com/* @todo remove some of the magic constants. -- ali 4511336Sandreas.hansson@arm.com * */ 4611336Sandreas.hansson@arm.comnamespace SparcISA 4711336Sandreas.hansson@arm.com{ 4811201Sandreas.hansson@arm.com 4911336Sandreas.hansson@arm.comTLB::TLB(const std::string &name, int s) 5011336Sandreas.hansson@arm.com : SimObject(name), size(s), usedEntries(0), lastReplaced(0), 5111201Sandreas.hansson@arm.com cacheValid(false) 5210585Sandreas.hansson@arm.com{ 5311502SCurtis.Dunham@arm.com // To make this work you'll have to change the hypervisor and OS 5411530Sandreas.sandberg@arm.com if (size > 64) 5511530Sandreas.sandberg@arm.com fatal("SPARC T1 TLB registers don't support more than 64 TLB entries."); 5610036SAli.Saidi@ARM.com 578721SN/A tlb = new TlbEntry[size]; 588721SN/A std::memset(tlb, 0, sizeof(TlbEntry) * size); 598721SN/A 608721SN/A for (int x = 0; x < size; x++) 6111336Sandreas.hansson@arm.com freeList.push_back(&tlb[x]); 6210409Sandreas.hansson@arm.com} 638721SN/A 6410409Sandreas.hansson@arm.comvoid 6511336Sandreas.hansson@arm.comTLB::clearUsedBits() 6610409Sandreas.hansson@arm.com{ 6710409Sandreas.hansson@arm.com MapIter i; 6810409Sandreas.hansson@arm.com for (i = lookupTable.begin(); i != lookupTable.end(); i++) { 6911336Sandreas.hansson@arm.com TlbEntry *t = i->second; 7010409Sandreas.hansson@arm.com if (!t->pte.locked()) { 7110409Sandreas.hansson@arm.com t->used = false; 7210409Sandreas.hansson@arm.com usedEntries--; 7311336Sandreas.hansson@arm.com } 7410409Sandreas.hansson@arm.com } 758721SN/A} 7611336Sandreas.hansson@arm.com 778721SN/A 788721SN/Avoid 798721SN/ATLB::insert(Addr va, int partition_id, int context_id, bool real, 808721SN/A const PageTableEntry& PTE, int entry) 818721SN/A{ 828721SN/A 838721SN/A 848721SN/A MapIter i; 856024SN/A TlbEntry *new_entry = NULL; 866024SN/A// TlbRange tr; 878721SN/A int x; 888721SN/A 8911530Sandreas.sandberg@arm.com cacheValid = false; 9011530Sandreas.sandberg@arm.com va &= ~(PTE.size()-1); 9111530Sandreas.sandberg@arm.com /* tr.va = va; 9211530Sandreas.sandberg@arm.com tr.size = PTE.size() - 1; 9311530Sandreas.sandberg@arm.com tr.contextId = context_id; 9411530Sandreas.sandberg@arm.com tr.partitionId = partition_id; 9511530Sandreas.sandberg@arm.com tr.real = real; 9611530Sandreas.sandberg@arm.com*/ 9711530Sandreas.sandberg@arm.com 9811530Sandreas.sandberg@arm.com DPRINTF(TLB, "TLB: Inserting TLB Entry; va=%#x pa=%#x pid=%d cid=%d r=%d entryid=%d\n", 9911502SCurtis.Dunham@arm.com va, PTE.paddr(), partition_id, context_id, (int)real, entry); 1008721SN/A 1018721SN/A // Demap any entry that conflicts 1022968SN/A for (x = 0; x < size; x++) { 10310409Sandreas.hansson@arm.com if (tlb[x].range.real == real && 10411336Sandreas.hansson@arm.com tlb[x].range.partitionId == partition_id && 10510409Sandreas.hansson@arm.com tlb[x].range.va < va + PTE.size() - 1 && 10611336Sandreas.hansson@arm.com tlb[x].range.va + tlb[x].range.size >= va && 10710409Sandreas.hansson@arm.com (real || tlb[x].range.contextId == context_id )) 10810409Sandreas.hansson@arm.com { 10911336Sandreas.hansson@arm.com if (tlb[x].valid) { 11011336Sandreas.hansson@arm.com freeList.push_front(&tlb[x]); 11110409Sandreas.hansson@arm.com DPRINTF(TLB, "TLB: Conflicting entry %#X , deleting it\n", x); 11210409Sandreas.hansson@arm.com 11310409Sandreas.hansson@arm.com tlb[x].valid = false; 11410409Sandreas.hansson@arm.com if (tlb[x].used) { 11510409Sandreas.hansson@arm.com tlb[x].used = false; 11610409Sandreas.hansson@arm.com usedEntries--; 11711502SCurtis.Dunham@arm.com } 11810409Sandreas.hansson@arm.com lookupTable.erase(tlb[x].range); 11910409Sandreas.hansson@arm.com } 12010409Sandreas.hansson@arm.com } 12111336Sandreas.hansson@arm.com } 12211502SCurtis.Dunham@arm.com 12310409Sandreas.hansson@arm.com 1246127SN/A/* 1256127SN/A i = lookupTable.find(tr); 1266127SN/A if (i != lookupTable.end()) { 12711336Sandreas.hansson@arm.com i->second->valid = false; 12811336Sandreas.hansson@arm.com if (i->second->used) { 12910409Sandreas.hansson@arm.com i->second->used = false; 13010409Sandreas.hansson@arm.com usedEntries--; 13110409Sandreas.hansson@arm.com } 13210409Sandreas.hansson@arm.com freeList.push_front(i->second); 13310409Sandreas.hansson@arm.com DPRINTF(TLB, "TLB: Found conflicting entry %#X , deleting it\n", 13410409Sandreas.hansson@arm.com i->second); 13510409Sandreas.hansson@arm.com lookupTable.erase(i); 13610409Sandreas.hansson@arm.com } 13710409Sandreas.hansson@arm.com*/ 13810409Sandreas.hansson@arm.com 13910409Sandreas.hansson@arm.com if (entry != -1) { 14010409Sandreas.hansson@arm.com assert(entry < size && entry >= 0); 14110409Sandreas.hansson@arm.com new_entry = &tlb[entry]; 14210409Sandreas.hansson@arm.com } else { 14310409Sandreas.hansson@arm.com if (!freeList.empty()) { 14410409Sandreas.hansson@arm.com new_entry = freeList.front(); 14510409Sandreas.hansson@arm.com } else { 14610409Sandreas.hansson@arm.com x = lastReplaced; 14710409Sandreas.hansson@arm.com do { 14810409Sandreas.hansson@arm.com ++x; 14910409Sandreas.hansson@arm.com if (x == size) 15010409Sandreas.hansson@arm.com x = 0; 15110409Sandreas.hansson@arm.com if (x == lastReplaced) 15210409Sandreas.hansson@arm.com goto insertAllLocked; 15310409Sandreas.hansson@arm.com } while (tlb[x].pte.locked()); 15410409Sandreas.hansson@arm.com lastReplaced = x; 15510409Sandreas.hansson@arm.com new_entry = &tlb[x]; 15610409Sandreas.hansson@arm.com } 1576291SN/A /* 1586291SN/A for (x = 0; x < size; x++) { 15910409Sandreas.hansson@arm.com if (!tlb[x].valid || !tlb[x].used) { 1608721SN/A new_entry = &tlb[x]; 16110409Sandreas.hansson@arm.com break; 16210409Sandreas.hansson@arm.com } 16310409Sandreas.hansson@arm.com }*/ 16410409Sandreas.hansson@arm.com } 16510409Sandreas.hansson@arm.com 16610409Sandreas.hansson@arm.cominsertAllLocked: 16710409Sandreas.hansson@arm.com // Update the last ently if their all locked 16811336Sandreas.hansson@arm.com if (!new_entry) { 16910409Sandreas.hansson@arm.com new_entry = &tlb[size-1]; 17010409Sandreas.hansson@arm.com } 17110409Sandreas.hansson@arm.com 17210409Sandreas.hansson@arm.com freeList.remove(new_entry); 17310409Sandreas.hansson@arm.com if (new_entry->valid && new_entry->used) 17410409Sandreas.hansson@arm.com usedEntries--; 17510409Sandreas.hansson@arm.com if (new_entry->valid) 17610409Sandreas.hansson@arm.com lookupTable.erase(new_entry->range); 17711336Sandreas.hansson@arm.com 17810409Sandreas.hansson@arm.com 17911336Sandreas.hansson@arm.com assert(PTE.valid()); 1808721SN/A new_entry->range.va = va; 18111336Sandreas.hansson@arm.com new_entry->range.size = PTE.size() - 1; 18211336Sandreas.hansson@arm.com new_entry->range.partitionId = partition_id; 1838721SN/A new_entry->range.contextId = context_id; 18411336Sandreas.hansson@arm.com new_entry->range.real = real; 1858721SN/A new_entry->pte = PTE; 1868983Snate@binkert.org new_entry->used = true;; 18711336Sandreas.hansson@arm.com new_entry->valid = true; 18811502SCurtis.Dunham@arm.com usedEntries++; 18911336Sandreas.hansson@arm.com 1908721SN/A 19110409Sandreas.hansson@arm.com 19211336Sandreas.hansson@arm.com i = lookupTable.insert(new_entry->range, new_entry); 19311336Sandreas.hansson@arm.com assert(i != lookupTable.end()); 19411336Sandreas.hansson@arm.com 19511201Sandreas.hansson@arm.com // If all entries have there used bit set, clear it on them all, but the 19611336Sandreas.hansson@arm.com // one we just inserted 19711336Sandreas.hansson@arm.com if (usedEntries == size) { 19811336Sandreas.hansson@arm.com clearUsedBits(); 19911201Sandreas.hansson@arm.com new_entry->used = true; 20011336Sandreas.hansson@arm.com usedEntries++; 20111336Sandreas.hansson@arm.com } 20211201Sandreas.hansson@arm.com 20311201Sandreas.hansson@arm.com} 20411336Sandreas.hansson@arm.com 20511336Sandreas.hansson@arm.com 20611336Sandreas.hansson@arm.comTlbEntry* 20711502SCurtis.Dunham@arm.comTLB::lookup(Addr va, int partition_id, bool real, int context_id, bool 20811336Sandreas.hansson@arm.com update_used) 20911201Sandreas.hansson@arm.com{ 21011201Sandreas.hansson@arm.com MapIter i; 21111336Sandreas.hansson@arm.com TlbRange tr; 21211336Sandreas.hansson@arm.com TlbEntry *t; 21311336Sandreas.hansson@arm.com 21411336Sandreas.hansson@arm.com DPRINTF(TLB, "TLB: Looking up entry va=%#x pid=%d cid=%d r=%d\n", 21511201Sandreas.hansson@arm.com va, partition_id, context_id, real); 21611201Sandreas.hansson@arm.com // Assemble full address structure 21711201Sandreas.hansson@arm.com tr.va = va; 21811201Sandreas.hansson@arm.com tr.size = MachineBytes; 21911201Sandreas.hansson@arm.com tr.contextId = context_id; 22011201Sandreas.hansson@arm.com tr.partitionId = partition_id; 22111201Sandreas.hansson@arm.com tr.real = real; 22211201Sandreas.hansson@arm.com 22311201Sandreas.hansson@arm.com // Try to find the entry 22411201Sandreas.hansson@arm.com i = lookupTable.find(tr); 22511201Sandreas.hansson@arm.com if (i == lookupTable.end()) { 22611201Sandreas.hansson@arm.com DPRINTF(TLB, "TLB: No valid entry found\n"); 22711201Sandreas.hansson@arm.com return NULL; 22811201Sandreas.hansson@arm.com } 22911201Sandreas.hansson@arm.com 23011201Sandreas.hansson@arm.com // Mark the entries used bit and clear other used bits in needed 23111201Sandreas.hansson@arm.com t = i->second; 23211201Sandreas.hansson@arm.com DPRINTF(TLB, "TLB: Valid entry found pa: %#x size: %#x\n", t->pte.paddr(), 23311201Sandreas.hansson@arm.com t->pte.size()); 23411201Sandreas.hansson@arm.com 23511201Sandreas.hansson@arm.com // Update the used bits only if this is a real access (not a fake one from 23611201Sandreas.hansson@arm.com // virttophys() 23711201Sandreas.hansson@arm.com if (!t->used && update_used) { 23811201Sandreas.hansson@arm.com t->used = true; 23911201Sandreas.hansson@arm.com usedEntries++; 24011201Sandreas.hansson@arm.com if (usedEntries == size) { 24111201Sandreas.hansson@arm.com clearUsedBits(); 24211336Sandreas.hansson@arm.com t->used = true; 24311336Sandreas.hansson@arm.com usedEntries++; 24411336Sandreas.hansson@arm.com } 24511201Sandreas.hansson@arm.com } 24611336Sandreas.hansson@arm.com 24711530Sandreas.sandberg@arm.com return t; 24811502SCurtis.Dunham@arm.com} 24911502SCurtis.Dunham@arm.com 25011502SCurtis.Dunham@arm.comvoid 25111502SCurtis.Dunham@arm.comTLB::dumpAll() 25211502SCurtis.Dunham@arm.com{ 25310585Sandreas.hansson@arm.com MapIter i; 25411502SCurtis.Dunham@arm.com for (int x = 0; x < size; x++) { 25510585Sandreas.hansson@arm.com if (tlb[x].valid) { 25610585Sandreas.hansson@arm.com DPRINTFN("%4d: %#2x:%#2x %c %#4x %#8x %#8x %#16x\n", 25710585Sandreas.hansson@arm.com x, tlb[x].range.partitionId, tlb[x].range.contextId, 25810585Sandreas.hansson@arm.com tlb[x].range.real ? 'R' : ' ', tlb[x].range.size, 25910585Sandreas.hansson@arm.com tlb[x].range.va, tlb[x].pte.paddr(), tlb[x].pte()); 26010585Sandreas.hansson@arm.com } 26110585Sandreas.hansson@arm.com } 26211502SCurtis.Dunham@arm.com} 26311502SCurtis.Dunham@arm.com 26411530Sandreas.sandberg@arm.comvoid 26511502SCurtis.Dunham@arm.comTLB::demapPage(Addr va, int partition_id, bool real, int context_id) 26611502SCurtis.Dunham@arm.com{ 26711336Sandreas.hansson@arm.com TlbRange tr; 26811336Sandreas.hansson@arm.com MapIter i; 26911336Sandreas.hansson@arm.com 27011336Sandreas.hansson@arm.com DPRINTF(IPR, "TLB: Demapping Page va=%#x pid=%#d cid=%d r=%d\n", 27111336Sandreas.hansson@arm.com va, partition_id, context_id, real); 27211336Sandreas.hansson@arm.com 27311502SCurtis.Dunham@arm.com cacheValid = false; 27411502SCurtis.Dunham@arm.com 27511502SCurtis.Dunham@arm.com // Assemble full address structure 27611502SCurtis.Dunham@arm.com tr.va = va; 27711502SCurtis.Dunham@arm.com tr.size = MachineBytes; 27811502SCurtis.Dunham@arm.com tr.contextId = context_id; 27911336Sandreas.hansson@arm.com tr.partitionId = partition_id; 28011336Sandreas.hansson@arm.com tr.real = real; 28111336Sandreas.hansson@arm.com 28211336Sandreas.hansson@arm.com // Demap any entry that conflicts 28311336Sandreas.hansson@arm.com i = lookupTable.find(tr); 28411336Sandreas.hansson@arm.com if (i != lookupTable.end()) { 28511502SCurtis.Dunham@arm.com DPRINTF(IPR, "TLB: Demapped page\n"); 28611502SCurtis.Dunham@arm.com i->second->valid = false; 28711502SCurtis.Dunham@arm.com if (i->second->used) { 28811502SCurtis.Dunham@arm.com i->second->used = false; 28911336Sandreas.hansson@arm.com usedEntries--; 29011336Sandreas.hansson@arm.com } 29111336Sandreas.hansson@arm.com freeList.push_front(i->second); 29211336Sandreas.hansson@arm.com lookupTable.erase(i); 29310585Sandreas.hansson@arm.com } 29410585Sandreas.hansson@arm.com} 29510585Sandreas.hansson@arm.com 29610585Sandreas.hansson@arm.comvoid 29711336Sandreas.hansson@arm.comTLB::demapContext(int partition_id, int context_id) 29811336Sandreas.hansson@arm.com{ 29911336Sandreas.hansson@arm.com int x; 30011336Sandreas.hansson@arm.com DPRINTF(IPR, "TLB: Demapping Context pid=%#d cid=%d\n", 30111336Sandreas.hansson@arm.com partition_id, context_id); 30211336Sandreas.hansson@arm.com cacheValid = false; 30311336Sandreas.hansson@arm.com for (x = 0; x < size; x++) { 30411336Sandreas.hansson@arm.com if (tlb[x].range.contextId == context_id && 30511336Sandreas.hansson@arm.com tlb[x].range.partitionId == partition_id) { 30611336Sandreas.hansson@arm.com if (tlb[x].valid == true) { 30711336Sandreas.hansson@arm.com freeList.push_front(&tlb[x]); 30811336Sandreas.hansson@arm.com } 30911336Sandreas.hansson@arm.com tlb[x].valid = false; 31011336Sandreas.hansson@arm.com if (tlb[x].used) { 31111336Sandreas.hansson@arm.com tlb[x].used = false; 31211336Sandreas.hansson@arm.com usedEntries--; 31310585Sandreas.hansson@arm.com } 31410585Sandreas.hansson@arm.com lookupTable.erase(tlb[x].range); 31510585Sandreas.hansson@arm.com } 31610585Sandreas.hansson@arm.com } 31710585Sandreas.hansson@arm.com} 31810585Sandreas.hansson@arm.com 31911502SCurtis.Dunham@arm.comvoid 32011502SCurtis.Dunham@arm.comTLB::demapAll(int partition_id) 32111530Sandreas.sandberg@arm.com{ 32211336Sandreas.hansson@arm.com int x; 32311336Sandreas.hansson@arm.com DPRINTF(TLB, "TLB: Demapping All pid=%#d\n", partition_id); 32411336Sandreas.hansson@arm.com cacheValid = false; 32511336Sandreas.hansson@arm.com for (x = 0; x < size; x++) { 32611336Sandreas.hansson@arm.com if (!tlb[x].pte.locked() && tlb[x].range.partitionId == partition_id) { 32710409Sandreas.hansson@arm.com if (tlb[x].valid == true){ 32811336Sandreas.hansson@arm.com freeList.push_front(&tlb[x]); 32910409Sandreas.hansson@arm.com } 33010409Sandreas.hansson@arm.com tlb[x].valid = false; 33110036SAli.Saidi@ARM.com if (tlb[x].used) { 33210409Sandreas.hansson@arm.com tlb[x].used = false; 33310409Sandreas.hansson@arm.com usedEntries--; 33410409Sandreas.hansson@arm.com } 33510036SAli.Saidi@ARM.com lookupTable.erase(tlb[x].range); 33611336Sandreas.hansson@arm.com } 33711336Sandreas.hansson@arm.com } 33811530Sandreas.sandberg@arm.com} 33911336Sandreas.hansson@arm.com 34011336Sandreas.hansson@arm.comvoid 34111336Sandreas.hansson@arm.comTLB::invalidateAll() 34211336Sandreas.hansson@arm.com{ 34311336Sandreas.hansson@arm.com int x; 34411336Sandreas.hansson@arm.com cacheValid = false; 34511336Sandreas.hansson@arm.com 34611336Sandreas.hansson@arm.com freeList.clear(); 34711336Sandreas.hansson@arm.com lookupTable.clear(); 34811336Sandreas.hansson@arm.com for (x = 0; x < size; x++) { 34911336Sandreas.hansson@arm.com if (tlb[x].valid == true) 35011336Sandreas.hansson@arm.com freeList.push_back(&tlb[x]); 35111336Sandreas.hansson@arm.com tlb[x].valid = false; 35211336Sandreas.hansson@arm.com tlb[x].used = false; 35311336Sandreas.hansson@arm.com } 35411336Sandreas.hansson@arm.com usedEntries = 0; 35511336Sandreas.hansson@arm.com} 35611336Sandreas.hansson@arm.com 35710409Sandreas.hansson@arm.comuint64_t 35810409Sandreas.hansson@arm.comTLB::TteRead(int entry) { 35910409Sandreas.hansson@arm.com if (entry >= size) 36010409Sandreas.hansson@arm.com panic("entry: %d\n", entry); 36110409Sandreas.hansson@arm.com 36210409Sandreas.hansson@arm.com assert(entry < size); 3638721SN/A if (tlb[entry].valid) 3648721SN/A return tlb[entry].pte(); 3658721SN/A else 3668721SN/A return (uint64_t)-1ll; 3678983Snate@binkert.org} 3688983Snate@binkert.org 36911336Sandreas.hansson@arm.comuint64_t 37011336Sandreas.hansson@arm.comTLB::TagRead(int entry) { 3718721SN/A assert(entry < size); 3728721SN/A uint64_t tag; 3738721SN/A if (!tlb[entry].valid) 3748721SN/A return (uint64_t)-1ll; 37511336Sandreas.hansson@arm.com 37610409Sandreas.hansson@arm.com tag = tlb[entry].range.contextId; 3778721SN/A tag |= tlb[entry].range.va; 37810409Sandreas.hansson@arm.com tag |= (uint64_t)tlb[entry].range.partitionId << 61; 37910409Sandreas.hansson@arm.com tag |= tlb[entry].range.real ? ULL(1) << 60 : 0; 38010409Sandreas.hansson@arm.com tag |= (uint64_t)~tlb[entry].pte._size() << 56; 38110409Sandreas.hansson@arm.com return tag; 38210409Sandreas.hansson@arm.com} 38311336Sandreas.hansson@arm.com 38410409Sandreas.hansson@arm.combool 38510409Sandreas.hansson@arm.comTLB::validVirtualAddress(Addr va, bool am) 38610409Sandreas.hansson@arm.com{ 38710409Sandreas.hansson@arm.com if (am) 38810409Sandreas.hansson@arm.com return true; 3898721SN/A if (va >= StartVAddrHole && va <= EndVAddrHole) 39010409Sandreas.hansson@arm.com return false; 3918721SN/A return true; 3928721SN/A} 3938721SN/A 3948721SN/Avoid 3958721SN/ATLB::writeSfsr(ThreadContext *tc, int reg, bool write, ContextType ct, 3968721SN/A bool se, FaultTypes ft, int asi) 3978721SN/A{ 3988721SN/A uint64_t sfsr; 3996024SN/A sfsr = tc->readMiscReg(reg); 4006024SN/A 4018721SN/A if (sfsr & 0x1) 4028721SN/A sfsr = 0x3; 40311530Sandreas.sandberg@arm.com else 40411530Sandreas.sandberg@arm.com sfsr = 1; 40511530Sandreas.sandberg@arm.com 40611530Sandreas.sandberg@arm.com if (write) 40711530Sandreas.sandberg@arm.com sfsr |= 1 << 2; 40811530Sandreas.sandberg@arm.com sfsr |= ct << 4; 40911530Sandreas.sandberg@arm.com if (se) 41011530Sandreas.sandberg@arm.com sfsr |= 1 << 6; 41111530Sandreas.sandberg@arm.com sfsr |= ft << 7; 41211530Sandreas.sandberg@arm.com sfsr |= asi << 16; 41311502SCurtis.Dunham@arm.com tc->setMiscRegWithEffect(reg, sfsr); 4148721SN/A} 4158721SN/A 4162968SN/Avoid 41710409Sandreas.hansson@arm.comTLB::writeTagAccess(ThreadContext *tc, int reg, Addr va, int context) 41810409Sandreas.hansson@arm.com{ 41910409Sandreas.hansson@arm.com DPRINTF(TLB, "TLB: Writing Tag Access: va: %#X ctx: %#X value: %#X\n", 42010409Sandreas.hansson@arm.com va, context, mbits(va, 63,13) | mbits(context,12,0)); 42110409Sandreas.hansson@arm.com 42210409Sandreas.hansson@arm.com tc->setMiscRegWithEffect(reg, mbits(va, 63,13) | mbits(context,12,0)); 42310409Sandreas.hansson@arm.com} 42410409Sandreas.hansson@arm.com 42510409Sandreas.hansson@arm.comvoid 42610409Sandreas.hansson@arm.comITB::writeSfsr(ThreadContext *tc, bool write, ContextType ct, 42710409Sandreas.hansson@arm.com bool se, FaultTypes ft, int asi) 42810409Sandreas.hansson@arm.com{ 42911502SCurtis.Dunham@arm.com DPRINTF(TLB, "TLB: ITB Fault: w=%d ct=%d ft=%d asi=%d\n", 43010409Sandreas.hansson@arm.com (int)write, ct, ft, asi); 43110409Sandreas.hansson@arm.com TLB::writeSfsr(tc, MISCREG_MMU_ITLB_SFSR, write, ct, se, ft, asi); 43211336Sandreas.hansson@arm.com} 43311502SCurtis.Dunham@arm.com 43410409Sandreas.hansson@arm.comvoid 4356127SN/AITB::writeTagAccess(ThreadContext *tc, Addr va, int context) 4366127SN/A{ 43710409Sandreas.hansson@arm.com TLB::writeTagAccess(tc, MISCREG_MMU_ITLB_TAG_ACCESS, va, context); 43810409Sandreas.hansson@arm.com} 43910409Sandreas.hansson@arm.com 44010409Sandreas.hansson@arm.comvoid 44110409Sandreas.hansson@arm.comDTB::writeSfr(ThreadContext *tc, Addr a, bool write, ContextType ct, 44210409Sandreas.hansson@arm.com bool se, FaultTypes ft, int asi) 44310409Sandreas.hansson@arm.com{ 44410409Sandreas.hansson@arm.com DPRINTF(TLB, "TLB: DTB Fault: A=%#x w=%d ct=%d ft=%d asi=%d\n", 44510409Sandreas.hansson@arm.com a, (int)write, ct, ft, asi); 44610409Sandreas.hansson@arm.com TLB::writeSfsr(tc, MISCREG_MMU_DTLB_SFSR, write, ct, se, ft, asi); 44710409Sandreas.hansson@arm.com tc->setMiscRegWithEffect(MISCREG_MMU_DTLB_SFAR, a); 44810409Sandreas.hansson@arm.com} 44910409Sandreas.hansson@arm.com 45010409Sandreas.hansson@arm.comvoid 45110409Sandreas.hansson@arm.comDTB::writeTagAccess(ThreadContext *tc, Addr va, int context) 45210409Sandreas.hansson@arm.com{ 45310409Sandreas.hansson@arm.com TLB::writeTagAccess(tc, MISCREG_MMU_DTLB_TAG_ACCESS, va, context); 45410409Sandreas.hansson@arm.com} 45510409Sandreas.hansson@arm.com 45610409Sandreas.hansson@arm.com 4578721SN/A 45810409Sandreas.hansson@arm.comFault 45910409Sandreas.hansson@arm.comITB::translate(RequestPtr &req, ThreadContext *tc) 46010409Sandreas.hansson@arm.com{ 46110409Sandreas.hansson@arm.com uint64_t tlbdata = tc->readMiscReg(MISCREG_TLB_DATA); 46210409Sandreas.hansson@arm.com 46310409Sandreas.hansson@arm.com Addr vaddr = req->getVaddr(); 46410409Sandreas.hansson@arm.com TlbEntry *e; 46510409Sandreas.hansson@arm.com 46610409Sandreas.hansson@arm.com assert(req->getAsi() == ASI_IMPLICIT); 46710409Sandreas.hansson@arm.com 46810409Sandreas.hansson@arm.com DPRINTF(TLB, "TLB: ITB Request to translate va=%#x size=%d\n", 46910409Sandreas.hansson@arm.com vaddr, req->getSize()); 47010409Sandreas.hansson@arm.com 47110409Sandreas.hansson@arm.com // Be fast if we can! 47210409Sandreas.hansson@arm.com if (cacheValid && cacheState == tlbdata) { 4738721SN/A if (cacheEntry) { 47410409Sandreas.hansson@arm.com if (cacheEntry->range.va < vaddr + sizeof(MachInst) && 47510409Sandreas.hansson@arm.com cacheEntry->range.va + cacheEntry->range.size >= vaddr) { 47610409Sandreas.hansson@arm.com req->setPaddr(cacheEntry->pte.paddr() & ~(cacheEntry->pte.size()-1) | 47710409Sandreas.hansson@arm.com vaddr & cacheEntry->pte.size()-1 ); 47810409Sandreas.hansson@arm.com return NoFault; 47910409Sandreas.hansson@arm.com } 48010409Sandreas.hansson@arm.com } else { 48110409Sandreas.hansson@arm.com req->setPaddr(vaddr & PAddrImplMask); 4828721SN/A return NoFault; 48310409Sandreas.hansson@arm.com } 48410409Sandreas.hansson@arm.com } 48511336Sandreas.hansson@arm.com 48610409Sandreas.hansson@arm.com bool hpriv = bits(tlbdata,0,0); 48711502SCurtis.Dunham@arm.com bool red = bits(tlbdata,1,1); 48810409Sandreas.hansson@arm.com bool priv = bits(tlbdata,2,2); 48911336Sandreas.hansson@arm.com bool addr_mask = bits(tlbdata,3,3); 49011336Sandreas.hansson@arm.com bool lsu_im = bits(tlbdata,4,4); 49111336Sandreas.hansson@arm.com 49211201Sandreas.hansson@arm.com int part_id = bits(tlbdata,15,8); 49311201Sandreas.hansson@arm.com int tl = bits(tlbdata,18,16); 49411336Sandreas.hansson@arm.com int pri_context = bits(tlbdata,47,32); 49511336Sandreas.hansson@arm.com int context; 49611201Sandreas.hansson@arm.com ContextType ct; 49711336Sandreas.hansson@arm.com int asi; 49811336Sandreas.hansson@arm.com bool real = false; 49911201Sandreas.hansson@arm.com 50011201Sandreas.hansson@arm.com DPRINTF(TLB, "TLB: priv:%d hpriv:%d red:%d lsuim:%d part_id: %#X\n", 50111336Sandreas.hansson@arm.com priv, hpriv, red, lsu_im, part_id); 50211336Sandreas.hansson@arm.com 50311201Sandreas.hansson@arm.com if (tl > 0) { 50411502SCurtis.Dunham@arm.com asi = ASI_N; 50511502SCurtis.Dunham@arm.com ct = Nucleus; 50611201Sandreas.hansson@arm.com context = 0; 50711201Sandreas.hansson@arm.com } else { 50811336Sandreas.hansson@arm.com asi = ASI_P; 50911201Sandreas.hansson@arm.com ct = Primary; 51011336Sandreas.hansson@arm.com context = pri_context; 51111201Sandreas.hansson@arm.com } 51211201Sandreas.hansson@arm.com 51311201Sandreas.hansson@arm.com if ( hpriv || red ) { 51411201Sandreas.hansson@arm.com cacheValid = true; 51511201Sandreas.hansson@arm.com cacheState = tlbdata; 51611201Sandreas.hansson@arm.com cacheEntry = NULL; 51711201Sandreas.hansson@arm.com req->setPaddr(vaddr & PAddrImplMask); 51811201Sandreas.hansson@arm.com return NoFault; 51911201Sandreas.hansson@arm.com } 52011201Sandreas.hansson@arm.com 52111201Sandreas.hansson@arm.com // If the access is unaligned trap 52211201Sandreas.hansson@arm.com if (vaddr & 0x3) { 52311201Sandreas.hansson@arm.com writeSfsr(tc, false, ct, false, OtherFault, asi); 52411201Sandreas.hansson@arm.com return new MemAddressNotAligned; 52511201Sandreas.hansson@arm.com } 52611201Sandreas.hansson@arm.com 52711201Sandreas.hansson@arm.com if (addr_mask) 52811201Sandreas.hansson@arm.com vaddr = vaddr & VAddrAMask; 52911201Sandreas.hansson@arm.com 53011201Sandreas.hansson@arm.com if (!validVirtualAddress(vaddr, addr_mask)) { 53111201Sandreas.hansson@arm.com writeSfsr(tc, false, ct, false, VaOutOfRange, asi); 53211201Sandreas.hansson@arm.com return new InstructionAccessException; 53311201Sandreas.hansson@arm.com } 53411201Sandreas.hansson@arm.com 53511201Sandreas.hansson@arm.com if (!lsu_im) { 53611201Sandreas.hansson@arm.com e = lookup(vaddr, part_id, true); 53711201Sandreas.hansson@arm.com real = true; 53811201Sandreas.hansson@arm.com context = 0; 53911336Sandreas.hansson@arm.com } else { 54011201Sandreas.hansson@arm.com e = lookup(vaddr, part_id, false, context); 54111201Sandreas.hansson@arm.com } 54211201Sandreas.hansson@arm.com 54311336Sandreas.hansson@arm.com if (e == NULL || !e->valid) { 54411530Sandreas.sandberg@arm.com writeTagAccess(tc, vaddr, context); 54511336Sandreas.hansson@arm.com if (real) 54611502SCurtis.Dunham@arm.com return new InstructionRealTranslationMiss; 54711336Sandreas.hansson@arm.com else 54811336Sandreas.hansson@arm.com return new FastInstructionAccessMMUMiss; 54911336Sandreas.hansson@arm.com } 55010409Sandreas.hansson@arm.com 55111502SCurtis.Dunham@arm.com // were not priviledged accesing priv page 55211336Sandreas.hansson@arm.com if (!priv && e->pte.priv()) { 55311336Sandreas.hansson@arm.com writeTagAccess(tc, vaddr, context); 55410409Sandreas.hansson@arm.com writeSfsr(tc, false, ct, false, PrivViolation, asi); 55510409Sandreas.hansson@arm.com return new InstructionAccessException; 55610409Sandreas.hansson@arm.com } 55710409Sandreas.hansson@arm.com 55811336Sandreas.hansson@arm.com // cache translation date for next translation 55911336Sandreas.hansson@arm.com cacheValid = true; 56011530Sandreas.sandberg@arm.com cacheState = tlbdata; 56111336Sandreas.hansson@arm.com cacheEntry = e; 56211336Sandreas.hansson@arm.com 56311336Sandreas.hansson@arm.com req->setPaddr(e->pte.paddr() & ~(e->pte.size()-1) | 56411336Sandreas.hansson@arm.com vaddr & e->pte.size()-1 ); 56511336Sandreas.hansson@arm.com DPRINTF(TLB, "TLB: %#X -> %#X\n", vaddr, req->getPaddr()); 56611336Sandreas.hansson@arm.com return NoFault; 56710409Sandreas.hansson@arm.com} 56810409Sandreas.hansson@arm.com 56910585Sandreas.hansson@arm.com 57010585Sandreas.hansson@arm.com 57110585Sandreas.hansson@arm.comFault 57210585Sandreas.hansson@arm.comDTB::translate(RequestPtr &req, ThreadContext *tc, bool write) 57311336Sandreas.hansson@arm.com{ 57411336Sandreas.hansson@arm.com /* @todo this could really use some profiling and fixing to make it faster! */ 57511336Sandreas.hansson@arm.com uint64_t tlbdata = tc->readMiscReg(MISCREG_TLB_DATA); 57611336Sandreas.hansson@arm.com Addr vaddr = req->getVaddr(); 57711336Sandreas.hansson@arm.com Addr size = req->getSize(); 57811336Sandreas.hansson@arm.com ASI asi; 57910409Sandreas.hansson@arm.com asi = (ASI)req->getAsi(); 58010409Sandreas.hansson@arm.com bool implicit = false; 58111336Sandreas.hansson@arm.com bool hpriv = bits(tlbdata,0,0); 58211336Sandreas.hansson@arm.com 58311336Sandreas.hansson@arm.com DPRINTF(TLB, "TLB: DTB Request to translate va=%#x size=%d asi=%#x\n", 58411336Sandreas.hansson@arm.com vaddr, size, asi); 58511336Sandreas.hansson@arm.com 58611336Sandreas.hansson@arm.com if (lookupTable.size() != 64 - freeList.size()) 58710409Sandreas.hansson@arm.com panic("Lookup table size: %d tlb size: %d\n", lookupTable.size(), 58810409Sandreas.hansson@arm.com freeList.size()); 58910409Sandreas.hansson@arm.com if (asi == ASI_IMPLICIT) 59010409Sandreas.hansson@arm.com implicit = true; 59110409Sandreas.hansson@arm.com 59210409Sandreas.hansson@arm.com if (hpriv && implicit) { 59311336Sandreas.hansson@arm.com req->setPaddr(vaddr & PAddrImplMask); 59411336Sandreas.hansson@arm.com return NoFault; 59511336Sandreas.hansson@arm.com } 59611336Sandreas.hansson@arm.com 59710409Sandreas.hansson@arm.com // Be fast if we can! 59810409Sandreas.hansson@arm.com if (cacheValid && cacheState == tlbdata) { 59910409Sandreas.hansson@arm.com if (cacheEntry[0] && cacheAsi[0] == asi && cacheEntry[0]->range.va < vaddr + size && 60010409Sandreas.hansson@arm.com cacheEntry[0]->range.va + cacheEntry[0]->range.size > vaddr && 60111336Sandreas.hansson@arm.com (!write || cacheEntry[0]->pte.writable())) { 60211336Sandreas.hansson@arm.com req->setPaddr(cacheEntry[0]->pte.paddr() & ~(cacheEntry[0]->pte.size()-1) | 60310409Sandreas.hansson@arm.com vaddr & cacheEntry[0]->pte.size()-1 ); 60410409Sandreas.hansson@arm.com return NoFault; 60510409Sandreas.hansson@arm.com } 60610409Sandreas.hansson@arm.com if (cacheEntry[1] && cacheAsi[1] == asi && cacheEntry[1]->range.va < vaddr + size && 60710409Sandreas.hansson@arm.com cacheEntry[1]->range.va + cacheEntry[1]->range.size > vaddr && 60810409Sandreas.hansson@arm.com (!write || cacheEntry[1]->pte.writable())) { 6098721SN/A req->setPaddr(cacheEntry[1]->pte.paddr() & ~(cacheEntry[1]->pte.size()-1) | 6108721SN/A vaddr & cacheEntry[1]->pte.size()-1 ); 6118721SN/A return NoFault; 6128721SN/A } 6138983Snate@binkert.org } 6148983Snate@binkert.org 61511336Sandreas.hansson@arm.com bool red = bits(tlbdata,1,1); 61611336Sandreas.hansson@arm.com bool priv = bits(tlbdata,2,2); 61711530Sandreas.sandberg@arm.com bool addr_mask = bits(tlbdata,3,3); 61811336Sandreas.hansson@arm.com bool lsu_dm = bits(tlbdata,5,5); 61911336Sandreas.hansson@arm.com 62011336Sandreas.hansson@arm.com int part_id = bits(tlbdata,15,8); 62111336Sandreas.hansson@arm.com int tl = bits(tlbdata,18,16); 62211336Sandreas.hansson@arm.com int pri_context = bits(tlbdata,47,32); 62311502SCurtis.Dunham@arm.com int sec_context = bits(tlbdata,63,48); 62411336Sandreas.hansson@arm.com 62510585Sandreas.hansson@arm.com bool real = false; 62610585Sandreas.hansson@arm.com ContextType ct = Primary; 62710585Sandreas.hansson@arm.com int context = 0; 62810585Sandreas.hansson@arm.com 62910585Sandreas.hansson@arm.com TlbEntry *e; 63010585Sandreas.hansson@arm.com 63111336Sandreas.hansson@arm.com DPRINTF(TLB, "TLB: priv:%d hpriv:%d red:%d lsudm:%d part_id: %#X\n", 63211336Sandreas.hansson@arm.com priv, hpriv, red, lsu_dm, part_id); 63311530Sandreas.sandberg@arm.com 63411336Sandreas.hansson@arm.com if (implicit) { 63511336Sandreas.hansson@arm.com if (tl > 0) { 63611336Sandreas.hansson@arm.com asi = ASI_N; 63711336Sandreas.hansson@arm.com ct = Nucleus; 63811336Sandreas.hansson@arm.com context = 0; 63911336Sandreas.hansson@arm.com } else { 64011336Sandreas.hansson@arm.com asi = ASI_P; 64111336Sandreas.hansson@arm.com ct = Primary; 64211336Sandreas.hansson@arm.com context = pri_context; 64311336Sandreas.hansson@arm.com } 64411336Sandreas.hansson@arm.com } else { 64511336Sandreas.hansson@arm.com // We need to check for priv level/asi priv 64611336Sandreas.hansson@arm.com if (!priv && !hpriv && !AsiIsUnPriv(asi)) { 64711336Sandreas.hansson@arm.com // It appears that context should be Nucleus in these cases? 64811336Sandreas.hansson@arm.com writeSfr(tc, vaddr, write, Nucleus, false, IllegalAsi, asi); 64911336Sandreas.hansson@arm.com return new PrivilegedAction; 65011336Sandreas.hansson@arm.com } 65111336Sandreas.hansson@arm.com 65211336Sandreas.hansson@arm.com if (!hpriv && AsiIsHPriv(asi)) { 65311336Sandreas.hansson@arm.com writeSfr(tc, vaddr, write, Nucleus, false, IllegalAsi, asi); 65411336Sandreas.hansson@arm.com return new DataAccessException; 65511336Sandreas.hansson@arm.com } 65611336Sandreas.hansson@arm.com 65711336Sandreas.hansson@arm.com if (AsiIsPrimary(asi)) { 65810585Sandreas.hansson@arm.com context = pri_context; 65910585Sandreas.hansson@arm.com ct = Primary; 66010585Sandreas.hansson@arm.com } else if (AsiIsSecondary(asi)) { 66110585Sandreas.hansson@arm.com context = sec_context; 66210585Sandreas.hansson@arm.com ct = Secondary; 66310585Sandreas.hansson@arm.com } else if (AsiIsNucleus(asi)) { 66411336Sandreas.hansson@arm.com ct = Nucleus; 66511336Sandreas.hansson@arm.com context = 0; 66610585Sandreas.hansson@arm.com } else { // ???? 66710585Sandreas.hansson@arm.com ct = Primary; 66810585Sandreas.hansson@arm.com context = pri_context; 66910585Sandreas.hansson@arm.com } 67010585Sandreas.hansson@arm.com } 67110585Sandreas.hansson@arm.com 67210585Sandreas.hansson@arm.com if (!implicit && asi != ASI_P && asi != ASI_S) { 67310585Sandreas.hansson@arm.com if (AsiIsLittle(asi)) 67410585Sandreas.hansson@arm.com panic("Little Endian ASIs not supported\n"); 67510585Sandreas.hansson@arm.com if (AsiIsNoFault(asi)) 67610585Sandreas.hansson@arm.com panic("No Fault ASIs not supported\n"); 67710585Sandreas.hansson@arm.com 67811530Sandreas.sandberg@arm.com if (AsiIsPartialStore(asi)) 67910585Sandreas.hansson@arm.com panic("Partial Store ASIs not supported\n"); 68010585Sandreas.hansson@arm.com if (AsiIsInterrupt(asi)) 68110585Sandreas.hansson@arm.com panic("Interrupt ASIs not supported\n"); 68210892Sandreas.hansson@arm.com 68310585Sandreas.hansson@arm.com if (AsiIsMmu(asi)) 68411245Sandreas.sandberg@arm.com goto handleMmuRegAccess; 68510585Sandreas.hansson@arm.com if (AsiIsScratchPad(asi)) 68610585Sandreas.hansson@arm.com goto handleScratchRegAccess; 68710585Sandreas.hansson@arm.com if (AsiIsQueue(asi)) 68810585Sandreas.hansson@arm.com goto handleQueueRegAccess; 68910585Sandreas.hansson@arm.com if (AsiIsSparcError(asi)) 69010585Sandreas.hansson@arm.com goto handleSparcErrorRegAccess; 69110585Sandreas.hansson@arm.com 69210585Sandreas.hansson@arm.com if (!AsiIsReal(asi) && !AsiIsNucleus(asi) && !AsiIsAsIfUser(asi) && 69310585Sandreas.hansson@arm.com !AsiIsTwin(asi) && !AsiIsBlock(asi)) 69410585Sandreas.hansson@arm.com panic("Accessing ASI %#X. Should we?\n", asi); 69510585Sandreas.hansson@arm.com } 69610585Sandreas.hansson@arm.com 69711245Sandreas.sandberg@arm.com // If the asi is unaligned trap 69810585Sandreas.hansson@arm.com if (vaddr & size-1) { 69910585Sandreas.hansson@arm.com writeSfr(tc, vaddr, false, ct, false, OtherFault, asi); 70010585Sandreas.hansson@arm.com return new MemAddressNotAligned; 70110585Sandreas.hansson@arm.com } 70210585Sandreas.hansson@arm.com 70310585Sandreas.hansson@arm.com if (addr_mask) 70410585Sandreas.hansson@arm.com vaddr = vaddr & VAddrAMask; 70510585Sandreas.hansson@arm.com 70610585Sandreas.hansson@arm.com if (!validVirtualAddress(vaddr, addr_mask)) { 70710585Sandreas.hansson@arm.com writeSfr(tc, vaddr, false, ct, true, VaOutOfRange, asi); 70810585Sandreas.hansson@arm.com return new DataAccessException; 70911530Sandreas.sandberg@arm.com } 71010585Sandreas.hansson@arm.com 71111336Sandreas.hansson@arm.com 71210585Sandreas.hansson@arm.com if ((!lsu_dm && !hpriv && !red) || AsiIsReal(asi)) { 71310585Sandreas.hansson@arm.com real = true; 71410585Sandreas.hansson@arm.com context = 0; 71511502SCurtis.Dunham@arm.com }; 71611336Sandreas.hansson@arm.com 71710585Sandreas.hansson@arm.com if (hpriv && (implicit || (!AsiIsAsIfUser(asi) && !AsiIsReal(asi)))) { 71810585Sandreas.hansson@arm.com req->setPaddr(vaddr & PAddrImplMask); 71910585Sandreas.hansson@arm.com return NoFault; 72010585Sandreas.hansson@arm.com } 72110585Sandreas.hansson@arm.com 72210585Sandreas.hansson@arm.com e = lookup(vaddr, part_id, real, context); 72310585Sandreas.hansson@arm.com 72411530Sandreas.sandberg@arm.com if (e == NULL || !e->valid) { 72510585Sandreas.hansson@arm.com writeTagAccess(tc, vaddr, context); 72610585Sandreas.hansson@arm.com DPRINTF(TLB, "TLB: DTB Failed to find matching TLB entry\n"); 72710892Sandreas.hansson@arm.com if (real) 72810892Sandreas.hansson@arm.com return new DataRealTranslationMiss; 72911456Sandreas.hansson@arm.com else 73011456Sandreas.hansson@arm.com return new FastDataAccessMMUMiss; 73111456Sandreas.hansson@arm.com 73211456Sandreas.hansson@arm.com } 73310585Sandreas.hansson@arm.com 73410585Sandreas.hansson@arm.com if (!priv && e->pte.priv()) { 73510892Sandreas.hansson@arm.com writeTagAccess(tc, vaddr, context); 73610892Sandreas.hansson@arm.com writeSfr(tc, vaddr, write, ct, e->pte.sideffect(), PrivViolation, asi); 73711456Sandreas.hansson@arm.com return new DataAccessException; 73811456Sandreas.hansson@arm.com } 73911456Sandreas.hansson@arm.com 74011456Sandreas.hansson@arm.com if (write && !e->pte.writable()) { 74110585Sandreas.hansson@arm.com writeTagAccess(tc, vaddr, context); 74210585Sandreas.hansson@arm.com writeSfr(tc, vaddr, write, ct, e->pte.sideffect(), OtherFault, asi); 74310892Sandreas.hansson@arm.com return new FastDataAccessProtection; 74410892Sandreas.hansson@arm.com } 74510585Sandreas.hansson@arm.com 74610585Sandreas.hansson@arm.com if (e->pte.nofault() && !AsiIsNoFault(asi)) { 74710585Sandreas.hansson@arm.com writeTagAccess(tc, vaddr, context); 74810585Sandreas.hansson@arm.com writeSfr(tc, vaddr, write, ct, e->pte.sideffect(), LoadFromNfo, asi); 74910585Sandreas.hansson@arm.com return new DataAccessException; 75010585Sandreas.hansson@arm.com } 75110585Sandreas.hansson@arm.com 75210585Sandreas.hansson@arm.com if (e->pte.sideffect() && AsiIsNoFault(asi)) { 75310585Sandreas.hansson@arm.com writeTagAccess(tc, vaddr, context); 75410585Sandreas.hansson@arm.com writeSfr(tc, vaddr, write, ct, e->pte.sideffect(), SideEffect, asi); 75510585Sandreas.hansson@arm.com return new DataAccessException; 75610585Sandreas.hansson@arm.com } 75711530Sandreas.sandberg@arm.com 75811336Sandreas.hansson@arm.com 75911502SCurtis.Dunham@arm.com if (e->pte.sideffect()) 76011502SCurtis.Dunham@arm.com req->setFlags(req->getFlags() | UNCACHEABLE); 76111336Sandreas.hansson@arm.com 76211502SCurtis.Dunham@arm.com // cache translation date for next translation 76310585Sandreas.hansson@arm.com cacheState = tlbdata; 76411502SCurtis.Dunham@arm.com if (!cacheValid) { 76511502SCurtis.Dunham@arm.com cacheEntry[1] = NULL; 76611502SCurtis.Dunham@arm.com cacheEntry[0] = NULL; 76711502SCurtis.Dunham@arm.com } 76811502SCurtis.Dunham@arm.com 76911336Sandreas.hansson@arm.com if (cacheEntry[0] != e && cacheEntry[1] != e) { 77011201Sandreas.hansson@arm.com cacheEntry[1] = cacheEntry[0]; 77111336Sandreas.hansson@arm.com cacheEntry[0] = e; 77211201Sandreas.hansson@arm.com cacheAsi[1] = cacheAsi[0]; 77311336Sandreas.hansson@arm.com cacheAsi[0] = asi; 77411336Sandreas.hansson@arm.com if (implicit) 77510585Sandreas.hansson@arm.com cacheAsi[0] = (ASI)0; 77610585Sandreas.hansson@arm.com } 77710585Sandreas.hansson@arm.com cacheValid = true; 77811336Sandreas.hansson@arm.com req->setPaddr(e->pte.paddr() & ~(e->pte.size()-1) | 77911336Sandreas.hansson@arm.com vaddr & e->pte.size()-1); 78011336Sandreas.hansson@arm.com DPRINTF(TLB, "TLB: %#X -> %#X\n", vaddr, req->getPaddr()); 78110585Sandreas.hansson@arm.com return NoFault; 78211502SCurtis.Dunham@arm.com /** Normal flow ends here. */ 78311502SCurtis.Dunham@arm.com 78411530Sandreas.sandberg@arm.comhandleScratchRegAccess: 78511502SCurtis.Dunham@arm.com if (vaddr > 0x38 || (vaddr >= 0x20 && vaddr < 0x30 && !hpriv)) { 78611502SCurtis.Dunham@arm.com writeSfr(tc, vaddr, write, Primary, true, IllegalAsi, asi); 78711502SCurtis.Dunham@arm.com return new DataAccessException; 78811502SCurtis.Dunham@arm.com } 78911336Sandreas.hansson@arm.com goto regAccessOk; 79011336Sandreas.hansson@arm.com 79111336Sandreas.hansson@arm.comhandleQueueRegAccess: 79211336Sandreas.hansson@arm.com if (!priv && !hpriv) { 79311336Sandreas.hansson@arm.com writeSfr(tc, vaddr, write, Primary, true, IllegalAsi, asi); 79411336Sandreas.hansson@arm.com return new PrivilegedAction; 79511502SCurtis.Dunham@arm.com } 79611336Sandreas.hansson@arm.com if (!hpriv && vaddr & 0xF || vaddr > 0x3f8 || vaddr < 0x3c0) { 79711502SCurtis.Dunham@arm.com writeSfr(tc, vaddr, write, Primary, true, IllegalAsi, asi); 79811336Sandreas.hansson@arm.com return new DataAccessException; 79911336Sandreas.hansson@arm.com } 80011336Sandreas.hansson@arm.com goto regAccessOk; 80111502SCurtis.Dunham@arm.com 80211502SCurtis.Dunham@arm.comhandleSparcErrorRegAccess: 80311502SCurtis.Dunham@arm.com if (!hpriv) { 80411336Sandreas.hansson@arm.com writeSfr(tc, vaddr, write, Primary, true, IllegalAsi, asi); 80511502SCurtis.Dunham@arm.com if (priv) 80611336Sandreas.hansson@arm.com return new DataAccessException; 80711502SCurtis.Dunham@arm.com else 80811502SCurtis.Dunham@arm.com return new PrivilegedAction; 80911336Sandreas.hansson@arm.com } 81011502SCurtis.Dunham@arm.com goto regAccessOk; 81111336Sandreas.hansson@arm.com 81211502SCurtis.Dunham@arm.com 81311502SCurtis.Dunham@arm.comregAccessOk: 81411336Sandreas.hansson@arm.comhandleMmuRegAccess: 81511336Sandreas.hansson@arm.com DPRINTF(TLB, "TLB: DTB Translating MM IPR access\n"); 81611336Sandreas.hansson@arm.com req->setMmapedIpr(true); 81711336Sandreas.hansson@arm.com req->setPaddr(req->getVaddr()); 81811336Sandreas.hansson@arm.com return NoFault; 81911336Sandreas.hansson@arm.com}; 82011336Sandreas.hansson@arm.com 82111336Sandreas.hansson@arm.comTick 82211336Sandreas.hansson@arm.comDTB::doMmuRegRead(ThreadContext *tc, Packet *pkt) 82311201Sandreas.hansson@arm.com{ 82411336Sandreas.hansson@arm.com Addr va = pkt->getAddr(); 82511336Sandreas.hansson@arm.com ASI asi = (ASI)pkt->req->getAsi(); 82611201Sandreas.hansson@arm.com uint64_t temp; 82711201Sandreas.hansson@arm.com 82811201Sandreas.hansson@arm.com DPRINTF(IPR, "Memory Mapped IPR Read: asi=%#X a=%#x\n", 82911201Sandreas.hansson@arm.com (uint32_t)pkt->req->getAsi(), pkt->getAddr()); 83011336Sandreas.hansson@arm.com 83111336Sandreas.hansson@arm.com switch (asi) { 83211336Sandreas.hansson@arm.com case ASI_LSU_CONTROL_REG: 83311336Sandreas.hansson@arm.com assert(va == 0); 83411201Sandreas.hansson@arm.com pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_LSU_CTRL)); 83511336Sandreas.hansson@arm.com break; 83611336Sandreas.hansson@arm.com case ASI_MMU: 83711336Sandreas.hansson@arm.com switch (va) { 83811336Sandreas.hansson@arm.com case 0x8: 83911502SCurtis.Dunham@arm.com pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_P_CONTEXT)); 84011502SCurtis.Dunham@arm.com break; 84111502SCurtis.Dunham@arm.com case 0x10: 84211502SCurtis.Dunham@arm.com pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_S_CONTEXT)); 84311336Sandreas.hansson@arm.com break; 84410585Sandreas.hansson@arm.com default: 84511336Sandreas.hansson@arm.com goto doMmuReadError; 84611336Sandreas.hansson@arm.com } 84710585Sandreas.hansson@arm.com break; 84811336Sandreas.hansson@arm.com case ASI_QUEUE: 84911502SCurtis.Dunham@arm.com pkt->set(tc->readMiscRegWithEffect(MISCREG_QUEUE_CPU_MONDO_HEAD + 85011336Sandreas.hansson@arm.com (va >> 4) - 0x3c)); 85111502SCurtis.Dunham@arm.com break; 85211336Sandreas.hansson@arm.com case ASI_DMMU_CTXT_ZERO_TSB_BASE_PS0: 85311336Sandreas.hansson@arm.com assert(va == 0); 85411336Sandreas.hansson@arm.com pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_C0_TSB_PS0)); 85511502SCurtis.Dunham@arm.com break; 85611502SCurtis.Dunham@arm.com case ASI_DMMU_CTXT_ZERO_TSB_BASE_PS1: 85711502SCurtis.Dunham@arm.com assert(va == 0); 85811336Sandreas.hansson@arm.com pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_C0_TSB_PS1)); 85911502SCurtis.Dunham@arm.com break; 86011336Sandreas.hansson@arm.com case ASI_DMMU_CTXT_ZERO_CONFIG: 86111502SCurtis.Dunham@arm.com assert(va == 0); 86211502SCurtis.Dunham@arm.com pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_C0_CONFIG)); 86311336Sandreas.hansson@arm.com break; 86411502SCurtis.Dunham@arm.com case ASI_IMMU_CTXT_ZERO_TSB_BASE_PS0: 86511336Sandreas.hansson@arm.com assert(va == 0); 86611502SCurtis.Dunham@arm.com pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_ITLB_C0_TSB_PS0)); 86711502SCurtis.Dunham@arm.com break; 86811336Sandreas.hansson@arm.com case ASI_IMMU_CTXT_ZERO_TSB_BASE_PS1: 86911336Sandreas.hansson@arm.com assert(va == 0); 87011336Sandreas.hansson@arm.com pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_ITLB_C0_TSB_PS1)); 87111336Sandreas.hansson@arm.com break; 87211336Sandreas.hansson@arm.com case ASI_IMMU_CTXT_ZERO_CONFIG: 87311336Sandreas.hansson@arm.com assert(va == 0); 87411502SCurtis.Dunham@arm.com pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_ITLB_C0_CONFIG)); 87511336Sandreas.hansson@arm.com break; 87611502SCurtis.Dunham@arm.com case ASI_DMMU_CTXT_NONZERO_TSB_BASE_PS0: 87711201Sandreas.hansson@arm.com assert(va == 0); 87811336Sandreas.hansson@arm.com pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_CX_TSB_PS0)); 87911336Sandreas.hansson@arm.com break; 88011502SCurtis.Dunham@arm.com case ASI_DMMU_CTXT_NONZERO_TSB_BASE_PS1: 88111201Sandreas.hansson@arm.com assert(va == 0); 88211502SCurtis.Dunham@arm.com pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_CX_TSB_PS1)); 88311201Sandreas.hansson@arm.com break; 88411502SCurtis.Dunham@arm.com case ASI_DMMU_CTXT_NONZERO_CONFIG: 88511336Sandreas.hansson@arm.com assert(va == 0); 88611336Sandreas.hansson@arm.com pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_CX_CONFIG)); 88711336Sandreas.hansson@arm.com break; 88811201Sandreas.hansson@arm.com case ASI_IMMU_CTXT_NONZERO_TSB_BASE_PS0: 88911502SCurtis.Dunham@arm.com assert(va == 0); 89011336Sandreas.hansson@arm.com pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_ITLB_CX_TSB_PS0)); 89111336Sandreas.hansson@arm.com break; 89211336Sandreas.hansson@arm.com case ASI_IMMU_CTXT_NONZERO_TSB_BASE_PS1: 89310585Sandreas.hansson@arm.com assert(va == 0); 89410585Sandreas.hansson@arm.com pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_ITLB_CX_TSB_PS1)); 89510585Sandreas.hansson@arm.com break; 89610585Sandreas.hansson@arm.com case ASI_IMMU_CTXT_NONZERO_CONFIG: 89710585Sandreas.hansson@arm.com assert(va == 0); 89810585Sandreas.hansson@arm.com pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_ITLB_CX_CONFIG)); 89911336Sandreas.hansson@arm.com break; 90011336Sandreas.hansson@arm.com case ASI_SPARC_ERROR_STATUS_REG: 90111502SCurtis.Dunham@arm.com pkt->set((uint64_t)0); 90211502SCurtis.Dunham@arm.com break; 90311502SCurtis.Dunham@arm.com case ASI_HYP_SCRATCHPAD: 90411502SCurtis.Dunham@arm.com case ASI_SCRATCHPAD: 90511502SCurtis.Dunham@arm.com pkt->set(tc->readMiscRegWithEffect(MISCREG_SCRATCHPAD_R0 + (va >> 3))); 90611502SCurtis.Dunham@arm.com break; 90711530Sandreas.sandberg@arm.com case ASI_IMMU: 90810892Sandreas.hansson@arm.com switch (va) { 90911336Sandreas.hansson@arm.com case 0x0: 91010585Sandreas.hansson@arm.com temp = tc->readMiscRegWithEffect(MISCREG_MMU_ITLB_TAG_ACCESS); 91110585Sandreas.hansson@arm.com pkt->set(bits(temp,63,22) | bits(temp,12,0) << 48); 91211336Sandreas.hansson@arm.com break; 91311336Sandreas.hansson@arm.com case 0x18: 91411336Sandreas.hansson@arm.com pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_ITLB_SFSR)); 91511336Sandreas.hansson@arm.com break; 91611336Sandreas.hansson@arm.com case 0x30: 91711502SCurtis.Dunham@arm.com pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_ITLB_TAG_ACCESS)); 91811201Sandreas.hansson@arm.com break; 91911336Sandreas.hansson@arm.com default: 92010892Sandreas.hansson@arm.com goto doMmuReadError; 92110892Sandreas.hansson@arm.com } 92210585Sandreas.hansson@arm.com break; 92311502SCurtis.Dunham@arm.com case ASI_DMMU: 92411502SCurtis.Dunham@arm.com switch (va) { 92511336Sandreas.hansson@arm.com case 0x0: 92611336Sandreas.hansson@arm.com temp = tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_TAG_ACCESS); 92711502SCurtis.Dunham@arm.com pkt->set(bits(temp,63,22) | bits(temp,12,0) << 48); 92810585Sandreas.hansson@arm.com break; 92911336Sandreas.hansson@arm.com case 0x18: 93011336Sandreas.hansson@arm.com pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_SFSR)); 93110892Sandreas.hansson@arm.com break; 93210892Sandreas.hansson@arm.com case 0x20: 93311336Sandreas.hansson@arm.com pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_SFAR)); 93410585Sandreas.hansson@arm.com break; 93511502SCurtis.Dunham@arm.com case 0x30: 93611502SCurtis.Dunham@arm.com pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_TAG_ACCESS)); 93711502SCurtis.Dunham@arm.com break; 93810585Sandreas.hansson@arm.com case 0x80: 93911502SCurtis.Dunham@arm.com pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_PART_ID)); 94011502SCurtis.Dunham@arm.com break; 94110585Sandreas.hansson@arm.com default: 94210585Sandreas.hansson@arm.com goto doMmuReadError; 94311502SCurtis.Dunham@arm.com } 94410585Sandreas.hansson@arm.com break; 94511502SCurtis.Dunham@arm.com case ASI_DMMU_TSB_PS0_PTR_REG: 94611530Sandreas.sandberg@arm.com pkt->set(MakeTsbPtr(Ps0, 94711502SCurtis.Dunham@arm.com tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_TAG_ACCESS), 94811502SCurtis.Dunham@arm.com tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_C0_TSB_PS0), 94911502SCurtis.Dunham@arm.com tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_C0_CONFIG), 95011138Sandreas.hansson@arm.com tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_CX_TSB_PS0), 95111138Sandreas.hansson@arm.com tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_CX_CONFIG))); 95211138Sandreas.hansson@arm.com break; 95311530Sandreas.sandberg@arm.com case ASI_DMMU_TSB_PS1_PTR_REG: 95410892Sandreas.hansson@arm.com pkt->set(MakeTsbPtr(Ps1, 95511502SCurtis.Dunham@arm.com tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_TAG_ACCESS), 95610585Sandreas.hansson@arm.com tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_C0_TSB_PS1), 95710585Sandreas.hansson@arm.com tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_C0_CONFIG), 95811502SCurtis.Dunham@arm.com tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_CX_TSB_PS1), 95911336Sandreas.hansson@arm.com tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_CX_CONFIG))); 96011502SCurtis.Dunham@arm.com break; 96111336Sandreas.hansson@arm.com case ASI_IMMU_TSB_PS0_PTR_REG: 96211336Sandreas.hansson@arm.com pkt->set(MakeTsbPtr(Ps0, 96311336Sandreas.hansson@arm.com tc->readMiscRegWithEffect(MISCREG_MMU_ITLB_TAG_ACCESS), 96411336Sandreas.hansson@arm.com tc->readMiscRegWithEffect(MISCREG_MMU_ITLB_C0_TSB_PS0), 96511336Sandreas.hansson@arm.com tc->readMiscRegWithEffect(MISCREG_MMU_ITLB_C0_CONFIG), 96611336Sandreas.hansson@arm.com tc->readMiscRegWithEffect(MISCREG_MMU_ITLB_CX_TSB_PS0), 96711502SCurtis.Dunham@arm.com tc->readMiscRegWithEffect(MISCREG_MMU_ITLB_CX_CONFIG))); 96811336Sandreas.hansson@arm.com break; 96911502SCurtis.Dunham@arm.com case ASI_IMMU_TSB_PS1_PTR_REG: 97011336Sandreas.hansson@arm.com pkt->set(MakeTsbPtr(Ps1, 97111336Sandreas.hansson@arm.com tc->readMiscRegWithEffect(MISCREG_MMU_ITLB_TAG_ACCESS), 97211502SCurtis.Dunham@arm.com tc->readMiscRegWithEffect(MISCREG_MMU_ITLB_C0_TSB_PS1), 97311336Sandreas.hansson@arm.com tc->readMiscRegWithEffect(MISCREG_MMU_ITLB_C0_CONFIG), 97411502SCurtis.Dunham@arm.com tc->readMiscRegWithEffect(MISCREG_MMU_ITLB_CX_TSB_PS1), 97511336Sandreas.hansson@arm.com tc->readMiscRegWithEffect(MISCREG_MMU_ITLB_CX_CONFIG))); 97611336Sandreas.hansson@arm.com break; 97711502SCurtis.Dunham@arm.com 97811502SCurtis.Dunham@arm.com default: 97911502SCurtis.Dunham@arm.comdoMmuReadError: 98011502SCurtis.Dunham@arm.com panic("need to impl DTB::doMmuRegRead() got asi=%#x, va=%#x\n", 98111502SCurtis.Dunham@arm.com (uint32_t)asi, va); 98210585Sandreas.hansson@arm.com } 98311502SCurtis.Dunham@arm.com pkt->result = Packet::Success; 98411502SCurtis.Dunham@arm.com return tc->getCpuPtr()->cycles(1); 98511138Sandreas.hansson@arm.com} 98611138Sandreas.hansson@arm.com 98711138Sandreas.hansson@arm.comTick 98810585Sandreas.hansson@arm.comDTB::doMmuRegWrite(ThreadContext *tc, Packet *pkt) 98911138Sandreas.hansson@arm.com{ 99011138Sandreas.hansson@arm.com uint64_t data = gtoh(pkt->get<uint64_t>()); 99111502SCurtis.Dunham@arm.com Addr va = pkt->getAddr(); 99211530Sandreas.sandberg@arm.com ASI asi = (ASI)pkt->req->getAsi(); 99311530Sandreas.sandberg@arm.com 99411530Sandreas.sandberg@arm.com Addr ta_insert; 99511530Sandreas.sandberg@arm.com Addr va_insert; 99610585Sandreas.hansson@arm.com Addr ct_insert; 99710585Sandreas.hansson@arm.com int part_insert; 99810585Sandreas.hansson@arm.com int entry_insert = -1; 99910585Sandreas.hansson@arm.com bool real_insert; 100010585Sandreas.hansson@arm.com bool ignore; 100110585Sandreas.hansson@arm.com int part_id; 100210585Sandreas.hansson@arm.com int ctx_id; 100310585Sandreas.hansson@arm.com PageTableEntry pte; 100410585Sandreas.hansson@arm.com 100510585Sandreas.hansson@arm.com DPRINTF(IPR, "Memory Mapped IPR Write: asi=%#X a=%#x d=%#X\n", 100610585Sandreas.hansson@arm.com (uint32_t)asi, va, data); 100710585Sandreas.hansson@arm.com 100810585Sandreas.hansson@arm.com switch (asi) { 100910585Sandreas.hansson@arm.com case ASI_LSU_CONTROL_REG: 101010585Sandreas.hansson@arm.com assert(va == 0); 101110585Sandreas.hansson@arm.com tc->setMiscRegWithEffect(MISCREG_MMU_LSU_CTRL, data); 101210585Sandreas.hansson@arm.com break; 101310585Sandreas.hansson@arm.com case ASI_MMU: 101410585Sandreas.hansson@arm.com switch (va) { 101510585Sandreas.hansson@arm.com case 0x8: 101610585Sandreas.hansson@arm.com tc->setMiscRegWithEffect(MISCREG_MMU_P_CONTEXT, data); 101710585Sandreas.hansson@arm.com break; 101810585Sandreas.hansson@arm.com case 0x10: 101910585Sandreas.hansson@arm.com tc->setMiscRegWithEffect(MISCREG_MMU_S_CONTEXT, data); 102010585Sandreas.hansson@arm.com break; 102110585Sandreas.hansson@arm.com default: 102210585Sandreas.hansson@arm.com goto doMmuWriteError; 102310585Sandreas.hansson@arm.com } 102410585Sandreas.hansson@arm.com break; 102510585Sandreas.hansson@arm.com case ASI_QUEUE: 102610585Sandreas.hansson@arm.com assert(mbits(data,13,6) == data); 102711530Sandreas.sandberg@arm.com tc->setMiscRegWithEffect(MISCREG_QUEUE_CPU_MONDO_HEAD + 102811530Sandreas.sandberg@arm.com (va >> 4) - 0x3c, data); 102911530Sandreas.sandberg@arm.com break; 103011530Sandreas.sandberg@arm.com case ASI_DMMU_CTXT_ZERO_TSB_BASE_PS0: 103111530Sandreas.sandberg@arm.com assert(va == 0); 103211530Sandreas.sandberg@arm.com tc->setMiscRegWithEffect(MISCREG_MMU_DTLB_C0_TSB_PS0, data); 103311530Sandreas.sandberg@arm.com break; 103411530Sandreas.sandberg@arm.com case ASI_DMMU_CTXT_ZERO_TSB_BASE_PS1: 103511530Sandreas.sandberg@arm.com assert(va == 0); 103611530Sandreas.sandberg@arm.com tc->setMiscRegWithEffect(MISCREG_MMU_DTLB_C0_TSB_PS1, data); 103711530Sandreas.sandberg@arm.com break; 103811530Sandreas.sandberg@arm.com case ASI_DMMU_CTXT_ZERO_CONFIG: 103911530Sandreas.sandberg@arm.com assert(va == 0); 104011530Sandreas.sandberg@arm.com tc->setMiscRegWithEffect(MISCREG_MMU_DTLB_C0_CONFIG, data); 104111530Sandreas.sandberg@arm.com break; 104211530Sandreas.sandberg@arm.com case ASI_IMMU_CTXT_ZERO_TSB_BASE_PS0: 104311530Sandreas.sandberg@arm.com assert(va == 0); 104411530Sandreas.sandberg@arm.com tc->setMiscRegWithEffect(MISCREG_MMU_ITLB_C0_TSB_PS0, data); 104511530Sandreas.sandberg@arm.com break; 104611530Sandreas.sandberg@arm.com case ASI_IMMU_CTXT_ZERO_TSB_BASE_PS1: 104711530Sandreas.sandberg@arm.com assert(va == 0); 104811530Sandreas.sandberg@arm.com tc->setMiscRegWithEffect(MISCREG_MMU_ITLB_C0_TSB_PS1, data); 104911530Sandreas.sandberg@arm.com break; 10502968SN/A case ASI_IMMU_CTXT_ZERO_CONFIG: 10512968SN/A assert(va == 0); 1052 tc->setMiscRegWithEffect(MISCREG_MMU_ITLB_C0_CONFIG, data); 1053 break; 1054 case ASI_DMMU_CTXT_NONZERO_TSB_BASE_PS0: 1055 assert(va == 0); 1056 tc->setMiscRegWithEffect(MISCREG_MMU_DTLB_CX_TSB_PS0, data); 1057 break; 1058 case ASI_DMMU_CTXT_NONZERO_TSB_BASE_PS1: 1059 assert(va == 0); 1060 tc->setMiscRegWithEffect(MISCREG_MMU_DTLB_CX_TSB_PS1, data); 1061 break; 1062 case ASI_DMMU_CTXT_NONZERO_CONFIG: 1063 assert(va == 0); 1064 tc->setMiscRegWithEffect(MISCREG_MMU_DTLB_CX_CONFIG, data); 1065 break; 1066 case ASI_IMMU_CTXT_NONZERO_TSB_BASE_PS0: 1067 assert(va == 0); 1068 tc->setMiscRegWithEffect(MISCREG_MMU_ITLB_CX_TSB_PS0, data); 1069 break; 1070 case ASI_IMMU_CTXT_NONZERO_TSB_BASE_PS1: 1071 assert(va == 0); 1072 tc->setMiscRegWithEffect(MISCREG_MMU_ITLB_CX_TSB_PS1, data); 1073 break; 1074 case ASI_IMMU_CTXT_NONZERO_CONFIG: 1075 assert(va == 0); 1076 tc->setMiscRegWithEffect(MISCREG_MMU_ITLB_CX_CONFIG, data); 1077 break; 1078 case ASI_SPARC_ERROR_EN_REG: 1079 case ASI_SPARC_ERROR_STATUS_REG: 1080 warn("Ignoring write to SPARC ERROR regsiter\n"); 1081 break; 1082 case ASI_HYP_SCRATCHPAD: 1083 case ASI_SCRATCHPAD: 1084 tc->setMiscRegWithEffect(MISCREG_SCRATCHPAD_R0 + (va >> 3), data); 1085 break; 1086 case ASI_IMMU: 1087 switch (va) { 1088 case 0x18: 1089 tc->setMiscRegWithEffect(MISCREG_MMU_ITLB_SFSR, data); 1090 break; 1091 case 0x30: 1092 sext<59>(bits(data, 59,0)); 1093 tc->setMiscRegWithEffect(MISCREG_MMU_ITLB_TAG_ACCESS, data); 1094 break; 1095 default: 1096 goto doMmuWriteError; 1097 } 1098 break; 1099 case ASI_ITLB_DATA_ACCESS_REG: 1100 entry_insert = bits(va, 8,3); 1101 case ASI_ITLB_DATA_IN_REG: 1102 assert(entry_insert != -1 || mbits(va,10,9) == va); 1103 ta_insert = tc->readMiscRegWithEffect(MISCREG_MMU_ITLB_TAG_ACCESS); 1104 va_insert = mbits(ta_insert, 63,13); 1105 ct_insert = mbits(ta_insert, 12,0); 1106 part_insert = tc->readMiscRegWithEffect(MISCREG_MMU_PART_ID); 1107 real_insert = bits(va, 9,9); 1108 pte.populate(data, bits(va,10,10) ? PageTableEntry::sun4v : 1109 PageTableEntry::sun4u); 1110 tc->getITBPtr()->insert(va_insert, part_insert, ct_insert, real_insert, 1111 pte, entry_insert); 1112 break; 1113 case ASI_DTLB_DATA_ACCESS_REG: 1114 entry_insert = bits(va, 8,3); 1115 case ASI_DTLB_DATA_IN_REG: 1116 assert(entry_insert != -1 || mbits(va,10,9) == va); 1117 ta_insert = tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_TAG_ACCESS); 1118 va_insert = mbits(ta_insert, 63,13); 1119 ct_insert = mbits(ta_insert, 12,0); 1120 part_insert = tc->readMiscRegWithEffect(MISCREG_MMU_PART_ID); 1121 real_insert = bits(va, 9,9); 1122 pte.populate(data, bits(va,10,10) ? PageTableEntry::sun4v : 1123 PageTableEntry::sun4u); 1124 insert(va_insert, part_insert, ct_insert, real_insert, pte, entry_insert); 1125 break; 1126 case ASI_IMMU_DEMAP: 1127 ignore = false; 1128 ctx_id = -1; 1129 part_id = tc->readMiscRegWithEffect(MISCREG_MMU_PART_ID); 1130 switch (bits(va,5,4)) { 1131 case 0: 1132 ctx_id = tc->readMiscRegWithEffect(MISCREG_MMU_P_CONTEXT); 1133 break; 1134 case 1: 1135 ignore = true; 1136 break; 1137 case 3: 1138 ctx_id = 0; 1139 break; 1140 default: 1141 ignore = true; 1142 } 1143 1144 switch(bits(va,7,6)) { 1145 case 0: // demap page 1146 if (!ignore) 1147 tc->getITBPtr()->demapPage(mbits(va,63,13), part_id, 1148 bits(va,9,9), ctx_id); 1149 break; 1150 case 1: //demap context 1151 if (!ignore) 1152 tc->getITBPtr()->demapContext(part_id, ctx_id); 1153 break; 1154 case 2: 1155 tc->getITBPtr()->demapAll(part_id); 1156 break; 1157 default: 1158 panic("Invalid type for IMMU demap\n"); 1159 } 1160 break; 1161 case ASI_DMMU: 1162 switch (va) { 1163 case 0x18: 1164 tc->setMiscRegWithEffect(MISCREG_MMU_DTLB_SFSR, data); 1165 break; 1166 case 0x30: 1167 sext<59>(bits(data, 59,0)); 1168 tc->setMiscRegWithEffect(MISCREG_MMU_DTLB_TAG_ACCESS, data); 1169 break; 1170 case 0x80: 1171 tc->setMiscRegWithEffect(MISCREG_MMU_PART_ID, data); 1172 break; 1173 default: 1174 goto doMmuWriteError; 1175 } 1176 break; 1177 case ASI_DMMU_DEMAP: 1178 ignore = false; 1179 ctx_id = -1; 1180 part_id = tc->readMiscRegWithEffect(MISCREG_MMU_PART_ID); 1181 switch (bits(va,5,4)) { 1182 case 0: 1183 ctx_id = tc->readMiscRegWithEffect(MISCREG_MMU_P_CONTEXT); 1184 break; 1185 case 1: 1186 ctx_id = tc->readMiscRegWithEffect(MISCREG_MMU_S_CONTEXT); 1187 break; 1188 case 3: 1189 ctx_id = 0; 1190 break; 1191 default: 1192 ignore = true; 1193 } 1194 1195 switch(bits(va,7,6)) { 1196 case 0: // demap page 1197 if (!ignore) 1198 demapPage(mbits(va,63,13), part_id, bits(va,9,9), ctx_id); 1199 break; 1200 case 1: //demap context 1201 if (!ignore) 1202 demapContext(part_id, ctx_id); 1203 break; 1204 case 2: 1205 demapAll(part_id); 1206 break; 1207 default: 1208 panic("Invalid type for IMMU demap\n"); 1209 } 1210 break; 1211 default: 1212doMmuWriteError: 1213 panic("need to impl DTB::doMmuRegWrite() got asi=%#x, va=%#x d=%#x\n", 1214 (uint32_t)pkt->req->getAsi(), pkt->getAddr(), data); 1215 } 1216 pkt->result = Packet::Success; 1217 return tc->getCpuPtr()->cycles(1); 1218} 1219 1220void 1221DTB::GetTsbPtr(ThreadContext *tc, Addr addr, int ctx, Addr *ptrs) 1222{ 1223 uint64_t tag_access = mbits(addr,63,13) | mbits(ctx,12,0); 1224 ptrs[0] = MakeTsbPtr(Ps0, tag_access, 1225 tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_C0_TSB_PS0), 1226 tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_C0_CONFIG), 1227 tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_CX_TSB_PS0), 1228 tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_CX_CONFIG)); 1229 ptrs[1] = MakeTsbPtr(Ps1, tag_access, 1230 tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_C0_TSB_PS1), 1231 tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_C0_CONFIG), 1232 tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_CX_TSB_PS1), 1233 tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_CX_CONFIG)); 1234 ptrs[2] = MakeTsbPtr(Ps0, tag_access, 1235 tc->readMiscRegWithEffect(MISCREG_MMU_ITLB_C0_TSB_PS0), 1236 tc->readMiscRegWithEffect(MISCREG_MMU_ITLB_C0_CONFIG), 1237 tc->readMiscRegWithEffect(MISCREG_MMU_ITLB_CX_TSB_PS0), 1238 tc->readMiscRegWithEffect(MISCREG_MMU_ITLB_CX_CONFIG)); 1239 ptrs[3] = MakeTsbPtr(Ps1, tag_access, 1240 tc->readMiscRegWithEffect(MISCREG_MMU_ITLB_C0_TSB_PS1), 1241 tc->readMiscRegWithEffect(MISCREG_MMU_ITLB_C0_CONFIG), 1242 tc->readMiscRegWithEffect(MISCREG_MMU_ITLB_CX_TSB_PS1), 1243 tc->readMiscRegWithEffect(MISCREG_MMU_ITLB_CX_CONFIG)); 1244} 1245 1246 1247 1248 1249 1250uint64_t 1251DTB::MakeTsbPtr(TsbPageSize ps, uint64_t tag_access, uint64_t c0_tsb, 1252 uint64_t c0_config, uint64_t cX_tsb, uint64_t cX_config) 1253{ 1254 uint64_t tsb; 1255 uint64_t config; 1256 1257 if (bits(tag_access, 12,0) == 0) { 1258 tsb = c0_tsb; 1259 config = c0_config; 1260 } else { 1261 tsb = cX_tsb; 1262 config = cX_config; 1263 } 1264 1265 uint64_t ptr = mbits(tsb,63,13); 1266 bool split = bits(tsb,12,12); 1267 int tsb_size = bits(tsb,3,0); 1268 int page_size = (ps == Ps0) ? bits(config, 2,0) : bits(config,10,8); 1269 1270 if (ps == Ps1 && split) 1271 ptr |= ULL(1) << (13 + tsb_size); 1272 ptr |= (tag_access >> (9 + page_size * 3)) & mask(12+tsb_size, 4); 1273 1274 return ptr; 1275} 1276 1277 1278void 1279TLB::serialize(std::ostream &os) 1280{ 1281 SERIALIZE_SCALAR(size); 1282 SERIALIZE_SCALAR(usedEntries); 1283 SERIALIZE_SCALAR(lastReplaced); 1284 1285 // convert the pointer based free list into an index based one 1286 int *free_list = (int*)malloc(sizeof(int) * size); 1287 int cntr = 0; 1288 std::list<TlbEntry*>::iterator i; 1289 i = freeList.begin(); 1290 while (i != freeList.end()) { 1291 free_list[cntr++] = ((size_t)*i - (size_t)tlb)/ sizeof(TlbEntry); 1292 i++; 1293 } 1294 SERIALIZE_SCALAR(cntr); 1295 SERIALIZE_ARRAY(free_list, cntr); 1296 1297 for (int x = 0; x < size; x++) { 1298 nameOut(os, csprintf("%s.PTE%d", name(), x)); 1299 tlb[x].serialize(os); 1300 } 1301} 1302 1303void 1304TLB::unserialize(Checkpoint *cp, const std::string §ion) 1305{ 1306 int oldSize; 1307 1308 paramIn(cp, section, "size", oldSize); 1309 if (oldSize != size) 1310 panic("Don't support unserializing different sized TLBs\n"); 1311 UNSERIALIZE_SCALAR(usedEntries); 1312 UNSERIALIZE_SCALAR(lastReplaced); 1313 1314 int cntr; 1315 UNSERIALIZE_SCALAR(cntr); 1316 1317 int *free_list = (int*)malloc(sizeof(int) * cntr); 1318 freeList.clear(); 1319 UNSERIALIZE_ARRAY(free_list, cntr); 1320 for (int x = 0; x < cntr; x++) 1321 freeList.push_back(&tlb[free_list[x]]); 1322 1323 lookupTable.clear(); 1324 for (int x = 0; x < size; x++) { 1325 tlb[x].unserialize(cp, csprintf("%s.PTE%d", section, x)); 1326 if (tlb[x].valid) 1327 lookupTable.insert(tlb[x].range, &tlb[x]); 1328 1329 } 1330} 1331 1332 1333DEFINE_SIM_OBJECT_CLASS_NAME("SparcTLB", TLB) 1334 1335BEGIN_DECLARE_SIM_OBJECT_PARAMS(ITB) 1336 1337 Param<int> size; 1338 1339END_DECLARE_SIM_OBJECT_PARAMS(ITB) 1340 1341BEGIN_INIT_SIM_OBJECT_PARAMS(ITB) 1342 1343 INIT_PARAM_DFLT(size, "TLB size", 48) 1344 1345END_INIT_SIM_OBJECT_PARAMS(ITB) 1346 1347 1348CREATE_SIM_OBJECT(ITB) 1349{ 1350 return new ITB(getInstanceName(), size); 1351} 1352 1353REGISTER_SIM_OBJECT("SparcITB", ITB) 1354 1355BEGIN_DECLARE_SIM_OBJECT_PARAMS(DTB) 1356 1357 Param<int> size; 1358 1359END_DECLARE_SIM_OBJECT_PARAMS(DTB) 1360 1361BEGIN_INIT_SIM_OBJECT_PARAMS(DTB) 1362 1363 INIT_PARAM_DFLT(size, "TLB size", 64) 1364 1365END_INIT_SIM_OBJECT_PARAMS(DTB) 1366 1367 1368CREATE_SIM_OBJECT(DTB) 1369{ 1370 return new DTB(getInstanceName(), size); 1371} 1372 1373REGISTER_SIM_OBJECT("SparcDTB", DTB) 1374} 1375