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