|
@@ -48,18 +48,19 @@ static bool cik_event_interrupt_isr(struct kfd_dev *dev,
|
|
|
return ihre->source_id == CIK_INTSRC_CP_END_OF_PIPE ||
|
|
|
ihre->source_id == CIK_INTSRC_SDMA_TRAP ||
|
|
|
ihre->source_id == CIK_INTSRC_SQ_INTERRUPT_MSG ||
|
|
|
- ihre->source_id == CIK_INTSRC_CP_BAD_OPCODE;
|
|
|
+ ihre->source_id == CIK_INTSRC_CP_BAD_OPCODE ||
|
|
|
+ ihre->source_id == CIK_INTSRC_GFX_PAGE_INV_FAULT ||
|
|
|
+ ihre->source_id == CIK_INTSRC_GFX_MEM_PROT_FAULT;
|
|
|
}
|
|
|
|
|
|
static void cik_event_interrupt_wq(struct kfd_dev *dev,
|
|
|
const uint32_t *ih_ring_entry)
|
|
|
{
|
|
|
- unsigned int pasid;
|
|
|
const struct cik_ih_ring_entry *ihre =
|
|
|
(const struct cik_ih_ring_entry *)ih_ring_entry;
|
|
|
uint32_t context_id = ihre->data & 0xfffffff;
|
|
|
-
|
|
|
- pasid = (ihre->ring_id & 0xffff0000) >> 16;
|
|
|
+ unsigned int vmid = (ihre->ring_id & 0x0000ff00) >> 8;
|
|
|
+ unsigned int pasid = (ihre->ring_id & 0xffff0000) >> 16;
|
|
|
|
|
|
if (pasid == 0)
|
|
|
return;
|
|
@@ -72,6 +73,22 @@ static void cik_event_interrupt_wq(struct kfd_dev *dev,
|
|
|
kfd_signal_event_interrupt(pasid, context_id & 0xff, 8);
|
|
|
else if (ihre->source_id == CIK_INTSRC_CP_BAD_OPCODE)
|
|
|
kfd_signal_hw_exception_event(pasid);
|
|
|
+ else if (ihre->source_id == CIK_INTSRC_GFX_PAGE_INV_FAULT ||
|
|
|
+ ihre->source_id == CIK_INTSRC_GFX_MEM_PROT_FAULT) {
|
|
|
+ struct kfd_vm_fault_info info;
|
|
|
+
|
|
|
+ kfd_process_vm_fault(dev->dqm, pasid);
|
|
|
+
|
|
|
+ memset(&info, 0, sizeof(info));
|
|
|
+ dev->kfd2kgd->get_vm_fault_info(dev->kgd, &info);
|
|
|
+ if (!info.page_addr && !info.status)
|
|
|
+ return;
|
|
|
+
|
|
|
+ if (info.vmid == vmid)
|
|
|
+ kfd_signal_vm_fault_event(dev, pasid, &info);
|
|
|
+ else
|
|
|
+ kfd_signal_vm_fault_event(dev, pasid, NULL);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
const struct kfd_event_interrupt_class event_interrupt_class_cik = {
|