aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFelix Kuehling <Felix.Kuehling@amd.com>2018-05-01 17:56:12 -0400
committerOded Gabbay <oded.gabbay@gmail.com>2018-05-01 17:56:12 -0400
commitc129db1206bd11ab0531a4d91a455a0809acae0e (patch)
treefd965f83948f9dfea0baf899d6e83fb0a90864e9
parent2533f0741e5f7259393d7edecb4bca3106c583c2 (diff)
drm/amdkfd: Add sanity checks in IRQ handlers
Only accept interrupts from KFD VMIDs. Just checking for a PASID may not be enough because amdgpu started using PASIDs to map VM faults to processes. Warn if an IRQ doesn't have a valid PASID (indicating a firmware bug). Suggested-by: Shaoyun Liu <Shaoyun.Liu@amd.com> Suggested-by: Oak Zeng <Oak.Zeng@amd.com> Signed-off-by: Felix Kuehling <Felix.Kuehling@amd.com> Reviewed-by: Oded Gabbay <oded.gabbay@gmail.com> Signed-off-by: Oded Gabbay <oded.gabbay@gmail.com>
-rw-r--r--drivers/gpu/drm/amd/amdkfd/cik_event_interrupt.c20
-rw-r--r--drivers/gpu/drm/amd/amdkfd/kfd_int_process_v9.c40
2 files changed, 39 insertions, 21 deletions
diff --git a/drivers/gpu/drm/amd/amdkfd/cik_event_interrupt.c b/drivers/gpu/drm/amd/amdkfd/cik_event_interrupt.c
index 3d5ccb3755d4..49df6c791cfc 100644
--- a/drivers/gpu/drm/amd/amdkfd/cik_event_interrupt.c
+++ b/drivers/gpu/drm/amd/amdkfd/cik_event_interrupt.c
@@ -27,18 +27,28 @@
27static bool cik_event_interrupt_isr(struct kfd_dev *dev, 27static bool cik_event_interrupt_isr(struct kfd_dev *dev,
28 const uint32_t *ih_ring_entry) 28 const uint32_t *ih_ring_entry)
29{ 29{
30 unsigned int pasid;
31 const struct cik_ih_ring_entry *ihre = 30 const struct cik_ih_ring_entry *ihre =
32 (const struct cik_ih_ring_entry *)ih_ring_entry; 31 (const struct cik_ih_ring_entry *)ih_ring_entry;
32 unsigned int vmid, pasid;
33
34 /* Only handle interrupts from KFD VMIDs */
35 vmid = (ihre->ring_id & 0x0000ff00) >> 8;
36 if (vmid < dev->vm_info.first_vmid_kfd ||
37 vmid > dev->vm_info.last_vmid_kfd)
38 return 0;
33 39
40 /* If there is no valid PASID, it's likely a firmware bug */
34 pasid = (ihre->ring_id & 0xffff0000) >> 16; 41 pasid = (ihre->ring_id & 0xffff0000) >> 16;
42 if (WARN_ONCE(pasid == 0, "FW bug: No PASID in KFD interrupt"))
43 return 0;
35 44
36 /* Do not process in ISR, just request it to be forwarded to WQ. */ 45 /* Interrupt types we care about: various signals and faults.
37 return (pasid != 0) && 46 * They will be forwarded to a work queue (see below).
38 (ihre->source_id == CIK_INTSRC_CP_END_OF_PIPE || 47 */
48 return ihre->source_id == CIK_INTSRC_CP_END_OF_PIPE ||
39 ihre->source_id == CIK_INTSRC_SDMA_TRAP || 49 ihre->source_id == CIK_INTSRC_SDMA_TRAP ||
40 ihre->source_id == CIK_INTSRC_SQ_INTERRUPT_MSG || 50 ihre->source_id == CIK_INTSRC_SQ_INTERRUPT_MSG ||
41 ihre->source_id == CIK_INTSRC_CP_BAD_OPCODE); 51 ihre->source_id == CIK_INTSRC_CP_BAD_OPCODE;
42} 52}
43 53
44static void cik_event_interrupt_wq(struct kfd_dev *dev, 54static void cik_event_interrupt_wq(struct kfd_dev *dev,
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_int_process_v9.c b/drivers/gpu/drm/amd/amdkfd/kfd_int_process_v9.c
index 39d41155581f..37029baa3346 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_int_process_v9.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_int_process_v9.c
@@ -29,27 +29,35 @@ static bool event_interrupt_isr_v9(struct kfd_dev *dev,
29 const uint32_t *ih_ring_entry) 29 const uint32_t *ih_ring_entry)
30{ 30{
31 uint16_t source_id, client_id, pasid, vmid; 31 uint16_t source_id, client_id, pasid, vmid;
32 const uint32_t *data = ih_ring_entry;
32 33
33 source_id = SOC15_SOURCE_ID_FROM_IH_ENTRY(ih_ring_entry); 34 /* Only handle interrupts from KFD VMIDs */
34 client_id = SOC15_CLIENT_ID_FROM_IH_ENTRY(ih_ring_entry);
35 pasid = SOC15_PASID_FROM_IH_ENTRY(ih_ring_entry);
36 vmid = SOC15_VMID_FROM_IH_ENTRY(ih_ring_entry); 35 vmid = SOC15_VMID_FROM_IH_ENTRY(ih_ring_entry);
36 if (vmid < dev->vm_info.first_vmid_kfd ||
37 vmid > dev->vm_info.last_vmid_kfd)
38 return 0;
39
40 /* If there is no valid PASID, it's likely a firmware bug */
41 pasid = SOC15_PASID_FROM_IH_ENTRY(ih_ring_entry);
42 if (WARN_ONCE(pasid == 0, "FW bug: No PASID in KFD interrupt"))
43 return 0;
37 44
38 if (pasid) { 45 source_id = SOC15_SOURCE_ID_FROM_IH_ENTRY(ih_ring_entry);
39 const uint32_t *data = ih_ring_entry; 46 client_id = SOC15_CLIENT_ID_FROM_IH_ENTRY(ih_ring_entry);
40 47
41 pr_debug("client id 0x%x, source id %d, pasid 0x%x. raw data:\n", 48 pr_debug("client id 0x%x, source id %d, pasid 0x%x. raw data:\n",
42 client_id, source_id, pasid); 49 client_id, source_id, pasid);
43 pr_debug("%8X, %8X, %8X, %8X, %8X, %8X, %8X, %8X.\n", 50 pr_debug("%8X, %8X, %8X, %8X, %8X, %8X, %8X, %8X.\n",
44 data[0], data[1], data[2], data[3], 51 data[0], data[1], data[2], data[3],
45 data[4], data[5], data[6], data[7]); 52 data[4], data[5], data[6], data[7]);
46 }
47 53
48 return (pasid != 0) && 54 /* Interrupt types we care about: various signals and faults.
49 (source_id == SOC15_INTSRC_CP_END_OF_PIPE || 55 * They will be forwarded to a work queue (see below).
50 source_id == SOC15_INTSRC_SDMA_TRAP || 56 */
51 source_id == SOC15_INTSRC_SQ_INTERRUPT_MSG || 57 return source_id == SOC15_INTSRC_CP_END_OF_PIPE ||
52 source_id == SOC15_INTSRC_CP_BAD_OPCODE); 58 source_id == SOC15_INTSRC_SDMA_TRAP ||
59 source_id == SOC15_INTSRC_SQ_INTERRUPT_MSG ||
60 source_id == SOC15_INTSRC_CP_BAD_OPCODE;
53} 61}
54 62
55static void event_interrupt_wq_v9(struct kfd_dev *dev, 63static void event_interrupt_wq_v9(struct kfd_dev *dev,