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