blob: ac31b95fd2ad8924501e07bb876d942ccb555f38 [file] [log] [blame]
/*
* Copyright (c) 2021 Advanced Micro Devices, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef __DEV_AMDGPU_AMDGPU_DEVICE_HH__
#define __DEV_AMDGPU_AMDGPU_DEVICE_HH__
#include <map>
#include "base/bitunion.hh"
#include "dev/amdgpu/amdgpu_defines.hh"
#include "dev/amdgpu/amdgpu_vm.hh"
#include "dev/amdgpu/memory_manager.hh"
#include "dev/amdgpu/mmio_reader.hh"
#include "dev/io_device.hh"
#include "dev/pci/device.hh"
#include "params/AMDGPUDevice.hh"
namespace gem5
{
class AMDGPUInterruptHandler;
class SDMAEngine;
/**
* Device model for an AMD GPU. This models the interface between the PCI bus
* and the various IP blocks behind it. It translates requests to the various
* BARs and sends them to the appropriate IP block. BAR0 requests are VRAM
* requests that go to device memory, BAR2 are doorbells which are decoded and
* sent to the corresponding IP block. BAR5 is the MMIO interface which writes
* data values to registers controlling the IP blocks.
*/
class AMDGPUDevice : public PciDevice
{
private:
/**
* Convert a PCI packet into a response
*/
void dispatchAccess(PacketPtr pkt, bool read);
/**
* Helper methods to handle specific BAR read/writes. Offset is the
* address of the packet - base address of the BAR.
*
* read/writeFrame are used for BAR0 requests
* read/writeDoorbell are used for BAR2 requests
* read/writeMMIO are used for BAR5 requests
*/
void readFrame(PacketPtr pkt, Addr offset);
void readDoorbell(PacketPtr pkt, Addr offset);
void readMMIO(PacketPtr pkt, Addr offset);
void writeFrame(PacketPtr pkt, Addr offset);
void writeDoorbell(PacketPtr pkt, Addr offset);
void writeMMIO(PacketPtr pkt, Addr offset);
/**
* Structures to hold registers, doorbells, and some frame memory
*/
using GPURegMap = std::unordered_map<uint32_t, uint64_t>;
GPURegMap regs;
std::unordered_map<uint32_t, QueueType> doorbells;
/**
* VGA ROM methods
*/
AddrRange romRange;
bool isROM(Addr addr) const { return romRange.contains(addr); }
void readROM(PacketPtr pkt);
std::array<uint8_t, ROM_SIZE> rom;
/**
* MMIO reader to populate device registers map.
*/
AMDMMIOReader mmioReader;
/**
* Blocks of the GPU
*/
AMDGPUMemoryManager *gpuMemMgr;
AMDGPUInterruptHandler *deviceIH;
AMDGPUVM gpuvm;
SDMAEngine *sdma0;
SDMAEngine *sdma1;
std::unordered_map<uint32_t, SDMAEngine *> sdmaEngs;
PM4PacketProcessor *pm4PktProc;
GPUCommandProcessor *cp;
/**
* Initial checkpoint support variables.
*/
bool checkpoint_before_mmios;
int init_interrupt_count;
// VMIDs data structures
// map of pasids to vmids
std::unordered_map<uint16_t, uint16_t> idMap;
// map of doorbell offsets to vmids
std::unordered_map<Addr, uint16_t> doorbellVMIDMap;
// map of vmid to all queue ids using that vmid
std::unordered_map<uint16_t, std::set<int>> usedVMIDs;
// last vmid allocated by map_process PM4 packet
uint16_t _lastVMID;
/*
* Backing store for GPU memory / framebuffer / VRAM
*/
memory::PhysicalMemory deviceMem;
public:
AMDGPUDevice(const AMDGPUDeviceParams &p);
/**
* Methods inherited from PciDevice
*/
void intrPost();
Tick writeConfig(PacketPtr pkt) override;
Tick readConfig(PacketPtr pkt) override;
Tick read(PacketPtr pkt) override;
Tick write(PacketPtr pkt) override;
AddrRangeList getAddrRanges() const override;
/**
* Checkpoint support
*/
void serialize(CheckpointOut &cp) const override;
void unserialize(CheckpointIn &cp) override;
/**
* Get handles to GPU blocks.
*/
AMDGPUInterruptHandler* getIH() { return deviceIH; }
SDMAEngine* getSDMAById(int id);
SDMAEngine* getSDMAEngine(Addr offset);
AMDGPUVM &getVM() { return gpuvm; }
AMDGPUMemoryManager* getMemMgr() { return gpuMemMgr; }
GPUCommandProcessor* CP() { return cp; }
/**
* Set handles to GPU blocks.
*/
void setDoorbellType(uint32_t offset, QueueType qt);
void setSDMAEngine(Addr offset, SDMAEngine *eng);
/**
* Register value getter/setter. Used by other GPU blocks to change
* values from incoming driver/user packets.
*/
uint32_t getRegVal(uint32_t addr);
void setRegVal(uint32_t addr, uint32_t value);
/**
* Methods related to translations and system/device memory.
*/
RequestorID vramRequestorId() { return gpuMemMgr->getRequestorID(); }
/* HW context stuff */
uint16_t lastVMID() { return _lastVMID; }
uint16_t allocateVMID(uint16_t pasid);
void deallocateVmid(uint16_t vmid);
void deallocatePasid(uint16_t pasid);
void deallocateAllQueues();
void mapDoorbellToVMID(Addr doorbell, uint16_t vmid);
uint16_t getVMID(Addr doorbell) { return doorbellVMIDMap[doorbell]; }
std::unordered_map<uint16_t, std::set<int>>& getUsedVMIDs();
void insertQId(uint16_t vmid, int id);
};
} // namespace gem5
#endif // __DEV_AMDGPU_AMDGPU_DEVICE_HH__