diff options
author | shaoyunl <Shaoyun.Liu@amd.com> | 2018-07-11 22:32:49 -0400 |
---|---|---|
committer | Oded Gabbay <oded.gabbay@gmail.com> | 2018-07-11 22:32:49 -0400 |
commit | b97dfa27ef3ad3eddd2cb97a3b6a140d7037827a (patch) | |
tree | a8df9ac8dfc2d082435a6252792f01760412ebb5 | |
parent | 101fee63cbb0a3df9e54aaafbfad0ab5821a34e6 (diff) |
drm/amdgpu: save vm fault information for amdkfd
amdgpu save the vm fault related information for KFD usage and keep the
copy until KFD read it.
Signed-off-by: shaoyun liu <shaoyun.liu@amd.com>
Signed-off-by: Felix Kuehling <Felix.Kuehling@amd.com>
Acked-by: Christian König <christian.koenig@amd.com>
Signed-off-by: Oded Gabbay <oded.gabbay@gmail.com>
-rw-r--r-- | drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h | 3 | ||||
-rw-r--r-- | drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v7.c | 1 | ||||
-rw-r--r-- | drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v8.c | 1 | ||||
-rw-r--r-- | drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c | 14 | ||||
-rw-r--r-- | drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.h | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c | 33 | ||||
-rw-r--r-- | drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c | 33 | ||||
-rw-r--r-- | drivers/gpu/drm/amd/include/kgd_kfd_interface.h | 20 |
8 files changed, 105 insertions, 2 deletions
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h index a8418a3f4e9d..3dc76d9b4d12 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h | |||
@@ -183,6 +183,9 @@ int amdgpu_amdkfd_gpuvm_map_gtt_bo_to_kernel(struct kgd_dev *kgd, | |||
183 | int amdgpu_amdkfd_gpuvm_restore_process_bos(void *process_info, | 183 | int amdgpu_amdkfd_gpuvm_restore_process_bos(void *process_info, |
184 | struct dma_fence **ef); | 184 | struct dma_fence **ef); |
185 | 185 | ||
186 | int amdgpu_amdkfd_gpuvm_get_vm_fault_info(struct kgd_dev *kgd, | ||
187 | struct kfd_vm_fault_info *info); | ||
188 | |||
186 | void amdgpu_amdkfd_gpuvm_init_mem_limits(void); | 189 | void amdgpu_amdkfd_gpuvm_init_mem_limits(void); |
187 | void amdgpu_amdkfd_unreserve_system_memory_limit(struct amdgpu_bo *bo); | 190 | void amdgpu_amdkfd_unreserve_system_memory_limit(struct amdgpu_bo *bo); |
188 | 191 | ||
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v7.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v7.c index ea79908dac4c..befc7c48b1cf 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v7.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v7.c | |||
@@ -216,6 +216,7 @@ static const struct kfd2kgd_calls kfd2kgd = { | |||
216 | .invalidate_tlbs = invalidate_tlbs, | 216 | .invalidate_tlbs = invalidate_tlbs, |
217 | .invalidate_tlbs_vmid = invalidate_tlbs_vmid, | 217 | .invalidate_tlbs_vmid = invalidate_tlbs_vmid, |
218 | .submit_ib = amdgpu_amdkfd_submit_ib, | 218 | .submit_ib = amdgpu_amdkfd_submit_ib, |
219 | .get_vm_fault_info = amdgpu_amdkfd_gpuvm_get_vm_fault_info | ||
219 | }; | 220 | }; |
220 | 221 | ||
221 | struct kfd2kgd_calls *amdgpu_amdkfd_gfx_7_get_functions(void) | 222 | struct kfd2kgd_calls *amdgpu_amdkfd_gfx_7_get_functions(void) |
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v8.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v8.c index 19dd665e7307..c68ef85f7753 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v8.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v8.c | |||
@@ -176,6 +176,7 @@ static const struct kfd2kgd_calls kfd2kgd = { | |||
176 | .invalidate_tlbs = invalidate_tlbs, | 176 | .invalidate_tlbs = invalidate_tlbs, |
177 | .invalidate_tlbs_vmid = invalidate_tlbs_vmid, | 177 | .invalidate_tlbs_vmid = invalidate_tlbs_vmid, |
178 | .submit_ib = amdgpu_amdkfd_submit_ib, | 178 | .submit_ib = amdgpu_amdkfd_submit_ib, |
179 | .get_vm_fault_info = amdgpu_amdkfd_gpuvm_get_vm_fault_info | ||
179 | }; | 180 | }; |
180 | 181 | ||
181 | struct kfd2kgd_calls *amdgpu_amdkfd_gfx_8_0_get_functions(void) | 182 | struct kfd2kgd_calls *amdgpu_amdkfd_gfx_8_0_get_functions(void) |
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c index fa38a960ce00..8a707d8bbb1c 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c | |||
@@ -1621,6 +1621,20 @@ bo_reserve_failed: | |||
1621 | return ret; | 1621 | return ret; |
1622 | } | 1622 | } |
1623 | 1623 | ||
1624 | int amdgpu_amdkfd_gpuvm_get_vm_fault_info(struct kgd_dev *kgd, | ||
1625 | struct kfd_vm_fault_info *mem) | ||
1626 | { | ||
1627 | struct amdgpu_device *adev; | ||
1628 | |||
1629 | adev = (struct amdgpu_device *)kgd; | ||
1630 | if (atomic_read(&adev->gmc.vm_fault_info_updated) == 1) { | ||
1631 | *mem = *adev->gmc.vm_fault_info; | ||
1632 | mb(); | ||
1633 | atomic_set(&adev->gmc.vm_fault_info_updated, 0); | ||
1634 | } | ||
1635 | return 0; | ||
1636 | } | ||
1637 | |||
1624 | /* Evict a userptr BO by stopping the queues if necessary | 1638 | /* Evict a userptr BO by stopping the queues if necessary |
1625 | * | 1639 | * |
1626 | * Runs in MMU notifier, may be in RECLAIM_FS context. This means it | 1640 | * Runs in MMU notifier, may be in RECLAIM_FS context. This means it |
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.h index 6cb4948233cb..bb5a47a45790 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.h | |||
@@ -105,6 +105,8 @@ struct amdgpu_gmc { | |||
105 | /* protects concurrent invalidation */ | 105 | /* protects concurrent invalidation */ |
106 | spinlock_t invalidate_lock; | 106 | spinlock_t invalidate_lock; |
107 | bool translate_further; | 107 | bool translate_further; |
108 | struct kfd_vm_fault_info *vm_fault_info; | ||
109 | atomic_t vm_fault_info_updated; | ||
108 | 110 | ||
109 | const struct amdgpu_gmc_funcs *gmc_funcs; | 111 | const struct amdgpu_gmc_funcs *gmc_funcs; |
110 | }; | 112 | }; |
diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c index 10920f0bd85f..36dc367c4b45 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c | |||
@@ -28,6 +28,7 @@ | |||
28 | #include "cik.h" | 28 | #include "cik.h" |
29 | #include "gmc_v7_0.h" | 29 | #include "gmc_v7_0.h" |
30 | #include "amdgpu_ucode.h" | 30 | #include "amdgpu_ucode.h" |
31 | #include "amdgpu_amdkfd.h" | ||
31 | 32 | ||
32 | #include "bif/bif_4_1_d.h" | 33 | #include "bif/bif_4_1_d.h" |
33 | #include "bif/bif_4_1_sh_mask.h" | 34 | #include "bif/bif_4_1_sh_mask.h" |
@@ -1078,6 +1079,12 @@ static int gmc_v7_0_sw_init(void *handle) | |||
1078 | adev->vm_manager.vram_base_offset = 0; | 1079 | adev->vm_manager.vram_base_offset = 0; |
1079 | } | 1080 | } |
1080 | 1081 | ||
1082 | adev->gmc.vm_fault_info = kmalloc(sizeof(struct kfd_vm_fault_info), | ||
1083 | GFP_KERNEL); | ||
1084 | if (!adev->gmc.vm_fault_info) | ||
1085 | return -ENOMEM; | ||
1086 | atomic_set(&adev->gmc.vm_fault_info_updated, 0); | ||
1087 | |||
1081 | return 0; | 1088 | return 0; |
1082 | } | 1089 | } |
1083 | 1090 | ||
@@ -1087,6 +1094,7 @@ static int gmc_v7_0_sw_fini(void *handle) | |||
1087 | 1094 | ||
1088 | amdgpu_gem_force_release(adev); | 1095 | amdgpu_gem_force_release(adev); |
1089 | amdgpu_vm_manager_fini(adev); | 1096 | amdgpu_vm_manager_fini(adev); |
1097 | kfree(adev->gmc.vm_fault_info); | ||
1090 | gmc_v7_0_gart_fini(adev); | 1098 | gmc_v7_0_gart_fini(adev); |
1091 | amdgpu_bo_fini(adev); | 1099 | amdgpu_bo_fini(adev); |
1092 | release_firmware(adev->gmc.fw); | 1100 | release_firmware(adev->gmc.fw); |
@@ -1276,7 +1284,7 @@ static int gmc_v7_0_process_interrupt(struct amdgpu_device *adev, | |||
1276 | struct amdgpu_irq_src *source, | 1284 | struct amdgpu_irq_src *source, |
1277 | struct amdgpu_iv_entry *entry) | 1285 | struct amdgpu_iv_entry *entry) |
1278 | { | 1286 | { |
1279 | u32 addr, status, mc_client; | 1287 | u32 addr, status, mc_client, vmid; |
1280 | 1288 | ||
1281 | addr = RREG32(mmVM_CONTEXT1_PROTECTION_FAULT_ADDR); | 1289 | addr = RREG32(mmVM_CONTEXT1_PROTECTION_FAULT_ADDR); |
1282 | status = RREG32(mmVM_CONTEXT1_PROTECTION_FAULT_STATUS); | 1290 | status = RREG32(mmVM_CONTEXT1_PROTECTION_FAULT_STATUS); |
@@ -1301,6 +1309,29 @@ static int gmc_v7_0_process_interrupt(struct amdgpu_device *adev, | |||
1301 | entry->pasid); | 1309 | entry->pasid); |
1302 | } | 1310 | } |
1303 | 1311 | ||
1312 | vmid = REG_GET_FIELD(status, VM_CONTEXT1_PROTECTION_FAULT_STATUS, | ||
1313 | VMID); | ||
1314 | if (amdgpu_amdkfd_is_kfd_vmid(adev, vmid) | ||
1315 | && !atomic_read(&adev->gmc.vm_fault_info_updated)) { | ||
1316 | struct kfd_vm_fault_info *info = adev->gmc.vm_fault_info; | ||
1317 | u32 protections = REG_GET_FIELD(status, | ||
1318 | VM_CONTEXT1_PROTECTION_FAULT_STATUS, | ||
1319 | PROTECTIONS); | ||
1320 | |||
1321 | info->vmid = vmid; | ||
1322 | info->mc_id = REG_GET_FIELD(status, | ||
1323 | VM_CONTEXT1_PROTECTION_FAULT_STATUS, | ||
1324 | MEMORY_CLIENT_ID); | ||
1325 | info->status = status; | ||
1326 | info->page_addr = addr; | ||
1327 | info->prot_valid = protections & 0x7 ? true : false; | ||
1328 | info->prot_read = protections & 0x8 ? true : false; | ||
1329 | info->prot_write = protections & 0x10 ? true : false; | ||
1330 | info->prot_exec = protections & 0x20 ? true : false; | ||
1331 | mb(); | ||
1332 | atomic_set(&adev->gmc.vm_fault_info_updated, 1); | ||
1333 | } | ||
1334 | |||
1304 | return 0; | 1335 | return 0; |
1305 | } | 1336 | } |
1306 | 1337 | ||
diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c index 75f3ffb2891e..70fc97b59b4f 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c | |||
@@ -26,6 +26,7 @@ | |||
26 | #include "amdgpu.h" | 26 | #include "amdgpu.h" |
27 | #include "gmc_v8_0.h" | 27 | #include "gmc_v8_0.h" |
28 | #include "amdgpu_ucode.h" | 28 | #include "amdgpu_ucode.h" |
29 | #include "amdgpu_amdkfd.h" | ||
29 | 30 | ||
30 | #include "gmc/gmc_8_1_d.h" | 31 | #include "gmc/gmc_8_1_d.h" |
31 | #include "gmc/gmc_8_1_sh_mask.h" | 32 | #include "gmc/gmc_8_1_sh_mask.h" |
@@ -1182,6 +1183,12 @@ static int gmc_v8_0_sw_init(void *handle) | |||
1182 | adev->vm_manager.vram_base_offset = 0; | 1183 | adev->vm_manager.vram_base_offset = 0; |
1183 | } | 1184 | } |
1184 | 1185 | ||
1186 | adev->gmc.vm_fault_info = kmalloc(sizeof(struct kfd_vm_fault_info), | ||
1187 | GFP_KERNEL); | ||
1188 | if (!adev->gmc.vm_fault_info) | ||
1189 | return -ENOMEM; | ||
1190 | atomic_set(&adev->gmc.vm_fault_info_updated, 0); | ||
1191 | |||
1185 | return 0; | 1192 | return 0; |
1186 | } | 1193 | } |
1187 | 1194 | ||
@@ -1191,6 +1198,7 @@ static int gmc_v8_0_sw_fini(void *handle) | |||
1191 | 1198 | ||
1192 | amdgpu_gem_force_release(adev); | 1199 | amdgpu_gem_force_release(adev); |
1193 | amdgpu_vm_manager_fini(adev); | 1200 | amdgpu_vm_manager_fini(adev); |
1201 | kfree(adev->gmc.vm_fault_info); | ||
1194 | gmc_v8_0_gart_fini(adev); | 1202 | gmc_v8_0_gart_fini(adev); |
1195 | amdgpu_bo_fini(adev); | 1203 | amdgpu_bo_fini(adev); |
1196 | release_firmware(adev->gmc.fw); | 1204 | release_firmware(adev->gmc.fw); |
@@ -1426,7 +1434,7 @@ static int gmc_v8_0_process_interrupt(struct amdgpu_device *adev, | |||
1426 | struct amdgpu_irq_src *source, | 1434 | struct amdgpu_irq_src *source, |
1427 | struct amdgpu_iv_entry *entry) | 1435 | struct amdgpu_iv_entry *entry) |
1428 | { | 1436 | { |
1429 | u32 addr, status, mc_client; | 1437 | u32 addr, status, mc_client, vmid; |
1430 | 1438 | ||
1431 | if (amdgpu_sriov_vf(adev)) { | 1439 | if (amdgpu_sriov_vf(adev)) { |
1432 | dev_err(adev->dev, "GPU fault detected: %d 0x%08x\n", | 1440 | dev_err(adev->dev, "GPU fault detected: %d 0x%08x\n", |
@@ -1463,6 +1471,29 @@ static int gmc_v8_0_process_interrupt(struct amdgpu_device *adev, | |||
1463 | entry->pasid); | 1471 | entry->pasid); |
1464 | } | 1472 | } |
1465 | 1473 | ||
1474 | vmid = REG_GET_FIELD(status, VM_CONTEXT1_PROTECTION_FAULT_STATUS, | ||
1475 | VMID); | ||
1476 | if (amdgpu_amdkfd_is_kfd_vmid(adev, vmid) | ||
1477 | && !atomic_read(&adev->gmc.vm_fault_info_updated)) { | ||
1478 | struct kfd_vm_fault_info *info = adev->gmc.vm_fault_info; | ||
1479 | u32 protections = REG_GET_FIELD(status, | ||
1480 | VM_CONTEXT1_PROTECTION_FAULT_STATUS, | ||
1481 | PROTECTIONS); | ||
1482 | |||
1483 | info->vmid = vmid; | ||
1484 | info->mc_id = REG_GET_FIELD(status, | ||
1485 | VM_CONTEXT1_PROTECTION_FAULT_STATUS, | ||
1486 | MEMORY_CLIENT_ID); | ||
1487 | info->status = status; | ||
1488 | info->page_addr = addr; | ||
1489 | info->prot_valid = protections & 0x7 ? true : false; | ||
1490 | info->prot_read = protections & 0x8 ? true : false; | ||
1491 | info->prot_write = protections & 0x10 ? true : false; | ||
1492 | info->prot_exec = protections & 0x20 ? true : false; | ||
1493 | mb(); | ||
1494 | atomic_set(&adev->gmc.vm_fault_info_updated, 1); | ||
1495 | } | ||
1496 | |||
1466 | return 0; | 1497 | return 0; |
1467 | } | 1498 | } |
1468 | 1499 | ||
diff --git a/drivers/gpu/drm/amd/include/kgd_kfd_interface.h b/drivers/gpu/drm/amd/include/kgd_kfd_interface.h index 5733fbee07f7..28b11d105288 100644 --- a/drivers/gpu/drm/amd/include/kgd_kfd_interface.h +++ b/drivers/gpu/drm/amd/include/kgd_kfd_interface.h | |||
@@ -47,6 +47,17 @@ enum kfd_preempt_type { | |||
47 | KFD_PREEMPT_TYPE_WAVEFRONT_RESET, | 47 | KFD_PREEMPT_TYPE_WAVEFRONT_RESET, |
48 | }; | 48 | }; |
49 | 49 | ||
50 | struct kfd_vm_fault_info { | ||
51 | uint64_t page_addr; | ||
52 | uint32_t vmid; | ||
53 | uint32_t mc_id; | ||
54 | uint32_t status; | ||
55 | bool prot_valid; | ||
56 | bool prot_read; | ||
57 | bool prot_write; | ||
58 | bool prot_exec; | ||
59 | }; | ||
60 | |||
50 | struct kfd_cu_info { | 61 | struct kfd_cu_info { |
51 | uint32_t num_shader_engines; | 62 | uint32_t num_shader_engines; |
52 | uint32_t num_shader_arrays_per_engine; | 63 | uint32_t num_shader_arrays_per_engine; |
@@ -259,6 +270,12 @@ struct tile_config { | |||
259 | * IB to the corresponding ring (ring type). The IB is executed with the | 270 | * IB to the corresponding ring (ring type). The IB is executed with the |
260 | * specified VMID in a user mode context. | 271 | * specified VMID in a user mode context. |
261 | * | 272 | * |
273 | * @get_vm_fault_info: Return information about a recent VM fault on | ||
274 | * GFXv7 and v8. If multiple VM faults occurred since the last call of | ||
275 | * this function, it will return information about the first of those | ||
276 | * faults. On GFXv9 VM fault information is fully contained in the IH | ||
277 | * packet and this function is not needed. | ||
278 | * | ||
262 | * This structure contains function pointers to services that the kgd driver | 279 | * This structure contains function pointers to services that the kgd driver |
263 | * provides to amdkfd driver. | 280 | * provides to amdkfd driver. |
264 | * | 281 | * |
@@ -374,6 +391,9 @@ struct kfd2kgd_calls { | |||
374 | int (*submit_ib)(struct kgd_dev *kgd, enum kgd_engine_type engine, | 391 | int (*submit_ib)(struct kgd_dev *kgd, enum kgd_engine_type engine, |
375 | uint32_t vmid, uint64_t gpu_addr, | 392 | uint32_t vmid, uint64_t gpu_addr, |
376 | uint32_t *ib_cmd, uint32_t ib_len); | 393 | uint32_t *ib_cmd, uint32_t ib_len); |
394 | |||
395 | int (*get_vm_fault_info)(struct kgd_dev *kgd, | ||
396 | struct kfd_vm_fault_info *info); | ||
377 | }; | 397 | }; |
378 | 398 | ||
379 | /** | 399 | /** |