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