gpu_tlb.cc revision 13449
111308Santhony.gutierrez@amd.com/* 211308Santhony.gutierrez@amd.com * Copyright (c) 2011-2015 Advanced Micro Devices, Inc. 311308Santhony.gutierrez@amd.com * All rights reserved. 411308Santhony.gutierrez@amd.com * 511308Santhony.gutierrez@amd.com * For use for simulation and test purposes only 611308Santhony.gutierrez@amd.com * 711308Santhony.gutierrez@amd.com * Redistribution and use in source and binary forms, with or without 811308Santhony.gutierrez@amd.com * modification, are permitted provided that the following conditions are met: 911308Santhony.gutierrez@amd.com * 1011308Santhony.gutierrez@amd.com * 1. Redistributions of source code must retain the above copyright notice, 1111308Santhony.gutierrez@amd.com * this list of conditions and the following disclaimer. 1211308Santhony.gutierrez@amd.com * 1311308Santhony.gutierrez@amd.com * 2. Redistributions in binary form must reproduce the above copyright notice, 1411308Santhony.gutierrez@amd.com * this list of conditions and the following disclaimer in the documentation 1511308Santhony.gutierrez@amd.com * and/or other materials provided with the distribution. 1611308Santhony.gutierrez@amd.com * 1711308Santhony.gutierrez@amd.com * 3. Neither the name of the copyright holder nor the names of its contributors 1811308Santhony.gutierrez@amd.com * may be used to endorse or promote products derived from this software 1911308Santhony.gutierrez@amd.com * without specific prior written permission. 2011308Santhony.gutierrez@amd.com * 2111308Santhony.gutierrez@amd.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 2211308Santhony.gutierrez@amd.com * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2311308Santhony.gutierrez@amd.com * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2411308Santhony.gutierrez@amd.com * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 2511308Santhony.gutierrez@amd.com * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 2611308Santhony.gutierrez@amd.com * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 2711308Santhony.gutierrez@amd.com * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 2811308Santhony.gutierrez@amd.com * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 2911308Santhony.gutierrez@amd.com * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 3011308Santhony.gutierrez@amd.com * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 3111308Santhony.gutierrez@amd.com * POSSIBILITY OF SUCH DAMAGE. 3211308Santhony.gutierrez@amd.com * 3311308Santhony.gutierrez@amd.com * Author: Lisa Hsu 3411308Santhony.gutierrez@amd.com */ 3511308Santhony.gutierrez@amd.com 3611308Santhony.gutierrez@amd.com#include "gpu-compute/gpu_tlb.hh" 3711308Santhony.gutierrez@amd.com 3811308Santhony.gutierrez@amd.com#include <cmath> 3911308Santhony.gutierrez@amd.com#include <cstring> 4011308Santhony.gutierrez@amd.com 4111308Santhony.gutierrez@amd.com#include "arch/x86/faults.hh" 4211308Santhony.gutierrez@amd.com#include "arch/x86/insts/microldstop.hh" 4311308Santhony.gutierrez@amd.com#include "arch/x86/pagetable.hh" 4411308Santhony.gutierrez@amd.com#include "arch/x86/pagetable_walker.hh" 4511308Santhony.gutierrez@amd.com#include "arch/x86/regs/misc.hh" 4611308Santhony.gutierrez@amd.com#include "arch/x86/x86_traits.hh" 4711308Santhony.gutierrez@amd.com#include "base/bitfield.hh" 4813449Sgabeblack@google.com#include "base/logging.hh" 4911308Santhony.gutierrez@amd.com#include "base/output.hh" 5011308Santhony.gutierrez@amd.com#include "base/trace.hh" 5111308Santhony.gutierrez@amd.com#include "cpu/base.hh" 5211308Santhony.gutierrez@amd.com#include "cpu/thread_context.hh" 5311308Santhony.gutierrez@amd.com#include "debug/GPUPrefetch.hh" 5411308Santhony.gutierrez@amd.com#include "debug/GPUTLB.hh" 5511308Santhony.gutierrez@amd.com#include "mem/packet_access.hh" 5611308Santhony.gutierrez@amd.com#include "mem/page_table.hh" 5711308Santhony.gutierrez@amd.com#include "mem/request.hh" 5811308Santhony.gutierrez@amd.com#include "sim/process.hh" 5911308Santhony.gutierrez@amd.com 6011308Santhony.gutierrez@amd.comnamespace X86ISA 6111308Santhony.gutierrez@amd.com{ 6211308Santhony.gutierrez@amd.com 6311308Santhony.gutierrez@amd.com GpuTLB::GpuTLB(const Params *p) 6411308Santhony.gutierrez@amd.com : MemObject(p), configAddress(0), size(p->size), 6512085Sspwilson2@wisc.edu cleanupEvent([this]{ cleanup(); }, name(), false, 6612085Sspwilson2@wisc.edu Event::Maximum_Pri), 6712085Sspwilson2@wisc.edu exitEvent([this]{ exitCallback(); }, name()) 6811308Santhony.gutierrez@amd.com { 6911308Santhony.gutierrez@amd.com assoc = p->assoc; 7011308Santhony.gutierrez@amd.com assert(assoc <= size); 7111308Santhony.gutierrez@amd.com numSets = size/assoc; 7211308Santhony.gutierrez@amd.com allocationPolicy = p->allocationPolicy; 7311308Santhony.gutierrez@amd.com hasMemSidePort = false; 7411308Santhony.gutierrez@amd.com accessDistance = p->accessDistance; 7511308Santhony.gutierrez@amd.com clock = p->clk_domain->clockPeriod(); 7611308Santhony.gutierrez@amd.com 7712717Sbrandon.potter@amd.com tlb.assign(size, TlbEntry()); 7811308Santhony.gutierrez@amd.com 7911308Santhony.gutierrez@amd.com freeList.resize(numSets); 8011308Santhony.gutierrez@amd.com entryList.resize(numSets); 8111308Santhony.gutierrez@amd.com 8211308Santhony.gutierrez@amd.com for (int set = 0; set < numSets; ++set) { 8311308Santhony.gutierrez@amd.com for (int way = 0; way < assoc; ++way) { 8411704Santhony.gutierrez@amd.com int x = set * assoc + way; 8511704Santhony.gutierrez@amd.com freeList[set].push_back(&tlb.at(x)); 8611308Santhony.gutierrez@amd.com } 8711308Santhony.gutierrez@amd.com } 8811308Santhony.gutierrez@amd.com 8911308Santhony.gutierrez@amd.com FA = (size == assoc); 9011308Santhony.gutierrez@amd.com 9111308Santhony.gutierrez@amd.com /** 9211308Santhony.gutierrez@amd.com * @warning: the set-associative version assumes you have a 9311308Santhony.gutierrez@amd.com * fixed page size of 4KB. 9411308Santhony.gutierrez@amd.com * If the page size is greather than 4KB (as defined in the 9511308Santhony.gutierrez@amd.com * TheISA::PageBytes), then there are various issues w/ the current 9611308Santhony.gutierrez@amd.com * implementation (you'd have the same 8KB page being replicated in 9711308Santhony.gutierrez@amd.com * different sets etc) 9811308Santhony.gutierrez@amd.com */ 9911308Santhony.gutierrez@amd.com setMask = numSets - 1; 10011308Santhony.gutierrez@amd.com 10111308Santhony.gutierrez@amd.com #if 0 10211308Santhony.gutierrez@amd.com // GpuTLB doesn't yet support full system 10311308Santhony.gutierrez@amd.com walker = p->walker; 10411308Santhony.gutierrez@amd.com walker->setTLB(this); 10511308Santhony.gutierrez@amd.com #endif 10611308Santhony.gutierrez@amd.com 10711308Santhony.gutierrez@amd.com maxCoalescedReqs = p->maxOutstandingReqs; 10811308Santhony.gutierrez@amd.com 10911308Santhony.gutierrez@amd.com // Do not allow maxCoalescedReqs to be more than the TLB associativity 11011308Santhony.gutierrez@amd.com if (maxCoalescedReqs > assoc) { 11111308Santhony.gutierrez@amd.com maxCoalescedReqs = assoc; 11211308Santhony.gutierrez@amd.com cprintf("Forcing maxCoalescedReqs to %d (TLB assoc.) \n", assoc); 11311308Santhony.gutierrez@amd.com } 11411308Santhony.gutierrez@amd.com 11511308Santhony.gutierrez@amd.com outstandingReqs = 0; 11611308Santhony.gutierrez@amd.com hitLatency = p->hitLatency; 11711308Santhony.gutierrez@amd.com missLatency1 = p->missLatency1; 11811308Santhony.gutierrez@amd.com missLatency2 = p->missLatency2; 11911308Santhony.gutierrez@amd.com 12011308Santhony.gutierrez@amd.com // create the slave ports based on the number of connected ports 12111308Santhony.gutierrez@amd.com for (size_t i = 0; i < p->port_slave_connection_count; ++i) { 12211308Santhony.gutierrez@amd.com cpuSidePort.push_back(new CpuSidePort(csprintf("%s-port%d", 12311308Santhony.gutierrez@amd.com name(), i), this, i)); 12411308Santhony.gutierrez@amd.com } 12511308Santhony.gutierrez@amd.com 12611308Santhony.gutierrez@amd.com // create the master ports based on the number of connected ports 12711308Santhony.gutierrez@amd.com for (size_t i = 0; i < p->port_master_connection_count; ++i) { 12811308Santhony.gutierrez@amd.com memSidePort.push_back(new MemSidePort(csprintf("%s-port%d", 12911308Santhony.gutierrez@amd.com name(), i), this, i)); 13011308Santhony.gutierrez@amd.com } 13111308Santhony.gutierrez@amd.com } 13211308Santhony.gutierrez@amd.com 13311308Santhony.gutierrez@amd.com // fixme: this is never called? 13411308Santhony.gutierrez@amd.com GpuTLB::~GpuTLB() 13511308Santhony.gutierrez@amd.com { 13611308Santhony.gutierrez@amd.com // make sure all the hash-maps are empty 13711308Santhony.gutierrez@amd.com assert(translationReturnEvent.empty()); 13811308Santhony.gutierrez@amd.com } 13911308Santhony.gutierrez@amd.com 14011308Santhony.gutierrez@amd.com BaseSlavePort& 14111308Santhony.gutierrez@amd.com GpuTLB::getSlavePort(const std::string &if_name, PortID idx) 14211308Santhony.gutierrez@amd.com { 14311308Santhony.gutierrez@amd.com if (if_name == "slave") { 14411308Santhony.gutierrez@amd.com if (idx >= static_cast<PortID>(cpuSidePort.size())) { 14511308Santhony.gutierrez@amd.com panic("TLBCoalescer::getSlavePort: unknown index %d\n", idx); 14611308Santhony.gutierrez@amd.com } 14711308Santhony.gutierrez@amd.com 14811308Santhony.gutierrez@amd.com return *cpuSidePort[idx]; 14911308Santhony.gutierrez@amd.com } else { 15011308Santhony.gutierrez@amd.com panic("TLBCoalescer::getSlavePort: unknown port %s\n", if_name); 15111308Santhony.gutierrez@amd.com } 15211308Santhony.gutierrez@amd.com } 15311308Santhony.gutierrez@amd.com 15411308Santhony.gutierrez@amd.com BaseMasterPort& 15511308Santhony.gutierrez@amd.com GpuTLB::getMasterPort(const std::string &if_name, PortID idx) 15611308Santhony.gutierrez@amd.com { 15711308Santhony.gutierrez@amd.com if (if_name == "master") { 15811308Santhony.gutierrez@amd.com if (idx >= static_cast<PortID>(memSidePort.size())) { 15911308Santhony.gutierrez@amd.com panic("TLBCoalescer::getMasterPort: unknown index %d\n", idx); 16011308Santhony.gutierrez@amd.com } 16111308Santhony.gutierrez@amd.com 16211308Santhony.gutierrez@amd.com hasMemSidePort = true; 16311308Santhony.gutierrez@amd.com 16411308Santhony.gutierrez@amd.com return *memSidePort[idx]; 16511308Santhony.gutierrez@amd.com } else { 16611308Santhony.gutierrez@amd.com panic("TLBCoalescer::getMasterPort: unknown port %s\n", if_name); 16711308Santhony.gutierrez@amd.com } 16811308Santhony.gutierrez@amd.com } 16911308Santhony.gutierrez@amd.com 17012717Sbrandon.potter@amd.com TlbEntry* 17112717Sbrandon.potter@amd.com GpuTLB::insert(Addr vpn, TlbEntry &entry) 17211308Santhony.gutierrez@amd.com { 17312717Sbrandon.potter@amd.com TlbEntry *newEntry = nullptr; 17411308Santhony.gutierrez@amd.com 17511308Santhony.gutierrez@amd.com /** 17611308Santhony.gutierrez@amd.com * vpn holds the virtual page address 17711308Santhony.gutierrez@amd.com * The least significant bits are simply masked 17811308Santhony.gutierrez@amd.com */ 17911308Santhony.gutierrez@amd.com int set = (vpn >> TheISA::PageShift) & setMask; 18011308Santhony.gutierrez@amd.com 18111308Santhony.gutierrez@amd.com if (!freeList[set].empty()) { 18211308Santhony.gutierrez@amd.com newEntry = freeList[set].front(); 18311308Santhony.gutierrez@amd.com freeList[set].pop_front(); 18411308Santhony.gutierrez@amd.com } else { 18511308Santhony.gutierrez@amd.com newEntry = entryList[set].back(); 18611308Santhony.gutierrez@amd.com entryList[set].pop_back(); 18711308Santhony.gutierrez@amd.com } 18811308Santhony.gutierrez@amd.com 18911308Santhony.gutierrez@amd.com *newEntry = entry; 19011308Santhony.gutierrez@amd.com newEntry->vaddr = vpn; 19111308Santhony.gutierrez@amd.com entryList[set].push_front(newEntry); 19211308Santhony.gutierrez@amd.com 19311308Santhony.gutierrez@amd.com return newEntry; 19411308Santhony.gutierrez@amd.com } 19511308Santhony.gutierrez@amd.com 19611308Santhony.gutierrez@amd.com GpuTLB::EntryList::iterator 19711308Santhony.gutierrez@amd.com GpuTLB::lookupIt(Addr va, bool update_lru) 19811308Santhony.gutierrez@amd.com { 19911308Santhony.gutierrez@amd.com int set = (va >> TheISA::PageShift) & setMask; 20011308Santhony.gutierrez@amd.com 20111308Santhony.gutierrez@amd.com if (FA) { 20211308Santhony.gutierrez@amd.com assert(!set); 20311308Santhony.gutierrez@amd.com } 20411308Santhony.gutierrez@amd.com 20511308Santhony.gutierrez@amd.com auto entry = entryList[set].begin(); 20611308Santhony.gutierrez@amd.com for (; entry != entryList[set].end(); ++entry) { 20711308Santhony.gutierrez@amd.com int page_size = (*entry)->size(); 20811308Santhony.gutierrez@amd.com 20911308Santhony.gutierrez@amd.com if ((*entry)->vaddr <= va && (*entry)->vaddr + page_size > va) { 21011308Santhony.gutierrez@amd.com DPRINTF(GPUTLB, "Matched vaddr %#x to entry starting at %#x " 21111308Santhony.gutierrez@amd.com "with size %#x.\n", va, (*entry)->vaddr, page_size); 21211308Santhony.gutierrez@amd.com 21311308Santhony.gutierrez@amd.com if (update_lru) { 21411308Santhony.gutierrez@amd.com entryList[set].push_front(*entry); 21511308Santhony.gutierrez@amd.com entryList[set].erase(entry); 21611308Santhony.gutierrez@amd.com entry = entryList[set].begin(); 21711308Santhony.gutierrez@amd.com } 21811308Santhony.gutierrez@amd.com 21911308Santhony.gutierrez@amd.com break; 22011308Santhony.gutierrez@amd.com } 22111308Santhony.gutierrez@amd.com } 22211308Santhony.gutierrez@amd.com 22311308Santhony.gutierrez@amd.com return entry; 22411308Santhony.gutierrez@amd.com } 22511308Santhony.gutierrez@amd.com 22612717Sbrandon.potter@amd.com TlbEntry* 22711308Santhony.gutierrez@amd.com GpuTLB::lookup(Addr va, bool update_lru) 22811308Santhony.gutierrez@amd.com { 22911308Santhony.gutierrez@amd.com int set = (va >> TheISA::PageShift) & setMask; 23011308Santhony.gutierrez@amd.com 23111308Santhony.gutierrez@amd.com auto entry = lookupIt(va, update_lru); 23211308Santhony.gutierrez@amd.com 23311308Santhony.gutierrez@amd.com if (entry == entryList[set].end()) 23411308Santhony.gutierrez@amd.com return nullptr; 23511308Santhony.gutierrez@amd.com else 23611308Santhony.gutierrez@amd.com return *entry; 23711308Santhony.gutierrez@amd.com } 23811308Santhony.gutierrez@amd.com 23911308Santhony.gutierrez@amd.com void 24011308Santhony.gutierrez@amd.com GpuTLB::invalidateAll() 24111308Santhony.gutierrez@amd.com { 24211308Santhony.gutierrez@amd.com DPRINTF(GPUTLB, "Invalidating all entries.\n"); 24311308Santhony.gutierrez@amd.com 24411308Santhony.gutierrez@amd.com for (int i = 0; i < numSets; ++i) { 24511308Santhony.gutierrez@amd.com while (!entryList[i].empty()) { 24612717Sbrandon.potter@amd.com TlbEntry *entry = entryList[i].front(); 24711308Santhony.gutierrez@amd.com entryList[i].pop_front(); 24811308Santhony.gutierrez@amd.com freeList[i].push_back(entry); 24911308Santhony.gutierrez@amd.com } 25011308Santhony.gutierrez@amd.com } 25111308Santhony.gutierrez@amd.com } 25211308Santhony.gutierrez@amd.com 25311308Santhony.gutierrez@amd.com void 25411308Santhony.gutierrez@amd.com GpuTLB::setConfigAddress(uint32_t addr) 25511308Santhony.gutierrez@amd.com { 25611308Santhony.gutierrez@amd.com configAddress = addr; 25711308Santhony.gutierrez@amd.com } 25811308Santhony.gutierrez@amd.com 25911308Santhony.gutierrez@amd.com void 26011308Santhony.gutierrez@amd.com GpuTLB::invalidateNonGlobal() 26111308Santhony.gutierrez@amd.com { 26211308Santhony.gutierrez@amd.com DPRINTF(GPUTLB, "Invalidating all non global entries.\n"); 26311308Santhony.gutierrez@amd.com 26411308Santhony.gutierrez@amd.com for (int i = 0; i < numSets; ++i) { 26511308Santhony.gutierrez@amd.com for (auto entryIt = entryList[i].begin(); 26611308Santhony.gutierrez@amd.com entryIt != entryList[i].end();) { 26711308Santhony.gutierrez@amd.com if (!(*entryIt)->global) { 26811308Santhony.gutierrez@amd.com freeList[i].push_back(*entryIt); 26911308Santhony.gutierrez@amd.com entryList[i].erase(entryIt++); 27011308Santhony.gutierrez@amd.com } else { 27111308Santhony.gutierrez@amd.com ++entryIt; 27211308Santhony.gutierrez@amd.com } 27311308Santhony.gutierrez@amd.com } 27411308Santhony.gutierrez@amd.com } 27511308Santhony.gutierrez@amd.com } 27611308Santhony.gutierrez@amd.com 27711308Santhony.gutierrez@amd.com void 27811308Santhony.gutierrez@amd.com GpuTLB::demapPage(Addr va, uint64_t asn) 27911308Santhony.gutierrez@amd.com { 28011308Santhony.gutierrez@amd.com 28111308Santhony.gutierrez@amd.com int set = (va >> TheISA::PageShift) & setMask; 28211308Santhony.gutierrez@amd.com auto entry = lookupIt(va, false); 28311308Santhony.gutierrez@amd.com 28411308Santhony.gutierrez@amd.com if (entry != entryList[set].end()) { 28511308Santhony.gutierrez@amd.com freeList[set].push_back(*entry); 28611308Santhony.gutierrez@amd.com entryList[set].erase(entry); 28711308Santhony.gutierrez@amd.com } 28811308Santhony.gutierrez@amd.com } 28911308Santhony.gutierrez@amd.com 29011308Santhony.gutierrez@amd.com Fault 29112749Sgiacomo.travaglini@arm.com GpuTLB::translateInt(const RequestPtr &req, ThreadContext *tc) 29211308Santhony.gutierrez@amd.com { 29311308Santhony.gutierrez@amd.com DPRINTF(GPUTLB, "Addresses references internal memory.\n"); 29411308Santhony.gutierrez@amd.com Addr vaddr = req->getVaddr(); 29511308Santhony.gutierrez@amd.com Addr prefix = (vaddr >> 3) & IntAddrPrefixMask; 29611308Santhony.gutierrez@amd.com 29711308Santhony.gutierrez@amd.com if (prefix == IntAddrPrefixCPUID) { 29811308Santhony.gutierrez@amd.com panic("CPUID memory space not yet implemented!\n"); 29911308Santhony.gutierrez@amd.com } else if (prefix == IntAddrPrefixMSR) { 30011308Santhony.gutierrez@amd.com vaddr = vaddr >> 3; 30111308Santhony.gutierrez@amd.com req->setFlags(Request::MMAPPED_IPR); 30211308Santhony.gutierrez@amd.com Addr regNum = 0; 30311308Santhony.gutierrez@amd.com 30411308Santhony.gutierrez@amd.com switch (vaddr & ~IntAddrPrefixMask) { 30511308Santhony.gutierrez@amd.com case 0x10: 30611308Santhony.gutierrez@amd.com regNum = MISCREG_TSC; 30711308Santhony.gutierrez@amd.com break; 30811308Santhony.gutierrez@amd.com case 0x1B: 30911308Santhony.gutierrez@amd.com regNum = MISCREG_APIC_BASE; 31011308Santhony.gutierrez@amd.com break; 31111308Santhony.gutierrez@amd.com case 0xFE: 31211308Santhony.gutierrez@amd.com regNum = MISCREG_MTRRCAP; 31311308Santhony.gutierrez@amd.com break; 31411308Santhony.gutierrez@amd.com case 0x174: 31511308Santhony.gutierrez@amd.com regNum = MISCREG_SYSENTER_CS; 31611308Santhony.gutierrez@amd.com break; 31711308Santhony.gutierrez@amd.com case 0x175: 31811308Santhony.gutierrez@amd.com regNum = MISCREG_SYSENTER_ESP; 31911308Santhony.gutierrez@amd.com break; 32011308Santhony.gutierrez@amd.com case 0x176: 32111308Santhony.gutierrez@amd.com regNum = MISCREG_SYSENTER_EIP; 32211308Santhony.gutierrez@amd.com break; 32311308Santhony.gutierrez@amd.com case 0x179: 32411308Santhony.gutierrez@amd.com regNum = MISCREG_MCG_CAP; 32511308Santhony.gutierrez@amd.com break; 32611308Santhony.gutierrez@amd.com case 0x17A: 32711308Santhony.gutierrez@amd.com regNum = MISCREG_MCG_STATUS; 32811308Santhony.gutierrez@amd.com break; 32911308Santhony.gutierrez@amd.com case 0x17B: 33011308Santhony.gutierrez@amd.com regNum = MISCREG_MCG_CTL; 33111308Santhony.gutierrez@amd.com break; 33211308Santhony.gutierrez@amd.com case 0x1D9: 33311308Santhony.gutierrez@amd.com regNum = MISCREG_DEBUG_CTL_MSR; 33411308Santhony.gutierrez@amd.com break; 33511308Santhony.gutierrez@amd.com case 0x1DB: 33611308Santhony.gutierrez@amd.com regNum = MISCREG_LAST_BRANCH_FROM_IP; 33711308Santhony.gutierrez@amd.com break; 33811308Santhony.gutierrez@amd.com case 0x1DC: 33911308Santhony.gutierrez@amd.com regNum = MISCREG_LAST_BRANCH_TO_IP; 34011308Santhony.gutierrez@amd.com break; 34111308Santhony.gutierrez@amd.com case 0x1DD: 34211308Santhony.gutierrez@amd.com regNum = MISCREG_LAST_EXCEPTION_FROM_IP; 34311308Santhony.gutierrez@amd.com break; 34411308Santhony.gutierrez@amd.com case 0x1DE: 34511308Santhony.gutierrez@amd.com regNum = MISCREG_LAST_EXCEPTION_TO_IP; 34611308Santhony.gutierrez@amd.com break; 34711308Santhony.gutierrez@amd.com case 0x200: 34811308Santhony.gutierrez@amd.com regNum = MISCREG_MTRR_PHYS_BASE_0; 34911308Santhony.gutierrez@amd.com break; 35011308Santhony.gutierrez@amd.com case 0x201: 35111308Santhony.gutierrez@amd.com regNum = MISCREG_MTRR_PHYS_MASK_0; 35211308Santhony.gutierrez@amd.com break; 35311308Santhony.gutierrez@amd.com case 0x202: 35411308Santhony.gutierrez@amd.com regNum = MISCREG_MTRR_PHYS_BASE_1; 35511308Santhony.gutierrez@amd.com break; 35611308Santhony.gutierrez@amd.com case 0x203: 35711308Santhony.gutierrez@amd.com regNum = MISCREG_MTRR_PHYS_MASK_1; 35811308Santhony.gutierrez@amd.com break; 35911308Santhony.gutierrez@amd.com case 0x204: 36011308Santhony.gutierrez@amd.com regNum = MISCREG_MTRR_PHYS_BASE_2; 36111308Santhony.gutierrez@amd.com break; 36211308Santhony.gutierrez@amd.com case 0x205: 36311308Santhony.gutierrez@amd.com regNum = MISCREG_MTRR_PHYS_MASK_2; 36411308Santhony.gutierrez@amd.com break; 36511308Santhony.gutierrez@amd.com case 0x206: 36611308Santhony.gutierrez@amd.com regNum = MISCREG_MTRR_PHYS_BASE_3; 36711308Santhony.gutierrez@amd.com break; 36811308Santhony.gutierrez@amd.com case 0x207: 36911308Santhony.gutierrez@amd.com regNum = MISCREG_MTRR_PHYS_MASK_3; 37011308Santhony.gutierrez@amd.com break; 37111308Santhony.gutierrez@amd.com case 0x208: 37211308Santhony.gutierrez@amd.com regNum = MISCREG_MTRR_PHYS_BASE_4; 37311308Santhony.gutierrez@amd.com break; 37411308Santhony.gutierrez@amd.com case 0x209: 37511308Santhony.gutierrez@amd.com regNum = MISCREG_MTRR_PHYS_MASK_4; 37611308Santhony.gutierrez@amd.com break; 37711308Santhony.gutierrez@amd.com case 0x20A: 37811308Santhony.gutierrez@amd.com regNum = MISCREG_MTRR_PHYS_BASE_5; 37911308Santhony.gutierrez@amd.com break; 38011308Santhony.gutierrez@amd.com case 0x20B: 38111308Santhony.gutierrez@amd.com regNum = MISCREG_MTRR_PHYS_MASK_5; 38211308Santhony.gutierrez@amd.com break; 38311308Santhony.gutierrez@amd.com case 0x20C: 38411308Santhony.gutierrez@amd.com regNum = MISCREG_MTRR_PHYS_BASE_6; 38511308Santhony.gutierrez@amd.com break; 38611308Santhony.gutierrez@amd.com case 0x20D: 38711308Santhony.gutierrez@amd.com regNum = MISCREG_MTRR_PHYS_MASK_6; 38811308Santhony.gutierrez@amd.com break; 38911308Santhony.gutierrez@amd.com case 0x20E: 39011308Santhony.gutierrez@amd.com regNum = MISCREG_MTRR_PHYS_BASE_7; 39111308Santhony.gutierrez@amd.com break; 39211308Santhony.gutierrez@amd.com case 0x20F: 39311308Santhony.gutierrez@amd.com regNum = MISCREG_MTRR_PHYS_MASK_7; 39411308Santhony.gutierrez@amd.com break; 39511308Santhony.gutierrez@amd.com case 0x250: 39611308Santhony.gutierrez@amd.com regNum = MISCREG_MTRR_FIX_64K_00000; 39711308Santhony.gutierrez@amd.com break; 39811308Santhony.gutierrez@amd.com case 0x258: 39911308Santhony.gutierrez@amd.com regNum = MISCREG_MTRR_FIX_16K_80000; 40011308Santhony.gutierrez@amd.com break; 40111308Santhony.gutierrez@amd.com case 0x259: 40211308Santhony.gutierrez@amd.com regNum = MISCREG_MTRR_FIX_16K_A0000; 40311308Santhony.gutierrez@amd.com break; 40411308Santhony.gutierrez@amd.com case 0x268: 40511308Santhony.gutierrez@amd.com regNum = MISCREG_MTRR_FIX_4K_C0000; 40611308Santhony.gutierrez@amd.com break; 40711308Santhony.gutierrez@amd.com case 0x269: 40811308Santhony.gutierrez@amd.com regNum = MISCREG_MTRR_FIX_4K_C8000; 40911308Santhony.gutierrez@amd.com break; 41011308Santhony.gutierrez@amd.com case 0x26A: 41111308Santhony.gutierrez@amd.com regNum = MISCREG_MTRR_FIX_4K_D0000; 41211308Santhony.gutierrez@amd.com break; 41311308Santhony.gutierrez@amd.com case 0x26B: 41411308Santhony.gutierrez@amd.com regNum = MISCREG_MTRR_FIX_4K_D8000; 41511308Santhony.gutierrez@amd.com break; 41611308Santhony.gutierrez@amd.com case 0x26C: 41711308Santhony.gutierrez@amd.com regNum = MISCREG_MTRR_FIX_4K_E0000; 41811308Santhony.gutierrez@amd.com break; 41911308Santhony.gutierrez@amd.com case 0x26D: 42011308Santhony.gutierrez@amd.com regNum = MISCREG_MTRR_FIX_4K_E8000; 42111308Santhony.gutierrez@amd.com break; 42211308Santhony.gutierrez@amd.com case 0x26E: 42311308Santhony.gutierrez@amd.com regNum = MISCREG_MTRR_FIX_4K_F0000; 42411308Santhony.gutierrez@amd.com break; 42511308Santhony.gutierrez@amd.com case 0x26F: 42611308Santhony.gutierrez@amd.com regNum = MISCREG_MTRR_FIX_4K_F8000; 42711308Santhony.gutierrez@amd.com break; 42811308Santhony.gutierrez@amd.com case 0x277: 42911308Santhony.gutierrez@amd.com regNum = MISCREG_PAT; 43011308Santhony.gutierrez@amd.com break; 43111308Santhony.gutierrez@amd.com case 0x2FF: 43211308Santhony.gutierrez@amd.com regNum = MISCREG_DEF_TYPE; 43311308Santhony.gutierrez@amd.com break; 43411308Santhony.gutierrez@amd.com case 0x400: 43511308Santhony.gutierrez@amd.com regNum = MISCREG_MC0_CTL; 43611308Santhony.gutierrez@amd.com break; 43711308Santhony.gutierrez@amd.com case 0x404: 43811308Santhony.gutierrez@amd.com regNum = MISCREG_MC1_CTL; 43911308Santhony.gutierrez@amd.com break; 44011308Santhony.gutierrez@amd.com case 0x408: 44111308Santhony.gutierrez@amd.com regNum = MISCREG_MC2_CTL; 44211308Santhony.gutierrez@amd.com break; 44311308Santhony.gutierrez@amd.com case 0x40C: 44411308Santhony.gutierrez@amd.com regNum = MISCREG_MC3_CTL; 44511308Santhony.gutierrez@amd.com break; 44611308Santhony.gutierrez@amd.com case 0x410: 44711308Santhony.gutierrez@amd.com regNum = MISCREG_MC4_CTL; 44811308Santhony.gutierrez@amd.com break; 44911308Santhony.gutierrez@amd.com case 0x414: 45011308Santhony.gutierrez@amd.com regNum = MISCREG_MC5_CTL; 45111308Santhony.gutierrez@amd.com break; 45211308Santhony.gutierrez@amd.com case 0x418: 45311308Santhony.gutierrez@amd.com regNum = MISCREG_MC6_CTL; 45411308Santhony.gutierrez@amd.com break; 45511308Santhony.gutierrez@amd.com case 0x41C: 45611308Santhony.gutierrez@amd.com regNum = MISCREG_MC7_CTL; 45711308Santhony.gutierrez@amd.com break; 45811308Santhony.gutierrez@amd.com case 0x401: 45911308Santhony.gutierrez@amd.com regNum = MISCREG_MC0_STATUS; 46011308Santhony.gutierrez@amd.com break; 46111308Santhony.gutierrez@amd.com case 0x405: 46211308Santhony.gutierrez@amd.com regNum = MISCREG_MC1_STATUS; 46311308Santhony.gutierrez@amd.com break; 46411308Santhony.gutierrez@amd.com case 0x409: 46511308Santhony.gutierrez@amd.com regNum = MISCREG_MC2_STATUS; 46611308Santhony.gutierrez@amd.com break; 46711308Santhony.gutierrez@amd.com case 0x40D: 46811308Santhony.gutierrez@amd.com regNum = MISCREG_MC3_STATUS; 46911308Santhony.gutierrez@amd.com break; 47011308Santhony.gutierrez@amd.com case 0x411: 47111308Santhony.gutierrez@amd.com regNum = MISCREG_MC4_STATUS; 47211308Santhony.gutierrez@amd.com break; 47311308Santhony.gutierrez@amd.com case 0x415: 47411308Santhony.gutierrez@amd.com regNum = MISCREG_MC5_STATUS; 47511308Santhony.gutierrez@amd.com break; 47611308Santhony.gutierrez@amd.com case 0x419: 47711308Santhony.gutierrez@amd.com regNum = MISCREG_MC6_STATUS; 47811308Santhony.gutierrez@amd.com break; 47911308Santhony.gutierrez@amd.com case 0x41D: 48011308Santhony.gutierrez@amd.com regNum = MISCREG_MC7_STATUS; 48111308Santhony.gutierrez@amd.com break; 48211308Santhony.gutierrez@amd.com case 0x402: 48311308Santhony.gutierrez@amd.com regNum = MISCREG_MC0_ADDR; 48411308Santhony.gutierrez@amd.com break; 48511308Santhony.gutierrez@amd.com case 0x406: 48611308Santhony.gutierrez@amd.com regNum = MISCREG_MC1_ADDR; 48711308Santhony.gutierrez@amd.com break; 48811308Santhony.gutierrez@amd.com case 0x40A: 48911308Santhony.gutierrez@amd.com regNum = MISCREG_MC2_ADDR; 49011308Santhony.gutierrez@amd.com break; 49111308Santhony.gutierrez@amd.com case 0x40E: 49211308Santhony.gutierrez@amd.com regNum = MISCREG_MC3_ADDR; 49311308Santhony.gutierrez@amd.com break; 49411308Santhony.gutierrez@amd.com case 0x412: 49511308Santhony.gutierrez@amd.com regNum = MISCREG_MC4_ADDR; 49611308Santhony.gutierrez@amd.com break; 49711308Santhony.gutierrez@amd.com case 0x416: 49811308Santhony.gutierrez@amd.com regNum = MISCREG_MC5_ADDR; 49911308Santhony.gutierrez@amd.com break; 50011308Santhony.gutierrez@amd.com case 0x41A: 50111308Santhony.gutierrez@amd.com regNum = MISCREG_MC6_ADDR; 50211308Santhony.gutierrez@amd.com break; 50311308Santhony.gutierrez@amd.com case 0x41E: 50411308Santhony.gutierrez@amd.com regNum = MISCREG_MC7_ADDR; 50511308Santhony.gutierrez@amd.com break; 50611308Santhony.gutierrez@amd.com case 0x403: 50711308Santhony.gutierrez@amd.com regNum = MISCREG_MC0_MISC; 50811308Santhony.gutierrez@amd.com break; 50911308Santhony.gutierrez@amd.com case 0x407: 51011308Santhony.gutierrez@amd.com regNum = MISCREG_MC1_MISC; 51111308Santhony.gutierrez@amd.com break; 51211308Santhony.gutierrez@amd.com case 0x40B: 51311308Santhony.gutierrez@amd.com regNum = MISCREG_MC2_MISC; 51411308Santhony.gutierrez@amd.com break; 51511308Santhony.gutierrez@amd.com case 0x40F: 51611308Santhony.gutierrez@amd.com regNum = MISCREG_MC3_MISC; 51711308Santhony.gutierrez@amd.com break; 51811308Santhony.gutierrez@amd.com case 0x413: 51911308Santhony.gutierrez@amd.com regNum = MISCREG_MC4_MISC; 52011308Santhony.gutierrez@amd.com break; 52111308Santhony.gutierrez@amd.com case 0x417: 52211308Santhony.gutierrez@amd.com regNum = MISCREG_MC5_MISC; 52311308Santhony.gutierrez@amd.com break; 52411308Santhony.gutierrez@amd.com case 0x41B: 52511308Santhony.gutierrez@amd.com regNum = MISCREG_MC6_MISC; 52611308Santhony.gutierrez@amd.com break; 52711308Santhony.gutierrez@amd.com case 0x41F: 52811308Santhony.gutierrez@amd.com regNum = MISCREG_MC7_MISC; 52911308Santhony.gutierrez@amd.com break; 53011308Santhony.gutierrez@amd.com case 0xC0000080: 53111308Santhony.gutierrez@amd.com regNum = MISCREG_EFER; 53211308Santhony.gutierrez@amd.com break; 53311308Santhony.gutierrez@amd.com case 0xC0000081: 53411308Santhony.gutierrez@amd.com regNum = MISCREG_STAR; 53511308Santhony.gutierrez@amd.com break; 53611308Santhony.gutierrez@amd.com case 0xC0000082: 53711308Santhony.gutierrez@amd.com regNum = MISCREG_LSTAR; 53811308Santhony.gutierrez@amd.com break; 53911308Santhony.gutierrez@amd.com case 0xC0000083: 54011308Santhony.gutierrez@amd.com regNum = MISCREG_CSTAR; 54111308Santhony.gutierrez@amd.com break; 54211308Santhony.gutierrez@amd.com case 0xC0000084: 54311308Santhony.gutierrez@amd.com regNum = MISCREG_SF_MASK; 54411308Santhony.gutierrez@amd.com break; 54511308Santhony.gutierrez@amd.com case 0xC0000100: 54611308Santhony.gutierrez@amd.com regNum = MISCREG_FS_BASE; 54711308Santhony.gutierrez@amd.com break; 54811308Santhony.gutierrez@amd.com case 0xC0000101: 54911308Santhony.gutierrez@amd.com regNum = MISCREG_GS_BASE; 55011308Santhony.gutierrez@amd.com break; 55111308Santhony.gutierrez@amd.com case 0xC0000102: 55211308Santhony.gutierrez@amd.com regNum = MISCREG_KERNEL_GS_BASE; 55311308Santhony.gutierrez@amd.com break; 55411308Santhony.gutierrez@amd.com case 0xC0000103: 55511308Santhony.gutierrez@amd.com regNum = MISCREG_TSC_AUX; 55611308Santhony.gutierrez@amd.com break; 55711308Santhony.gutierrez@amd.com case 0xC0010000: 55811308Santhony.gutierrez@amd.com regNum = MISCREG_PERF_EVT_SEL0; 55911308Santhony.gutierrez@amd.com break; 56011308Santhony.gutierrez@amd.com case 0xC0010001: 56111308Santhony.gutierrez@amd.com regNum = MISCREG_PERF_EVT_SEL1; 56211308Santhony.gutierrez@amd.com break; 56311308Santhony.gutierrez@amd.com case 0xC0010002: 56411308Santhony.gutierrez@amd.com regNum = MISCREG_PERF_EVT_SEL2; 56511308Santhony.gutierrez@amd.com break; 56611308Santhony.gutierrez@amd.com case 0xC0010003: 56711308Santhony.gutierrez@amd.com regNum = MISCREG_PERF_EVT_SEL3; 56811308Santhony.gutierrez@amd.com break; 56911308Santhony.gutierrez@amd.com case 0xC0010004: 57011308Santhony.gutierrez@amd.com regNum = MISCREG_PERF_EVT_CTR0; 57111308Santhony.gutierrez@amd.com break; 57211308Santhony.gutierrez@amd.com case 0xC0010005: 57311308Santhony.gutierrez@amd.com regNum = MISCREG_PERF_EVT_CTR1; 57411308Santhony.gutierrez@amd.com break; 57511308Santhony.gutierrez@amd.com case 0xC0010006: 57611308Santhony.gutierrez@amd.com regNum = MISCREG_PERF_EVT_CTR2; 57711308Santhony.gutierrez@amd.com break; 57811308Santhony.gutierrez@amd.com case 0xC0010007: 57911308Santhony.gutierrez@amd.com regNum = MISCREG_PERF_EVT_CTR3; 58011308Santhony.gutierrez@amd.com break; 58111308Santhony.gutierrez@amd.com case 0xC0010010: 58211308Santhony.gutierrez@amd.com regNum = MISCREG_SYSCFG; 58311308Santhony.gutierrez@amd.com break; 58411308Santhony.gutierrez@amd.com case 0xC0010016: 58511308Santhony.gutierrez@amd.com regNum = MISCREG_IORR_BASE0; 58611308Santhony.gutierrez@amd.com break; 58711308Santhony.gutierrez@amd.com case 0xC0010017: 58811308Santhony.gutierrez@amd.com regNum = MISCREG_IORR_BASE1; 58911308Santhony.gutierrez@amd.com break; 59011308Santhony.gutierrez@amd.com case 0xC0010018: 59111308Santhony.gutierrez@amd.com regNum = MISCREG_IORR_MASK0; 59211308Santhony.gutierrez@amd.com break; 59311308Santhony.gutierrez@amd.com case 0xC0010019: 59411308Santhony.gutierrez@amd.com regNum = MISCREG_IORR_MASK1; 59511308Santhony.gutierrez@amd.com break; 59611308Santhony.gutierrez@amd.com case 0xC001001A: 59711308Santhony.gutierrez@amd.com regNum = MISCREG_TOP_MEM; 59811308Santhony.gutierrez@amd.com break; 59911308Santhony.gutierrez@amd.com case 0xC001001D: 60011308Santhony.gutierrez@amd.com regNum = MISCREG_TOP_MEM2; 60111308Santhony.gutierrez@amd.com break; 60211308Santhony.gutierrez@amd.com case 0xC0010114: 60311308Santhony.gutierrez@amd.com regNum = MISCREG_VM_CR; 60411308Santhony.gutierrez@amd.com break; 60511308Santhony.gutierrez@amd.com case 0xC0010115: 60611308Santhony.gutierrez@amd.com regNum = MISCREG_IGNNE; 60711308Santhony.gutierrez@amd.com break; 60811308Santhony.gutierrez@amd.com case 0xC0010116: 60911308Santhony.gutierrez@amd.com regNum = MISCREG_SMM_CTL; 61011308Santhony.gutierrez@amd.com break; 61111308Santhony.gutierrez@amd.com case 0xC0010117: 61211308Santhony.gutierrez@amd.com regNum = MISCREG_VM_HSAVE_PA; 61311308Santhony.gutierrez@amd.com break; 61411308Santhony.gutierrez@amd.com default: 61511308Santhony.gutierrez@amd.com return std::make_shared<GeneralProtection>(0); 61611308Santhony.gutierrez@amd.com } 61711308Santhony.gutierrez@amd.com //The index is multiplied by the size of a MiscReg so that 61811308Santhony.gutierrez@amd.com //any memory dependence calculations will not see these as 61911308Santhony.gutierrez@amd.com //overlapping. 62011308Santhony.gutierrez@amd.com req->setPaddr(regNum * sizeof(MiscReg)); 62111308Santhony.gutierrez@amd.com return NoFault; 62211308Santhony.gutierrez@amd.com } else if (prefix == IntAddrPrefixIO) { 62311308Santhony.gutierrez@amd.com // TODO If CPL > IOPL or in virtual mode, check the I/O permission 62411308Santhony.gutierrez@amd.com // bitmap in the TSS. 62511308Santhony.gutierrez@amd.com 62611308Santhony.gutierrez@amd.com Addr IOPort = vaddr & ~IntAddrPrefixMask; 62711308Santhony.gutierrez@amd.com // Make sure the address fits in the expected 16 bit IO address 62811308Santhony.gutierrez@amd.com // space. 62911308Santhony.gutierrez@amd.com assert(!(IOPort & ~0xFFFF)); 63011308Santhony.gutierrez@amd.com 63111308Santhony.gutierrez@amd.com if (IOPort == 0xCF8 && req->getSize() == 4) { 63211308Santhony.gutierrez@amd.com req->setFlags(Request::MMAPPED_IPR); 63311308Santhony.gutierrez@amd.com req->setPaddr(MISCREG_PCI_CONFIG_ADDRESS * sizeof(MiscReg)); 63411308Santhony.gutierrez@amd.com } else if ((IOPort & ~mask(2)) == 0xCFC) { 63511308Santhony.gutierrez@amd.com req->setFlags(Request::UNCACHEABLE); 63611308Santhony.gutierrez@amd.com 63711308Santhony.gutierrez@amd.com Addr configAddress = 63811308Santhony.gutierrez@amd.com tc->readMiscRegNoEffect(MISCREG_PCI_CONFIG_ADDRESS); 63911308Santhony.gutierrez@amd.com 64011308Santhony.gutierrez@amd.com if (bits(configAddress, 31, 31)) { 64111308Santhony.gutierrez@amd.com req->setPaddr(PhysAddrPrefixPciConfig | 64211308Santhony.gutierrez@amd.com mbits(configAddress, 30, 2) | 64311308Santhony.gutierrez@amd.com (IOPort & mask(2))); 64411308Santhony.gutierrez@amd.com } else { 64511308Santhony.gutierrez@amd.com req->setPaddr(PhysAddrPrefixIO | IOPort); 64611308Santhony.gutierrez@amd.com } 64711308Santhony.gutierrez@amd.com } else { 64811308Santhony.gutierrez@amd.com req->setFlags(Request::UNCACHEABLE); 64911308Santhony.gutierrez@amd.com req->setPaddr(PhysAddrPrefixIO | IOPort); 65011308Santhony.gutierrez@amd.com } 65111308Santhony.gutierrez@amd.com return NoFault; 65211308Santhony.gutierrez@amd.com } else { 65311308Santhony.gutierrez@amd.com panic("Access to unrecognized internal address space %#x.\n", 65411308Santhony.gutierrez@amd.com prefix); 65511308Santhony.gutierrez@amd.com } 65611308Santhony.gutierrez@amd.com } 65711308Santhony.gutierrez@amd.com 65811308Santhony.gutierrez@amd.com /** 65911308Santhony.gutierrez@amd.com * TLB_lookup will only perform a TLB lookup returning true on a TLB hit 66011308Santhony.gutierrez@amd.com * and false on a TLB miss. 66111308Santhony.gutierrez@amd.com * Many of the checks about different modes have been converted to 66211308Santhony.gutierrez@amd.com * assertions, since these parts of the code are not really used. 66311308Santhony.gutierrez@amd.com * On a hit it will update the LRU stack. 66411308Santhony.gutierrez@amd.com */ 66511308Santhony.gutierrez@amd.com bool 66612749Sgiacomo.travaglini@arm.com GpuTLB::tlbLookup(const RequestPtr &req, 66712749Sgiacomo.travaglini@arm.com ThreadContext *tc, bool update_stats) 66811308Santhony.gutierrez@amd.com { 66911308Santhony.gutierrez@amd.com bool tlb_hit = false; 67011308Santhony.gutierrez@amd.com #ifndef NDEBUG 67111308Santhony.gutierrez@amd.com uint32_t flags = req->getFlags(); 67211308Santhony.gutierrez@amd.com int seg = flags & SegmentFlagMask; 67311308Santhony.gutierrez@amd.com #endif 67411308Santhony.gutierrez@amd.com 67511308Santhony.gutierrez@amd.com assert(seg != SEGMENT_REG_MS); 67611308Santhony.gutierrez@amd.com Addr vaddr = req->getVaddr(); 67711308Santhony.gutierrez@amd.com DPRINTF(GPUTLB, "TLB Lookup for vaddr %#x.\n", vaddr); 67811308Santhony.gutierrez@amd.com HandyM5Reg m5Reg = tc->readMiscRegNoEffect(MISCREG_M5_REG); 67911308Santhony.gutierrez@amd.com 68011308Santhony.gutierrez@amd.com if (m5Reg.prot) { 68111308Santhony.gutierrez@amd.com DPRINTF(GPUTLB, "In protected mode.\n"); 68211308Santhony.gutierrez@amd.com // make sure we are in 64-bit mode 68311308Santhony.gutierrez@amd.com assert(m5Reg.mode == LongMode); 68411308Santhony.gutierrez@amd.com 68511308Santhony.gutierrez@amd.com // If paging is enabled, do the translation. 68611308Santhony.gutierrez@amd.com if (m5Reg.paging) { 68711308Santhony.gutierrez@amd.com DPRINTF(GPUTLB, "Paging enabled.\n"); 68811308Santhony.gutierrez@amd.com //update LRU stack on a hit 68912717Sbrandon.potter@amd.com TlbEntry *entry = lookup(vaddr, true); 69011308Santhony.gutierrez@amd.com 69111308Santhony.gutierrez@amd.com if (entry) 69211308Santhony.gutierrez@amd.com tlb_hit = true; 69311308Santhony.gutierrez@amd.com 69411308Santhony.gutierrez@amd.com if (!update_stats) { 69511308Santhony.gutierrez@amd.com // functional tlb access for memory initialization 69611308Santhony.gutierrez@amd.com // i.e., memory seeding or instr. seeding -> don't update 69711308Santhony.gutierrez@amd.com // TLB and stats 69811308Santhony.gutierrez@amd.com return tlb_hit; 69911308Santhony.gutierrez@amd.com } 70011308Santhony.gutierrez@amd.com 70111308Santhony.gutierrez@amd.com localNumTLBAccesses++; 70211308Santhony.gutierrez@amd.com 70311308Santhony.gutierrez@amd.com if (!entry) { 70411308Santhony.gutierrez@amd.com localNumTLBMisses++; 70511308Santhony.gutierrez@amd.com } else { 70611308Santhony.gutierrez@amd.com localNumTLBHits++; 70711308Santhony.gutierrez@amd.com } 70811308Santhony.gutierrez@amd.com } 70911308Santhony.gutierrez@amd.com } 71011308Santhony.gutierrez@amd.com 71111308Santhony.gutierrez@amd.com return tlb_hit; 71211308Santhony.gutierrez@amd.com } 71311308Santhony.gutierrez@amd.com 71411308Santhony.gutierrez@amd.com Fault 71512749Sgiacomo.travaglini@arm.com GpuTLB::translate(const RequestPtr &req, ThreadContext *tc, 71611308Santhony.gutierrez@amd.com Translation *translation, Mode mode, 71711308Santhony.gutierrez@amd.com bool &delayedResponse, bool timing, int &latency) 71811308Santhony.gutierrez@amd.com { 71911308Santhony.gutierrez@amd.com uint32_t flags = req->getFlags(); 72011308Santhony.gutierrez@amd.com int seg = flags & SegmentFlagMask; 72111308Santhony.gutierrez@amd.com bool storeCheck = flags & (StoreCheck << FlagShift); 72211308Santhony.gutierrez@amd.com 72311308Santhony.gutierrez@amd.com // If this is true, we're dealing with a request 72411308Santhony.gutierrez@amd.com // to a non-memory address space. 72511308Santhony.gutierrez@amd.com if (seg == SEGMENT_REG_MS) { 72611308Santhony.gutierrez@amd.com return translateInt(req, tc); 72711308Santhony.gutierrez@amd.com } 72811308Santhony.gutierrez@amd.com 72911308Santhony.gutierrez@amd.com delayedResponse = false; 73011308Santhony.gutierrez@amd.com Addr vaddr = req->getVaddr(); 73111308Santhony.gutierrez@amd.com DPRINTF(GPUTLB, "Translating vaddr %#x.\n", vaddr); 73211308Santhony.gutierrez@amd.com 73311308Santhony.gutierrez@amd.com HandyM5Reg m5Reg = tc->readMiscRegNoEffect(MISCREG_M5_REG); 73411308Santhony.gutierrez@amd.com 73511308Santhony.gutierrez@amd.com // If protected mode has been enabled... 73611308Santhony.gutierrez@amd.com if (m5Reg.prot) { 73711308Santhony.gutierrez@amd.com DPRINTF(GPUTLB, "In protected mode.\n"); 73811308Santhony.gutierrez@amd.com // If we're not in 64-bit mode, do protection/limit checks 73911308Santhony.gutierrez@amd.com if (m5Reg.mode != LongMode) { 74011308Santhony.gutierrez@amd.com DPRINTF(GPUTLB, "Not in long mode. Checking segment " 74111308Santhony.gutierrez@amd.com "protection.\n"); 74211308Santhony.gutierrez@amd.com 74311308Santhony.gutierrez@amd.com // Check for a null segment selector. 74411308Santhony.gutierrez@amd.com if (!(seg == SEGMENT_REG_TSG || seg == SYS_SEGMENT_REG_IDTR || 74511308Santhony.gutierrez@amd.com seg == SEGMENT_REG_HS || seg == SEGMENT_REG_LS) 74611308Santhony.gutierrez@amd.com && !tc->readMiscRegNoEffect(MISCREG_SEG_SEL(seg))) { 74711308Santhony.gutierrez@amd.com return std::make_shared<GeneralProtection>(0); 74811308Santhony.gutierrez@amd.com } 74911308Santhony.gutierrez@amd.com 75011308Santhony.gutierrez@amd.com bool expandDown = false; 75111308Santhony.gutierrez@amd.com SegAttr attr = tc->readMiscRegNoEffect(MISCREG_SEG_ATTR(seg)); 75211308Santhony.gutierrez@amd.com 75311308Santhony.gutierrez@amd.com if (seg >= SEGMENT_REG_ES && seg <= SEGMENT_REG_HS) { 75411308Santhony.gutierrez@amd.com if (!attr.writable && (mode == BaseTLB::Write || 75511308Santhony.gutierrez@amd.com storeCheck)) 75611308Santhony.gutierrez@amd.com return std::make_shared<GeneralProtection>(0); 75711308Santhony.gutierrez@amd.com 75811308Santhony.gutierrez@amd.com if (!attr.readable && mode == BaseTLB::Read) 75911308Santhony.gutierrez@amd.com return std::make_shared<GeneralProtection>(0); 76011308Santhony.gutierrez@amd.com 76111308Santhony.gutierrez@amd.com expandDown = attr.expandDown; 76211308Santhony.gutierrez@amd.com 76311308Santhony.gutierrez@amd.com } 76411308Santhony.gutierrez@amd.com 76511308Santhony.gutierrez@amd.com Addr base = tc->readMiscRegNoEffect(MISCREG_SEG_BASE(seg)); 76611308Santhony.gutierrez@amd.com Addr limit = tc->readMiscRegNoEffect(MISCREG_SEG_LIMIT(seg)); 76711308Santhony.gutierrez@amd.com // This assumes we're not in 64 bit mode. If we were, the 76811308Santhony.gutierrez@amd.com // default address size is 64 bits, overridable to 32. 76911308Santhony.gutierrez@amd.com int size = 32; 77011308Santhony.gutierrez@amd.com bool sizeOverride = (flags & (AddrSizeFlagBit << FlagShift)); 77111308Santhony.gutierrez@amd.com SegAttr csAttr = tc->readMiscRegNoEffect(MISCREG_CS_ATTR); 77211308Santhony.gutierrez@amd.com 77311308Santhony.gutierrez@amd.com if ((csAttr.defaultSize && sizeOverride) || 77411308Santhony.gutierrez@amd.com (!csAttr.defaultSize && !sizeOverride)) { 77511308Santhony.gutierrez@amd.com size = 16; 77611308Santhony.gutierrez@amd.com } 77711308Santhony.gutierrez@amd.com 77811308Santhony.gutierrez@amd.com Addr offset = bits(vaddr - base, size - 1, 0); 77911308Santhony.gutierrez@amd.com Addr endOffset = offset + req->getSize() - 1; 78011308Santhony.gutierrez@amd.com 78111308Santhony.gutierrez@amd.com if (expandDown) { 78211308Santhony.gutierrez@amd.com DPRINTF(GPUTLB, "Checking an expand down segment.\n"); 78311308Santhony.gutierrez@amd.com warn_once("Expand down segments are untested.\n"); 78411308Santhony.gutierrez@amd.com 78511308Santhony.gutierrez@amd.com if (offset <= limit || endOffset <= limit) 78611308Santhony.gutierrez@amd.com return std::make_shared<GeneralProtection>(0); 78711308Santhony.gutierrez@amd.com } else { 78811308Santhony.gutierrez@amd.com if (offset > limit || endOffset > limit) 78911308Santhony.gutierrez@amd.com return std::make_shared<GeneralProtection>(0); 79011308Santhony.gutierrez@amd.com } 79111308Santhony.gutierrez@amd.com } 79211308Santhony.gutierrez@amd.com 79311308Santhony.gutierrez@amd.com // If paging is enabled, do the translation. 79411308Santhony.gutierrez@amd.com if (m5Reg.paging) { 79511308Santhony.gutierrez@amd.com DPRINTF(GPUTLB, "Paging enabled.\n"); 79611308Santhony.gutierrez@amd.com // The vaddr already has the segment base applied. 79712717Sbrandon.potter@amd.com TlbEntry *entry = lookup(vaddr); 79811308Santhony.gutierrez@amd.com localNumTLBAccesses++; 79911308Santhony.gutierrez@amd.com 80011308Santhony.gutierrez@amd.com if (!entry) { 80111308Santhony.gutierrez@amd.com localNumTLBMisses++; 80211308Santhony.gutierrez@amd.com if (timing) { 80311308Santhony.gutierrez@amd.com latency = missLatency1; 80411308Santhony.gutierrez@amd.com } 80511308Santhony.gutierrez@amd.com 80611308Santhony.gutierrez@amd.com if (FullSystem) { 80711308Santhony.gutierrez@amd.com fatal("GpuTLB doesn't support full-system mode\n"); 80811308Santhony.gutierrez@amd.com } else { 80911308Santhony.gutierrez@amd.com DPRINTF(GPUTLB, "Handling a TLB miss for address %#x " 81011308Santhony.gutierrez@amd.com "at pc %#x.\n", vaddr, tc->instAddr()); 81111308Santhony.gutierrez@amd.com 81211308Santhony.gutierrez@amd.com Process *p = tc->getProcessPtr(); 81312461Sgabeblack@google.com const EmulationPageTable::Entry *pte = 81412461Sgabeblack@google.com p->pTable->lookup(vaddr); 81511308Santhony.gutierrez@amd.com 81612461Sgabeblack@google.com if (!pte && mode != BaseTLB::Execute) { 81711308Santhony.gutierrez@amd.com // penalize a "page fault" more 81812455Sgabeblack@google.com if (timing) 81911308Santhony.gutierrez@amd.com latency += missLatency2; 82011308Santhony.gutierrez@amd.com 82111308Santhony.gutierrez@amd.com if (p->fixupStackFault(vaddr)) 82212461Sgabeblack@google.com pte = p->pTable->lookup(vaddr); 82311308Santhony.gutierrez@amd.com } 82411308Santhony.gutierrez@amd.com 82512461Sgabeblack@google.com if (!pte) { 82611308Santhony.gutierrez@amd.com return std::make_shared<PageFault>(vaddr, true, 82711308Santhony.gutierrez@amd.com mode, true, 82811308Santhony.gutierrez@amd.com false); 82911308Santhony.gutierrez@amd.com } else { 83011308Santhony.gutierrez@amd.com Addr alignedVaddr = p->pTable->pageAlign(vaddr); 83111308Santhony.gutierrez@amd.com 83211308Santhony.gutierrez@amd.com DPRINTF(GPUTLB, "Mapping %#x to %#x\n", 83312461Sgabeblack@google.com alignedVaddr, pte->paddr); 83411308Santhony.gutierrez@amd.com 83512717Sbrandon.potter@amd.com TlbEntry gpuEntry(p->pid(), alignedVaddr, 83612717Sbrandon.potter@amd.com pte->paddr, false, false); 83712455Sgabeblack@google.com entry = insert(alignedVaddr, gpuEntry); 83811308Santhony.gutierrez@amd.com } 83911308Santhony.gutierrez@amd.com 84011308Santhony.gutierrez@amd.com DPRINTF(GPUTLB, "Miss was serviced.\n"); 84111308Santhony.gutierrez@amd.com } 84211308Santhony.gutierrez@amd.com } else { 84311308Santhony.gutierrez@amd.com localNumTLBHits++; 84411308Santhony.gutierrez@amd.com 84511308Santhony.gutierrez@amd.com if (timing) { 84611308Santhony.gutierrez@amd.com latency = hitLatency; 84711308Santhony.gutierrez@amd.com } 84811308Santhony.gutierrez@amd.com } 84911308Santhony.gutierrez@amd.com 85011308Santhony.gutierrez@amd.com // Do paging protection checks. 85111308Santhony.gutierrez@amd.com bool inUser = (m5Reg.cpl == 3 && 85211308Santhony.gutierrez@amd.com !(flags & (CPL0FlagBit << FlagShift))); 85311308Santhony.gutierrez@amd.com 85411308Santhony.gutierrez@amd.com CR0 cr0 = tc->readMiscRegNoEffect(MISCREG_CR0); 85511308Santhony.gutierrez@amd.com bool badWrite = (!entry->writable && (inUser || cr0.wp)); 85611308Santhony.gutierrez@amd.com 85711308Santhony.gutierrez@amd.com if ((inUser && !entry->user) || (mode == BaseTLB::Write && 85811308Santhony.gutierrez@amd.com badWrite)) { 85911308Santhony.gutierrez@amd.com // The page must have been present to get into the TLB in 86011308Santhony.gutierrez@amd.com // the first place. We'll assume the reserved bits are 86111308Santhony.gutierrez@amd.com // fine even though we're not checking them. 86211308Santhony.gutierrez@amd.com return std::make_shared<PageFault>(vaddr, true, mode, 86311308Santhony.gutierrez@amd.com inUser, false); 86411308Santhony.gutierrez@amd.com } 86511308Santhony.gutierrez@amd.com 86611308Santhony.gutierrez@amd.com if (storeCheck && badWrite) { 86711308Santhony.gutierrez@amd.com // This would fault if this were a write, so return a page 86811308Santhony.gutierrez@amd.com // fault that reflects that happening. 86911308Santhony.gutierrez@amd.com return std::make_shared<PageFault>(vaddr, true, 87011308Santhony.gutierrez@amd.com BaseTLB::Write, 87111308Santhony.gutierrez@amd.com inUser, false); 87211308Santhony.gutierrez@amd.com } 87311308Santhony.gutierrez@amd.com 87411308Santhony.gutierrez@amd.com 87511308Santhony.gutierrez@amd.com DPRINTF(GPUTLB, "Entry found with paddr %#x, doing protection " 87611308Santhony.gutierrez@amd.com "checks.\n", entry->paddr); 87711308Santhony.gutierrez@amd.com 87811308Santhony.gutierrez@amd.com int page_size = entry->size(); 87911308Santhony.gutierrez@amd.com Addr paddr = entry->paddr | (vaddr & (page_size - 1)); 88011308Santhony.gutierrez@amd.com DPRINTF(GPUTLB, "Translated %#x -> %#x.\n", vaddr, paddr); 88111308Santhony.gutierrez@amd.com req->setPaddr(paddr); 88211308Santhony.gutierrez@amd.com 88311308Santhony.gutierrez@amd.com if (entry->uncacheable) 88411308Santhony.gutierrez@amd.com req->setFlags(Request::UNCACHEABLE); 88511308Santhony.gutierrez@amd.com } else { 88611308Santhony.gutierrez@amd.com //Use the address which already has segmentation applied. 88711308Santhony.gutierrez@amd.com DPRINTF(GPUTLB, "Paging disabled.\n"); 88811308Santhony.gutierrez@amd.com DPRINTF(GPUTLB, "Translated %#x -> %#x.\n", vaddr, vaddr); 88911308Santhony.gutierrez@amd.com req->setPaddr(vaddr); 89011308Santhony.gutierrez@amd.com } 89111308Santhony.gutierrez@amd.com } else { 89211308Santhony.gutierrez@amd.com // Real mode 89311308Santhony.gutierrez@amd.com DPRINTF(GPUTLB, "In real mode.\n"); 89411308Santhony.gutierrez@amd.com DPRINTF(GPUTLB, "Translated %#x -> %#x.\n", vaddr, vaddr); 89511308Santhony.gutierrez@amd.com req->setPaddr(vaddr); 89611308Santhony.gutierrez@amd.com } 89711308Santhony.gutierrez@amd.com 89811308Santhony.gutierrez@amd.com // Check for an access to the local APIC 89911308Santhony.gutierrez@amd.com if (FullSystem) { 90011308Santhony.gutierrez@amd.com LocalApicBase localApicBase = 90111308Santhony.gutierrez@amd.com tc->readMiscRegNoEffect(MISCREG_APIC_BASE); 90211308Santhony.gutierrez@amd.com 90311308Santhony.gutierrez@amd.com Addr baseAddr = localApicBase.base * PageBytes; 90411308Santhony.gutierrez@amd.com Addr paddr = req->getPaddr(); 90511308Santhony.gutierrez@amd.com 90611308Santhony.gutierrez@amd.com if (baseAddr <= paddr && baseAddr + PageBytes > paddr) { 90711308Santhony.gutierrez@amd.com // Force the access to be uncacheable. 90811308Santhony.gutierrez@amd.com req->setFlags(Request::UNCACHEABLE); 90911308Santhony.gutierrez@amd.com req->setPaddr(x86LocalAPICAddress(tc->contextId(), 91011308Santhony.gutierrez@amd.com paddr - baseAddr)); 91111308Santhony.gutierrez@amd.com } 91211308Santhony.gutierrez@amd.com } 91311308Santhony.gutierrez@amd.com 91411308Santhony.gutierrez@amd.com return NoFault; 91511308Santhony.gutierrez@amd.com }; 91611308Santhony.gutierrez@amd.com 91711308Santhony.gutierrez@amd.com Fault 91812749Sgiacomo.travaglini@arm.com GpuTLB::translateAtomic(const RequestPtr &req, ThreadContext *tc, 91912749Sgiacomo.travaglini@arm.com Mode mode, int &latency) 92011308Santhony.gutierrez@amd.com { 92111308Santhony.gutierrez@amd.com bool delayedResponse; 92211308Santhony.gutierrez@amd.com 92311308Santhony.gutierrez@amd.com return GpuTLB::translate(req, tc, nullptr, mode, delayedResponse, false, 92411308Santhony.gutierrez@amd.com latency); 92511308Santhony.gutierrez@amd.com } 92611308Santhony.gutierrez@amd.com 92711308Santhony.gutierrez@amd.com void 92812749Sgiacomo.travaglini@arm.com GpuTLB::translateTiming(const RequestPtr &req, ThreadContext *tc, 92911308Santhony.gutierrez@amd.com Translation *translation, Mode mode, int &latency) 93011308Santhony.gutierrez@amd.com { 93111308Santhony.gutierrez@amd.com bool delayedResponse; 93211308Santhony.gutierrez@amd.com assert(translation); 93311308Santhony.gutierrez@amd.com 93411308Santhony.gutierrez@amd.com Fault fault = GpuTLB::translate(req, tc, translation, mode, 93511308Santhony.gutierrez@amd.com delayedResponse, true, latency); 93611308Santhony.gutierrez@amd.com 93711308Santhony.gutierrez@amd.com if (!delayedResponse) 93811308Santhony.gutierrez@amd.com translation->finish(fault, req, tc, mode); 93911308Santhony.gutierrez@amd.com } 94011308Santhony.gutierrez@amd.com 94111308Santhony.gutierrez@amd.com Walker* 94211308Santhony.gutierrez@amd.com GpuTLB::getWalker() 94311308Santhony.gutierrez@amd.com { 94411308Santhony.gutierrez@amd.com return walker; 94511308Santhony.gutierrez@amd.com } 94611308Santhony.gutierrez@amd.com 94711308Santhony.gutierrez@amd.com 94811308Santhony.gutierrez@amd.com void 94911308Santhony.gutierrez@amd.com GpuTLB::serialize(CheckpointOut &cp) const 95011308Santhony.gutierrez@amd.com { 95111308Santhony.gutierrez@amd.com } 95211308Santhony.gutierrez@amd.com 95311308Santhony.gutierrez@amd.com void 95411308Santhony.gutierrez@amd.com GpuTLB::unserialize(CheckpointIn &cp) 95511308Santhony.gutierrez@amd.com { 95611308Santhony.gutierrez@amd.com } 95711308Santhony.gutierrez@amd.com 95811308Santhony.gutierrez@amd.com void 95911308Santhony.gutierrez@amd.com GpuTLB::regStats() 96011308Santhony.gutierrez@amd.com { 96111523Sdavid.guillen@arm.com MemObject::regStats(); 96211523Sdavid.guillen@arm.com 96311308Santhony.gutierrez@amd.com localNumTLBAccesses 96411308Santhony.gutierrez@amd.com .name(name() + ".local_TLB_accesses") 96511308Santhony.gutierrez@amd.com .desc("Number of TLB accesses") 96611308Santhony.gutierrez@amd.com ; 96711308Santhony.gutierrez@amd.com 96811308Santhony.gutierrez@amd.com localNumTLBHits 96911308Santhony.gutierrez@amd.com .name(name() + ".local_TLB_hits") 97011308Santhony.gutierrez@amd.com .desc("Number of TLB hits") 97111308Santhony.gutierrez@amd.com ; 97211308Santhony.gutierrez@amd.com 97311308Santhony.gutierrez@amd.com localNumTLBMisses 97411308Santhony.gutierrez@amd.com .name(name() + ".local_TLB_misses") 97511308Santhony.gutierrez@amd.com .desc("Number of TLB misses") 97611308Santhony.gutierrez@amd.com ; 97711308Santhony.gutierrez@amd.com 97811308Santhony.gutierrez@amd.com localTLBMissRate 97911308Santhony.gutierrez@amd.com .name(name() + ".local_TLB_miss_rate") 98011308Santhony.gutierrez@amd.com .desc("TLB miss rate") 98111308Santhony.gutierrez@amd.com ; 98211308Santhony.gutierrez@amd.com 98311308Santhony.gutierrez@amd.com accessCycles 98411308Santhony.gutierrez@amd.com .name(name() + ".access_cycles") 98511308Santhony.gutierrez@amd.com .desc("Cycles spent accessing this TLB level") 98611308Santhony.gutierrez@amd.com ; 98711308Santhony.gutierrez@amd.com 98811308Santhony.gutierrez@amd.com pageTableCycles 98911308Santhony.gutierrez@amd.com .name(name() + ".page_table_cycles") 99011308Santhony.gutierrez@amd.com .desc("Cycles spent accessing the page table") 99111308Santhony.gutierrez@amd.com ; 99211308Santhony.gutierrez@amd.com 99311308Santhony.gutierrez@amd.com localTLBMissRate = 100 * localNumTLBMisses / localNumTLBAccesses; 99411308Santhony.gutierrez@amd.com 99511308Santhony.gutierrez@amd.com numUniquePages 99611308Santhony.gutierrez@amd.com .name(name() + ".unique_pages") 99711308Santhony.gutierrez@amd.com .desc("Number of unique pages touched") 99811308Santhony.gutierrez@amd.com ; 99911308Santhony.gutierrez@amd.com 100011308Santhony.gutierrez@amd.com localCycles 100111308Santhony.gutierrez@amd.com .name(name() + ".local_cycles") 100211308Santhony.gutierrez@amd.com .desc("Number of cycles spent in queue for all incoming reqs") 100311308Santhony.gutierrez@amd.com ; 100411308Santhony.gutierrez@amd.com 100511308Santhony.gutierrez@amd.com localLatency 100611308Santhony.gutierrez@amd.com .name(name() + ".local_latency") 100711308Santhony.gutierrez@amd.com .desc("Avg. latency over incoming coalesced reqs") 100811308Santhony.gutierrez@amd.com ; 100911308Santhony.gutierrez@amd.com 101011308Santhony.gutierrez@amd.com localLatency = localCycles / localNumTLBAccesses; 101111308Santhony.gutierrez@amd.com 101211308Santhony.gutierrez@amd.com globalNumTLBAccesses 101311308Santhony.gutierrez@amd.com .name(name() + ".global_TLB_accesses") 101411308Santhony.gutierrez@amd.com .desc("Number of TLB accesses") 101511308Santhony.gutierrez@amd.com ; 101611308Santhony.gutierrez@amd.com 101711308Santhony.gutierrez@amd.com globalNumTLBHits 101811308Santhony.gutierrez@amd.com .name(name() + ".global_TLB_hits") 101911308Santhony.gutierrez@amd.com .desc("Number of TLB hits") 102011308Santhony.gutierrez@amd.com ; 102111308Santhony.gutierrez@amd.com 102211308Santhony.gutierrez@amd.com globalNumTLBMisses 102311308Santhony.gutierrez@amd.com .name(name() + ".global_TLB_misses") 102411308Santhony.gutierrez@amd.com .desc("Number of TLB misses") 102511308Santhony.gutierrez@amd.com ; 102611308Santhony.gutierrez@amd.com 102711308Santhony.gutierrez@amd.com globalTLBMissRate 102811308Santhony.gutierrez@amd.com .name(name() + ".global_TLB_miss_rate") 102911308Santhony.gutierrez@amd.com .desc("TLB miss rate") 103011308Santhony.gutierrez@amd.com ; 103111308Santhony.gutierrez@amd.com 103211308Santhony.gutierrez@amd.com globalTLBMissRate = 100 * globalNumTLBMisses / globalNumTLBAccesses; 103311308Santhony.gutierrez@amd.com 103411308Santhony.gutierrez@amd.com avgReuseDistance 103511308Santhony.gutierrez@amd.com .name(name() + ".avg_reuse_distance") 103611308Santhony.gutierrez@amd.com .desc("avg. reuse distance over all pages (in ticks)") 103711308Santhony.gutierrez@amd.com ; 103811308Santhony.gutierrez@amd.com 103911308Santhony.gutierrez@amd.com } 104011308Santhony.gutierrez@amd.com 104111308Santhony.gutierrez@amd.com /** 104211308Santhony.gutierrez@amd.com * Do the TLB lookup for this coalesced request and schedule 104311308Santhony.gutierrez@amd.com * another event <TLB access latency> cycles later. 104411308Santhony.gutierrez@amd.com */ 104511308Santhony.gutierrez@amd.com 104611308Santhony.gutierrez@amd.com void 104711308Santhony.gutierrez@amd.com GpuTLB::issueTLBLookup(PacketPtr pkt) 104811308Santhony.gutierrez@amd.com { 104911308Santhony.gutierrez@amd.com assert(pkt); 105011308Santhony.gutierrez@amd.com assert(pkt->senderState); 105111308Santhony.gutierrez@amd.com 105211308Santhony.gutierrez@amd.com Addr virt_page_addr = roundDown(pkt->req->getVaddr(), 105311308Santhony.gutierrez@amd.com TheISA::PageBytes); 105411308Santhony.gutierrez@amd.com 105511308Santhony.gutierrez@amd.com TranslationState *sender_state = 105611308Santhony.gutierrez@amd.com safe_cast<TranslationState*>(pkt->senderState); 105711308Santhony.gutierrez@amd.com 105811308Santhony.gutierrez@amd.com bool update_stats = !sender_state->prefetch; 105911308Santhony.gutierrez@amd.com ThreadContext * tmp_tc = sender_state->tc; 106011308Santhony.gutierrez@amd.com 106111308Santhony.gutierrez@amd.com DPRINTF(GPUTLB, "Translation req. for virt. page addr %#x\n", 106211308Santhony.gutierrez@amd.com virt_page_addr); 106311308Santhony.gutierrez@amd.com 106411308Santhony.gutierrez@amd.com int req_cnt = sender_state->reqCnt.back(); 106511308Santhony.gutierrez@amd.com 106611308Santhony.gutierrez@amd.com if (update_stats) { 106711308Santhony.gutierrez@amd.com accessCycles -= (curTick() * req_cnt); 106811308Santhony.gutierrez@amd.com localCycles -= curTick(); 106911308Santhony.gutierrez@amd.com updatePageFootprint(virt_page_addr); 107011308Santhony.gutierrez@amd.com globalNumTLBAccesses += req_cnt; 107111308Santhony.gutierrez@amd.com } 107211308Santhony.gutierrez@amd.com 107311308Santhony.gutierrez@amd.com tlbOutcome lookup_outcome = TLB_MISS; 107412749Sgiacomo.travaglini@arm.com const RequestPtr &tmp_req = pkt->req; 107511308Santhony.gutierrez@amd.com 107611308Santhony.gutierrez@amd.com // Access the TLB and figure out if it's a hit or a miss. 107711308Santhony.gutierrez@amd.com bool success = tlbLookup(tmp_req, tmp_tc, update_stats); 107811308Santhony.gutierrez@amd.com 107911308Santhony.gutierrez@amd.com if (success) { 108011308Santhony.gutierrez@amd.com lookup_outcome = TLB_HIT; 108111308Santhony.gutierrez@amd.com // Put the entry in SenderState 108212717Sbrandon.potter@amd.com TlbEntry *entry = lookup(tmp_req->getVaddr(), false); 108311308Santhony.gutierrez@amd.com assert(entry); 108411308Santhony.gutierrez@amd.com 108512717Sbrandon.potter@amd.com auto p = sender_state->tc->getProcessPtr(); 108611308Santhony.gutierrez@amd.com sender_state->tlbEntry = 108712717Sbrandon.potter@amd.com new TlbEntry(p->pid(), entry->vaddr, entry->paddr, 108812717Sbrandon.potter@amd.com false, false); 108911308Santhony.gutierrez@amd.com 109011308Santhony.gutierrez@amd.com if (update_stats) { 109111308Santhony.gutierrez@amd.com // the reqCnt has an entry per level, so its size tells us 109211308Santhony.gutierrez@amd.com // which level we are in 109311308Santhony.gutierrez@amd.com sender_state->hitLevel = sender_state->reqCnt.size(); 109411308Santhony.gutierrez@amd.com globalNumTLBHits += req_cnt; 109511308Santhony.gutierrez@amd.com } 109611308Santhony.gutierrez@amd.com } else { 109711308Santhony.gutierrez@amd.com if (update_stats) 109811308Santhony.gutierrez@amd.com globalNumTLBMisses += req_cnt; 109911308Santhony.gutierrez@amd.com } 110011308Santhony.gutierrez@amd.com 110111308Santhony.gutierrez@amd.com /* 110211308Santhony.gutierrez@amd.com * We now know the TLB lookup outcome (if it's a hit or a miss), as well 110311308Santhony.gutierrez@amd.com * as the TLB access latency. 110411308Santhony.gutierrez@amd.com * 110511308Santhony.gutierrez@amd.com * We create and schedule a new TLBEvent which will help us take the 110611308Santhony.gutierrez@amd.com * appropriate actions (e.g., update TLB on a hit, send request to lower 110711308Santhony.gutierrez@amd.com * level TLB on a miss, or start a page walk if this was the last-level 110811308Santhony.gutierrez@amd.com * TLB) 110911308Santhony.gutierrez@amd.com */ 111011308Santhony.gutierrez@amd.com TLBEvent *tlb_event = 111111308Santhony.gutierrez@amd.com new TLBEvent(this, virt_page_addr, lookup_outcome, pkt); 111211308Santhony.gutierrez@amd.com 111311308Santhony.gutierrez@amd.com if (translationReturnEvent.count(virt_page_addr)) { 111411308Santhony.gutierrez@amd.com panic("Virtual Page Address %#x already has a return event\n", 111511308Santhony.gutierrez@amd.com virt_page_addr); 111611308Santhony.gutierrez@amd.com } 111711308Santhony.gutierrez@amd.com 111811308Santhony.gutierrez@amd.com translationReturnEvent[virt_page_addr] = tlb_event; 111911308Santhony.gutierrez@amd.com assert(tlb_event); 112011308Santhony.gutierrez@amd.com 112111308Santhony.gutierrez@amd.com DPRINTF(GPUTLB, "schedule translationReturnEvent @ curTick %d\n", 112211308Santhony.gutierrez@amd.com curTick() + this->ticks(hitLatency)); 112311308Santhony.gutierrez@amd.com 112411308Santhony.gutierrez@amd.com schedule(tlb_event, curTick() + this->ticks(hitLatency)); 112511308Santhony.gutierrez@amd.com } 112611308Santhony.gutierrez@amd.com 112711308Santhony.gutierrez@amd.com GpuTLB::TLBEvent::TLBEvent(GpuTLB* _tlb, Addr _addr, tlbOutcome tlb_outcome, 112811308Santhony.gutierrez@amd.com PacketPtr _pkt) 112911308Santhony.gutierrez@amd.com : Event(CPU_Tick_Pri), tlb(_tlb), virtPageAddr(_addr), 113011308Santhony.gutierrez@amd.com outcome(tlb_outcome), pkt(_pkt) 113111308Santhony.gutierrez@amd.com { 113211308Santhony.gutierrez@amd.com } 113311308Santhony.gutierrez@amd.com 113411308Santhony.gutierrez@amd.com /** 113511308Santhony.gutierrez@amd.com * Do Paging protection checks. If we encounter a page fault, then 113611308Santhony.gutierrez@amd.com * an assertion is fired. 113711308Santhony.gutierrez@amd.com */ 113811308Santhony.gutierrez@amd.com void 113911308Santhony.gutierrez@amd.com GpuTLB::pagingProtectionChecks(ThreadContext *tc, PacketPtr pkt, 114012717Sbrandon.potter@amd.com TlbEntry * tlb_entry, Mode mode) 114111308Santhony.gutierrez@amd.com { 114211308Santhony.gutierrez@amd.com HandyM5Reg m5Reg = tc->readMiscRegNoEffect(MISCREG_M5_REG); 114311308Santhony.gutierrez@amd.com uint32_t flags = pkt->req->getFlags(); 114411308Santhony.gutierrez@amd.com bool storeCheck = flags & (StoreCheck << FlagShift); 114511308Santhony.gutierrez@amd.com 114611308Santhony.gutierrez@amd.com // Do paging protection checks. 114711308Santhony.gutierrez@amd.com bool inUser = (m5Reg.cpl == 3 && !(flags & (CPL0FlagBit << FlagShift))); 114811308Santhony.gutierrez@amd.com CR0 cr0 = tc->readMiscRegNoEffect(MISCREG_CR0); 114911308Santhony.gutierrez@amd.com 115011308Santhony.gutierrez@amd.com bool badWrite = (!tlb_entry->writable && (inUser || cr0.wp)); 115111308Santhony.gutierrez@amd.com 115211308Santhony.gutierrez@amd.com if ((inUser && !tlb_entry->user) || 115311308Santhony.gutierrez@amd.com (mode == BaseTLB::Write && badWrite)) { 115413449Sgabeblack@google.com // The page must have been present to get into the TLB in 115513449Sgabeblack@google.com // the first place. We'll assume the reserved bits are 115613449Sgabeblack@google.com // fine even though we're not checking them. 115713449Sgabeblack@google.com panic("Page fault detected"); 115811308Santhony.gutierrez@amd.com } 115911308Santhony.gutierrez@amd.com 116011308Santhony.gutierrez@amd.com if (storeCheck && badWrite) { 116113449Sgabeblack@google.com // This would fault if this were a write, so return a page 116213449Sgabeblack@google.com // fault that reflects that happening. 116313449Sgabeblack@google.com panic("Page fault detected"); 116411308Santhony.gutierrez@amd.com } 116511308Santhony.gutierrez@amd.com } 116611308Santhony.gutierrez@amd.com 116711308Santhony.gutierrez@amd.com /** 116811308Santhony.gutierrez@amd.com * handleTranslationReturn is called on a TLB hit, 116911308Santhony.gutierrez@amd.com * when a TLB miss returns or when a page fault returns. 117011308Santhony.gutierrez@amd.com * The latter calls handelHit with TLB miss as tlbOutcome. 117111308Santhony.gutierrez@amd.com */ 117211308Santhony.gutierrez@amd.com void 117311308Santhony.gutierrez@amd.com GpuTLB::handleTranslationReturn(Addr virt_page_addr, tlbOutcome tlb_outcome, 117411308Santhony.gutierrez@amd.com PacketPtr pkt) 117511308Santhony.gutierrez@amd.com { 117611308Santhony.gutierrez@amd.com 117711308Santhony.gutierrez@amd.com assert(pkt); 117811308Santhony.gutierrez@amd.com Addr vaddr = pkt->req->getVaddr(); 117911308Santhony.gutierrez@amd.com 118011308Santhony.gutierrez@amd.com TranslationState *sender_state = 118111308Santhony.gutierrez@amd.com safe_cast<TranslationState*>(pkt->senderState); 118211308Santhony.gutierrez@amd.com 118311308Santhony.gutierrez@amd.com ThreadContext *tc = sender_state->tc; 118411308Santhony.gutierrez@amd.com Mode mode = sender_state->tlbMode; 118511308Santhony.gutierrez@amd.com 118612717Sbrandon.potter@amd.com TlbEntry *local_entry, *new_entry; 118711308Santhony.gutierrez@amd.com 118811308Santhony.gutierrez@amd.com if (tlb_outcome == TLB_HIT) { 118911308Santhony.gutierrez@amd.com DPRINTF(GPUTLB, "Translation Done - TLB Hit for addr %#x\n", vaddr); 119011308Santhony.gutierrez@amd.com local_entry = sender_state->tlbEntry; 119111308Santhony.gutierrez@amd.com } else { 119211308Santhony.gutierrez@amd.com DPRINTF(GPUTLB, "Translation Done - TLB Miss for addr %#x\n", 119311308Santhony.gutierrez@amd.com vaddr); 119411308Santhony.gutierrez@amd.com 119511308Santhony.gutierrez@amd.com // We are returning either from a page walk or from a hit at a lower 119611308Santhony.gutierrez@amd.com // TLB level. The senderState should be "carrying" a pointer to the 119711308Santhony.gutierrez@amd.com // correct TLBEntry. 119811308Santhony.gutierrez@amd.com new_entry = sender_state->tlbEntry; 119911308Santhony.gutierrez@amd.com assert(new_entry); 120011308Santhony.gutierrez@amd.com local_entry = new_entry; 120111308Santhony.gutierrez@amd.com 120211308Santhony.gutierrez@amd.com if (allocationPolicy) { 120311308Santhony.gutierrez@amd.com DPRINTF(GPUTLB, "allocating entry w/ addr %#x\n", 120411308Santhony.gutierrez@amd.com virt_page_addr); 120511308Santhony.gutierrez@amd.com 120611308Santhony.gutierrez@amd.com local_entry = insert(virt_page_addr, *new_entry); 120711308Santhony.gutierrez@amd.com } 120811308Santhony.gutierrez@amd.com 120911308Santhony.gutierrez@amd.com assert(local_entry); 121011308Santhony.gutierrez@amd.com } 121111308Santhony.gutierrez@amd.com 121211308Santhony.gutierrez@amd.com /** 121311308Santhony.gutierrez@amd.com * At this point the packet carries an up-to-date tlbEntry pointer 121411308Santhony.gutierrez@amd.com * in its senderState. 121511308Santhony.gutierrez@amd.com * Next step is to do the paging protection checks. 121611308Santhony.gutierrez@amd.com */ 121711308Santhony.gutierrez@amd.com DPRINTF(GPUTLB, "Entry found with vaddr %#x, doing protection checks " 121811308Santhony.gutierrez@amd.com "while paddr was %#x.\n", local_entry->vaddr, 121911308Santhony.gutierrez@amd.com local_entry->paddr); 122011308Santhony.gutierrez@amd.com 122111308Santhony.gutierrez@amd.com pagingProtectionChecks(tc, pkt, local_entry, mode); 122211308Santhony.gutierrez@amd.com int page_size = local_entry->size(); 122311308Santhony.gutierrez@amd.com Addr paddr = local_entry->paddr | (vaddr & (page_size - 1)); 122411308Santhony.gutierrez@amd.com DPRINTF(GPUTLB, "Translated %#x -> %#x.\n", vaddr, paddr); 122511308Santhony.gutierrez@amd.com 122611308Santhony.gutierrez@amd.com // Since this packet will be sent through the cpu side slave port, 122711308Santhony.gutierrez@amd.com // it must be converted to a response pkt if it is not one already 122811308Santhony.gutierrez@amd.com if (pkt->isRequest()) { 122911308Santhony.gutierrez@amd.com pkt->makeTimingResponse(); 123011308Santhony.gutierrez@amd.com } 123111308Santhony.gutierrez@amd.com 123211308Santhony.gutierrez@amd.com pkt->req->setPaddr(paddr); 123311308Santhony.gutierrez@amd.com 123411308Santhony.gutierrez@amd.com if (local_entry->uncacheable) { 123511308Santhony.gutierrez@amd.com pkt->req->setFlags(Request::UNCACHEABLE); 123611308Santhony.gutierrez@amd.com } 123711308Santhony.gutierrez@amd.com 123811308Santhony.gutierrez@amd.com //send packet back to coalescer 123911308Santhony.gutierrez@amd.com cpuSidePort[0]->sendTimingResp(pkt); 124011308Santhony.gutierrez@amd.com //schedule cleanup event 124111308Santhony.gutierrez@amd.com cleanupQueue.push(virt_page_addr); 124211308Santhony.gutierrez@amd.com 124311308Santhony.gutierrez@amd.com // schedule this only once per cycle. 124411308Santhony.gutierrez@amd.com // The check is required because we might have multiple translations 124511308Santhony.gutierrez@amd.com // returning the same cycle 124611308Santhony.gutierrez@amd.com // this is a maximum priority event and must be on the same cycle 124711308Santhony.gutierrez@amd.com // as the cleanup event in TLBCoalescer to avoid a race with 124811308Santhony.gutierrez@amd.com // IssueProbeEvent caused by TLBCoalescer::MemSidePort::recvReqRetry 124911308Santhony.gutierrez@amd.com if (!cleanupEvent.scheduled()) 125011308Santhony.gutierrez@amd.com schedule(cleanupEvent, curTick()); 125111308Santhony.gutierrez@amd.com } 125211308Santhony.gutierrez@amd.com 125311308Santhony.gutierrez@amd.com /** 125411308Santhony.gutierrez@amd.com * Here we take the appropriate actions based on the result of the 125511308Santhony.gutierrez@amd.com * TLB lookup. 125611308Santhony.gutierrez@amd.com */ 125711308Santhony.gutierrez@amd.com void 125811308Santhony.gutierrez@amd.com GpuTLB::translationReturn(Addr virtPageAddr, tlbOutcome outcome, 125911308Santhony.gutierrez@amd.com PacketPtr pkt) 126011308Santhony.gutierrez@amd.com { 126111308Santhony.gutierrez@amd.com DPRINTF(GPUTLB, "Triggered TLBEvent for addr %#x\n", virtPageAddr); 126211308Santhony.gutierrez@amd.com 126311308Santhony.gutierrez@amd.com assert(translationReturnEvent[virtPageAddr]); 126411308Santhony.gutierrez@amd.com assert(pkt); 126511308Santhony.gutierrez@amd.com 126611308Santhony.gutierrez@amd.com TranslationState *tmp_sender_state = 126711308Santhony.gutierrez@amd.com safe_cast<TranslationState*>(pkt->senderState); 126811308Santhony.gutierrez@amd.com 126911308Santhony.gutierrez@amd.com int req_cnt = tmp_sender_state->reqCnt.back(); 127011308Santhony.gutierrez@amd.com bool update_stats = !tmp_sender_state->prefetch; 127111308Santhony.gutierrez@amd.com 127211308Santhony.gutierrez@amd.com 127311308Santhony.gutierrez@amd.com if (outcome == TLB_HIT) { 127411308Santhony.gutierrez@amd.com handleTranslationReturn(virtPageAddr, TLB_HIT, pkt); 127511308Santhony.gutierrez@amd.com 127611308Santhony.gutierrez@amd.com if (update_stats) { 127711308Santhony.gutierrez@amd.com accessCycles += (req_cnt * curTick()); 127811308Santhony.gutierrez@amd.com localCycles += curTick(); 127911308Santhony.gutierrez@amd.com } 128011308Santhony.gutierrez@amd.com 128111308Santhony.gutierrez@amd.com } else if (outcome == TLB_MISS) { 128211308Santhony.gutierrez@amd.com 128311308Santhony.gutierrez@amd.com DPRINTF(GPUTLB, "This is a TLB miss\n"); 128411308Santhony.gutierrez@amd.com if (update_stats) { 128511308Santhony.gutierrez@amd.com accessCycles += (req_cnt*curTick()); 128611308Santhony.gutierrez@amd.com localCycles += curTick(); 128711308Santhony.gutierrez@amd.com } 128811308Santhony.gutierrez@amd.com 128911308Santhony.gutierrez@amd.com if (hasMemSidePort) { 129011308Santhony.gutierrez@amd.com // the one cyle added here represent the delay from when we get 129111308Santhony.gutierrez@amd.com // the reply back till when we propagate it to the coalescer 129211308Santhony.gutierrez@amd.com // above. 129311308Santhony.gutierrez@amd.com if (update_stats) { 129411308Santhony.gutierrez@amd.com accessCycles += (req_cnt * 1); 129511308Santhony.gutierrez@amd.com localCycles += 1; 129611308Santhony.gutierrez@amd.com } 129711308Santhony.gutierrez@amd.com 129811308Santhony.gutierrez@amd.com /** 129911308Santhony.gutierrez@amd.com * There is a TLB below. Send the coalesced request. 130011308Santhony.gutierrez@amd.com * We actually send the very first packet of all the 130111308Santhony.gutierrez@amd.com * pending packets for this virtual page address. 130211308Santhony.gutierrez@amd.com */ 130311308Santhony.gutierrez@amd.com if (!memSidePort[0]->sendTimingReq(pkt)) { 130411308Santhony.gutierrez@amd.com DPRINTF(GPUTLB, "Failed sending translation request to " 130511308Santhony.gutierrez@amd.com "lower level TLB for addr %#x\n", virtPageAddr); 130611308Santhony.gutierrez@amd.com 130711308Santhony.gutierrez@amd.com memSidePort[0]->retries.push_back(pkt); 130811308Santhony.gutierrez@amd.com } else { 130911308Santhony.gutierrez@amd.com DPRINTF(GPUTLB, "Sent translation request to lower level " 131011308Santhony.gutierrez@amd.com "TLB for addr %#x\n", virtPageAddr); 131111308Santhony.gutierrez@amd.com } 131211308Santhony.gutierrez@amd.com } else { 131311308Santhony.gutierrez@amd.com //this is the last level TLB. Start a page walk 131411308Santhony.gutierrez@amd.com DPRINTF(GPUTLB, "Last level TLB - start a page walk for " 131511308Santhony.gutierrez@amd.com "addr %#x\n", virtPageAddr); 131611308Santhony.gutierrez@amd.com 131711308Santhony.gutierrez@amd.com if (update_stats) 131811308Santhony.gutierrez@amd.com pageTableCycles -= (req_cnt*curTick()); 131911308Santhony.gutierrez@amd.com 132011308Santhony.gutierrez@amd.com TLBEvent *tlb_event = translationReturnEvent[virtPageAddr]; 132111308Santhony.gutierrez@amd.com assert(tlb_event); 132211308Santhony.gutierrez@amd.com tlb_event->updateOutcome(PAGE_WALK); 132311308Santhony.gutierrez@amd.com schedule(tlb_event, curTick() + ticks(missLatency2)); 132411308Santhony.gutierrez@amd.com } 132511308Santhony.gutierrez@amd.com } else if (outcome == PAGE_WALK) { 132611308Santhony.gutierrez@amd.com if (update_stats) 132711308Santhony.gutierrez@amd.com pageTableCycles += (req_cnt*curTick()); 132811308Santhony.gutierrez@amd.com 132911308Santhony.gutierrez@amd.com // Need to access the page table and update the TLB 133011308Santhony.gutierrez@amd.com DPRINTF(GPUTLB, "Doing a page walk for address %#x\n", 133111308Santhony.gutierrez@amd.com virtPageAddr); 133211308Santhony.gutierrez@amd.com 133311308Santhony.gutierrez@amd.com TranslationState *sender_state = 133411308Santhony.gutierrez@amd.com safe_cast<TranslationState*>(pkt->senderState); 133511308Santhony.gutierrez@amd.com 133611308Santhony.gutierrez@amd.com Process *p = sender_state->tc->getProcessPtr(); 133711308Santhony.gutierrez@amd.com Addr vaddr = pkt->req->getVaddr(); 133811308Santhony.gutierrez@amd.com #ifndef NDEBUG 133911308Santhony.gutierrez@amd.com Addr alignedVaddr = p->pTable->pageAlign(vaddr); 134011308Santhony.gutierrez@amd.com assert(alignedVaddr == virtPageAddr); 134111308Santhony.gutierrez@amd.com #endif 134212461Sgabeblack@google.com const EmulationPageTable::Entry *pte = p->pTable->lookup(vaddr); 134312461Sgabeblack@google.com if (!pte && sender_state->tlbMode != BaseTLB::Execute && 134412455Sgabeblack@google.com p->fixupStackFault(vaddr)) { 134512461Sgabeblack@google.com pte = p->pTable->lookup(vaddr); 134611308Santhony.gutierrez@amd.com } 134711308Santhony.gutierrez@amd.com 134812461Sgabeblack@google.com if (pte) { 134912455Sgabeblack@google.com DPRINTF(GPUTLB, "Mapping %#x to %#x\n", alignedVaddr, 135012461Sgabeblack@google.com pte->paddr); 135111308Santhony.gutierrez@amd.com 135212455Sgabeblack@google.com sender_state->tlbEntry = 135312717Sbrandon.potter@amd.com new TlbEntry(p->pid(), virtPageAddr, pte->paddr, false, 135412717Sbrandon.potter@amd.com false); 135512455Sgabeblack@google.com } else { 135612717Sbrandon.potter@amd.com sender_state->tlbEntry = nullptr; 135712455Sgabeblack@google.com } 135811308Santhony.gutierrez@amd.com 135911308Santhony.gutierrez@amd.com handleTranslationReturn(virtPageAddr, TLB_MISS, pkt); 136011308Santhony.gutierrez@amd.com } else if (outcome == MISS_RETURN) { 136111308Santhony.gutierrez@amd.com /** we add an extra cycle in the return path of the translation 136211308Santhony.gutierrez@amd.com * requests in between the various TLB levels. 136311308Santhony.gutierrez@amd.com */ 136411308Santhony.gutierrez@amd.com handleTranslationReturn(virtPageAddr, TLB_MISS, pkt); 136511308Santhony.gutierrez@amd.com } else { 136613449Sgabeblack@google.com panic("Unexpected TLB outcome %d", outcome); 136711308Santhony.gutierrez@amd.com } 136811308Santhony.gutierrez@amd.com } 136911308Santhony.gutierrez@amd.com 137011308Santhony.gutierrez@amd.com void 137111308Santhony.gutierrez@amd.com GpuTLB::TLBEvent::process() 137211308Santhony.gutierrez@amd.com { 137311308Santhony.gutierrez@amd.com tlb->translationReturn(virtPageAddr, outcome, pkt); 137411308Santhony.gutierrez@amd.com } 137511308Santhony.gutierrez@amd.com 137611308Santhony.gutierrez@amd.com const char* 137711308Santhony.gutierrez@amd.com GpuTLB::TLBEvent::description() const 137811308Santhony.gutierrez@amd.com { 137911308Santhony.gutierrez@amd.com return "trigger translationDoneEvent"; 138011308Santhony.gutierrez@amd.com } 138111308Santhony.gutierrez@amd.com 138211308Santhony.gutierrez@amd.com void 138311308Santhony.gutierrez@amd.com GpuTLB::TLBEvent::updateOutcome(tlbOutcome _outcome) 138411308Santhony.gutierrez@amd.com { 138511308Santhony.gutierrez@amd.com outcome = _outcome; 138611308Santhony.gutierrez@amd.com } 138711308Santhony.gutierrez@amd.com 138811308Santhony.gutierrez@amd.com Addr 138911308Santhony.gutierrez@amd.com GpuTLB::TLBEvent::getTLBEventVaddr() 139011308Santhony.gutierrez@amd.com { 139111308Santhony.gutierrez@amd.com return virtPageAddr; 139211308Santhony.gutierrez@amd.com } 139311308Santhony.gutierrez@amd.com 139411308Santhony.gutierrez@amd.com /* 139511308Santhony.gutierrez@amd.com * recvTiming receives a coalesced timing request from a TLBCoalescer 139611308Santhony.gutierrez@amd.com * and it calls issueTLBLookup() 139711308Santhony.gutierrez@amd.com * It only rejects the packet if we have exceeded the max 139811308Santhony.gutierrez@amd.com * outstanding number of requests for the TLB 139911308Santhony.gutierrez@amd.com */ 140011308Santhony.gutierrez@amd.com bool 140111308Santhony.gutierrez@amd.com GpuTLB::CpuSidePort::recvTimingReq(PacketPtr pkt) 140211308Santhony.gutierrez@amd.com { 140311308Santhony.gutierrez@amd.com if (tlb->outstandingReqs < tlb->maxCoalescedReqs) { 140411308Santhony.gutierrez@amd.com tlb->issueTLBLookup(pkt); 140511308Santhony.gutierrez@amd.com // update number of outstanding translation requests 140611308Santhony.gutierrez@amd.com tlb->outstandingReqs++; 140711308Santhony.gutierrez@amd.com return true; 140811308Santhony.gutierrez@amd.com } else { 140911308Santhony.gutierrez@amd.com DPRINTF(GPUTLB, "Reached maxCoalescedReqs number %d\n", 141011308Santhony.gutierrez@amd.com tlb->outstandingReqs); 141111308Santhony.gutierrez@amd.com return false; 141211308Santhony.gutierrez@amd.com } 141311308Santhony.gutierrez@amd.com } 141411308Santhony.gutierrez@amd.com 141511308Santhony.gutierrez@amd.com /** 141611308Santhony.gutierrez@amd.com * handleFuncTranslationReturn is called on a TLB hit, 141711308Santhony.gutierrez@amd.com * when a TLB miss returns or when a page fault returns. 141811308Santhony.gutierrez@amd.com * It updates LRU, inserts the TLB entry on a miss 141911308Santhony.gutierrez@amd.com * depending on the allocation policy and does the required 142011308Santhony.gutierrez@amd.com * protection checks. It does NOT create a new packet to 142111308Santhony.gutierrez@amd.com * update the packet's addr; this is done in hsail-gpu code. 142211308Santhony.gutierrez@amd.com */ 142311308Santhony.gutierrez@amd.com void 142411308Santhony.gutierrez@amd.com GpuTLB::handleFuncTranslationReturn(PacketPtr pkt, tlbOutcome tlb_outcome) 142511308Santhony.gutierrez@amd.com { 142611308Santhony.gutierrez@amd.com TranslationState *sender_state = 142711308Santhony.gutierrez@amd.com safe_cast<TranslationState*>(pkt->senderState); 142811308Santhony.gutierrez@amd.com 142911308Santhony.gutierrez@amd.com ThreadContext *tc = sender_state->tc; 143011308Santhony.gutierrez@amd.com Mode mode = sender_state->tlbMode; 143111308Santhony.gutierrez@amd.com Addr vaddr = pkt->req->getVaddr(); 143211308Santhony.gutierrez@amd.com 143312717Sbrandon.potter@amd.com TlbEntry *local_entry, *new_entry; 143411308Santhony.gutierrez@amd.com 143511308Santhony.gutierrez@amd.com if (tlb_outcome == TLB_HIT) { 143611308Santhony.gutierrez@amd.com DPRINTF(GPUTLB, "Functional Translation Done - TLB hit for addr " 143711308Santhony.gutierrez@amd.com "%#x\n", vaddr); 143811308Santhony.gutierrez@amd.com 143911308Santhony.gutierrez@amd.com local_entry = sender_state->tlbEntry; 144011308Santhony.gutierrez@amd.com } else { 144111308Santhony.gutierrez@amd.com DPRINTF(GPUTLB, "Functional Translation Done - TLB miss for addr " 144211308Santhony.gutierrez@amd.com "%#x\n", vaddr); 144311308Santhony.gutierrez@amd.com 144411308Santhony.gutierrez@amd.com // We are returning either from a page walk or from a hit at a lower 144511308Santhony.gutierrez@amd.com // TLB level. The senderState should be "carrying" a pointer to the 144611308Santhony.gutierrez@amd.com // correct TLBEntry. 144711308Santhony.gutierrez@amd.com new_entry = sender_state->tlbEntry; 144811308Santhony.gutierrez@amd.com assert(new_entry); 144911308Santhony.gutierrez@amd.com local_entry = new_entry; 145011308Santhony.gutierrez@amd.com 145111308Santhony.gutierrez@amd.com if (allocationPolicy) { 145211308Santhony.gutierrez@amd.com Addr virt_page_addr = roundDown(vaddr, TheISA::PageBytes); 145311308Santhony.gutierrez@amd.com 145411308Santhony.gutierrez@amd.com DPRINTF(GPUTLB, "allocating entry w/ addr %#x\n", 145511308Santhony.gutierrez@amd.com virt_page_addr); 145611308Santhony.gutierrez@amd.com 145711308Santhony.gutierrez@amd.com local_entry = insert(virt_page_addr, *new_entry); 145811308Santhony.gutierrez@amd.com } 145911308Santhony.gutierrez@amd.com 146011308Santhony.gutierrez@amd.com assert(local_entry); 146111308Santhony.gutierrez@amd.com } 146211308Santhony.gutierrez@amd.com 146311308Santhony.gutierrez@amd.com DPRINTF(GPUTLB, "Entry found with vaddr %#x, doing protection checks " 146411308Santhony.gutierrez@amd.com "while paddr was %#x.\n", local_entry->vaddr, 146511308Santhony.gutierrez@amd.com local_entry->paddr); 146611308Santhony.gutierrez@amd.com 146712717Sbrandon.potter@amd.com /** 146812717Sbrandon.potter@amd.com * Do paging checks if it's a normal functional access. If it's for a 146912717Sbrandon.potter@amd.com * prefetch, then sometimes you can try to prefetch something that 147012717Sbrandon.potter@amd.com * won't pass protection. We don't actually want to fault becuase there 147112717Sbrandon.potter@amd.com * is no demand access to deem this a violation. Just put it in the 147212717Sbrandon.potter@amd.com * TLB and it will fault if indeed a future demand access touches it in 147312717Sbrandon.potter@amd.com * violation. 147412717Sbrandon.potter@amd.com * 147512717Sbrandon.potter@amd.com * This feature could be used to explore security issues around 147612717Sbrandon.potter@amd.com * speculative memory accesses. 147712717Sbrandon.potter@amd.com */ 147812717Sbrandon.potter@amd.com if (!sender_state->prefetch && sender_state->tlbEntry) 147911308Santhony.gutierrez@amd.com pagingProtectionChecks(tc, pkt, local_entry, mode); 148011308Santhony.gutierrez@amd.com 148111308Santhony.gutierrez@amd.com int page_size = local_entry->size(); 148211308Santhony.gutierrez@amd.com Addr paddr = local_entry->paddr | (vaddr & (page_size - 1)); 148311308Santhony.gutierrez@amd.com DPRINTF(GPUTLB, "Translated %#x -> %#x.\n", vaddr, paddr); 148411308Santhony.gutierrez@amd.com 148511308Santhony.gutierrez@amd.com pkt->req->setPaddr(paddr); 148611308Santhony.gutierrez@amd.com 148711308Santhony.gutierrez@amd.com if (local_entry->uncacheable) 148811308Santhony.gutierrez@amd.com pkt->req->setFlags(Request::UNCACHEABLE); 148911308Santhony.gutierrez@amd.com } 149011308Santhony.gutierrez@amd.com 149111308Santhony.gutierrez@amd.com // This is used for atomic translations. Need to 149211308Santhony.gutierrez@amd.com // make it all happen during the same cycle. 149311308Santhony.gutierrez@amd.com void 149411308Santhony.gutierrez@amd.com GpuTLB::CpuSidePort::recvFunctional(PacketPtr pkt) 149511308Santhony.gutierrez@amd.com { 149611308Santhony.gutierrez@amd.com TranslationState *sender_state = 149711308Santhony.gutierrez@amd.com safe_cast<TranslationState*>(pkt->senderState); 149811308Santhony.gutierrez@amd.com 149911308Santhony.gutierrez@amd.com ThreadContext *tc = sender_state->tc; 150011308Santhony.gutierrez@amd.com bool update_stats = !sender_state->prefetch; 150111308Santhony.gutierrez@amd.com 150211308Santhony.gutierrez@amd.com Addr virt_page_addr = roundDown(pkt->req->getVaddr(), 150311308Santhony.gutierrez@amd.com TheISA::PageBytes); 150411308Santhony.gutierrez@amd.com 150511308Santhony.gutierrez@amd.com if (update_stats) 150611308Santhony.gutierrez@amd.com tlb->updatePageFootprint(virt_page_addr); 150711308Santhony.gutierrez@amd.com 150811308Santhony.gutierrez@amd.com // do the TLB lookup without updating the stats 150911308Santhony.gutierrez@amd.com bool success = tlb->tlbLookup(pkt->req, tc, update_stats); 151011308Santhony.gutierrez@amd.com tlbOutcome tlb_outcome = success ? TLB_HIT : TLB_MISS; 151111308Santhony.gutierrez@amd.com 151211308Santhony.gutierrez@amd.com // functional mode means no coalescing 151311308Santhony.gutierrez@amd.com // global metrics are the same as the local metrics 151411308Santhony.gutierrez@amd.com if (update_stats) { 151511308Santhony.gutierrez@amd.com tlb->globalNumTLBAccesses++; 151611308Santhony.gutierrez@amd.com 151711308Santhony.gutierrez@amd.com if (success) { 151811308Santhony.gutierrez@amd.com sender_state->hitLevel = sender_state->reqCnt.size(); 151911308Santhony.gutierrez@amd.com tlb->globalNumTLBHits++; 152011308Santhony.gutierrez@amd.com } 152111308Santhony.gutierrez@amd.com } 152211308Santhony.gutierrez@amd.com 152311308Santhony.gutierrez@amd.com if (!success) { 152411308Santhony.gutierrez@amd.com if (update_stats) 152511308Santhony.gutierrez@amd.com tlb->globalNumTLBMisses++; 152611308Santhony.gutierrez@amd.com if (tlb->hasMemSidePort) { 152711308Santhony.gutierrez@amd.com // there is a TLB below -> propagate down the TLB hierarchy 152811308Santhony.gutierrez@amd.com tlb->memSidePort[0]->sendFunctional(pkt); 152911308Santhony.gutierrez@amd.com // If no valid translation from a prefetch, then just return 153011308Santhony.gutierrez@amd.com if (sender_state->prefetch && !pkt->req->hasPaddr()) 153111308Santhony.gutierrez@amd.com return; 153211308Santhony.gutierrez@amd.com } else { 153311308Santhony.gutierrez@amd.com // Need to access the page table and update the TLB 153411308Santhony.gutierrez@amd.com DPRINTF(GPUTLB, "Doing a page walk for address %#x\n", 153511308Santhony.gutierrez@amd.com virt_page_addr); 153611308Santhony.gutierrez@amd.com 153711308Santhony.gutierrez@amd.com Process *p = tc->getProcessPtr(); 153811308Santhony.gutierrez@amd.com 153911308Santhony.gutierrez@amd.com Addr vaddr = pkt->req->getVaddr(); 154011308Santhony.gutierrez@amd.com #ifndef NDEBUG 154111308Santhony.gutierrez@amd.com Addr alignedVaddr = p->pTable->pageAlign(vaddr); 154211308Santhony.gutierrez@amd.com assert(alignedVaddr == virt_page_addr); 154311308Santhony.gutierrez@amd.com #endif 154411308Santhony.gutierrez@amd.com 154512461Sgabeblack@google.com const EmulationPageTable::Entry *pte = 154612461Sgabeblack@google.com p->pTable->lookup(vaddr); 154712461Sgabeblack@google.com if (!pte && sender_state->tlbMode != BaseTLB::Execute && 154812455Sgabeblack@google.com p->fixupStackFault(vaddr)) { 154912461Sgabeblack@google.com pte = p->pTable->lookup(vaddr); 155011308Santhony.gutierrez@amd.com } 155111308Santhony.gutierrez@amd.com 155211308Santhony.gutierrez@amd.com if (!sender_state->prefetch) { 155311308Santhony.gutierrez@amd.com // no PageFaults are permitted after 155411308Santhony.gutierrez@amd.com // the second page table lookup 155512663Santhony.gutierrez@amd.com assert(pte); 155611308Santhony.gutierrez@amd.com 155711308Santhony.gutierrez@amd.com DPRINTF(GPUTLB, "Mapping %#x to %#x\n", alignedVaddr, 155812461Sgabeblack@google.com pte->paddr); 155911308Santhony.gutierrez@amd.com 156012455Sgabeblack@google.com sender_state->tlbEntry = 156112717Sbrandon.potter@amd.com new TlbEntry(p->pid(), virt_page_addr, 156212717Sbrandon.potter@amd.com pte->paddr, false, false); 156311308Santhony.gutierrez@amd.com } else { 156411308Santhony.gutierrez@amd.com // If this was a prefetch, then do the normal thing if it 156511308Santhony.gutierrez@amd.com // was a successful translation. Otherwise, send an empty 156611308Santhony.gutierrez@amd.com // TLB entry back so that it can be figured out as empty and 156711308Santhony.gutierrez@amd.com // handled accordingly. 156812461Sgabeblack@google.com if (pte) { 156911308Santhony.gutierrez@amd.com DPRINTF(GPUTLB, "Mapping %#x to %#x\n", alignedVaddr, 157012461Sgabeblack@google.com pte->paddr); 157111308Santhony.gutierrez@amd.com 157212455Sgabeblack@google.com sender_state->tlbEntry = 157312717Sbrandon.potter@amd.com new TlbEntry(p->pid(), virt_page_addr, 157412717Sbrandon.potter@amd.com pte->paddr, false, false); 157511308Santhony.gutierrez@amd.com } else { 157611308Santhony.gutierrez@amd.com DPRINTF(GPUPrefetch, "Prefetch failed %#x\n", 157711308Santhony.gutierrez@amd.com alignedVaddr); 157811308Santhony.gutierrez@amd.com 157912717Sbrandon.potter@amd.com sender_state->tlbEntry = nullptr; 158011308Santhony.gutierrez@amd.com 158111308Santhony.gutierrez@amd.com return; 158211308Santhony.gutierrez@amd.com } 158311308Santhony.gutierrez@amd.com } 158411308Santhony.gutierrez@amd.com } 158511308Santhony.gutierrez@amd.com } else { 158611308Santhony.gutierrez@amd.com DPRINTF(GPUPrefetch, "Functional Hit for vaddr %#x\n", 158711308Santhony.gutierrez@amd.com tlb->lookup(pkt->req->getVaddr())); 158811308Santhony.gutierrez@amd.com 158912717Sbrandon.potter@amd.com TlbEntry *entry = tlb->lookup(pkt->req->getVaddr(), 159011308Santhony.gutierrez@amd.com update_stats); 159111308Santhony.gutierrez@amd.com 159211308Santhony.gutierrez@amd.com assert(entry); 159311308Santhony.gutierrez@amd.com 159412717Sbrandon.potter@amd.com auto p = sender_state->tc->getProcessPtr(); 159511308Santhony.gutierrez@amd.com sender_state->tlbEntry = 159612717Sbrandon.potter@amd.com new TlbEntry(p->pid(), entry->vaddr, entry->paddr, 159712717Sbrandon.potter@amd.com false, false); 159811308Santhony.gutierrez@amd.com } 159911308Santhony.gutierrez@amd.com // This is the function that would populate pkt->req with the paddr of 160011308Santhony.gutierrez@amd.com // the translation. But if no translation happens (i.e Prefetch fails) 160111308Santhony.gutierrez@amd.com // then the early returns in the above code wiill keep this function 160211308Santhony.gutierrez@amd.com // from executing. 160311308Santhony.gutierrez@amd.com tlb->handleFuncTranslationReturn(pkt, tlb_outcome); 160411308Santhony.gutierrez@amd.com } 160511308Santhony.gutierrez@amd.com 160611308Santhony.gutierrez@amd.com void 160711308Santhony.gutierrez@amd.com GpuTLB::CpuSidePort::recvReqRetry() 160811308Santhony.gutierrez@amd.com { 160911308Santhony.gutierrez@amd.com // The CPUSidePort never sends anything but replies. No retries 161011308Santhony.gutierrez@amd.com // expected. 161113449Sgabeblack@google.com panic("recvReqRetry called"); 161211308Santhony.gutierrez@amd.com } 161311308Santhony.gutierrez@amd.com 161411308Santhony.gutierrez@amd.com AddrRangeList 161511308Santhony.gutierrez@amd.com GpuTLB::CpuSidePort::getAddrRanges() const 161611308Santhony.gutierrez@amd.com { 161711308Santhony.gutierrez@amd.com // currently not checked by the master 161811308Santhony.gutierrez@amd.com AddrRangeList ranges; 161911308Santhony.gutierrez@amd.com 162011308Santhony.gutierrez@amd.com return ranges; 162111308Santhony.gutierrez@amd.com } 162211308Santhony.gutierrez@amd.com 162311308Santhony.gutierrez@amd.com /** 162411308Santhony.gutierrez@amd.com * MemSidePort receives the packet back. 162511308Santhony.gutierrez@amd.com * We need to call the handleTranslationReturn 162611308Santhony.gutierrez@amd.com * and propagate up the hierarchy. 162711308Santhony.gutierrez@amd.com */ 162811308Santhony.gutierrez@amd.com bool 162911308Santhony.gutierrez@amd.com GpuTLB::MemSidePort::recvTimingResp(PacketPtr pkt) 163011308Santhony.gutierrez@amd.com { 163111308Santhony.gutierrez@amd.com Addr virt_page_addr = roundDown(pkt->req->getVaddr(), 163211308Santhony.gutierrez@amd.com TheISA::PageBytes); 163311308Santhony.gutierrez@amd.com 163411308Santhony.gutierrez@amd.com DPRINTF(GPUTLB, "MemSidePort recvTiming for virt_page_addr %#x\n", 163511308Santhony.gutierrez@amd.com virt_page_addr); 163611308Santhony.gutierrez@amd.com 163711308Santhony.gutierrez@amd.com TLBEvent *tlb_event = tlb->translationReturnEvent[virt_page_addr]; 163811308Santhony.gutierrez@amd.com assert(tlb_event); 163911308Santhony.gutierrez@amd.com assert(virt_page_addr == tlb_event->getTLBEventVaddr()); 164011308Santhony.gutierrez@amd.com 164111308Santhony.gutierrez@amd.com tlb_event->updateOutcome(MISS_RETURN); 164211308Santhony.gutierrez@amd.com tlb->schedule(tlb_event, curTick()+tlb->ticks(1)); 164311308Santhony.gutierrez@amd.com 164411308Santhony.gutierrez@amd.com return true; 164511308Santhony.gutierrez@amd.com } 164611308Santhony.gutierrez@amd.com 164711308Santhony.gutierrez@amd.com void 164811308Santhony.gutierrez@amd.com GpuTLB::MemSidePort::recvReqRetry() 164911308Santhony.gutierrez@amd.com { 165011308Santhony.gutierrez@amd.com // No retries should reach the TLB. The retries 165111308Santhony.gutierrez@amd.com // should only reach the TLBCoalescer. 165213449Sgabeblack@google.com panic("recvReqRetry called"); 165311308Santhony.gutierrez@amd.com } 165411308Santhony.gutierrez@amd.com 165511308Santhony.gutierrez@amd.com void 165611308Santhony.gutierrez@amd.com GpuTLB::cleanup() 165711308Santhony.gutierrez@amd.com { 165811308Santhony.gutierrez@amd.com while (!cleanupQueue.empty()) { 165911308Santhony.gutierrez@amd.com Addr cleanup_addr = cleanupQueue.front(); 166011308Santhony.gutierrez@amd.com cleanupQueue.pop(); 166111308Santhony.gutierrez@amd.com 166211308Santhony.gutierrez@amd.com // delete TLBEvent 166311308Santhony.gutierrez@amd.com TLBEvent * old_tlb_event = translationReturnEvent[cleanup_addr]; 166411308Santhony.gutierrez@amd.com delete old_tlb_event; 166511308Santhony.gutierrez@amd.com translationReturnEvent.erase(cleanup_addr); 166611308Santhony.gutierrez@amd.com 166711308Santhony.gutierrez@amd.com // update number of outstanding requests 166811308Santhony.gutierrez@amd.com outstandingReqs--; 166911308Santhony.gutierrez@amd.com } 167011308Santhony.gutierrez@amd.com 167111308Santhony.gutierrez@amd.com /** the higher level coalescer should retry if it has 167211308Santhony.gutierrez@amd.com * any pending requests. 167311308Santhony.gutierrez@amd.com */ 167411308Santhony.gutierrez@amd.com for (int i = 0; i < cpuSidePort.size(); ++i) { 167511308Santhony.gutierrez@amd.com cpuSidePort[i]->sendRetryReq(); 167611308Santhony.gutierrez@amd.com } 167711308Santhony.gutierrez@amd.com } 167811308Santhony.gutierrez@amd.com 167911308Santhony.gutierrez@amd.com void 168011308Santhony.gutierrez@amd.com GpuTLB::updatePageFootprint(Addr virt_page_addr) 168111308Santhony.gutierrez@amd.com { 168211308Santhony.gutierrez@amd.com 168311308Santhony.gutierrez@amd.com std::pair<AccessPatternTable::iterator, bool> ret; 168411308Santhony.gutierrez@amd.com 168511308Santhony.gutierrez@amd.com AccessInfo tmp_access_info; 168611308Santhony.gutierrez@amd.com tmp_access_info.lastTimeAccessed = 0; 168711308Santhony.gutierrez@amd.com tmp_access_info.accessesPerPage = 0; 168811308Santhony.gutierrez@amd.com tmp_access_info.totalReuseDistance = 0; 168911308Santhony.gutierrez@amd.com tmp_access_info.sumDistance = 0; 169011308Santhony.gutierrez@amd.com tmp_access_info.meanDistance = 0; 169111308Santhony.gutierrez@amd.com 169211308Santhony.gutierrez@amd.com ret = TLBFootprint.insert(AccessPatternTable::value_type(virt_page_addr, 169311308Santhony.gutierrez@amd.com tmp_access_info)); 169411308Santhony.gutierrez@amd.com 169511308Santhony.gutierrez@amd.com bool first_page_access = ret.second; 169611308Santhony.gutierrez@amd.com 169711308Santhony.gutierrez@amd.com if (first_page_access) { 169811308Santhony.gutierrez@amd.com numUniquePages++; 169911308Santhony.gutierrez@amd.com } else { 170011308Santhony.gutierrez@amd.com int accessed_before; 170111308Santhony.gutierrez@amd.com accessed_before = curTick() - ret.first->second.lastTimeAccessed; 170211308Santhony.gutierrez@amd.com ret.first->second.totalReuseDistance += accessed_before; 170311308Santhony.gutierrez@amd.com } 170411308Santhony.gutierrez@amd.com 170511308Santhony.gutierrez@amd.com ret.first->second.accessesPerPage++; 170611308Santhony.gutierrez@amd.com ret.first->second.lastTimeAccessed = curTick(); 170711308Santhony.gutierrez@amd.com 170811308Santhony.gutierrez@amd.com if (accessDistance) { 170911308Santhony.gutierrez@amd.com ret.first->second.localTLBAccesses 171011308Santhony.gutierrez@amd.com .push_back(localNumTLBAccesses.value()); 171111308Santhony.gutierrez@amd.com } 171211308Santhony.gutierrez@amd.com } 171311308Santhony.gutierrez@amd.com 171411308Santhony.gutierrez@amd.com void 171511308Santhony.gutierrez@amd.com GpuTLB::exitCallback() 171611308Santhony.gutierrez@amd.com { 171711308Santhony.gutierrez@amd.com std::ostream *page_stat_file = nullptr; 171811308Santhony.gutierrez@amd.com 171911308Santhony.gutierrez@amd.com if (accessDistance) { 172011308Santhony.gutierrez@amd.com 172111308Santhony.gutierrez@amd.com // print per page statistics to a separate file (.csv format) 172211308Santhony.gutierrez@amd.com // simout is the gem5 output directory (default is m5out or the one 172311308Santhony.gutierrez@amd.com // specified with -d 172411364Sandreas.hansson@arm.com page_stat_file = simout.create(name().c_str())->stream(); 172511308Santhony.gutierrez@amd.com 172611308Santhony.gutierrez@amd.com // print header 172711308Santhony.gutierrez@amd.com *page_stat_file << "page,max_access_distance,mean_access_distance, " 172811308Santhony.gutierrez@amd.com << "stddev_distance" << std::endl; 172911308Santhony.gutierrez@amd.com } 173011308Santhony.gutierrez@amd.com 173111308Santhony.gutierrez@amd.com // update avg. reuse distance footprint 173211308Santhony.gutierrez@amd.com AccessPatternTable::iterator iter, iter_begin, iter_end; 173311308Santhony.gutierrez@amd.com unsigned int sum_avg_reuse_distance_per_page = 0; 173411308Santhony.gutierrez@amd.com 173511308Santhony.gutierrez@amd.com // iterate through all pages seen by this TLB 173611308Santhony.gutierrez@amd.com for (iter = TLBFootprint.begin(); iter != TLBFootprint.end(); iter++) { 173711308Santhony.gutierrez@amd.com sum_avg_reuse_distance_per_page += iter->second.totalReuseDistance / 173811308Santhony.gutierrez@amd.com iter->second.accessesPerPage; 173911308Santhony.gutierrez@amd.com 174011308Santhony.gutierrez@amd.com if (accessDistance) { 174111308Santhony.gutierrez@amd.com unsigned int tmp = iter->second.localTLBAccesses[0]; 174211308Santhony.gutierrez@amd.com unsigned int prev = tmp; 174311308Santhony.gutierrez@amd.com 174411308Santhony.gutierrez@amd.com for (int i = 0; i < iter->second.localTLBAccesses.size(); ++i) { 174511308Santhony.gutierrez@amd.com if (i) { 174611308Santhony.gutierrez@amd.com tmp = prev + 1; 174711308Santhony.gutierrez@amd.com } 174811308Santhony.gutierrez@amd.com 174911308Santhony.gutierrez@amd.com prev = iter->second.localTLBAccesses[i]; 175011308Santhony.gutierrez@amd.com // update the localTLBAccesses value 175111308Santhony.gutierrez@amd.com // with the actual differece 175211308Santhony.gutierrez@amd.com iter->second.localTLBAccesses[i] -= tmp; 175311308Santhony.gutierrez@amd.com // compute the sum of AccessDistance per page 175411308Santhony.gutierrez@amd.com // used later for mean 175511308Santhony.gutierrez@amd.com iter->second.sumDistance += 175611308Santhony.gutierrez@amd.com iter->second.localTLBAccesses[i]; 175711308Santhony.gutierrez@amd.com } 175811308Santhony.gutierrez@amd.com 175911308Santhony.gutierrez@amd.com iter->second.meanDistance = 176011308Santhony.gutierrez@amd.com iter->second.sumDistance / iter->second.accessesPerPage; 176111308Santhony.gutierrez@amd.com 176211308Santhony.gutierrez@amd.com // compute std_dev and max (we need a second round because we 176311308Santhony.gutierrez@amd.com // need to know the mean value 176411308Santhony.gutierrez@amd.com unsigned int max_distance = 0; 176511308Santhony.gutierrez@amd.com unsigned int stddev_distance = 0; 176611308Santhony.gutierrez@amd.com 176711308Santhony.gutierrez@amd.com for (int i = 0; i < iter->second.localTLBAccesses.size(); ++i) { 176811308Santhony.gutierrez@amd.com unsigned int tmp_access_distance = 176911308Santhony.gutierrez@amd.com iter->second.localTLBAccesses[i]; 177011308Santhony.gutierrez@amd.com 177111308Santhony.gutierrez@amd.com if (tmp_access_distance > max_distance) { 177211308Santhony.gutierrez@amd.com max_distance = tmp_access_distance; 177311308Santhony.gutierrez@amd.com } 177411308Santhony.gutierrez@amd.com 177511308Santhony.gutierrez@amd.com unsigned int diff = 177611308Santhony.gutierrez@amd.com tmp_access_distance - iter->second.meanDistance; 177711308Santhony.gutierrez@amd.com stddev_distance += pow(diff, 2); 177811308Santhony.gutierrez@amd.com 177911308Santhony.gutierrez@amd.com } 178011308Santhony.gutierrez@amd.com 178111308Santhony.gutierrez@amd.com stddev_distance = 178211308Santhony.gutierrez@amd.com sqrt(stddev_distance/iter->second.accessesPerPage); 178311308Santhony.gutierrez@amd.com 178411308Santhony.gutierrez@amd.com if (page_stat_file) { 178511308Santhony.gutierrez@amd.com *page_stat_file << std::hex << iter->first << ","; 178611308Santhony.gutierrez@amd.com *page_stat_file << std::dec << max_distance << ","; 178711308Santhony.gutierrez@amd.com *page_stat_file << std::dec << iter->second.meanDistance 178811308Santhony.gutierrez@amd.com << ","; 178911308Santhony.gutierrez@amd.com *page_stat_file << std::dec << stddev_distance; 179011308Santhony.gutierrez@amd.com *page_stat_file << std::endl; 179111308Santhony.gutierrez@amd.com } 179211308Santhony.gutierrez@amd.com 179311308Santhony.gutierrez@amd.com // erase the localTLBAccesses array 179411308Santhony.gutierrez@amd.com iter->second.localTLBAccesses.clear(); 179511308Santhony.gutierrez@amd.com } 179611308Santhony.gutierrez@amd.com } 179711308Santhony.gutierrez@amd.com 179811308Santhony.gutierrez@amd.com if (!TLBFootprint.empty()) { 179911308Santhony.gutierrez@amd.com avgReuseDistance = 180011308Santhony.gutierrez@amd.com sum_avg_reuse_distance_per_page / TLBFootprint.size(); 180111308Santhony.gutierrez@amd.com } 180211308Santhony.gutierrez@amd.com 180311308Santhony.gutierrez@amd.com //clear the TLBFootprint map 180411308Santhony.gutierrez@amd.com TLBFootprint.clear(); 180511308Santhony.gutierrez@amd.com } 180611308Santhony.gutierrez@amd.com} // namespace X86ISA 180711308Santhony.gutierrez@amd.com 180811308Santhony.gutierrez@amd.comX86ISA::GpuTLB* 180911308Santhony.gutierrez@amd.comX86GPUTLBParams::create() 181011308Santhony.gutierrez@amd.com{ 181111308Santhony.gutierrez@amd.com return new X86ISA::GpuTLB(this); 181211308Santhony.gutierrez@amd.com} 181311308Santhony.gutierrez@amd.com 1814