gpu_tlb.cc revision 13784
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 14013784Sgabeblack@google.com Port & 14113784Sgabeblack@google.com GpuTLB::getPort(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())) { 14513784Sgabeblack@google.com panic("TLBCoalescer::getPort: unknown index %d\n", idx); 14611308Santhony.gutierrez@amd.com } 14711308Santhony.gutierrez@amd.com 14811308Santhony.gutierrez@amd.com return *cpuSidePort[idx]; 14913784Sgabeblack@google.com } else if (if_name == "master") { 15011308Santhony.gutierrez@amd.com if (idx >= static_cast<PortID>(memSidePort.size())) { 15113784Sgabeblack@google.com panic("TLBCoalescer::getPort: unknown index %d\n", idx); 15211308Santhony.gutierrez@amd.com } 15311308Santhony.gutierrez@amd.com 15411308Santhony.gutierrez@amd.com hasMemSidePort = true; 15511308Santhony.gutierrez@amd.com 15611308Santhony.gutierrez@amd.com return *memSidePort[idx]; 15711308Santhony.gutierrez@amd.com } else { 15813784Sgabeblack@google.com panic("TLBCoalescer::getPort: unknown port %s\n", if_name); 15911308Santhony.gutierrez@amd.com } 16011308Santhony.gutierrez@amd.com } 16111308Santhony.gutierrez@amd.com 16212717Sbrandon.potter@amd.com TlbEntry* 16312717Sbrandon.potter@amd.com GpuTLB::insert(Addr vpn, TlbEntry &entry) 16411308Santhony.gutierrez@amd.com { 16512717Sbrandon.potter@amd.com TlbEntry *newEntry = nullptr; 16611308Santhony.gutierrez@amd.com 16711308Santhony.gutierrez@amd.com /** 16811308Santhony.gutierrez@amd.com * vpn holds the virtual page address 16911308Santhony.gutierrez@amd.com * The least significant bits are simply masked 17011308Santhony.gutierrez@amd.com */ 17111308Santhony.gutierrez@amd.com int set = (vpn >> TheISA::PageShift) & setMask; 17211308Santhony.gutierrez@amd.com 17311308Santhony.gutierrez@amd.com if (!freeList[set].empty()) { 17411308Santhony.gutierrez@amd.com newEntry = freeList[set].front(); 17511308Santhony.gutierrez@amd.com freeList[set].pop_front(); 17611308Santhony.gutierrez@amd.com } else { 17711308Santhony.gutierrez@amd.com newEntry = entryList[set].back(); 17811308Santhony.gutierrez@amd.com entryList[set].pop_back(); 17911308Santhony.gutierrez@amd.com } 18011308Santhony.gutierrez@amd.com 18111308Santhony.gutierrez@amd.com *newEntry = entry; 18211308Santhony.gutierrez@amd.com newEntry->vaddr = vpn; 18311308Santhony.gutierrez@amd.com entryList[set].push_front(newEntry); 18411308Santhony.gutierrez@amd.com 18511308Santhony.gutierrez@amd.com return newEntry; 18611308Santhony.gutierrez@amd.com } 18711308Santhony.gutierrez@amd.com 18811308Santhony.gutierrez@amd.com GpuTLB::EntryList::iterator 18911308Santhony.gutierrez@amd.com GpuTLB::lookupIt(Addr va, bool update_lru) 19011308Santhony.gutierrez@amd.com { 19111308Santhony.gutierrez@amd.com int set = (va >> TheISA::PageShift) & setMask; 19211308Santhony.gutierrez@amd.com 19311308Santhony.gutierrez@amd.com if (FA) { 19411308Santhony.gutierrez@amd.com assert(!set); 19511308Santhony.gutierrez@amd.com } 19611308Santhony.gutierrez@amd.com 19711308Santhony.gutierrez@amd.com auto entry = entryList[set].begin(); 19811308Santhony.gutierrez@amd.com for (; entry != entryList[set].end(); ++entry) { 19911308Santhony.gutierrez@amd.com int page_size = (*entry)->size(); 20011308Santhony.gutierrez@amd.com 20111308Santhony.gutierrez@amd.com if ((*entry)->vaddr <= va && (*entry)->vaddr + page_size > va) { 20211308Santhony.gutierrez@amd.com DPRINTF(GPUTLB, "Matched vaddr %#x to entry starting at %#x " 20311308Santhony.gutierrez@amd.com "with size %#x.\n", va, (*entry)->vaddr, page_size); 20411308Santhony.gutierrez@amd.com 20511308Santhony.gutierrez@amd.com if (update_lru) { 20611308Santhony.gutierrez@amd.com entryList[set].push_front(*entry); 20711308Santhony.gutierrez@amd.com entryList[set].erase(entry); 20811308Santhony.gutierrez@amd.com entry = entryList[set].begin(); 20911308Santhony.gutierrez@amd.com } 21011308Santhony.gutierrez@amd.com 21111308Santhony.gutierrez@amd.com break; 21211308Santhony.gutierrez@amd.com } 21311308Santhony.gutierrez@amd.com } 21411308Santhony.gutierrez@amd.com 21511308Santhony.gutierrez@amd.com return entry; 21611308Santhony.gutierrez@amd.com } 21711308Santhony.gutierrez@amd.com 21812717Sbrandon.potter@amd.com TlbEntry* 21911308Santhony.gutierrez@amd.com GpuTLB::lookup(Addr va, bool update_lru) 22011308Santhony.gutierrez@amd.com { 22111308Santhony.gutierrez@amd.com int set = (va >> TheISA::PageShift) & setMask; 22211308Santhony.gutierrez@amd.com 22311308Santhony.gutierrez@amd.com auto entry = lookupIt(va, update_lru); 22411308Santhony.gutierrez@amd.com 22511308Santhony.gutierrez@amd.com if (entry == entryList[set].end()) 22611308Santhony.gutierrez@amd.com return nullptr; 22711308Santhony.gutierrez@amd.com else 22811308Santhony.gutierrez@amd.com return *entry; 22911308Santhony.gutierrez@amd.com } 23011308Santhony.gutierrez@amd.com 23111308Santhony.gutierrez@amd.com void 23211308Santhony.gutierrez@amd.com GpuTLB::invalidateAll() 23311308Santhony.gutierrez@amd.com { 23411308Santhony.gutierrez@amd.com DPRINTF(GPUTLB, "Invalidating all entries.\n"); 23511308Santhony.gutierrez@amd.com 23611308Santhony.gutierrez@amd.com for (int i = 0; i < numSets; ++i) { 23711308Santhony.gutierrez@amd.com while (!entryList[i].empty()) { 23812717Sbrandon.potter@amd.com TlbEntry *entry = entryList[i].front(); 23911308Santhony.gutierrez@amd.com entryList[i].pop_front(); 24011308Santhony.gutierrez@amd.com freeList[i].push_back(entry); 24111308Santhony.gutierrez@amd.com } 24211308Santhony.gutierrez@amd.com } 24311308Santhony.gutierrez@amd.com } 24411308Santhony.gutierrez@amd.com 24511308Santhony.gutierrez@amd.com void 24611308Santhony.gutierrez@amd.com GpuTLB::setConfigAddress(uint32_t addr) 24711308Santhony.gutierrez@amd.com { 24811308Santhony.gutierrez@amd.com configAddress = addr; 24911308Santhony.gutierrez@amd.com } 25011308Santhony.gutierrez@amd.com 25111308Santhony.gutierrez@amd.com void 25211308Santhony.gutierrez@amd.com GpuTLB::invalidateNonGlobal() 25311308Santhony.gutierrez@amd.com { 25411308Santhony.gutierrez@amd.com DPRINTF(GPUTLB, "Invalidating all non global entries.\n"); 25511308Santhony.gutierrez@amd.com 25611308Santhony.gutierrez@amd.com for (int i = 0; i < numSets; ++i) { 25711308Santhony.gutierrez@amd.com for (auto entryIt = entryList[i].begin(); 25811308Santhony.gutierrez@amd.com entryIt != entryList[i].end();) { 25911308Santhony.gutierrez@amd.com if (!(*entryIt)->global) { 26011308Santhony.gutierrez@amd.com freeList[i].push_back(*entryIt); 26111308Santhony.gutierrez@amd.com entryList[i].erase(entryIt++); 26211308Santhony.gutierrez@amd.com } else { 26311308Santhony.gutierrez@amd.com ++entryIt; 26411308Santhony.gutierrez@amd.com } 26511308Santhony.gutierrez@amd.com } 26611308Santhony.gutierrez@amd.com } 26711308Santhony.gutierrez@amd.com } 26811308Santhony.gutierrez@amd.com 26911308Santhony.gutierrez@amd.com void 27011308Santhony.gutierrez@amd.com GpuTLB::demapPage(Addr va, uint64_t asn) 27111308Santhony.gutierrez@amd.com { 27211308Santhony.gutierrez@amd.com 27311308Santhony.gutierrez@amd.com int set = (va >> TheISA::PageShift) & setMask; 27411308Santhony.gutierrez@amd.com auto entry = lookupIt(va, false); 27511308Santhony.gutierrez@amd.com 27611308Santhony.gutierrez@amd.com if (entry != entryList[set].end()) { 27711308Santhony.gutierrez@amd.com freeList[set].push_back(*entry); 27811308Santhony.gutierrez@amd.com entryList[set].erase(entry); 27911308Santhony.gutierrez@amd.com } 28011308Santhony.gutierrez@amd.com } 28111308Santhony.gutierrez@amd.com 28211308Santhony.gutierrez@amd.com Fault 28312749Sgiacomo.travaglini@arm.com GpuTLB::translateInt(const RequestPtr &req, ThreadContext *tc) 28411308Santhony.gutierrez@amd.com { 28511308Santhony.gutierrez@amd.com DPRINTF(GPUTLB, "Addresses references internal memory.\n"); 28611308Santhony.gutierrez@amd.com Addr vaddr = req->getVaddr(); 28711308Santhony.gutierrez@amd.com Addr prefix = (vaddr >> 3) & IntAddrPrefixMask; 28811308Santhony.gutierrez@amd.com 28911308Santhony.gutierrez@amd.com if (prefix == IntAddrPrefixCPUID) { 29011308Santhony.gutierrez@amd.com panic("CPUID memory space not yet implemented!\n"); 29111308Santhony.gutierrez@amd.com } else if (prefix == IntAddrPrefixMSR) { 29211308Santhony.gutierrez@amd.com vaddr = vaddr >> 3; 29311308Santhony.gutierrez@amd.com req->setFlags(Request::MMAPPED_IPR); 29411308Santhony.gutierrez@amd.com Addr regNum = 0; 29511308Santhony.gutierrez@amd.com 29611308Santhony.gutierrez@amd.com switch (vaddr & ~IntAddrPrefixMask) { 29711308Santhony.gutierrez@amd.com case 0x10: 29811308Santhony.gutierrez@amd.com regNum = MISCREG_TSC; 29911308Santhony.gutierrez@amd.com break; 30011308Santhony.gutierrez@amd.com case 0x1B: 30111308Santhony.gutierrez@amd.com regNum = MISCREG_APIC_BASE; 30211308Santhony.gutierrez@amd.com break; 30311308Santhony.gutierrez@amd.com case 0xFE: 30411308Santhony.gutierrez@amd.com regNum = MISCREG_MTRRCAP; 30511308Santhony.gutierrez@amd.com break; 30611308Santhony.gutierrez@amd.com case 0x174: 30711308Santhony.gutierrez@amd.com regNum = MISCREG_SYSENTER_CS; 30811308Santhony.gutierrez@amd.com break; 30911308Santhony.gutierrez@amd.com case 0x175: 31011308Santhony.gutierrez@amd.com regNum = MISCREG_SYSENTER_ESP; 31111308Santhony.gutierrez@amd.com break; 31211308Santhony.gutierrez@amd.com case 0x176: 31311308Santhony.gutierrez@amd.com regNum = MISCREG_SYSENTER_EIP; 31411308Santhony.gutierrez@amd.com break; 31511308Santhony.gutierrez@amd.com case 0x179: 31611308Santhony.gutierrez@amd.com regNum = MISCREG_MCG_CAP; 31711308Santhony.gutierrez@amd.com break; 31811308Santhony.gutierrez@amd.com case 0x17A: 31911308Santhony.gutierrez@amd.com regNum = MISCREG_MCG_STATUS; 32011308Santhony.gutierrez@amd.com break; 32111308Santhony.gutierrez@amd.com case 0x17B: 32211308Santhony.gutierrez@amd.com regNum = MISCREG_MCG_CTL; 32311308Santhony.gutierrez@amd.com break; 32411308Santhony.gutierrez@amd.com case 0x1D9: 32511308Santhony.gutierrez@amd.com regNum = MISCREG_DEBUG_CTL_MSR; 32611308Santhony.gutierrez@amd.com break; 32711308Santhony.gutierrez@amd.com case 0x1DB: 32811308Santhony.gutierrez@amd.com regNum = MISCREG_LAST_BRANCH_FROM_IP; 32911308Santhony.gutierrez@amd.com break; 33011308Santhony.gutierrez@amd.com case 0x1DC: 33111308Santhony.gutierrez@amd.com regNum = MISCREG_LAST_BRANCH_TO_IP; 33211308Santhony.gutierrez@amd.com break; 33311308Santhony.gutierrez@amd.com case 0x1DD: 33411308Santhony.gutierrez@amd.com regNum = MISCREG_LAST_EXCEPTION_FROM_IP; 33511308Santhony.gutierrez@amd.com break; 33611308Santhony.gutierrez@amd.com case 0x1DE: 33711308Santhony.gutierrez@amd.com regNum = MISCREG_LAST_EXCEPTION_TO_IP; 33811308Santhony.gutierrez@amd.com break; 33911308Santhony.gutierrez@amd.com case 0x200: 34011308Santhony.gutierrez@amd.com regNum = MISCREG_MTRR_PHYS_BASE_0; 34111308Santhony.gutierrez@amd.com break; 34211308Santhony.gutierrez@amd.com case 0x201: 34311308Santhony.gutierrez@amd.com regNum = MISCREG_MTRR_PHYS_MASK_0; 34411308Santhony.gutierrez@amd.com break; 34511308Santhony.gutierrez@amd.com case 0x202: 34611308Santhony.gutierrez@amd.com regNum = MISCREG_MTRR_PHYS_BASE_1; 34711308Santhony.gutierrez@amd.com break; 34811308Santhony.gutierrez@amd.com case 0x203: 34911308Santhony.gutierrez@amd.com regNum = MISCREG_MTRR_PHYS_MASK_1; 35011308Santhony.gutierrez@amd.com break; 35111308Santhony.gutierrez@amd.com case 0x204: 35211308Santhony.gutierrez@amd.com regNum = MISCREG_MTRR_PHYS_BASE_2; 35311308Santhony.gutierrez@amd.com break; 35411308Santhony.gutierrez@amd.com case 0x205: 35511308Santhony.gutierrez@amd.com regNum = MISCREG_MTRR_PHYS_MASK_2; 35611308Santhony.gutierrez@amd.com break; 35711308Santhony.gutierrez@amd.com case 0x206: 35811308Santhony.gutierrez@amd.com regNum = MISCREG_MTRR_PHYS_BASE_3; 35911308Santhony.gutierrez@amd.com break; 36011308Santhony.gutierrez@amd.com case 0x207: 36111308Santhony.gutierrez@amd.com regNum = MISCREG_MTRR_PHYS_MASK_3; 36211308Santhony.gutierrez@amd.com break; 36311308Santhony.gutierrez@amd.com case 0x208: 36411308Santhony.gutierrez@amd.com regNum = MISCREG_MTRR_PHYS_BASE_4; 36511308Santhony.gutierrez@amd.com break; 36611308Santhony.gutierrez@amd.com case 0x209: 36711308Santhony.gutierrez@amd.com regNum = MISCREG_MTRR_PHYS_MASK_4; 36811308Santhony.gutierrez@amd.com break; 36911308Santhony.gutierrez@amd.com case 0x20A: 37011308Santhony.gutierrez@amd.com regNum = MISCREG_MTRR_PHYS_BASE_5; 37111308Santhony.gutierrez@amd.com break; 37211308Santhony.gutierrez@amd.com case 0x20B: 37311308Santhony.gutierrez@amd.com regNum = MISCREG_MTRR_PHYS_MASK_5; 37411308Santhony.gutierrez@amd.com break; 37511308Santhony.gutierrez@amd.com case 0x20C: 37611308Santhony.gutierrez@amd.com regNum = MISCREG_MTRR_PHYS_BASE_6; 37711308Santhony.gutierrez@amd.com break; 37811308Santhony.gutierrez@amd.com case 0x20D: 37911308Santhony.gutierrez@amd.com regNum = MISCREG_MTRR_PHYS_MASK_6; 38011308Santhony.gutierrez@amd.com break; 38111308Santhony.gutierrez@amd.com case 0x20E: 38211308Santhony.gutierrez@amd.com regNum = MISCREG_MTRR_PHYS_BASE_7; 38311308Santhony.gutierrez@amd.com break; 38411308Santhony.gutierrez@amd.com case 0x20F: 38511308Santhony.gutierrez@amd.com regNum = MISCREG_MTRR_PHYS_MASK_7; 38611308Santhony.gutierrez@amd.com break; 38711308Santhony.gutierrez@amd.com case 0x250: 38811308Santhony.gutierrez@amd.com regNum = MISCREG_MTRR_FIX_64K_00000; 38911308Santhony.gutierrez@amd.com break; 39011308Santhony.gutierrez@amd.com case 0x258: 39111308Santhony.gutierrez@amd.com regNum = MISCREG_MTRR_FIX_16K_80000; 39211308Santhony.gutierrez@amd.com break; 39311308Santhony.gutierrez@amd.com case 0x259: 39411308Santhony.gutierrez@amd.com regNum = MISCREG_MTRR_FIX_16K_A0000; 39511308Santhony.gutierrez@amd.com break; 39611308Santhony.gutierrez@amd.com case 0x268: 39711308Santhony.gutierrez@amd.com regNum = MISCREG_MTRR_FIX_4K_C0000; 39811308Santhony.gutierrez@amd.com break; 39911308Santhony.gutierrez@amd.com case 0x269: 40011308Santhony.gutierrez@amd.com regNum = MISCREG_MTRR_FIX_4K_C8000; 40111308Santhony.gutierrez@amd.com break; 40211308Santhony.gutierrez@amd.com case 0x26A: 40311308Santhony.gutierrez@amd.com regNum = MISCREG_MTRR_FIX_4K_D0000; 40411308Santhony.gutierrez@amd.com break; 40511308Santhony.gutierrez@amd.com case 0x26B: 40611308Santhony.gutierrez@amd.com regNum = MISCREG_MTRR_FIX_4K_D8000; 40711308Santhony.gutierrez@amd.com break; 40811308Santhony.gutierrez@amd.com case 0x26C: 40911308Santhony.gutierrez@amd.com regNum = MISCREG_MTRR_FIX_4K_E0000; 41011308Santhony.gutierrez@amd.com break; 41111308Santhony.gutierrez@amd.com case 0x26D: 41211308Santhony.gutierrez@amd.com regNum = MISCREG_MTRR_FIX_4K_E8000; 41311308Santhony.gutierrez@amd.com break; 41411308Santhony.gutierrez@amd.com case 0x26E: 41511308Santhony.gutierrez@amd.com regNum = MISCREG_MTRR_FIX_4K_F0000; 41611308Santhony.gutierrez@amd.com break; 41711308Santhony.gutierrez@amd.com case 0x26F: 41811308Santhony.gutierrez@amd.com regNum = MISCREG_MTRR_FIX_4K_F8000; 41911308Santhony.gutierrez@amd.com break; 42011308Santhony.gutierrez@amd.com case 0x277: 42111308Santhony.gutierrez@amd.com regNum = MISCREG_PAT; 42211308Santhony.gutierrez@amd.com break; 42311308Santhony.gutierrez@amd.com case 0x2FF: 42411308Santhony.gutierrez@amd.com regNum = MISCREG_DEF_TYPE; 42511308Santhony.gutierrez@amd.com break; 42611308Santhony.gutierrez@amd.com case 0x400: 42711308Santhony.gutierrez@amd.com regNum = MISCREG_MC0_CTL; 42811308Santhony.gutierrez@amd.com break; 42911308Santhony.gutierrez@amd.com case 0x404: 43011308Santhony.gutierrez@amd.com regNum = MISCREG_MC1_CTL; 43111308Santhony.gutierrez@amd.com break; 43211308Santhony.gutierrez@amd.com case 0x408: 43311308Santhony.gutierrez@amd.com regNum = MISCREG_MC2_CTL; 43411308Santhony.gutierrez@amd.com break; 43511308Santhony.gutierrez@amd.com case 0x40C: 43611308Santhony.gutierrez@amd.com regNum = MISCREG_MC3_CTL; 43711308Santhony.gutierrez@amd.com break; 43811308Santhony.gutierrez@amd.com case 0x410: 43911308Santhony.gutierrez@amd.com regNum = MISCREG_MC4_CTL; 44011308Santhony.gutierrez@amd.com break; 44111308Santhony.gutierrez@amd.com case 0x414: 44211308Santhony.gutierrez@amd.com regNum = MISCREG_MC5_CTL; 44311308Santhony.gutierrez@amd.com break; 44411308Santhony.gutierrez@amd.com case 0x418: 44511308Santhony.gutierrez@amd.com regNum = MISCREG_MC6_CTL; 44611308Santhony.gutierrez@amd.com break; 44711308Santhony.gutierrez@amd.com case 0x41C: 44811308Santhony.gutierrez@amd.com regNum = MISCREG_MC7_CTL; 44911308Santhony.gutierrez@amd.com break; 45011308Santhony.gutierrez@amd.com case 0x401: 45111308Santhony.gutierrez@amd.com regNum = MISCREG_MC0_STATUS; 45211308Santhony.gutierrez@amd.com break; 45311308Santhony.gutierrez@amd.com case 0x405: 45411308Santhony.gutierrez@amd.com regNum = MISCREG_MC1_STATUS; 45511308Santhony.gutierrez@amd.com break; 45611308Santhony.gutierrez@amd.com case 0x409: 45711308Santhony.gutierrez@amd.com regNum = MISCREG_MC2_STATUS; 45811308Santhony.gutierrez@amd.com break; 45911308Santhony.gutierrez@amd.com case 0x40D: 46011308Santhony.gutierrez@amd.com regNum = MISCREG_MC3_STATUS; 46111308Santhony.gutierrez@amd.com break; 46211308Santhony.gutierrez@amd.com case 0x411: 46311308Santhony.gutierrez@amd.com regNum = MISCREG_MC4_STATUS; 46411308Santhony.gutierrez@amd.com break; 46511308Santhony.gutierrez@amd.com case 0x415: 46611308Santhony.gutierrez@amd.com regNum = MISCREG_MC5_STATUS; 46711308Santhony.gutierrez@amd.com break; 46811308Santhony.gutierrez@amd.com case 0x419: 46911308Santhony.gutierrez@amd.com regNum = MISCREG_MC6_STATUS; 47011308Santhony.gutierrez@amd.com break; 47111308Santhony.gutierrez@amd.com case 0x41D: 47211308Santhony.gutierrez@amd.com regNum = MISCREG_MC7_STATUS; 47311308Santhony.gutierrez@amd.com break; 47411308Santhony.gutierrez@amd.com case 0x402: 47511308Santhony.gutierrez@amd.com regNum = MISCREG_MC0_ADDR; 47611308Santhony.gutierrez@amd.com break; 47711308Santhony.gutierrez@amd.com case 0x406: 47811308Santhony.gutierrez@amd.com regNum = MISCREG_MC1_ADDR; 47911308Santhony.gutierrez@amd.com break; 48011308Santhony.gutierrez@amd.com case 0x40A: 48111308Santhony.gutierrez@amd.com regNum = MISCREG_MC2_ADDR; 48211308Santhony.gutierrez@amd.com break; 48311308Santhony.gutierrez@amd.com case 0x40E: 48411308Santhony.gutierrez@amd.com regNum = MISCREG_MC3_ADDR; 48511308Santhony.gutierrez@amd.com break; 48611308Santhony.gutierrez@amd.com case 0x412: 48711308Santhony.gutierrez@amd.com regNum = MISCREG_MC4_ADDR; 48811308Santhony.gutierrez@amd.com break; 48911308Santhony.gutierrez@amd.com case 0x416: 49011308Santhony.gutierrez@amd.com regNum = MISCREG_MC5_ADDR; 49111308Santhony.gutierrez@amd.com break; 49211308Santhony.gutierrez@amd.com case 0x41A: 49311308Santhony.gutierrez@amd.com regNum = MISCREG_MC6_ADDR; 49411308Santhony.gutierrez@amd.com break; 49511308Santhony.gutierrez@amd.com case 0x41E: 49611308Santhony.gutierrez@amd.com regNum = MISCREG_MC7_ADDR; 49711308Santhony.gutierrez@amd.com break; 49811308Santhony.gutierrez@amd.com case 0x403: 49911308Santhony.gutierrez@amd.com regNum = MISCREG_MC0_MISC; 50011308Santhony.gutierrez@amd.com break; 50111308Santhony.gutierrez@amd.com case 0x407: 50211308Santhony.gutierrez@amd.com regNum = MISCREG_MC1_MISC; 50311308Santhony.gutierrez@amd.com break; 50411308Santhony.gutierrez@amd.com case 0x40B: 50511308Santhony.gutierrez@amd.com regNum = MISCREG_MC2_MISC; 50611308Santhony.gutierrez@amd.com break; 50711308Santhony.gutierrez@amd.com case 0x40F: 50811308Santhony.gutierrez@amd.com regNum = MISCREG_MC3_MISC; 50911308Santhony.gutierrez@amd.com break; 51011308Santhony.gutierrez@amd.com case 0x413: 51111308Santhony.gutierrez@amd.com regNum = MISCREG_MC4_MISC; 51211308Santhony.gutierrez@amd.com break; 51311308Santhony.gutierrez@amd.com case 0x417: 51411308Santhony.gutierrez@amd.com regNum = MISCREG_MC5_MISC; 51511308Santhony.gutierrez@amd.com break; 51611308Santhony.gutierrez@amd.com case 0x41B: 51711308Santhony.gutierrez@amd.com regNum = MISCREG_MC6_MISC; 51811308Santhony.gutierrez@amd.com break; 51911308Santhony.gutierrez@amd.com case 0x41F: 52011308Santhony.gutierrez@amd.com regNum = MISCREG_MC7_MISC; 52111308Santhony.gutierrez@amd.com break; 52211308Santhony.gutierrez@amd.com case 0xC0000080: 52311308Santhony.gutierrez@amd.com regNum = MISCREG_EFER; 52411308Santhony.gutierrez@amd.com break; 52511308Santhony.gutierrez@amd.com case 0xC0000081: 52611308Santhony.gutierrez@amd.com regNum = MISCREG_STAR; 52711308Santhony.gutierrez@amd.com break; 52811308Santhony.gutierrez@amd.com case 0xC0000082: 52911308Santhony.gutierrez@amd.com regNum = MISCREG_LSTAR; 53011308Santhony.gutierrez@amd.com break; 53111308Santhony.gutierrez@amd.com case 0xC0000083: 53211308Santhony.gutierrez@amd.com regNum = MISCREG_CSTAR; 53311308Santhony.gutierrez@amd.com break; 53411308Santhony.gutierrez@amd.com case 0xC0000084: 53511308Santhony.gutierrez@amd.com regNum = MISCREG_SF_MASK; 53611308Santhony.gutierrez@amd.com break; 53711308Santhony.gutierrez@amd.com case 0xC0000100: 53811308Santhony.gutierrez@amd.com regNum = MISCREG_FS_BASE; 53911308Santhony.gutierrez@amd.com break; 54011308Santhony.gutierrez@amd.com case 0xC0000101: 54111308Santhony.gutierrez@amd.com regNum = MISCREG_GS_BASE; 54211308Santhony.gutierrez@amd.com break; 54311308Santhony.gutierrez@amd.com case 0xC0000102: 54411308Santhony.gutierrez@amd.com regNum = MISCREG_KERNEL_GS_BASE; 54511308Santhony.gutierrez@amd.com break; 54611308Santhony.gutierrez@amd.com case 0xC0000103: 54711308Santhony.gutierrez@amd.com regNum = MISCREG_TSC_AUX; 54811308Santhony.gutierrez@amd.com break; 54911308Santhony.gutierrez@amd.com case 0xC0010000: 55011308Santhony.gutierrez@amd.com regNum = MISCREG_PERF_EVT_SEL0; 55111308Santhony.gutierrez@amd.com break; 55211308Santhony.gutierrez@amd.com case 0xC0010001: 55311308Santhony.gutierrez@amd.com regNum = MISCREG_PERF_EVT_SEL1; 55411308Santhony.gutierrez@amd.com break; 55511308Santhony.gutierrez@amd.com case 0xC0010002: 55611308Santhony.gutierrez@amd.com regNum = MISCREG_PERF_EVT_SEL2; 55711308Santhony.gutierrez@amd.com break; 55811308Santhony.gutierrez@amd.com case 0xC0010003: 55911308Santhony.gutierrez@amd.com regNum = MISCREG_PERF_EVT_SEL3; 56011308Santhony.gutierrez@amd.com break; 56111308Santhony.gutierrez@amd.com case 0xC0010004: 56211308Santhony.gutierrez@amd.com regNum = MISCREG_PERF_EVT_CTR0; 56311308Santhony.gutierrez@amd.com break; 56411308Santhony.gutierrez@amd.com case 0xC0010005: 56511308Santhony.gutierrez@amd.com regNum = MISCREG_PERF_EVT_CTR1; 56611308Santhony.gutierrez@amd.com break; 56711308Santhony.gutierrez@amd.com case 0xC0010006: 56811308Santhony.gutierrez@amd.com regNum = MISCREG_PERF_EVT_CTR2; 56911308Santhony.gutierrez@amd.com break; 57011308Santhony.gutierrez@amd.com case 0xC0010007: 57111308Santhony.gutierrez@amd.com regNum = MISCREG_PERF_EVT_CTR3; 57211308Santhony.gutierrez@amd.com break; 57311308Santhony.gutierrez@amd.com case 0xC0010010: 57411308Santhony.gutierrez@amd.com regNum = MISCREG_SYSCFG; 57511308Santhony.gutierrez@amd.com break; 57611308Santhony.gutierrez@amd.com case 0xC0010016: 57711308Santhony.gutierrez@amd.com regNum = MISCREG_IORR_BASE0; 57811308Santhony.gutierrez@amd.com break; 57911308Santhony.gutierrez@amd.com case 0xC0010017: 58011308Santhony.gutierrez@amd.com regNum = MISCREG_IORR_BASE1; 58111308Santhony.gutierrez@amd.com break; 58211308Santhony.gutierrez@amd.com case 0xC0010018: 58311308Santhony.gutierrez@amd.com regNum = MISCREG_IORR_MASK0; 58411308Santhony.gutierrez@amd.com break; 58511308Santhony.gutierrez@amd.com case 0xC0010019: 58611308Santhony.gutierrez@amd.com regNum = MISCREG_IORR_MASK1; 58711308Santhony.gutierrez@amd.com break; 58811308Santhony.gutierrez@amd.com case 0xC001001A: 58911308Santhony.gutierrez@amd.com regNum = MISCREG_TOP_MEM; 59011308Santhony.gutierrez@amd.com break; 59111308Santhony.gutierrez@amd.com case 0xC001001D: 59211308Santhony.gutierrez@amd.com regNum = MISCREG_TOP_MEM2; 59311308Santhony.gutierrez@amd.com break; 59411308Santhony.gutierrez@amd.com case 0xC0010114: 59511308Santhony.gutierrez@amd.com regNum = MISCREG_VM_CR; 59611308Santhony.gutierrez@amd.com break; 59711308Santhony.gutierrez@amd.com case 0xC0010115: 59811308Santhony.gutierrez@amd.com regNum = MISCREG_IGNNE; 59911308Santhony.gutierrez@amd.com break; 60011308Santhony.gutierrez@amd.com case 0xC0010116: 60111308Santhony.gutierrez@amd.com regNum = MISCREG_SMM_CTL; 60211308Santhony.gutierrez@amd.com break; 60311308Santhony.gutierrez@amd.com case 0xC0010117: 60411308Santhony.gutierrez@amd.com regNum = MISCREG_VM_HSAVE_PA; 60511308Santhony.gutierrez@amd.com break; 60611308Santhony.gutierrez@amd.com default: 60711308Santhony.gutierrez@amd.com return std::make_shared<GeneralProtection>(0); 60811308Santhony.gutierrez@amd.com } 60911308Santhony.gutierrez@amd.com //The index is multiplied by the size of a MiscReg so that 61011308Santhony.gutierrez@amd.com //any memory dependence calculations will not see these as 61111308Santhony.gutierrez@amd.com //overlapping. 61213557Sgabeblack@google.com req->setPaddr(regNum * sizeof(RegVal)); 61311308Santhony.gutierrez@amd.com return NoFault; 61411308Santhony.gutierrez@amd.com } else if (prefix == IntAddrPrefixIO) { 61511308Santhony.gutierrez@amd.com // TODO If CPL > IOPL or in virtual mode, check the I/O permission 61611308Santhony.gutierrez@amd.com // bitmap in the TSS. 61711308Santhony.gutierrez@amd.com 61811308Santhony.gutierrez@amd.com Addr IOPort = vaddr & ~IntAddrPrefixMask; 61911308Santhony.gutierrez@amd.com // Make sure the address fits in the expected 16 bit IO address 62011308Santhony.gutierrez@amd.com // space. 62111308Santhony.gutierrez@amd.com assert(!(IOPort & ~0xFFFF)); 62211308Santhony.gutierrez@amd.com 62311308Santhony.gutierrez@amd.com if (IOPort == 0xCF8 && req->getSize() == 4) { 62411308Santhony.gutierrez@amd.com req->setFlags(Request::MMAPPED_IPR); 62513557Sgabeblack@google.com req->setPaddr(MISCREG_PCI_CONFIG_ADDRESS * sizeof(RegVal)); 62611308Santhony.gutierrez@amd.com } else if ((IOPort & ~mask(2)) == 0xCFC) { 62711308Santhony.gutierrez@amd.com req->setFlags(Request::UNCACHEABLE); 62811308Santhony.gutierrez@amd.com 62911308Santhony.gutierrez@amd.com Addr configAddress = 63011308Santhony.gutierrez@amd.com tc->readMiscRegNoEffect(MISCREG_PCI_CONFIG_ADDRESS); 63111308Santhony.gutierrez@amd.com 63211308Santhony.gutierrez@amd.com if (bits(configAddress, 31, 31)) { 63311308Santhony.gutierrez@amd.com req->setPaddr(PhysAddrPrefixPciConfig | 63411308Santhony.gutierrez@amd.com mbits(configAddress, 30, 2) | 63511308Santhony.gutierrez@amd.com (IOPort & mask(2))); 63611308Santhony.gutierrez@amd.com } else { 63711308Santhony.gutierrez@amd.com req->setPaddr(PhysAddrPrefixIO | IOPort); 63811308Santhony.gutierrez@amd.com } 63911308Santhony.gutierrez@amd.com } else { 64011308Santhony.gutierrez@amd.com req->setFlags(Request::UNCACHEABLE); 64111308Santhony.gutierrez@amd.com req->setPaddr(PhysAddrPrefixIO | IOPort); 64211308Santhony.gutierrez@amd.com } 64311308Santhony.gutierrez@amd.com return NoFault; 64411308Santhony.gutierrez@amd.com } else { 64511308Santhony.gutierrez@amd.com panic("Access to unrecognized internal address space %#x.\n", 64611308Santhony.gutierrez@amd.com prefix); 64711308Santhony.gutierrez@amd.com } 64811308Santhony.gutierrez@amd.com } 64911308Santhony.gutierrez@amd.com 65011308Santhony.gutierrez@amd.com /** 65111308Santhony.gutierrez@amd.com * TLB_lookup will only perform a TLB lookup returning true on a TLB hit 65211308Santhony.gutierrez@amd.com * and false on a TLB miss. 65311308Santhony.gutierrez@amd.com * Many of the checks about different modes have been converted to 65411308Santhony.gutierrez@amd.com * assertions, since these parts of the code are not really used. 65511308Santhony.gutierrez@amd.com * On a hit it will update the LRU stack. 65611308Santhony.gutierrez@amd.com */ 65711308Santhony.gutierrez@amd.com bool 65812749Sgiacomo.travaglini@arm.com GpuTLB::tlbLookup(const RequestPtr &req, 65912749Sgiacomo.travaglini@arm.com ThreadContext *tc, bool update_stats) 66011308Santhony.gutierrez@amd.com { 66111308Santhony.gutierrez@amd.com bool tlb_hit = false; 66211308Santhony.gutierrez@amd.com #ifndef NDEBUG 66311308Santhony.gutierrez@amd.com uint32_t flags = req->getFlags(); 66411308Santhony.gutierrez@amd.com int seg = flags & SegmentFlagMask; 66511308Santhony.gutierrez@amd.com #endif 66611308Santhony.gutierrez@amd.com 66711308Santhony.gutierrez@amd.com assert(seg != SEGMENT_REG_MS); 66811308Santhony.gutierrez@amd.com Addr vaddr = req->getVaddr(); 66911308Santhony.gutierrez@amd.com DPRINTF(GPUTLB, "TLB Lookup for vaddr %#x.\n", vaddr); 67011308Santhony.gutierrez@amd.com HandyM5Reg m5Reg = tc->readMiscRegNoEffect(MISCREG_M5_REG); 67111308Santhony.gutierrez@amd.com 67211308Santhony.gutierrez@amd.com if (m5Reg.prot) { 67311308Santhony.gutierrez@amd.com DPRINTF(GPUTLB, "In protected mode.\n"); 67411308Santhony.gutierrez@amd.com // make sure we are in 64-bit mode 67511308Santhony.gutierrez@amd.com assert(m5Reg.mode == LongMode); 67611308Santhony.gutierrez@amd.com 67711308Santhony.gutierrez@amd.com // If paging is enabled, do the translation. 67811308Santhony.gutierrez@amd.com if (m5Reg.paging) { 67911308Santhony.gutierrez@amd.com DPRINTF(GPUTLB, "Paging enabled.\n"); 68011308Santhony.gutierrez@amd.com //update LRU stack on a hit 68112717Sbrandon.potter@amd.com TlbEntry *entry = lookup(vaddr, true); 68211308Santhony.gutierrez@amd.com 68311308Santhony.gutierrez@amd.com if (entry) 68411308Santhony.gutierrez@amd.com tlb_hit = true; 68511308Santhony.gutierrez@amd.com 68611308Santhony.gutierrez@amd.com if (!update_stats) { 68711308Santhony.gutierrez@amd.com // functional tlb access for memory initialization 68811308Santhony.gutierrez@amd.com // i.e., memory seeding or instr. seeding -> don't update 68911308Santhony.gutierrez@amd.com // TLB and stats 69011308Santhony.gutierrez@amd.com return tlb_hit; 69111308Santhony.gutierrez@amd.com } 69211308Santhony.gutierrez@amd.com 69311308Santhony.gutierrez@amd.com localNumTLBAccesses++; 69411308Santhony.gutierrez@amd.com 69511308Santhony.gutierrez@amd.com if (!entry) { 69611308Santhony.gutierrez@amd.com localNumTLBMisses++; 69711308Santhony.gutierrez@amd.com } else { 69811308Santhony.gutierrez@amd.com localNumTLBHits++; 69911308Santhony.gutierrez@amd.com } 70011308Santhony.gutierrez@amd.com } 70111308Santhony.gutierrez@amd.com } 70211308Santhony.gutierrez@amd.com 70311308Santhony.gutierrez@amd.com return tlb_hit; 70411308Santhony.gutierrez@amd.com } 70511308Santhony.gutierrez@amd.com 70611308Santhony.gutierrez@amd.com Fault 70712749Sgiacomo.travaglini@arm.com GpuTLB::translate(const RequestPtr &req, ThreadContext *tc, 70811308Santhony.gutierrez@amd.com Translation *translation, Mode mode, 70911308Santhony.gutierrez@amd.com bool &delayedResponse, bool timing, int &latency) 71011308Santhony.gutierrez@amd.com { 71111308Santhony.gutierrez@amd.com uint32_t flags = req->getFlags(); 71211308Santhony.gutierrez@amd.com int seg = flags & SegmentFlagMask; 71311308Santhony.gutierrez@amd.com bool storeCheck = flags & (StoreCheck << FlagShift); 71411308Santhony.gutierrez@amd.com 71511308Santhony.gutierrez@amd.com // If this is true, we're dealing with a request 71611308Santhony.gutierrez@amd.com // to a non-memory address space. 71711308Santhony.gutierrez@amd.com if (seg == SEGMENT_REG_MS) { 71811308Santhony.gutierrez@amd.com return translateInt(req, tc); 71911308Santhony.gutierrez@amd.com } 72011308Santhony.gutierrez@amd.com 72111308Santhony.gutierrez@amd.com delayedResponse = false; 72211308Santhony.gutierrez@amd.com Addr vaddr = req->getVaddr(); 72311308Santhony.gutierrez@amd.com DPRINTF(GPUTLB, "Translating vaddr %#x.\n", vaddr); 72411308Santhony.gutierrez@amd.com 72511308Santhony.gutierrez@amd.com HandyM5Reg m5Reg = tc->readMiscRegNoEffect(MISCREG_M5_REG); 72611308Santhony.gutierrez@amd.com 72711308Santhony.gutierrez@amd.com // If protected mode has been enabled... 72811308Santhony.gutierrez@amd.com if (m5Reg.prot) { 72911308Santhony.gutierrez@amd.com DPRINTF(GPUTLB, "In protected mode.\n"); 73011308Santhony.gutierrez@amd.com // If we're not in 64-bit mode, do protection/limit checks 73111308Santhony.gutierrez@amd.com if (m5Reg.mode != LongMode) { 73211308Santhony.gutierrez@amd.com DPRINTF(GPUTLB, "Not in long mode. Checking segment " 73311308Santhony.gutierrez@amd.com "protection.\n"); 73411308Santhony.gutierrez@amd.com 73511308Santhony.gutierrez@amd.com // Check for a null segment selector. 73611308Santhony.gutierrez@amd.com if (!(seg == SEGMENT_REG_TSG || seg == SYS_SEGMENT_REG_IDTR || 73711308Santhony.gutierrez@amd.com seg == SEGMENT_REG_HS || seg == SEGMENT_REG_LS) 73811308Santhony.gutierrez@amd.com && !tc->readMiscRegNoEffect(MISCREG_SEG_SEL(seg))) { 73911308Santhony.gutierrez@amd.com return std::make_shared<GeneralProtection>(0); 74011308Santhony.gutierrez@amd.com } 74111308Santhony.gutierrez@amd.com 74211308Santhony.gutierrez@amd.com bool expandDown = false; 74311308Santhony.gutierrez@amd.com SegAttr attr = tc->readMiscRegNoEffect(MISCREG_SEG_ATTR(seg)); 74411308Santhony.gutierrez@amd.com 74511308Santhony.gutierrez@amd.com if (seg >= SEGMENT_REG_ES && seg <= SEGMENT_REG_HS) { 74611308Santhony.gutierrez@amd.com if (!attr.writable && (mode == BaseTLB::Write || 74711308Santhony.gutierrez@amd.com storeCheck)) 74811308Santhony.gutierrez@amd.com return std::make_shared<GeneralProtection>(0); 74911308Santhony.gutierrez@amd.com 75011308Santhony.gutierrez@amd.com if (!attr.readable && mode == BaseTLB::Read) 75111308Santhony.gutierrez@amd.com return std::make_shared<GeneralProtection>(0); 75211308Santhony.gutierrez@amd.com 75311308Santhony.gutierrez@amd.com expandDown = attr.expandDown; 75411308Santhony.gutierrez@amd.com 75511308Santhony.gutierrez@amd.com } 75611308Santhony.gutierrez@amd.com 75711308Santhony.gutierrez@amd.com Addr base = tc->readMiscRegNoEffect(MISCREG_SEG_BASE(seg)); 75811308Santhony.gutierrez@amd.com Addr limit = tc->readMiscRegNoEffect(MISCREG_SEG_LIMIT(seg)); 75911308Santhony.gutierrez@amd.com // This assumes we're not in 64 bit mode. If we were, the 76011308Santhony.gutierrez@amd.com // default address size is 64 bits, overridable to 32. 76111308Santhony.gutierrez@amd.com int size = 32; 76211308Santhony.gutierrez@amd.com bool sizeOverride = (flags & (AddrSizeFlagBit << FlagShift)); 76311308Santhony.gutierrez@amd.com SegAttr csAttr = tc->readMiscRegNoEffect(MISCREG_CS_ATTR); 76411308Santhony.gutierrez@amd.com 76511308Santhony.gutierrez@amd.com if ((csAttr.defaultSize && sizeOverride) || 76611308Santhony.gutierrez@amd.com (!csAttr.defaultSize && !sizeOverride)) { 76711308Santhony.gutierrez@amd.com size = 16; 76811308Santhony.gutierrez@amd.com } 76911308Santhony.gutierrez@amd.com 77011308Santhony.gutierrez@amd.com Addr offset = bits(vaddr - base, size - 1, 0); 77111308Santhony.gutierrez@amd.com Addr endOffset = offset + req->getSize() - 1; 77211308Santhony.gutierrez@amd.com 77311308Santhony.gutierrez@amd.com if (expandDown) { 77411308Santhony.gutierrez@amd.com DPRINTF(GPUTLB, "Checking an expand down segment.\n"); 77511308Santhony.gutierrez@amd.com warn_once("Expand down segments are untested.\n"); 77611308Santhony.gutierrez@amd.com 77711308Santhony.gutierrez@amd.com if (offset <= limit || endOffset <= limit) 77811308Santhony.gutierrez@amd.com return std::make_shared<GeneralProtection>(0); 77911308Santhony.gutierrez@amd.com } else { 78011308Santhony.gutierrez@amd.com if (offset > limit || endOffset > limit) 78111308Santhony.gutierrez@amd.com return std::make_shared<GeneralProtection>(0); 78211308Santhony.gutierrez@amd.com } 78311308Santhony.gutierrez@amd.com } 78411308Santhony.gutierrez@amd.com 78511308Santhony.gutierrez@amd.com // If paging is enabled, do the translation. 78611308Santhony.gutierrez@amd.com if (m5Reg.paging) { 78711308Santhony.gutierrez@amd.com DPRINTF(GPUTLB, "Paging enabled.\n"); 78811308Santhony.gutierrez@amd.com // The vaddr already has the segment base applied. 78912717Sbrandon.potter@amd.com TlbEntry *entry = lookup(vaddr); 79011308Santhony.gutierrez@amd.com localNumTLBAccesses++; 79111308Santhony.gutierrez@amd.com 79211308Santhony.gutierrez@amd.com if (!entry) { 79311308Santhony.gutierrez@amd.com localNumTLBMisses++; 79411308Santhony.gutierrez@amd.com if (timing) { 79511308Santhony.gutierrez@amd.com latency = missLatency1; 79611308Santhony.gutierrez@amd.com } 79711308Santhony.gutierrez@amd.com 79811308Santhony.gutierrez@amd.com if (FullSystem) { 79911308Santhony.gutierrez@amd.com fatal("GpuTLB doesn't support full-system mode\n"); 80011308Santhony.gutierrez@amd.com } else { 80111308Santhony.gutierrez@amd.com DPRINTF(GPUTLB, "Handling a TLB miss for address %#x " 80211308Santhony.gutierrez@amd.com "at pc %#x.\n", vaddr, tc->instAddr()); 80311308Santhony.gutierrez@amd.com 80411308Santhony.gutierrez@amd.com Process *p = tc->getProcessPtr(); 80512461Sgabeblack@google.com const EmulationPageTable::Entry *pte = 80612461Sgabeblack@google.com p->pTable->lookup(vaddr); 80711308Santhony.gutierrez@amd.com 80812461Sgabeblack@google.com if (!pte && mode != BaseTLB::Execute) { 80911308Santhony.gutierrez@amd.com // penalize a "page fault" more 81012455Sgabeblack@google.com if (timing) 81111308Santhony.gutierrez@amd.com latency += missLatency2; 81211308Santhony.gutierrez@amd.com 81311308Santhony.gutierrez@amd.com if (p->fixupStackFault(vaddr)) 81412461Sgabeblack@google.com pte = p->pTable->lookup(vaddr); 81511308Santhony.gutierrez@amd.com } 81611308Santhony.gutierrez@amd.com 81712461Sgabeblack@google.com if (!pte) { 81811308Santhony.gutierrez@amd.com return std::make_shared<PageFault>(vaddr, true, 81911308Santhony.gutierrez@amd.com mode, true, 82011308Santhony.gutierrez@amd.com false); 82111308Santhony.gutierrez@amd.com } else { 82211308Santhony.gutierrez@amd.com Addr alignedVaddr = p->pTable->pageAlign(vaddr); 82311308Santhony.gutierrez@amd.com 82411308Santhony.gutierrez@amd.com DPRINTF(GPUTLB, "Mapping %#x to %#x\n", 82512461Sgabeblack@google.com alignedVaddr, pte->paddr); 82611308Santhony.gutierrez@amd.com 82712717Sbrandon.potter@amd.com TlbEntry gpuEntry(p->pid(), alignedVaddr, 82812717Sbrandon.potter@amd.com pte->paddr, false, false); 82912455Sgabeblack@google.com entry = insert(alignedVaddr, gpuEntry); 83011308Santhony.gutierrez@amd.com } 83111308Santhony.gutierrez@amd.com 83211308Santhony.gutierrez@amd.com DPRINTF(GPUTLB, "Miss was serviced.\n"); 83311308Santhony.gutierrez@amd.com } 83411308Santhony.gutierrez@amd.com } else { 83511308Santhony.gutierrez@amd.com localNumTLBHits++; 83611308Santhony.gutierrez@amd.com 83711308Santhony.gutierrez@amd.com if (timing) { 83811308Santhony.gutierrez@amd.com latency = hitLatency; 83911308Santhony.gutierrez@amd.com } 84011308Santhony.gutierrez@amd.com } 84111308Santhony.gutierrez@amd.com 84211308Santhony.gutierrez@amd.com // Do paging protection checks. 84311308Santhony.gutierrez@amd.com bool inUser = (m5Reg.cpl == 3 && 84411308Santhony.gutierrez@amd.com !(flags & (CPL0FlagBit << FlagShift))); 84511308Santhony.gutierrez@amd.com 84611308Santhony.gutierrez@amd.com CR0 cr0 = tc->readMiscRegNoEffect(MISCREG_CR0); 84711308Santhony.gutierrez@amd.com bool badWrite = (!entry->writable && (inUser || cr0.wp)); 84811308Santhony.gutierrez@amd.com 84911308Santhony.gutierrez@amd.com if ((inUser && !entry->user) || (mode == BaseTLB::Write && 85011308Santhony.gutierrez@amd.com badWrite)) { 85111308Santhony.gutierrez@amd.com // The page must have been present to get into the TLB in 85211308Santhony.gutierrez@amd.com // the first place. We'll assume the reserved bits are 85311308Santhony.gutierrez@amd.com // fine even though we're not checking them. 85411308Santhony.gutierrez@amd.com return std::make_shared<PageFault>(vaddr, true, mode, 85511308Santhony.gutierrez@amd.com inUser, false); 85611308Santhony.gutierrez@amd.com } 85711308Santhony.gutierrez@amd.com 85811308Santhony.gutierrez@amd.com if (storeCheck && badWrite) { 85911308Santhony.gutierrez@amd.com // This would fault if this were a write, so return a page 86011308Santhony.gutierrez@amd.com // fault that reflects that happening. 86111308Santhony.gutierrez@amd.com return std::make_shared<PageFault>(vaddr, true, 86211308Santhony.gutierrez@amd.com BaseTLB::Write, 86311308Santhony.gutierrez@amd.com inUser, false); 86411308Santhony.gutierrez@amd.com } 86511308Santhony.gutierrez@amd.com 86611308Santhony.gutierrez@amd.com 86711308Santhony.gutierrez@amd.com DPRINTF(GPUTLB, "Entry found with paddr %#x, doing protection " 86811308Santhony.gutierrez@amd.com "checks.\n", entry->paddr); 86911308Santhony.gutierrez@amd.com 87011308Santhony.gutierrez@amd.com int page_size = entry->size(); 87111308Santhony.gutierrez@amd.com Addr paddr = entry->paddr | (vaddr & (page_size - 1)); 87211308Santhony.gutierrez@amd.com DPRINTF(GPUTLB, "Translated %#x -> %#x.\n", vaddr, paddr); 87311308Santhony.gutierrez@amd.com req->setPaddr(paddr); 87411308Santhony.gutierrez@amd.com 87511308Santhony.gutierrez@amd.com if (entry->uncacheable) 87611308Santhony.gutierrez@amd.com req->setFlags(Request::UNCACHEABLE); 87711308Santhony.gutierrez@amd.com } else { 87811308Santhony.gutierrez@amd.com //Use the address which already has segmentation applied. 87911308Santhony.gutierrez@amd.com DPRINTF(GPUTLB, "Paging disabled.\n"); 88011308Santhony.gutierrez@amd.com DPRINTF(GPUTLB, "Translated %#x -> %#x.\n", vaddr, vaddr); 88111308Santhony.gutierrez@amd.com req->setPaddr(vaddr); 88211308Santhony.gutierrez@amd.com } 88311308Santhony.gutierrez@amd.com } else { 88411308Santhony.gutierrez@amd.com // Real mode 88511308Santhony.gutierrez@amd.com DPRINTF(GPUTLB, "In real mode.\n"); 88611308Santhony.gutierrez@amd.com DPRINTF(GPUTLB, "Translated %#x -> %#x.\n", vaddr, vaddr); 88711308Santhony.gutierrez@amd.com req->setPaddr(vaddr); 88811308Santhony.gutierrez@amd.com } 88911308Santhony.gutierrez@amd.com 89011308Santhony.gutierrez@amd.com // Check for an access to the local APIC 89111308Santhony.gutierrez@amd.com if (FullSystem) { 89211308Santhony.gutierrez@amd.com LocalApicBase localApicBase = 89311308Santhony.gutierrez@amd.com tc->readMiscRegNoEffect(MISCREG_APIC_BASE); 89411308Santhony.gutierrez@amd.com 89511308Santhony.gutierrez@amd.com Addr baseAddr = localApicBase.base * PageBytes; 89611308Santhony.gutierrez@amd.com Addr paddr = req->getPaddr(); 89711308Santhony.gutierrez@amd.com 89811308Santhony.gutierrez@amd.com if (baseAddr <= paddr && baseAddr + PageBytes > paddr) { 89911308Santhony.gutierrez@amd.com // Force the access to be uncacheable. 90011308Santhony.gutierrez@amd.com req->setFlags(Request::UNCACHEABLE); 90111308Santhony.gutierrez@amd.com req->setPaddr(x86LocalAPICAddress(tc->contextId(), 90211308Santhony.gutierrez@amd.com paddr - baseAddr)); 90311308Santhony.gutierrez@amd.com } 90411308Santhony.gutierrez@amd.com } 90511308Santhony.gutierrez@amd.com 90611308Santhony.gutierrez@amd.com return NoFault; 90711308Santhony.gutierrez@amd.com }; 90811308Santhony.gutierrez@amd.com 90911308Santhony.gutierrez@amd.com Fault 91012749Sgiacomo.travaglini@arm.com GpuTLB::translateAtomic(const RequestPtr &req, ThreadContext *tc, 91112749Sgiacomo.travaglini@arm.com Mode mode, int &latency) 91211308Santhony.gutierrez@amd.com { 91311308Santhony.gutierrez@amd.com bool delayedResponse; 91411308Santhony.gutierrez@amd.com 91511308Santhony.gutierrez@amd.com return GpuTLB::translate(req, tc, nullptr, mode, delayedResponse, false, 91611308Santhony.gutierrez@amd.com latency); 91711308Santhony.gutierrez@amd.com } 91811308Santhony.gutierrez@amd.com 91911308Santhony.gutierrez@amd.com void 92012749Sgiacomo.travaglini@arm.com GpuTLB::translateTiming(const RequestPtr &req, ThreadContext *tc, 92111308Santhony.gutierrez@amd.com Translation *translation, Mode mode, int &latency) 92211308Santhony.gutierrez@amd.com { 92311308Santhony.gutierrez@amd.com bool delayedResponse; 92411308Santhony.gutierrez@amd.com assert(translation); 92511308Santhony.gutierrez@amd.com 92611308Santhony.gutierrez@amd.com Fault fault = GpuTLB::translate(req, tc, translation, mode, 92711308Santhony.gutierrez@amd.com delayedResponse, true, latency); 92811308Santhony.gutierrez@amd.com 92911308Santhony.gutierrez@amd.com if (!delayedResponse) 93011308Santhony.gutierrez@amd.com translation->finish(fault, req, tc, mode); 93111308Santhony.gutierrez@amd.com } 93211308Santhony.gutierrez@amd.com 93311308Santhony.gutierrez@amd.com Walker* 93411308Santhony.gutierrez@amd.com GpuTLB::getWalker() 93511308Santhony.gutierrez@amd.com { 93611308Santhony.gutierrez@amd.com return walker; 93711308Santhony.gutierrez@amd.com } 93811308Santhony.gutierrez@amd.com 93911308Santhony.gutierrez@amd.com 94011308Santhony.gutierrez@amd.com void 94111308Santhony.gutierrez@amd.com GpuTLB::serialize(CheckpointOut &cp) const 94211308Santhony.gutierrez@amd.com { 94311308Santhony.gutierrez@amd.com } 94411308Santhony.gutierrez@amd.com 94511308Santhony.gutierrez@amd.com void 94611308Santhony.gutierrez@amd.com GpuTLB::unserialize(CheckpointIn &cp) 94711308Santhony.gutierrez@amd.com { 94811308Santhony.gutierrez@amd.com } 94911308Santhony.gutierrez@amd.com 95011308Santhony.gutierrez@amd.com void 95111308Santhony.gutierrez@amd.com GpuTLB::regStats() 95211308Santhony.gutierrez@amd.com { 95311523Sdavid.guillen@arm.com MemObject::regStats(); 95411523Sdavid.guillen@arm.com 95511308Santhony.gutierrez@amd.com localNumTLBAccesses 95611308Santhony.gutierrez@amd.com .name(name() + ".local_TLB_accesses") 95711308Santhony.gutierrez@amd.com .desc("Number of TLB accesses") 95811308Santhony.gutierrez@amd.com ; 95911308Santhony.gutierrez@amd.com 96011308Santhony.gutierrez@amd.com localNumTLBHits 96111308Santhony.gutierrez@amd.com .name(name() + ".local_TLB_hits") 96211308Santhony.gutierrez@amd.com .desc("Number of TLB hits") 96311308Santhony.gutierrez@amd.com ; 96411308Santhony.gutierrez@amd.com 96511308Santhony.gutierrez@amd.com localNumTLBMisses 96611308Santhony.gutierrez@amd.com .name(name() + ".local_TLB_misses") 96711308Santhony.gutierrez@amd.com .desc("Number of TLB misses") 96811308Santhony.gutierrez@amd.com ; 96911308Santhony.gutierrez@amd.com 97011308Santhony.gutierrez@amd.com localTLBMissRate 97111308Santhony.gutierrez@amd.com .name(name() + ".local_TLB_miss_rate") 97211308Santhony.gutierrez@amd.com .desc("TLB miss rate") 97311308Santhony.gutierrez@amd.com ; 97411308Santhony.gutierrez@amd.com 97511308Santhony.gutierrez@amd.com accessCycles 97611308Santhony.gutierrez@amd.com .name(name() + ".access_cycles") 97711308Santhony.gutierrez@amd.com .desc("Cycles spent accessing this TLB level") 97811308Santhony.gutierrez@amd.com ; 97911308Santhony.gutierrez@amd.com 98011308Santhony.gutierrez@amd.com pageTableCycles 98111308Santhony.gutierrez@amd.com .name(name() + ".page_table_cycles") 98211308Santhony.gutierrez@amd.com .desc("Cycles spent accessing the page table") 98311308Santhony.gutierrez@amd.com ; 98411308Santhony.gutierrez@amd.com 98511308Santhony.gutierrez@amd.com localTLBMissRate = 100 * localNumTLBMisses / localNumTLBAccesses; 98611308Santhony.gutierrez@amd.com 98711308Santhony.gutierrez@amd.com numUniquePages 98811308Santhony.gutierrez@amd.com .name(name() + ".unique_pages") 98911308Santhony.gutierrez@amd.com .desc("Number of unique pages touched") 99011308Santhony.gutierrez@amd.com ; 99111308Santhony.gutierrez@amd.com 99211308Santhony.gutierrez@amd.com localCycles 99311308Santhony.gutierrez@amd.com .name(name() + ".local_cycles") 99411308Santhony.gutierrez@amd.com .desc("Number of cycles spent in queue for all incoming reqs") 99511308Santhony.gutierrez@amd.com ; 99611308Santhony.gutierrez@amd.com 99711308Santhony.gutierrez@amd.com localLatency 99811308Santhony.gutierrez@amd.com .name(name() + ".local_latency") 99911308Santhony.gutierrez@amd.com .desc("Avg. latency over incoming coalesced reqs") 100011308Santhony.gutierrez@amd.com ; 100111308Santhony.gutierrez@amd.com 100211308Santhony.gutierrez@amd.com localLatency = localCycles / localNumTLBAccesses; 100311308Santhony.gutierrez@amd.com 100411308Santhony.gutierrez@amd.com globalNumTLBAccesses 100511308Santhony.gutierrez@amd.com .name(name() + ".global_TLB_accesses") 100611308Santhony.gutierrez@amd.com .desc("Number of TLB accesses") 100711308Santhony.gutierrez@amd.com ; 100811308Santhony.gutierrez@amd.com 100911308Santhony.gutierrez@amd.com globalNumTLBHits 101011308Santhony.gutierrez@amd.com .name(name() + ".global_TLB_hits") 101111308Santhony.gutierrez@amd.com .desc("Number of TLB hits") 101211308Santhony.gutierrez@amd.com ; 101311308Santhony.gutierrez@amd.com 101411308Santhony.gutierrez@amd.com globalNumTLBMisses 101511308Santhony.gutierrez@amd.com .name(name() + ".global_TLB_misses") 101611308Santhony.gutierrez@amd.com .desc("Number of TLB misses") 101711308Santhony.gutierrez@amd.com ; 101811308Santhony.gutierrez@amd.com 101911308Santhony.gutierrez@amd.com globalTLBMissRate 102011308Santhony.gutierrez@amd.com .name(name() + ".global_TLB_miss_rate") 102111308Santhony.gutierrez@amd.com .desc("TLB miss rate") 102211308Santhony.gutierrez@amd.com ; 102311308Santhony.gutierrez@amd.com 102411308Santhony.gutierrez@amd.com globalTLBMissRate = 100 * globalNumTLBMisses / globalNumTLBAccesses; 102511308Santhony.gutierrez@amd.com 102611308Santhony.gutierrez@amd.com avgReuseDistance 102711308Santhony.gutierrez@amd.com .name(name() + ".avg_reuse_distance") 102811308Santhony.gutierrez@amd.com .desc("avg. reuse distance over all pages (in ticks)") 102911308Santhony.gutierrez@amd.com ; 103011308Santhony.gutierrez@amd.com 103111308Santhony.gutierrez@amd.com } 103211308Santhony.gutierrez@amd.com 103311308Santhony.gutierrez@amd.com /** 103411308Santhony.gutierrez@amd.com * Do the TLB lookup for this coalesced request and schedule 103511308Santhony.gutierrez@amd.com * another event <TLB access latency> cycles later. 103611308Santhony.gutierrez@amd.com */ 103711308Santhony.gutierrez@amd.com 103811308Santhony.gutierrez@amd.com void 103911308Santhony.gutierrez@amd.com GpuTLB::issueTLBLookup(PacketPtr pkt) 104011308Santhony.gutierrez@amd.com { 104111308Santhony.gutierrez@amd.com assert(pkt); 104211308Santhony.gutierrez@amd.com assert(pkt->senderState); 104311308Santhony.gutierrez@amd.com 104411308Santhony.gutierrez@amd.com Addr virt_page_addr = roundDown(pkt->req->getVaddr(), 104511308Santhony.gutierrez@amd.com TheISA::PageBytes); 104611308Santhony.gutierrez@amd.com 104711308Santhony.gutierrez@amd.com TranslationState *sender_state = 104811308Santhony.gutierrez@amd.com safe_cast<TranslationState*>(pkt->senderState); 104911308Santhony.gutierrez@amd.com 105011308Santhony.gutierrez@amd.com bool update_stats = !sender_state->prefetch; 105111308Santhony.gutierrez@amd.com ThreadContext * tmp_tc = sender_state->tc; 105211308Santhony.gutierrez@amd.com 105311308Santhony.gutierrez@amd.com DPRINTF(GPUTLB, "Translation req. for virt. page addr %#x\n", 105411308Santhony.gutierrez@amd.com virt_page_addr); 105511308Santhony.gutierrez@amd.com 105611308Santhony.gutierrez@amd.com int req_cnt = sender_state->reqCnt.back(); 105711308Santhony.gutierrez@amd.com 105811308Santhony.gutierrez@amd.com if (update_stats) { 105911308Santhony.gutierrez@amd.com accessCycles -= (curTick() * req_cnt); 106011308Santhony.gutierrez@amd.com localCycles -= curTick(); 106111308Santhony.gutierrez@amd.com updatePageFootprint(virt_page_addr); 106211308Santhony.gutierrez@amd.com globalNumTLBAccesses += req_cnt; 106311308Santhony.gutierrez@amd.com } 106411308Santhony.gutierrez@amd.com 106511308Santhony.gutierrez@amd.com tlbOutcome lookup_outcome = TLB_MISS; 106612749Sgiacomo.travaglini@arm.com const RequestPtr &tmp_req = pkt->req; 106711308Santhony.gutierrez@amd.com 106811308Santhony.gutierrez@amd.com // Access the TLB and figure out if it's a hit or a miss. 106911308Santhony.gutierrez@amd.com bool success = tlbLookup(tmp_req, tmp_tc, update_stats); 107011308Santhony.gutierrez@amd.com 107111308Santhony.gutierrez@amd.com if (success) { 107211308Santhony.gutierrez@amd.com lookup_outcome = TLB_HIT; 107311308Santhony.gutierrez@amd.com // Put the entry in SenderState 107412717Sbrandon.potter@amd.com TlbEntry *entry = lookup(tmp_req->getVaddr(), false); 107511308Santhony.gutierrez@amd.com assert(entry); 107611308Santhony.gutierrez@amd.com 107712717Sbrandon.potter@amd.com auto p = sender_state->tc->getProcessPtr(); 107811308Santhony.gutierrez@amd.com sender_state->tlbEntry = 107912717Sbrandon.potter@amd.com new TlbEntry(p->pid(), entry->vaddr, entry->paddr, 108012717Sbrandon.potter@amd.com false, false); 108111308Santhony.gutierrez@amd.com 108211308Santhony.gutierrez@amd.com if (update_stats) { 108311308Santhony.gutierrez@amd.com // the reqCnt has an entry per level, so its size tells us 108411308Santhony.gutierrez@amd.com // which level we are in 108511308Santhony.gutierrez@amd.com sender_state->hitLevel = sender_state->reqCnt.size(); 108611308Santhony.gutierrez@amd.com globalNumTLBHits += req_cnt; 108711308Santhony.gutierrez@amd.com } 108811308Santhony.gutierrez@amd.com } else { 108911308Santhony.gutierrez@amd.com if (update_stats) 109011308Santhony.gutierrez@amd.com globalNumTLBMisses += req_cnt; 109111308Santhony.gutierrez@amd.com } 109211308Santhony.gutierrez@amd.com 109311308Santhony.gutierrez@amd.com /* 109411308Santhony.gutierrez@amd.com * We now know the TLB lookup outcome (if it's a hit or a miss), as well 109511308Santhony.gutierrez@amd.com * as the TLB access latency. 109611308Santhony.gutierrez@amd.com * 109711308Santhony.gutierrez@amd.com * We create and schedule a new TLBEvent which will help us take the 109811308Santhony.gutierrez@amd.com * appropriate actions (e.g., update TLB on a hit, send request to lower 109911308Santhony.gutierrez@amd.com * level TLB on a miss, or start a page walk if this was the last-level 110011308Santhony.gutierrez@amd.com * TLB) 110111308Santhony.gutierrez@amd.com */ 110211308Santhony.gutierrez@amd.com TLBEvent *tlb_event = 110311308Santhony.gutierrez@amd.com new TLBEvent(this, virt_page_addr, lookup_outcome, pkt); 110411308Santhony.gutierrez@amd.com 110511308Santhony.gutierrez@amd.com if (translationReturnEvent.count(virt_page_addr)) { 110611308Santhony.gutierrez@amd.com panic("Virtual Page Address %#x already has a return event\n", 110711308Santhony.gutierrez@amd.com virt_page_addr); 110811308Santhony.gutierrez@amd.com } 110911308Santhony.gutierrez@amd.com 111011308Santhony.gutierrez@amd.com translationReturnEvent[virt_page_addr] = tlb_event; 111111308Santhony.gutierrez@amd.com assert(tlb_event); 111211308Santhony.gutierrez@amd.com 111311308Santhony.gutierrez@amd.com DPRINTF(GPUTLB, "schedule translationReturnEvent @ curTick %d\n", 111411308Santhony.gutierrez@amd.com curTick() + this->ticks(hitLatency)); 111511308Santhony.gutierrez@amd.com 111611308Santhony.gutierrez@amd.com schedule(tlb_event, curTick() + this->ticks(hitLatency)); 111711308Santhony.gutierrez@amd.com } 111811308Santhony.gutierrez@amd.com 111911308Santhony.gutierrez@amd.com GpuTLB::TLBEvent::TLBEvent(GpuTLB* _tlb, Addr _addr, tlbOutcome tlb_outcome, 112011308Santhony.gutierrez@amd.com PacketPtr _pkt) 112111308Santhony.gutierrez@amd.com : Event(CPU_Tick_Pri), tlb(_tlb), virtPageAddr(_addr), 112211308Santhony.gutierrez@amd.com outcome(tlb_outcome), pkt(_pkt) 112311308Santhony.gutierrez@amd.com { 112411308Santhony.gutierrez@amd.com } 112511308Santhony.gutierrez@amd.com 112611308Santhony.gutierrez@amd.com /** 112711308Santhony.gutierrez@amd.com * Do Paging protection checks. If we encounter a page fault, then 112811308Santhony.gutierrez@amd.com * an assertion is fired. 112911308Santhony.gutierrez@amd.com */ 113011308Santhony.gutierrez@amd.com void 113111308Santhony.gutierrez@amd.com GpuTLB::pagingProtectionChecks(ThreadContext *tc, PacketPtr pkt, 113212717Sbrandon.potter@amd.com TlbEntry * tlb_entry, Mode mode) 113311308Santhony.gutierrez@amd.com { 113411308Santhony.gutierrez@amd.com HandyM5Reg m5Reg = tc->readMiscRegNoEffect(MISCREG_M5_REG); 113511308Santhony.gutierrez@amd.com uint32_t flags = pkt->req->getFlags(); 113611308Santhony.gutierrez@amd.com bool storeCheck = flags & (StoreCheck << FlagShift); 113711308Santhony.gutierrez@amd.com 113811308Santhony.gutierrez@amd.com // Do paging protection checks. 113911308Santhony.gutierrez@amd.com bool inUser = (m5Reg.cpl == 3 && !(flags & (CPL0FlagBit << FlagShift))); 114011308Santhony.gutierrez@amd.com CR0 cr0 = tc->readMiscRegNoEffect(MISCREG_CR0); 114111308Santhony.gutierrez@amd.com 114211308Santhony.gutierrez@amd.com bool badWrite = (!tlb_entry->writable && (inUser || cr0.wp)); 114311308Santhony.gutierrez@amd.com 114411308Santhony.gutierrez@amd.com if ((inUser && !tlb_entry->user) || 114511308Santhony.gutierrez@amd.com (mode == BaseTLB::Write && badWrite)) { 114613449Sgabeblack@google.com // The page must have been present to get into the TLB in 114713449Sgabeblack@google.com // the first place. We'll assume the reserved bits are 114813449Sgabeblack@google.com // fine even though we're not checking them. 114913449Sgabeblack@google.com panic("Page fault detected"); 115011308Santhony.gutierrez@amd.com } 115111308Santhony.gutierrez@amd.com 115211308Santhony.gutierrez@amd.com if (storeCheck && badWrite) { 115313449Sgabeblack@google.com // This would fault if this were a write, so return a page 115413449Sgabeblack@google.com // fault that reflects that happening. 115513449Sgabeblack@google.com panic("Page fault detected"); 115611308Santhony.gutierrez@amd.com } 115711308Santhony.gutierrez@amd.com } 115811308Santhony.gutierrez@amd.com 115911308Santhony.gutierrez@amd.com /** 116011308Santhony.gutierrez@amd.com * handleTranslationReturn is called on a TLB hit, 116111308Santhony.gutierrez@amd.com * when a TLB miss returns or when a page fault returns. 116211308Santhony.gutierrez@amd.com * The latter calls handelHit with TLB miss as tlbOutcome. 116311308Santhony.gutierrez@amd.com */ 116411308Santhony.gutierrez@amd.com void 116511308Santhony.gutierrez@amd.com GpuTLB::handleTranslationReturn(Addr virt_page_addr, tlbOutcome tlb_outcome, 116611308Santhony.gutierrez@amd.com PacketPtr pkt) 116711308Santhony.gutierrez@amd.com { 116811308Santhony.gutierrez@amd.com 116911308Santhony.gutierrez@amd.com assert(pkt); 117011308Santhony.gutierrez@amd.com Addr vaddr = pkt->req->getVaddr(); 117111308Santhony.gutierrez@amd.com 117211308Santhony.gutierrez@amd.com TranslationState *sender_state = 117311308Santhony.gutierrez@amd.com safe_cast<TranslationState*>(pkt->senderState); 117411308Santhony.gutierrez@amd.com 117511308Santhony.gutierrez@amd.com ThreadContext *tc = sender_state->tc; 117611308Santhony.gutierrez@amd.com Mode mode = sender_state->tlbMode; 117711308Santhony.gutierrez@amd.com 117812717Sbrandon.potter@amd.com TlbEntry *local_entry, *new_entry; 117911308Santhony.gutierrez@amd.com 118011308Santhony.gutierrez@amd.com if (tlb_outcome == TLB_HIT) { 118111308Santhony.gutierrez@amd.com DPRINTF(GPUTLB, "Translation Done - TLB Hit for addr %#x\n", vaddr); 118211308Santhony.gutierrez@amd.com local_entry = sender_state->tlbEntry; 118311308Santhony.gutierrez@amd.com } else { 118411308Santhony.gutierrez@amd.com DPRINTF(GPUTLB, "Translation Done - TLB Miss for addr %#x\n", 118511308Santhony.gutierrez@amd.com vaddr); 118611308Santhony.gutierrez@amd.com 118711308Santhony.gutierrez@amd.com // We are returning either from a page walk or from a hit at a lower 118811308Santhony.gutierrez@amd.com // TLB level. The senderState should be "carrying" a pointer to the 118911308Santhony.gutierrez@amd.com // correct TLBEntry. 119011308Santhony.gutierrez@amd.com new_entry = sender_state->tlbEntry; 119111308Santhony.gutierrez@amd.com assert(new_entry); 119211308Santhony.gutierrez@amd.com local_entry = new_entry; 119311308Santhony.gutierrez@amd.com 119411308Santhony.gutierrez@amd.com if (allocationPolicy) { 119511308Santhony.gutierrez@amd.com DPRINTF(GPUTLB, "allocating entry w/ addr %#x\n", 119611308Santhony.gutierrez@amd.com virt_page_addr); 119711308Santhony.gutierrez@amd.com 119811308Santhony.gutierrez@amd.com local_entry = insert(virt_page_addr, *new_entry); 119911308Santhony.gutierrez@amd.com } 120011308Santhony.gutierrez@amd.com 120111308Santhony.gutierrez@amd.com assert(local_entry); 120211308Santhony.gutierrez@amd.com } 120311308Santhony.gutierrez@amd.com 120411308Santhony.gutierrez@amd.com /** 120511308Santhony.gutierrez@amd.com * At this point the packet carries an up-to-date tlbEntry pointer 120611308Santhony.gutierrez@amd.com * in its senderState. 120711308Santhony.gutierrez@amd.com * Next step is to do the paging protection checks. 120811308Santhony.gutierrez@amd.com */ 120911308Santhony.gutierrez@amd.com DPRINTF(GPUTLB, "Entry found with vaddr %#x, doing protection checks " 121011308Santhony.gutierrez@amd.com "while paddr was %#x.\n", local_entry->vaddr, 121111308Santhony.gutierrez@amd.com local_entry->paddr); 121211308Santhony.gutierrez@amd.com 121311308Santhony.gutierrez@amd.com pagingProtectionChecks(tc, pkt, local_entry, mode); 121411308Santhony.gutierrez@amd.com int page_size = local_entry->size(); 121511308Santhony.gutierrez@amd.com Addr paddr = local_entry->paddr | (vaddr & (page_size - 1)); 121611308Santhony.gutierrez@amd.com DPRINTF(GPUTLB, "Translated %#x -> %#x.\n", vaddr, paddr); 121711308Santhony.gutierrez@amd.com 121811308Santhony.gutierrez@amd.com // Since this packet will be sent through the cpu side slave port, 121911308Santhony.gutierrez@amd.com // it must be converted to a response pkt if it is not one already 122011308Santhony.gutierrez@amd.com if (pkt->isRequest()) { 122111308Santhony.gutierrez@amd.com pkt->makeTimingResponse(); 122211308Santhony.gutierrez@amd.com } 122311308Santhony.gutierrez@amd.com 122411308Santhony.gutierrez@amd.com pkt->req->setPaddr(paddr); 122511308Santhony.gutierrez@amd.com 122611308Santhony.gutierrez@amd.com if (local_entry->uncacheable) { 122711308Santhony.gutierrez@amd.com pkt->req->setFlags(Request::UNCACHEABLE); 122811308Santhony.gutierrez@amd.com } 122911308Santhony.gutierrez@amd.com 123011308Santhony.gutierrez@amd.com //send packet back to coalescer 123111308Santhony.gutierrez@amd.com cpuSidePort[0]->sendTimingResp(pkt); 123211308Santhony.gutierrez@amd.com //schedule cleanup event 123311308Santhony.gutierrez@amd.com cleanupQueue.push(virt_page_addr); 123411308Santhony.gutierrez@amd.com 123511308Santhony.gutierrez@amd.com // schedule this only once per cycle. 123611308Santhony.gutierrez@amd.com // The check is required because we might have multiple translations 123711308Santhony.gutierrez@amd.com // returning the same cycle 123811308Santhony.gutierrez@amd.com // this is a maximum priority event and must be on the same cycle 123911308Santhony.gutierrez@amd.com // as the cleanup event in TLBCoalescer to avoid a race with 124011308Santhony.gutierrez@amd.com // IssueProbeEvent caused by TLBCoalescer::MemSidePort::recvReqRetry 124111308Santhony.gutierrez@amd.com if (!cleanupEvent.scheduled()) 124211308Santhony.gutierrez@amd.com schedule(cleanupEvent, curTick()); 124311308Santhony.gutierrez@amd.com } 124411308Santhony.gutierrez@amd.com 124511308Santhony.gutierrez@amd.com /** 124611308Santhony.gutierrez@amd.com * Here we take the appropriate actions based on the result of the 124711308Santhony.gutierrez@amd.com * TLB lookup. 124811308Santhony.gutierrez@amd.com */ 124911308Santhony.gutierrez@amd.com void 125011308Santhony.gutierrez@amd.com GpuTLB::translationReturn(Addr virtPageAddr, tlbOutcome outcome, 125111308Santhony.gutierrez@amd.com PacketPtr pkt) 125211308Santhony.gutierrez@amd.com { 125311308Santhony.gutierrez@amd.com DPRINTF(GPUTLB, "Triggered TLBEvent for addr %#x\n", virtPageAddr); 125411308Santhony.gutierrez@amd.com 125511308Santhony.gutierrez@amd.com assert(translationReturnEvent[virtPageAddr]); 125611308Santhony.gutierrez@amd.com assert(pkt); 125711308Santhony.gutierrez@amd.com 125811308Santhony.gutierrez@amd.com TranslationState *tmp_sender_state = 125911308Santhony.gutierrez@amd.com safe_cast<TranslationState*>(pkt->senderState); 126011308Santhony.gutierrez@amd.com 126111308Santhony.gutierrez@amd.com int req_cnt = tmp_sender_state->reqCnt.back(); 126211308Santhony.gutierrez@amd.com bool update_stats = !tmp_sender_state->prefetch; 126311308Santhony.gutierrez@amd.com 126411308Santhony.gutierrez@amd.com 126511308Santhony.gutierrez@amd.com if (outcome == TLB_HIT) { 126611308Santhony.gutierrez@amd.com handleTranslationReturn(virtPageAddr, TLB_HIT, pkt); 126711308Santhony.gutierrez@amd.com 126811308Santhony.gutierrez@amd.com if (update_stats) { 126911308Santhony.gutierrez@amd.com accessCycles += (req_cnt * curTick()); 127011308Santhony.gutierrez@amd.com localCycles += curTick(); 127111308Santhony.gutierrez@amd.com } 127211308Santhony.gutierrez@amd.com 127311308Santhony.gutierrez@amd.com } else if (outcome == TLB_MISS) { 127411308Santhony.gutierrez@amd.com 127511308Santhony.gutierrez@amd.com DPRINTF(GPUTLB, "This is a TLB miss\n"); 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 if (hasMemSidePort) { 128211308Santhony.gutierrez@amd.com // the one cyle added here represent the delay from when we get 128311308Santhony.gutierrez@amd.com // the reply back till when we propagate it to the coalescer 128411308Santhony.gutierrez@amd.com // above. 128511308Santhony.gutierrez@amd.com if (update_stats) { 128611308Santhony.gutierrez@amd.com accessCycles += (req_cnt * 1); 128711308Santhony.gutierrez@amd.com localCycles += 1; 128811308Santhony.gutierrez@amd.com } 128911308Santhony.gutierrez@amd.com 129011308Santhony.gutierrez@amd.com /** 129111308Santhony.gutierrez@amd.com * There is a TLB below. Send the coalesced request. 129211308Santhony.gutierrez@amd.com * We actually send the very first packet of all the 129311308Santhony.gutierrez@amd.com * pending packets for this virtual page address. 129411308Santhony.gutierrez@amd.com */ 129511308Santhony.gutierrez@amd.com if (!memSidePort[0]->sendTimingReq(pkt)) { 129611308Santhony.gutierrez@amd.com DPRINTF(GPUTLB, "Failed sending translation request to " 129711308Santhony.gutierrez@amd.com "lower level TLB for addr %#x\n", virtPageAddr); 129811308Santhony.gutierrez@amd.com 129911308Santhony.gutierrez@amd.com memSidePort[0]->retries.push_back(pkt); 130011308Santhony.gutierrez@amd.com } else { 130111308Santhony.gutierrez@amd.com DPRINTF(GPUTLB, "Sent translation request to lower level " 130211308Santhony.gutierrez@amd.com "TLB for addr %#x\n", virtPageAddr); 130311308Santhony.gutierrez@amd.com } 130411308Santhony.gutierrez@amd.com } else { 130511308Santhony.gutierrez@amd.com //this is the last level TLB. Start a page walk 130611308Santhony.gutierrez@amd.com DPRINTF(GPUTLB, "Last level TLB - start a page walk for " 130711308Santhony.gutierrez@amd.com "addr %#x\n", virtPageAddr); 130811308Santhony.gutierrez@amd.com 130911308Santhony.gutierrez@amd.com if (update_stats) 131011308Santhony.gutierrez@amd.com pageTableCycles -= (req_cnt*curTick()); 131111308Santhony.gutierrez@amd.com 131211308Santhony.gutierrez@amd.com TLBEvent *tlb_event = translationReturnEvent[virtPageAddr]; 131311308Santhony.gutierrez@amd.com assert(tlb_event); 131411308Santhony.gutierrez@amd.com tlb_event->updateOutcome(PAGE_WALK); 131511308Santhony.gutierrez@amd.com schedule(tlb_event, curTick() + ticks(missLatency2)); 131611308Santhony.gutierrez@amd.com } 131711308Santhony.gutierrez@amd.com } else if (outcome == PAGE_WALK) { 131811308Santhony.gutierrez@amd.com if (update_stats) 131911308Santhony.gutierrez@amd.com pageTableCycles += (req_cnt*curTick()); 132011308Santhony.gutierrez@amd.com 132111308Santhony.gutierrez@amd.com // Need to access the page table and update the TLB 132211308Santhony.gutierrez@amd.com DPRINTF(GPUTLB, "Doing a page walk for address %#x\n", 132311308Santhony.gutierrez@amd.com virtPageAddr); 132411308Santhony.gutierrez@amd.com 132511308Santhony.gutierrez@amd.com TranslationState *sender_state = 132611308Santhony.gutierrez@amd.com safe_cast<TranslationState*>(pkt->senderState); 132711308Santhony.gutierrez@amd.com 132811308Santhony.gutierrez@amd.com Process *p = sender_state->tc->getProcessPtr(); 132911308Santhony.gutierrez@amd.com Addr vaddr = pkt->req->getVaddr(); 133011308Santhony.gutierrez@amd.com #ifndef NDEBUG 133111308Santhony.gutierrez@amd.com Addr alignedVaddr = p->pTable->pageAlign(vaddr); 133211308Santhony.gutierrez@amd.com assert(alignedVaddr == virtPageAddr); 133311308Santhony.gutierrez@amd.com #endif 133412461Sgabeblack@google.com const EmulationPageTable::Entry *pte = p->pTable->lookup(vaddr); 133512461Sgabeblack@google.com if (!pte && sender_state->tlbMode != BaseTLB::Execute && 133612455Sgabeblack@google.com p->fixupStackFault(vaddr)) { 133712461Sgabeblack@google.com pte = p->pTable->lookup(vaddr); 133811308Santhony.gutierrez@amd.com } 133911308Santhony.gutierrez@amd.com 134012461Sgabeblack@google.com if (pte) { 134112455Sgabeblack@google.com DPRINTF(GPUTLB, "Mapping %#x to %#x\n", alignedVaddr, 134212461Sgabeblack@google.com pte->paddr); 134311308Santhony.gutierrez@amd.com 134412455Sgabeblack@google.com sender_state->tlbEntry = 134512717Sbrandon.potter@amd.com new TlbEntry(p->pid(), virtPageAddr, pte->paddr, false, 134612717Sbrandon.potter@amd.com false); 134712455Sgabeblack@google.com } else { 134812717Sbrandon.potter@amd.com sender_state->tlbEntry = nullptr; 134912455Sgabeblack@google.com } 135011308Santhony.gutierrez@amd.com 135111308Santhony.gutierrez@amd.com handleTranslationReturn(virtPageAddr, TLB_MISS, pkt); 135211308Santhony.gutierrez@amd.com } else if (outcome == MISS_RETURN) { 135311308Santhony.gutierrez@amd.com /** we add an extra cycle in the return path of the translation 135411308Santhony.gutierrez@amd.com * requests in between the various TLB levels. 135511308Santhony.gutierrez@amd.com */ 135611308Santhony.gutierrez@amd.com handleTranslationReturn(virtPageAddr, TLB_MISS, pkt); 135711308Santhony.gutierrez@amd.com } else { 135813449Sgabeblack@google.com panic("Unexpected TLB outcome %d", outcome); 135911308Santhony.gutierrez@amd.com } 136011308Santhony.gutierrez@amd.com } 136111308Santhony.gutierrez@amd.com 136211308Santhony.gutierrez@amd.com void 136311308Santhony.gutierrez@amd.com GpuTLB::TLBEvent::process() 136411308Santhony.gutierrez@amd.com { 136511308Santhony.gutierrez@amd.com tlb->translationReturn(virtPageAddr, outcome, pkt); 136611308Santhony.gutierrez@amd.com } 136711308Santhony.gutierrez@amd.com 136811308Santhony.gutierrez@amd.com const char* 136911308Santhony.gutierrez@amd.com GpuTLB::TLBEvent::description() const 137011308Santhony.gutierrez@amd.com { 137111308Santhony.gutierrez@amd.com return "trigger translationDoneEvent"; 137211308Santhony.gutierrez@amd.com } 137311308Santhony.gutierrez@amd.com 137411308Santhony.gutierrez@amd.com void 137511308Santhony.gutierrez@amd.com GpuTLB::TLBEvent::updateOutcome(tlbOutcome _outcome) 137611308Santhony.gutierrez@amd.com { 137711308Santhony.gutierrez@amd.com outcome = _outcome; 137811308Santhony.gutierrez@amd.com } 137911308Santhony.gutierrez@amd.com 138011308Santhony.gutierrez@amd.com Addr 138111308Santhony.gutierrez@amd.com GpuTLB::TLBEvent::getTLBEventVaddr() 138211308Santhony.gutierrez@amd.com { 138311308Santhony.gutierrez@amd.com return virtPageAddr; 138411308Santhony.gutierrez@amd.com } 138511308Santhony.gutierrez@amd.com 138611308Santhony.gutierrez@amd.com /* 138711308Santhony.gutierrez@amd.com * recvTiming receives a coalesced timing request from a TLBCoalescer 138811308Santhony.gutierrez@amd.com * and it calls issueTLBLookup() 138911308Santhony.gutierrez@amd.com * It only rejects the packet if we have exceeded the max 139011308Santhony.gutierrez@amd.com * outstanding number of requests for the TLB 139111308Santhony.gutierrez@amd.com */ 139211308Santhony.gutierrez@amd.com bool 139311308Santhony.gutierrez@amd.com GpuTLB::CpuSidePort::recvTimingReq(PacketPtr pkt) 139411308Santhony.gutierrez@amd.com { 139511308Santhony.gutierrez@amd.com if (tlb->outstandingReqs < tlb->maxCoalescedReqs) { 139611308Santhony.gutierrez@amd.com tlb->issueTLBLookup(pkt); 139711308Santhony.gutierrez@amd.com // update number of outstanding translation requests 139811308Santhony.gutierrez@amd.com tlb->outstandingReqs++; 139911308Santhony.gutierrez@amd.com return true; 140011308Santhony.gutierrez@amd.com } else { 140111308Santhony.gutierrez@amd.com DPRINTF(GPUTLB, "Reached maxCoalescedReqs number %d\n", 140211308Santhony.gutierrez@amd.com tlb->outstandingReqs); 140311308Santhony.gutierrez@amd.com return false; 140411308Santhony.gutierrez@amd.com } 140511308Santhony.gutierrez@amd.com } 140611308Santhony.gutierrez@amd.com 140711308Santhony.gutierrez@amd.com /** 140811308Santhony.gutierrez@amd.com * handleFuncTranslationReturn is called on a TLB hit, 140911308Santhony.gutierrez@amd.com * when a TLB miss returns or when a page fault returns. 141011308Santhony.gutierrez@amd.com * It updates LRU, inserts the TLB entry on a miss 141111308Santhony.gutierrez@amd.com * depending on the allocation policy and does the required 141211308Santhony.gutierrez@amd.com * protection checks. It does NOT create a new packet to 141311308Santhony.gutierrez@amd.com * update the packet's addr; this is done in hsail-gpu code. 141411308Santhony.gutierrez@amd.com */ 141511308Santhony.gutierrez@amd.com void 141611308Santhony.gutierrez@amd.com GpuTLB::handleFuncTranslationReturn(PacketPtr pkt, tlbOutcome tlb_outcome) 141711308Santhony.gutierrez@amd.com { 141811308Santhony.gutierrez@amd.com TranslationState *sender_state = 141911308Santhony.gutierrez@amd.com safe_cast<TranslationState*>(pkt->senderState); 142011308Santhony.gutierrez@amd.com 142111308Santhony.gutierrez@amd.com ThreadContext *tc = sender_state->tc; 142211308Santhony.gutierrez@amd.com Mode mode = sender_state->tlbMode; 142311308Santhony.gutierrez@amd.com Addr vaddr = pkt->req->getVaddr(); 142411308Santhony.gutierrez@amd.com 142512717Sbrandon.potter@amd.com TlbEntry *local_entry, *new_entry; 142611308Santhony.gutierrez@amd.com 142711308Santhony.gutierrez@amd.com if (tlb_outcome == TLB_HIT) { 142811308Santhony.gutierrez@amd.com DPRINTF(GPUTLB, "Functional Translation Done - TLB hit for addr " 142911308Santhony.gutierrez@amd.com "%#x\n", vaddr); 143011308Santhony.gutierrez@amd.com 143111308Santhony.gutierrez@amd.com local_entry = sender_state->tlbEntry; 143211308Santhony.gutierrez@amd.com } else { 143311308Santhony.gutierrez@amd.com DPRINTF(GPUTLB, "Functional Translation Done - TLB miss for addr " 143411308Santhony.gutierrez@amd.com "%#x\n", vaddr); 143511308Santhony.gutierrez@amd.com 143611308Santhony.gutierrez@amd.com // We are returning either from a page walk or from a hit at a lower 143711308Santhony.gutierrez@amd.com // TLB level. The senderState should be "carrying" a pointer to the 143811308Santhony.gutierrez@amd.com // correct TLBEntry. 143911308Santhony.gutierrez@amd.com new_entry = sender_state->tlbEntry; 144011308Santhony.gutierrez@amd.com assert(new_entry); 144111308Santhony.gutierrez@amd.com local_entry = new_entry; 144211308Santhony.gutierrez@amd.com 144311308Santhony.gutierrez@amd.com if (allocationPolicy) { 144411308Santhony.gutierrez@amd.com Addr virt_page_addr = roundDown(vaddr, TheISA::PageBytes); 144511308Santhony.gutierrez@amd.com 144611308Santhony.gutierrez@amd.com DPRINTF(GPUTLB, "allocating entry w/ addr %#x\n", 144711308Santhony.gutierrez@amd.com virt_page_addr); 144811308Santhony.gutierrez@amd.com 144911308Santhony.gutierrez@amd.com local_entry = insert(virt_page_addr, *new_entry); 145011308Santhony.gutierrez@amd.com } 145111308Santhony.gutierrez@amd.com 145211308Santhony.gutierrez@amd.com assert(local_entry); 145311308Santhony.gutierrez@amd.com } 145411308Santhony.gutierrez@amd.com 145511308Santhony.gutierrez@amd.com DPRINTF(GPUTLB, "Entry found with vaddr %#x, doing protection checks " 145611308Santhony.gutierrez@amd.com "while paddr was %#x.\n", local_entry->vaddr, 145711308Santhony.gutierrez@amd.com local_entry->paddr); 145811308Santhony.gutierrez@amd.com 145912717Sbrandon.potter@amd.com /** 146012717Sbrandon.potter@amd.com * Do paging checks if it's a normal functional access. If it's for a 146112717Sbrandon.potter@amd.com * prefetch, then sometimes you can try to prefetch something that 146212717Sbrandon.potter@amd.com * won't pass protection. We don't actually want to fault becuase there 146312717Sbrandon.potter@amd.com * is no demand access to deem this a violation. Just put it in the 146412717Sbrandon.potter@amd.com * TLB and it will fault if indeed a future demand access touches it in 146512717Sbrandon.potter@amd.com * violation. 146612717Sbrandon.potter@amd.com * 146712717Sbrandon.potter@amd.com * This feature could be used to explore security issues around 146812717Sbrandon.potter@amd.com * speculative memory accesses. 146912717Sbrandon.potter@amd.com */ 147012717Sbrandon.potter@amd.com if (!sender_state->prefetch && sender_state->tlbEntry) 147111308Santhony.gutierrez@amd.com pagingProtectionChecks(tc, pkt, local_entry, mode); 147211308Santhony.gutierrez@amd.com 147311308Santhony.gutierrez@amd.com int page_size = local_entry->size(); 147411308Santhony.gutierrez@amd.com Addr paddr = local_entry->paddr | (vaddr & (page_size - 1)); 147511308Santhony.gutierrez@amd.com DPRINTF(GPUTLB, "Translated %#x -> %#x.\n", vaddr, paddr); 147611308Santhony.gutierrez@amd.com 147711308Santhony.gutierrez@amd.com pkt->req->setPaddr(paddr); 147811308Santhony.gutierrez@amd.com 147911308Santhony.gutierrez@amd.com if (local_entry->uncacheable) 148011308Santhony.gutierrez@amd.com pkt->req->setFlags(Request::UNCACHEABLE); 148111308Santhony.gutierrez@amd.com } 148211308Santhony.gutierrez@amd.com 148311308Santhony.gutierrez@amd.com // This is used for atomic translations. Need to 148411308Santhony.gutierrez@amd.com // make it all happen during the same cycle. 148511308Santhony.gutierrez@amd.com void 148611308Santhony.gutierrez@amd.com GpuTLB::CpuSidePort::recvFunctional(PacketPtr pkt) 148711308Santhony.gutierrez@amd.com { 148811308Santhony.gutierrez@amd.com TranslationState *sender_state = 148911308Santhony.gutierrez@amd.com safe_cast<TranslationState*>(pkt->senderState); 149011308Santhony.gutierrez@amd.com 149111308Santhony.gutierrez@amd.com ThreadContext *tc = sender_state->tc; 149211308Santhony.gutierrez@amd.com bool update_stats = !sender_state->prefetch; 149311308Santhony.gutierrez@amd.com 149411308Santhony.gutierrez@amd.com Addr virt_page_addr = roundDown(pkt->req->getVaddr(), 149511308Santhony.gutierrez@amd.com TheISA::PageBytes); 149611308Santhony.gutierrez@amd.com 149711308Santhony.gutierrez@amd.com if (update_stats) 149811308Santhony.gutierrez@amd.com tlb->updatePageFootprint(virt_page_addr); 149911308Santhony.gutierrez@amd.com 150011308Santhony.gutierrez@amd.com // do the TLB lookup without updating the stats 150111308Santhony.gutierrez@amd.com bool success = tlb->tlbLookup(pkt->req, tc, update_stats); 150211308Santhony.gutierrez@amd.com tlbOutcome tlb_outcome = success ? TLB_HIT : TLB_MISS; 150311308Santhony.gutierrez@amd.com 150411308Santhony.gutierrez@amd.com // functional mode means no coalescing 150511308Santhony.gutierrez@amd.com // global metrics are the same as the local metrics 150611308Santhony.gutierrez@amd.com if (update_stats) { 150711308Santhony.gutierrez@amd.com tlb->globalNumTLBAccesses++; 150811308Santhony.gutierrez@amd.com 150911308Santhony.gutierrez@amd.com if (success) { 151011308Santhony.gutierrez@amd.com sender_state->hitLevel = sender_state->reqCnt.size(); 151111308Santhony.gutierrez@amd.com tlb->globalNumTLBHits++; 151211308Santhony.gutierrez@amd.com } 151311308Santhony.gutierrez@amd.com } 151411308Santhony.gutierrez@amd.com 151511308Santhony.gutierrez@amd.com if (!success) { 151611308Santhony.gutierrez@amd.com if (update_stats) 151711308Santhony.gutierrez@amd.com tlb->globalNumTLBMisses++; 151811308Santhony.gutierrez@amd.com if (tlb->hasMemSidePort) { 151911308Santhony.gutierrez@amd.com // there is a TLB below -> propagate down the TLB hierarchy 152011308Santhony.gutierrez@amd.com tlb->memSidePort[0]->sendFunctional(pkt); 152111308Santhony.gutierrez@amd.com // If no valid translation from a prefetch, then just return 152211308Santhony.gutierrez@amd.com if (sender_state->prefetch && !pkt->req->hasPaddr()) 152311308Santhony.gutierrez@amd.com return; 152411308Santhony.gutierrez@amd.com } else { 152511308Santhony.gutierrez@amd.com // Need to access the page table and update the TLB 152611308Santhony.gutierrez@amd.com DPRINTF(GPUTLB, "Doing a page walk for address %#x\n", 152711308Santhony.gutierrez@amd.com virt_page_addr); 152811308Santhony.gutierrez@amd.com 152911308Santhony.gutierrez@amd.com Process *p = tc->getProcessPtr(); 153011308Santhony.gutierrez@amd.com 153111308Santhony.gutierrez@amd.com Addr vaddr = pkt->req->getVaddr(); 153211308Santhony.gutierrez@amd.com #ifndef NDEBUG 153311308Santhony.gutierrez@amd.com Addr alignedVaddr = p->pTable->pageAlign(vaddr); 153411308Santhony.gutierrez@amd.com assert(alignedVaddr == virt_page_addr); 153511308Santhony.gutierrez@amd.com #endif 153611308Santhony.gutierrez@amd.com 153712461Sgabeblack@google.com const EmulationPageTable::Entry *pte = 153812461Sgabeblack@google.com p->pTable->lookup(vaddr); 153912461Sgabeblack@google.com if (!pte && sender_state->tlbMode != BaseTLB::Execute && 154012455Sgabeblack@google.com p->fixupStackFault(vaddr)) { 154112461Sgabeblack@google.com pte = p->pTable->lookup(vaddr); 154211308Santhony.gutierrez@amd.com } 154311308Santhony.gutierrez@amd.com 154411308Santhony.gutierrez@amd.com if (!sender_state->prefetch) { 154511308Santhony.gutierrez@amd.com // no PageFaults are permitted after 154611308Santhony.gutierrez@amd.com // the second page table lookup 154712663Santhony.gutierrez@amd.com assert(pte); 154811308Santhony.gutierrez@amd.com 154911308Santhony.gutierrez@amd.com DPRINTF(GPUTLB, "Mapping %#x to %#x\n", alignedVaddr, 155012461Sgabeblack@google.com pte->paddr); 155111308Santhony.gutierrez@amd.com 155212455Sgabeblack@google.com sender_state->tlbEntry = 155312717Sbrandon.potter@amd.com new TlbEntry(p->pid(), virt_page_addr, 155412717Sbrandon.potter@amd.com pte->paddr, false, false); 155511308Santhony.gutierrez@amd.com } else { 155611308Santhony.gutierrez@amd.com // If this was a prefetch, then do the normal thing if it 155711308Santhony.gutierrez@amd.com // was a successful translation. Otherwise, send an empty 155811308Santhony.gutierrez@amd.com // TLB entry back so that it can be figured out as empty and 155911308Santhony.gutierrez@amd.com // handled accordingly. 156012461Sgabeblack@google.com if (pte) { 156111308Santhony.gutierrez@amd.com DPRINTF(GPUTLB, "Mapping %#x to %#x\n", alignedVaddr, 156212461Sgabeblack@google.com pte->paddr); 156311308Santhony.gutierrez@amd.com 156412455Sgabeblack@google.com sender_state->tlbEntry = 156512717Sbrandon.potter@amd.com new TlbEntry(p->pid(), virt_page_addr, 156612717Sbrandon.potter@amd.com pte->paddr, false, false); 156711308Santhony.gutierrez@amd.com } else { 156811308Santhony.gutierrez@amd.com DPRINTF(GPUPrefetch, "Prefetch failed %#x\n", 156911308Santhony.gutierrez@amd.com alignedVaddr); 157011308Santhony.gutierrez@amd.com 157112717Sbrandon.potter@amd.com sender_state->tlbEntry = nullptr; 157211308Santhony.gutierrez@amd.com 157311308Santhony.gutierrez@amd.com return; 157411308Santhony.gutierrez@amd.com } 157511308Santhony.gutierrez@amd.com } 157611308Santhony.gutierrez@amd.com } 157711308Santhony.gutierrez@amd.com } else { 157811308Santhony.gutierrez@amd.com DPRINTF(GPUPrefetch, "Functional Hit for vaddr %#x\n", 157911308Santhony.gutierrez@amd.com tlb->lookup(pkt->req->getVaddr())); 158011308Santhony.gutierrez@amd.com 158112717Sbrandon.potter@amd.com TlbEntry *entry = tlb->lookup(pkt->req->getVaddr(), 158211308Santhony.gutierrez@amd.com update_stats); 158311308Santhony.gutierrez@amd.com 158411308Santhony.gutierrez@amd.com assert(entry); 158511308Santhony.gutierrez@amd.com 158612717Sbrandon.potter@amd.com auto p = sender_state->tc->getProcessPtr(); 158711308Santhony.gutierrez@amd.com sender_state->tlbEntry = 158812717Sbrandon.potter@amd.com new TlbEntry(p->pid(), entry->vaddr, entry->paddr, 158912717Sbrandon.potter@amd.com false, false); 159011308Santhony.gutierrez@amd.com } 159111308Santhony.gutierrez@amd.com // This is the function that would populate pkt->req with the paddr of 159211308Santhony.gutierrez@amd.com // the translation. But if no translation happens (i.e Prefetch fails) 159311308Santhony.gutierrez@amd.com // then the early returns in the above code wiill keep this function 159411308Santhony.gutierrez@amd.com // from executing. 159511308Santhony.gutierrez@amd.com tlb->handleFuncTranslationReturn(pkt, tlb_outcome); 159611308Santhony.gutierrez@amd.com } 159711308Santhony.gutierrez@amd.com 159811308Santhony.gutierrez@amd.com void 159911308Santhony.gutierrez@amd.com GpuTLB::CpuSidePort::recvReqRetry() 160011308Santhony.gutierrez@amd.com { 160111308Santhony.gutierrez@amd.com // The CPUSidePort never sends anything but replies. No retries 160211308Santhony.gutierrez@amd.com // expected. 160313449Sgabeblack@google.com panic("recvReqRetry called"); 160411308Santhony.gutierrez@amd.com } 160511308Santhony.gutierrez@amd.com 160611308Santhony.gutierrez@amd.com AddrRangeList 160711308Santhony.gutierrez@amd.com GpuTLB::CpuSidePort::getAddrRanges() const 160811308Santhony.gutierrez@amd.com { 160911308Santhony.gutierrez@amd.com // currently not checked by the master 161011308Santhony.gutierrez@amd.com AddrRangeList ranges; 161111308Santhony.gutierrez@amd.com 161211308Santhony.gutierrez@amd.com return ranges; 161311308Santhony.gutierrez@amd.com } 161411308Santhony.gutierrez@amd.com 161511308Santhony.gutierrez@amd.com /** 161611308Santhony.gutierrez@amd.com * MemSidePort receives the packet back. 161711308Santhony.gutierrez@amd.com * We need to call the handleTranslationReturn 161811308Santhony.gutierrez@amd.com * and propagate up the hierarchy. 161911308Santhony.gutierrez@amd.com */ 162011308Santhony.gutierrez@amd.com bool 162111308Santhony.gutierrez@amd.com GpuTLB::MemSidePort::recvTimingResp(PacketPtr pkt) 162211308Santhony.gutierrez@amd.com { 162311308Santhony.gutierrez@amd.com Addr virt_page_addr = roundDown(pkt->req->getVaddr(), 162411308Santhony.gutierrez@amd.com TheISA::PageBytes); 162511308Santhony.gutierrez@amd.com 162611308Santhony.gutierrez@amd.com DPRINTF(GPUTLB, "MemSidePort recvTiming for virt_page_addr %#x\n", 162711308Santhony.gutierrez@amd.com virt_page_addr); 162811308Santhony.gutierrez@amd.com 162911308Santhony.gutierrez@amd.com TLBEvent *tlb_event = tlb->translationReturnEvent[virt_page_addr]; 163011308Santhony.gutierrez@amd.com assert(tlb_event); 163111308Santhony.gutierrez@amd.com assert(virt_page_addr == tlb_event->getTLBEventVaddr()); 163211308Santhony.gutierrez@amd.com 163311308Santhony.gutierrez@amd.com tlb_event->updateOutcome(MISS_RETURN); 163411308Santhony.gutierrez@amd.com tlb->schedule(tlb_event, curTick()+tlb->ticks(1)); 163511308Santhony.gutierrez@amd.com 163611308Santhony.gutierrez@amd.com return true; 163711308Santhony.gutierrez@amd.com } 163811308Santhony.gutierrez@amd.com 163911308Santhony.gutierrez@amd.com void 164011308Santhony.gutierrez@amd.com GpuTLB::MemSidePort::recvReqRetry() 164111308Santhony.gutierrez@amd.com { 164211308Santhony.gutierrez@amd.com // No retries should reach the TLB. The retries 164311308Santhony.gutierrez@amd.com // should only reach the TLBCoalescer. 164413449Sgabeblack@google.com panic("recvReqRetry called"); 164511308Santhony.gutierrez@amd.com } 164611308Santhony.gutierrez@amd.com 164711308Santhony.gutierrez@amd.com void 164811308Santhony.gutierrez@amd.com GpuTLB::cleanup() 164911308Santhony.gutierrez@amd.com { 165011308Santhony.gutierrez@amd.com while (!cleanupQueue.empty()) { 165111308Santhony.gutierrez@amd.com Addr cleanup_addr = cleanupQueue.front(); 165211308Santhony.gutierrez@amd.com cleanupQueue.pop(); 165311308Santhony.gutierrez@amd.com 165411308Santhony.gutierrez@amd.com // delete TLBEvent 165511308Santhony.gutierrez@amd.com TLBEvent * old_tlb_event = translationReturnEvent[cleanup_addr]; 165611308Santhony.gutierrez@amd.com delete old_tlb_event; 165711308Santhony.gutierrez@amd.com translationReturnEvent.erase(cleanup_addr); 165811308Santhony.gutierrez@amd.com 165911308Santhony.gutierrez@amd.com // update number of outstanding requests 166011308Santhony.gutierrez@amd.com outstandingReqs--; 166111308Santhony.gutierrez@amd.com } 166211308Santhony.gutierrez@amd.com 166311308Santhony.gutierrez@amd.com /** the higher level coalescer should retry if it has 166411308Santhony.gutierrez@amd.com * any pending requests. 166511308Santhony.gutierrez@amd.com */ 166611308Santhony.gutierrez@amd.com for (int i = 0; i < cpuSidePort.size(); ++i) { 166711308Santhony.gutierrez@amd.com cpuSidePort[i]->sendRetryReq(); 166811308Santhony.gutierrez@amd.com } 166911308Santhony.gutierrez@amd.com } 167011308Santhony.gutierrez@amd.com 167111308Santhony.gutierrez@amd.com void 167211308Santhony.gutierrez@amd.com GpuTLB::updatePageFootprint(Addr virt_page_addr) 167311308Santhony.gutierrez@amd.com { 167411308Santhony.gutierrez@amd.com 167511308Santhony.gutierrez@amd.com std::pair<AccessPatternTable::iterator, bool> ret; 167611308Santhony.gutierrez@amd.com 167711308Santhony.gutierrez@amd.com AccessInfo tmp_access_info; 167811308Santhony.gutierrez@amd.com tmp_access_info.lastTimeAccessed = 0; 167911308Santhony.gutierrez@amd.com tmp_access_info.accessesPerPage = 0; 168011308Santhony.gutierrez@amd.com tmp_access_info.totalReuseDistance = 0; 168111308Santhony.gutierrez@amd.com tmp_access_info.sumDistance = 0; 168211308Santhony.gutierrez@amd.com tmp_access_info.meanDistance = 0; 168311308Santhony.gutierrez@amd.com 168411308Santhony.gutierrez@amd.com ret = TLBFootprint.insert(AccessPatternTable::value_type(virt_page_addr, 168511308Santhony.gutierrez@amd.com tmp_access_info)); 168611308Santhony.gutierrez@amd.com 168711308Santhony.gutierrez@amd.com bool first_page_access = ret.second; 168811308Santhony.gutierrez@amd.com 168911308Santhony.gutierrez@amd.com if (first_page_access) { 169011308Santhony.gutierrez@amd.com numUniquePages++; 169111308Santhony.gutierrez@amd.com } else { 169211308Santhony.gutierrez@amd.com int accessed_before; 169311308Santhony.gutierrez@amd.com accessed_before = curTick() - ret.first->second.lastTimeAccessed; 169411308Santhony.gutierrez@amd.com ret.first->second.totalReuseDistance += accessed_before; 169511308Santhony.gutierrez@amd.com } 169611308Santhony.gutierrez@amd.com 169711308Santhony.gutierrez@amd.com ret.first->second.accessesPerPage++; 169811308Santhony.gutierrez@amd.com ret.first->second.lastTimeAccessed = curTick(); 169911308Santhony.gutierrez@amd.com 170011308Santhony.gutierrez@amd.com if (accessDistance) { 170111308Santhony.gutierrez@amd.com ret.first->second.localTLBAccesses 170211308Santhony.gutierrez@amd.com .push_back(localNumTLBAccesses.value()); 170311308Santhony.gutierrez@amd.com } 170411308Santhony.gutierrez@amd.com } 170511308Santhony.gutierrez@amd.com 170611308Santhony.gutierrez@amd.com void 170711308Santhony.gutierrez@amd.com GpuTLB::exitCallback() 170811308Santhony.gutierrez@amd.com { 170911308Santhony.gutierrez@amd.com std::ostream *page_stat_file = nullptr; 171011308Santhony.gutierrez@amd.com 171111308Santhony.gutierrez@amd.com if (accessDistance) { 171211308Santhony.gutierrez@amd.com 171311308Santhony.gutierrez@amd.com // print per page statistics to a separate file (.csv format) 171411308Santhony.gutierrez@amd.com // simout is the gem5 output directory (default is m5out or the one 171511308Santhony.gutierrez@amd.com // specified with -d 171611364Sandreas.hansson@arm.com page_stat_file = simout.create(name().c_str())->stream(); 171711308Santhony.gutierrez@amd.com 171811308Santhony.gutierrez@amd.com // print header 171911308Santhony.gutierrez@amd.com *page_stat_file << "page,max_access_distance,mean_access_distance, " 172011308Santhony.gutierrez@amd.com << "stddev_distance" << std::endl; 172111308Santhony.gutierrez@amd.com } 172211308Santhony.gutierrez@amd.com 172311308Santhony.gutierrez@amd.com // update avg. reuse distance footprint 172411308Santhony.gutierrez@amd.com AccessPatternTable::iterator iter, iter_begin, iter_end; 172511308Santhony.gutierrez@amd.com unsigned int sum_avg_reuse_distance_per_page = 0; 172611308Santhony.gutierrez@amd.com 172711308Santhony.gutierrez@amd.com // iterate through all pages seen by this TLB 172811308Santhony.gutierrez@amd.com for (iter = TLBFootprint.begin(); iter != TLBFootprint.end(); iter++) { 172911308Santhony.gutierrez@amd.com sum_avg_reuse_distance_per_page += iter->second.totalReuseDistance / 173011308Santhony.gutierrez@amd.com iter->second.accessesPerPage; 173111308Santhony.gutierrez@amd.com 173211308Santhony.gutierrez@amd.com if (accessDistance) { 173311308Santhony.gutierrez@amd.com unsigned int tmp = iter->second.localTLBAccesses[0]; 173411308Santhony.gutierrez@amd.com unsigned int prev = tmp; 173511308Santhony.gutierrez@amd.com 173611308Santhony.gutierrez@amd.com for (int i = 0; i < iter->second.localTLBAccesses.size(); ++i) { 173711308Santhony.gutierrez@amd.com if (i) { 173811308Santhony.gutierrez@amd.com tmp = prev + 1; 173911308Santhony.gutierrez@amd.com } 174011308Santhony.gutierrez@amd.com 174111308Santhony.gutierrez@amd.com prev = iter->second.localTLBAccesses[i]; 174211308Santhony.gutierrez@amd.com // update the localTLBAccesses value 174311308Santhony.gutierrez@amd.com // with the actual differece 174411308Santhony.gutierrez@amd.com iter->second.localTLBAccesses[i] -= tmp; 174511308Santhony.gutierrez@amd.com // compute the sum of AccessDistance per page 174611308Santhony.gutierrez@amd.com // used later for mean 174711308Santhony.gutierrez@amd.com iter->second.sumDistance += 174811308Santhony.gutierrez@amd.com iter->second.localTLBAccesses[i]; 174911308Santhony.gutierrez@amd.com } 175011308Santhony.gutierrez@amd.com 175111308Santhony.gutierrez@amd.com iter->second.meanDistance = 175211308Santhony.gutierrez@amd.com iter->second.sumDistance / iter->second.accessesPerPage; 175311308Santhony.gutierrez@amd.com 175411308Santhony.gutierrez@amd.com // compute std_dev and max (we need a second round because we 175511308Santhony.gutierrez@amd.com // need to know the mean value 175611308Santhony.gutierrez@amd.com unsigned int max_distance = 0; 175711308Santhony.gutierrez@amd.com unsigned int stddev_distance = 0; 175811308Santhony.gutierrez@amd.com 175911308Santhony.gutierrez@amd.com for (int i = 0; i < iter->second.localTLBAccesses.size(); ++i) { 176011308Santhony.gutierrez@amd.com unsigned int tmp_access_distance = 176111308Santhony.gutierrez@amd.com iter->second.localTLBAccesses[i]; 176211308Santhony.gutierrez@amd.com 176311308Santhony.gutierrez@amd.com if (tmp_access_distance > max_distance) { 176411308Santhony.gutierrez@amd.com max_distance = tmp_access_distance; 176511308Santhony.gutierrez@amd.com } 176611308Santhony.gutierrez@amd.com 176711308Santhony.gutierrez@amd.com unsigned int diff = 176811308Santhony.gutierrez@amd.com tmp_access_distance - iter->second.meanDistance; 176911308Santhony.gutierrez@amd.com stddev_distance += pow(diff, 2); 177011308Santhony.gutierrez@amd.com 177111308Santhony.gutierrez@amd.com } 177211308Santhony.gutierrez@amd.com 177311308Santhony.gutierrez@amd.com stddev_distance = 177411308Santhony.gutierrez@amd.com sqrt(stddev_distance/iter->second.accessesPerPage); 177511308Santhony.gutierrez@amd.com 177611308Santhony.gutierrez@amd.com if (page_stat_file) { 177711308Santhony.gutierrez@amd.com *page_stat_file << std::hex << iter->first << ","; 177811308Santhony.gutierrez@amd.com *page_stat_file << std::dec << max_distance << ","; 177911308Santhony.gutierrez@amd.com *page_stat_file << std::dec << iter->second.meanDistance 178011308Santhony.gutierrez@amd.com << ","; 178111308Santhony.gutierrez@amd.com *page_stat_file << std::dec << stddev_distance; 178211308Santhony.gutierrez@amd.com *page_stat_file << std::endl; 178311308Santhony.gutierrez@amd.com } 178411308Santhony.gutierrez@amd.com 178511308Santhony.gutierrez@amd.com // erase the localTLBAccesses array 178611308Santhony.gutierrez@amd.com iter->second.localTLBAccesses.clear(); 178711308Santhony.gutierrez@amd.com } 178811308Santhony.gutierrez@amd.com } 178911308Santhony.gutierrez@amd.com 179011308Santhony.gutierrez@amd.com if (!TLBFootprint.empty()) { 179111308Santhony.gutierrez@amd.com avgReuseDistance = 179211308Santhony.gutierrez@amd.com sum_avg_reuse_distance_per_page / TLBFootprint.size(); 179311308Santhony.gutierrez@amd.com } 179411308Santhony.gutierrez@amd.com 179511308Santhony.gutierrez@amd.com //clear the TLBFootprint map 179611308Santhony.gutierrez@amd.com TLBFootprint.clear(); 179711308Santhony.gutierrez@amd.com } 179811308Santhony.gutierrez@amd.com} // namespace X86ISA 179911308Santhony.gutierrez@amd.com 180011308Santhony.gutierrez@amd.comX86ISA::GpuTLB* 180111308Santhony.gutierrez@amd.comX86GPUTLBParams::create() 180211308Santhony.gutierrez@amd.com{ 180311308Santhony.gutierrez@amd.com return new X86ISA::GpuTLB(this); 180411308Santhony.gutierrez@amd.com} 180511308Santhony.gutierrez@amd.com 1806