dev-amdgpu: Add GPU interrupt handler object
Add device interrupt handler for amdgpu device. The interrupt handler is primarily used to signal that fences in the kernel driver can be passed. Change-Id: I574fbfdef6e3bae310ec7f86058811e1e4886df6 Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/51849 Maintainer: Matthew Poremba <matthew.poremba@amd.com> Reviewed-by: Matt Sinclair <mattdsinclair@gmail.com> Maintainer: Matt Sinclair <mattdsinclair@gmail.com> Tested-by: kokoro <noreply+kokoro@google.com>
This commit is contained in:
176
src/dev/amdgpu/interrupt_handler.hh
Normal file
176
src/dev/amdgpu/interrupt_handler.hh
Normal file
@@ -0,0 +1,176 @@
|
||||
/*
|
||||
* 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_INTERRUPT_HANDLER__
|
||||
#define __DEV_AMDGPU_INTERRUPT_HANDLER__
|
||||
|
||||
#include <bitset>
|
||||
#include <iostream>
|
||||
#include <queue>
|
||||
#include <vector>
|
||||
|
||||
#include "base/addr_range.hh"
|
||||
#include "base/flags.hh"
|
||||
#include "base/types.hh"
|
||||
#include "dev/amdgpu/amdgpu_device.hh"
|
||||
#include "dev/dma_device.hh"
|
||||
#include "params/AMDGPUInterruptHandler.hh"
|
||||
|
||||
namespace gem5
|
||||
{
|
||||
|
||||
/*
|
||||
* MSI-style interrupts. Send a "cookie" response to clear interrupts.
|
||||
* From [1] we know the size of the struct is 8 dwords. Then we can look at
|
||||
* the register shift offsets in [2] to guess the rest. Or we can also look
|
||||
* at [3].
|
||||
*
|
||||
* [1] https://github.com/RadeonOpenCompute/ROCK-Kernel-Driver/blob/roc-4.3.x/
|
||||
* drivers/gpu/drm/amd/amdkfd/kfd_device.c#L316
|
||||
* [2] https://github.com/RadeonOpenCompute/ROCK-Kernel-Driver/blob/roc-4.3.x/
|
||||
* drivers/gpu/drm/amd/include/asic_reg/oss/osssys_4_0_sh_mask.h#L122
|
||||
* [3] https://github.com/RadeonOpenCompute/ROCK-Kernel-Driver/blob/roc-4.3.x/
|
||||
drivers/gpu/drm/amd/amdgpu/amdgpu_irq.h#L46
|
||||
*
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
uint32_t clientId : 8;
|
||||
uint32_t sourceId : 8;
|
||||
uint32_t ringId : 8;
|
||||
uint32_t vmId : 4;
|
||||
uint32_t reserved1 : 3;
|
||||
uint32_t vmid_type : 1;
|
||||
uint32_t timestamp_Lo;
|
||||
uint32_t timestamp_Hi : 16;
|
||||
uint32_t reserved2 : 15;
|
||||
uint32_t timestamp_src : 1;
|
||||
uint32_t pasid : 16;
|
||||
uint32_t reserved3 : 15;
|
||||
uint32_t pasid_src : 1;
|
||||
uint32_t source_data_dw1;
|
||||
uint32_t source_data_dw2;
|
||||
uint32_t source_data_dw3;
|
||||
uint32_t source_data_dw4;
|
||||
} AMDGPUInterruptCookie;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint32_t IH_Cntl;
|
||||
uint32_t IH_Base;
|
||||
uint32_t IH_Base_Hi;
|
||||
Addr baseAddr;
|
||||
uint32_t IH_Rptr;
|
||||
uint32_t IH_Wptr;
|
||||
uint32_t IH_Wptr_Addr_Lo;
|
||||
uint32_t IH_Wptr_Addr_Hi;
|
||||
Addr WptrAddr;
|
||||
uint32_t IH_Doorbell;
|
||||
} AMDGPUIHRegs;
|
||||
|
||||
constexpr uint32_t INTR_COOKIE_SIZE = 32; // in bytes
|
||||
|
||||
class AMDGPUInterruptHandler : public DmaDevice
|
||||
{
|
||||
public:
|
||||
class DmaEvent : public Event
|
||||
{
|
||||
private:
|
||||
AMDGPUInterruptHandler *deviceIh;
|
||||
uint32_t data;
|
||||
|
||||
public:
|
||||
DmaEvent(AMDGPUInterruptHandler *deviceIh, uint32_t data)
|
||||
: Event(), deviceIh(deviceIh), data(data)
|
||||
{
|
||||
setFlags(Event::AutoDelete);
|
||||
}
|
||||
void process();
|
||||
const char *description() const {
|
||||
return "AMDGPUInterruptHandler Dma";
|
||||
}
|
||||
|
||||
void setData(uint32_t _data) { data = _data; }
|
||||
uint32_t getData() { return data; }
|
||||
};
|
||||
|
||||
struct SenderState : public Packet::SenderState
|
||||
{
|
||||
SenderState(Packet::SenderState *sender_state, Addr addr)
|
||||
: saved(sender_state), _addr(addr)
|
||||
{
|
||||
}
|
||||
Packet::SenderState *saved;
|
||||
Addr _addr;
|
||||
};
|
||||
|
||||
AMDGPUInterruptHandler(const AMDGPUInterruptHandlerParams &p);
|
||||
|
||||
Tick write(PacketPtr pkt) override { return 0; }
|
||||
Tick read(PacketPtr pkt) override { return 0; }
|
||||
AddrRangeList getAddrRanges() const override;
|
||||
void serialize(CheckpointOut &cp) const override;
|
||||
void unserialize(CheckpointIn &cp) override;
|
||||
|
||||
void setGPUDevice(AMDGPUDevice *gpu_device) { gpuDevice = gpu_device; }
|
||||
void prepareInterruptCookie(ContextID cntxtId, uint32_t ring_id,
|
||||
uint32_t client_id, uint32_t source_id);
|
||||
void submitInterruptCookie();
|
||||
void submitWritePointer();
|
||||
void intrPost();
|
||||
|
||||
/**
|
||||
* Methods for setting the values of interrupt handler MMIO registers.
|
||||
*/
|
||||
void writeMMIO(PacketPtr pkt, Addr mmio_offset);
|
||||
|
||||
uint32_t getDoorbellOffset() const { return regs.IH_Doorbell; }
|
||||
void setCntl(const uint32_t &data);
|
||||
void setBase(const uint32_t &data);
|
||||
void setBaseHi(const uint32_t &data);
|
||||
void setRptr(const uint32_t &data);
|
||||
void setWptr(const uint32_t &data);
|
||||
void setWptrAddrLo(const uint32_t &data);
|
||||
void setWptrAddrHi(const uint32_t &data);
|
||||
void setDoorbellOffset(const uint32_t &data);
|
||||
void updateRptr(const uint32_t &data);
|
||||
|
||||
private:
|
||||
AMDGPUDevice *gpuDevice;
|
||||
AMDGPUIHRegs regs;
|
||||
std::queue<AMDGPUInterruptCookie*> interruptQueue;
|
||||
AMDGPUInterruptHandler::DmaEvent *dmaEvent;
|
||||
};
|
||||
|
||||
} // namespace gem5
|
||||
|
||||
#endif // __DEV_AMDGPU_INTERRUPT_HANDLER__
|
||||
Reference in New Issue
Block a user