gem5  v22.1.0.0
interrupt_handler.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2021 Advanced Micro Devices, Inc.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  *
8  * 1. Redistributions of source code must retain the above copyright notice,
9  * this list of conditions and the following disclaimer.
10  *
11  * 2. Redistributions in binary form must reproduce the above copyright notice,
12  * this list of conditions and the following disclaimer in the documentation
13  * and/or other materials provided with the distribution.
14  *
15  * 3. Neither the name of the copyright holder nor the names of its
16  * contributors may be used to endorse or promote products derived from this
17  * software without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
23  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29  * POSSIBILITY OF SUCH DAMAGE.
30  *
31  */
32 
34 
35 #include "debug/AMDGPUDevice.hh"
36 #include "dev/amdgpu/ih_mmio.hh"
37 #include "mem/packet_access.hh"
38 
39 // For generating interrupts, the object causing interrupt communicates with
40 // the Interrupt Handler (IH), which submits a 256-bit Interrupt packet to the
41 // system memory. The location where the IH submits the packet is the
42 // IH Ring buffer in the system memory. The IH updates the Write Pointer
43 // and the host consumes the ring buffer and once done, updates the Read
44 // Pointer through the doorbell.
45 
46 // IH_RB_BaseAddr, IH_RB_WptrAddr (Lo/Hi), IH_RB_RptrAddr (Lo/Hi), etc. are
47 // not GART addresses but system dma addresses and thus don't require
48 // translations through the GART table.
49 
50 namespace gem5
51 {
52 
54  const AMDGPUInterruptHandlerParams &p)
55  : DmaDevice(p)
56 {
57  memset(&regs, 0, sizeof(AMDGPUIHRegs));
58 }
59 
62 {
63  AddrRangeList ranges;
64  return ranges;
65 }
66 
67 void
69 {
70  if (gpuDevice)
72 }
73 
74 void
76  uint32_t ring_id,
77  uint32_t client_id,
78  uint32_t source_id)
79 {
80  assert(client_id == SOC15_IH_CLIENTID_RLC ||
81  client_id == SOC15_IH_CLIENTID_SDMA0 ||
82  client_id == SOC15_IH_CLIENTID_SDMA1 ||
83  client_id == SOC15_IH_CLIENTID_GRBM_CP);
84  assert(source_id == CP_EOP || source_id == TRAP_ID);
85 
96  memset(cookie, 0, sizeof(AMDGPUInterruptCookie));
97 
98  // Currently only one process is supported and the first pasid from driver
99  // is always 0x8000. In the future this can be obtained from the PM4
100  // MAP_PROCESS packet and may need to be passed to this function.
101  //
102  // On a related note, leave vmid fields alone as they are only used for
103  // memory exceptions. Memory exceptions are not supported on gfx900.
104  cookie->pasid = 0x8000;
105  cookie->timestamp_Lo = 0x40;
106  cookie->clientId = client_id;
107  cookie->sourceId = source_id;
108  cookie->ringId = ring_id;
109  cookie->source_data_dw1 = cntxt_id;
110  interruptQueue.push(cookie);
111 }
112 
113 void
115 {
116  if (data == 1) {
117  DPRINTF(AMDGPUDevice, "Completed interrupt cookie write\n");
119  } else if (data == 2) {
120  DPRINTF(AMDGPUDevice, "Completed interrupt write pointer update\n");
121  deviceIh->intrPost();
122  } else {
123  fatal("Interrupt Handler DMA event returned bad value: %d\n", data);
124  }
125 }
126 
127 void
129 {
130  uint8_t *dataPtr = new uint8_t[sizeof(uint32_t)];
132  Addr paddr = regs.WptrAddr;
133  std::memcpy(dataPtr, &regs.IH_Wptr, sizeof(uint32_t));
134 
136  dmaWrite(paddr, sizeof(uint32_t), dmaEvent, dataPtr);
137 }
138 
139 void
141 {
142  assert(!interruptQueue.empty());
143  auto cookie = interruptQueue.front();
144  size_t cookieSize = sizeof(AMDGPUInterruptCookie);
145 
146  uint8_t *dataPtr = new uint8_t[cookieSize];
147  std::memcpy(dataPtr, cookie, cookieSize);
148  Addr paddr = regs.baseAddr + regs.IH_Wptr;
149 
150  DPRINTF(AMDGPUDevice, "InterruptHandler rptr: 0x%x wptr: 0x%x\n",
153  dmaWrite(paddr, cookieSize, dmaEvent, dataPtr);
154 
155  interruptQueue.pop();
156 }
157 
158 void
160 {
161  switch (mmio_offset) {
162  case mmIH_RB_CNTL:
163  setCntl(pkt->getLE<uint32_t>());
164  break;
165  case mmIH_RB_BASE:
166  setBase(pkt->getLE<uint32_t>());
167  break;
168  case mmIH_RB_BASE_HI:
169  setBaseHi(pkt->getLE<uint32_t>());
170  break;
171  case mmIH_RB_RPTR:
172  setRptr(pkt->getLE<uint32_t>());
173  break;
174  case mmIH_RB_WPTR:
175  setWptr(pkt->getLE<uint32_t>());
176  break;
178  setWptrAddrLo(pkt->getLE<uint32_t>());
179  break;
181  setWptrAddrHi(pkt->getLE<uint32_t>());
182  break;
183  case mmIH_DOORBELL_RPTR:
184  setDoorbellOffset(pkt->getLE<uint32_t>());
185  if (bits(pkt->getLE<uint32_t>(), 28, 28)) {
188  }
189  break;
190  default:
191  DPRINTF(AMDGPUDevice, "IH Unknown MMIO %#x\n", mmio_offset);
192  break;
193  }
194 }
195 
196 void
198 {
199  regs.IH_Cntl = data;
200 }
201 
202 void
204 {
205  regs.baseAddr = data;
206  regs.baseAddr <<= 8;
207 }
208 
209 void
211 {
212  regs.baseAddr |= static_cast<uint64_t>(data) << 40;
213 }
214 
215 void
217 {
218  regs.IH_Rptr = data;
219 }
220 
221 void
223 {
224  regs.IH_Wptr = data;
225 }
226 
227 void
229 {
232 }
233 
234 void
236 {
238  regs.WptrAddr |= ((uint64_t)regs.IH_Wptr_Addr_Hi) << 32;
239 }
240 
241 void
243 {
244  regs.IH_Doorbell = data & 0x3ffffff;
245 }
246 
247 void
249 {
250  regs.IH_Rptr = data; // update ring buffer rptr offset
251 }
252 
253 void
255 {
256  uint32_t ih_cntl = regs.IH_Cntl;
257  uint32_t ih_base = regs.IH_Base;
258  uint32_t ih_base_hi = regs.IH_Base_Hi;
259  Addr ih_baseAddr = regs.baseAddr;
260  uint32_t ih_rptr = regs.IH_Rptr;
261  uint32_t ih_wptr = regs.IH_Wptr;
262  uint32_t ih_wptr_addr_lo = regs.IH_Wptr_Addr_Lo;
263  uint32_t ih_wptr_addr_hi = regs.IH_Wptr_Addr_Hi;
264  Addr ih_wptrAddr = regs.WptrAddr;
265  uint32_t ih_doorbellOffset = regs.IH_Doorbell;
266 
267  SERIALIZE_SCALAR(ih_cntl);
268  SERIALIZE_SCALAR(ih_base);
269  SERIALIZE_SCALAR(ih_base_hi);
270  SERIALIZE_SCALAR(ih_baseAddr);
271  SERIALIZE_SCALAR(ih_rptr);
272  SERIALIZE_SCALAR(ih_wptr);
273  SERIALIZE_SCALAR(ih_wptr_addr_lo);
274  SERIALIZE_SCALAR(ih_wptr_addr_hi);
275  SERIALIZE_SCALAR(ih_wptrAddr);
276  SERIALIZE_SCALAR(ih_doorbellOffset);
277 }
278 
279 void
281 {
282  uint32_t ih_cntl;
283  uint32_t ih_base;
284  uint32_t ih_base_hi;
285  Addr ih_baseAddr;
286  uint32_t ih_rptr;
287  uint32_t ih_wptr;
288  uint32_t ih_wptr_addr_lo;
289  uint32_t ih_wptr_addr_hi;
290  Addr ih_wptrAddr;
291  uint32_t ih_doorbellOffset;
292 
293  UNSERIALIZE_SCALAR(ih_cntl);
294  UNSERIALIZE_SCALAR(ih_base);
295  UNSERIALIZE_SCALAR(ih_base_hi);
296  UNSERIALIZE_SCALAR(ih_baseAddr);
297  UNSERIALIZE_SCALAR(ih_rptr);
298  UNSERIALIZE_SCALAR(ih_wptr);
299  UNSERIALIZE_SCALAR(ih_wptr_addr_lo);
300  UNSERIALIZE_SCALAR(ih_wptr_addr_hi);
301  UNSERIALIZE_SCALAR(ih_wptrAddr);
302  UNSERIALIZE_SCALAR(ih_doorbellOffset);
303 
304  regs.IH_Cntl = ih_cntl;
305  regs.IH_Base = ih_base;
306  regs.IH_Base_Hi = ih_base_hi;
307  regs.baseAddr = ih_baseAddr;
308  regs.IH_Rptr = ih_rptr;
309  regs.IH_Wptr = ih_wptr;
310  regs.IH_Wptr_Addr_Lo = ih_wptr_addr_lo;
311  regs.IH_Wptr_Addr_Hi = ih_wptr_addr_hi;
312  regs.WptrAddr = ih_wptrAddr;
313  regs.IH_Doorbell = ih_doorbellOffset;
314 }
315 
316 } // namespace gem5
#define DPRINTF(x,...)
Definition: trace.hh:186
const char data[]
Device model for an AMD GPU.
void setDoorbellType(uint32_t offset, QueueType qt)
Set handles to GPU blocks.
void intrPost()
Methods inherited from PciDevice.
void prepareInterruptCookie(ContextID cntxtId, uint32_t ring_id, uint32_t client_id, uint32_t source_id)
void setCntl(const uint32_t &data)
void setRptr(const uint32_t &data)
void setWptrAddrLo(const uint32_t &data)
AMDGPUInterruptHandler::DmaEvent * dmaEvent
AMDGPUInterruptHandler(const AMDGPUInterruptHandlerParams &p)
AddrRangeList getAddrRanges() const override
Every PIO device is obliged to provide an implementation that returns the address ranges the device r...
void unserialize(CheckpointIn &cp) override
Unserialize an object.
void setWptrAddrHi(const uint32_t &data)
void setBase(const uint32_t &data)
void serialize(CheckpointOut &cp) const override
Serialize an object.
void setDoorbellOffset(const uint32_t &data)
void updateRptr(const uint32_t &data)
void setBaseHi(const uint32_t &data)
void setWptr(const uint32_t &data)
std::queue< AMDGPUInterruptCookie * > interruptQueue
void writeMMIO(PacketPtr pkt, Addr mmio_offset)
Methods for setting the values of interrupt handler MMIO registers.
void dmaWrite(Addr addr, int size, Event *event, uint8_t *data, uint32_t sid, uint32_t ssid, Tick delay=0)
Definition: dma_device.hh:214
A Packet is used to encapsulate a transfer between two objects in the memory system (e....
Definition: packet.hh:294
T getLE() const
Get the data in the packet byte swapped from little endian to host endian.
constexpr T bits(T val, unsigned first, unsigned last)
Extract the bitfield from position 'first' to 'last' (inclusive) from 'val' and right justify it.
Definition: bitfield.hh:76
#define fatal(...)
This implements a cprintf based fatal() function.
Definition: logging.hh:190
#define mmIH_RB_CNTL
MMIO offsets for interrupt handler.
Definition: ih_mmio.hh:42
#define mmIH_RB_WPTR_ADDR_LO
Definition: ih_mmio.hh:48
#define mmIH_RB_WPTR
Definition: ih_mmio.hh:46
#define mmIH_RB_RPTR
Definition: ih_mmio.hh:45
#define mmIH_DOORBELL_RPTR
Definition: ih_mmio.hh:49
#define mmIH_RB_BASE_HI
Definition: ih_mmio.hh:44
#define mmIH_RB_BASE
Definition: ih_mmio.hh:43
#define mmIH_RB_WPTR_ADDR_HI
Definition: ih_mmio.hh:47
Bitfield< 54 > p
Definition: pagetable.hh:70
Reference material can be found at the JEDEC website: UFS standard http://www.jedec....
std::ostream CheckpointOut
Definition: serialize.hh:66
@ InterruptHandler
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
Definition: types.hh:147
@ SOC15_IH_CLIENTID_SDMA0
@ SOC15_IH_CLIENTID_GRBM_CP
@ SOC15_IH_CLIENTID_SDMA1
@ SOC15_IH_CLIENTID_RLC
int ContextID
Globally unique thread context ID.
Definition: types.hh:239
#define UNSERIALIZE_SCALAR(scalar)
Definition: serialize.hh:575
#define SERIALIZE_SCALAR(scalar)
Definition: serialize.hh:568
Struct to contain all interrupt handler related registers.

Generated on Wed Dec 21 2022 10:22:32 for gem5 by doxygen 1.9.1