Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

drm/amdkfd: Disable SVM per GPU, not per process

When some GPUs don't support SVM, don't disabe it for the entire process.
That would be inconsistent with the information the process got from the
topology, which indicates SVM support per GPU.

Instead disable SVM support only for the unsupported GPUs. This is done
by checking any per-device attributes against the bitmap of supported
GPUs. Also use the supported GPU bitmap to initialize access bitmaps for
new SVM address ranges.

Don't handle recoverable page faults from unsupported GPUs. (I don't
think there will be unsupported GPUs that can generate recoverable page
faults. But better safe than sorry.)

Signed-off-by: Felix Kuehling <Felix.Kuehling@amd.com>
Reviewed-by: Philip Yang <philip.yang@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>

authored by

Felix Kuehling and committed by
Alex Deucher
5a75ea56 d0414a83

+45 -38
-3
drivers/gpu/drm/amd/amdkfd/kfd_chardev.c
··· 1797 1797 struct kfd_ioctl_svm_args *args = data; 1798 1798 int r = 0; 1799 1799 1800 - if (p->svm_disabled) 1801 - return -EPERM; 1802 - 1803 1800 pr_debug("start 0x%llx size 0x%llx op 0x%x nattr 0x%x\n", 1804 1801 args->start_addr, args->size, args->op, args->nattr); 1805 1802
-4
drivers/gpu/drm/amd/amdkfd/kfd_flat_memory.c
··· 405 405 case CHIP_POLARIS12: 406 406 case CHIP_VEGAM: 407 407 kfd_init_apertures_vi(pdd, id); 408 - /* VI GPUs cannot support SVM with only 409 - * 40 bits of virtual address space. 410 - */ 411 - process->svm_disabled = true; 412 408 break; 413 409 case CHIP_VEGA10: 414 410 case CHIP_VEGA12:
+1 -1
drivers/gpu/drm/amd/amdkfd/kfd_priv.h
··· 743 743 spinlock_t deferred_list_lock; 744 744 atomic_t evicted_ranges; 745 745 struct delayed_work restore_work; 746 + DECLARE_BITMAP(bitmap_supported, MAX_GPU_INSTANCE); 746 747 }; 747 748 748 749 /* Process data */ ··· 827 826 828 827 /* shared virtual memory registered by this process */ 829 828 struct svm_range_list svms; 830 - bool svm_disabled; 831 829 832 830 bool xnack_enabled; 833 831 };
-1
drivers/gpu/drm/amd/amdkfd/kfd_process.c
··· 1260 1260 process->mm = thread->mm; 1261 1261 process->lead_thread = thread->group_leader; 1262 1262 process->n_pdds = 0; 1263 - process->svm_disabled = false; 1264 1263 INIT_DELAYED_WORK(&process->eviction_work, evict_process_worker); 1265 1264 INIT_DELAYED_WORK(&process->restore_work, restore_process_worker); 1266 1265 process->last_restore_timestamp = get_jiffies_64();
+35 -25
drivers/gpu/drm/amd/amdkfd/kfd_svm.c
··· 281 281 282 282 p = container_of(svms, struct kfd_process, svms); 283 283 if (p->xnack_enabled) 284 - bitmap_fill(prange->bitmap_access, MAX_GPU_INSTANCE); 284 + bitmap_copy(prange->bitmap_access, svms->bitmap_supported, 285 + MAX_GPU_INSTANCE); 285 286 286 287 svm_range_set_default_attributes(&prange->preferred_loc, 287 288 &prange->prefetch_loc, ··· 578 577 uint32_t nattr, struct kfd_ioctl_svm_attribute *attrs) 579 578 { 580 579 uint32_t i; 581 - int gpuidx; 582 580 583 581 for (i = 0; i < nattr; i++) { 582 + uint32_t val = attrs[i].value; 583 + int gpuidx = MAX_GPU_INSTANCE; 584 + 584 585 switch (attrs[i].type) { 585 586 case KFD_IOCTL_SVM_ATTR_PREFERRED_LOC: 586 - if (attrs[i].value != KFD_IOCTL_SVM_LOCATION_SYSMEM && 587 - attrs[i].value != KFD_IOCTL_SVM_LOCATION_UNDEFINED && 588 - kfd_process_gpuidx_from_gpuid(p, 589 - attrs[i].value) < 0) { 590 - pr_debug("no GPU 0x%x found\n", attrs[i].value); 591 - return -EINVAL; 592 - } 587 + if (val != KFD_IOCTL_SVM_LOCATION_SYSMEM && 588 + val != KFD_IOCTL_SVM_LOCATION_UNDEFINED) 589 + gpuidx = kfd_process_gpuidx_from_gpuid(p, val); 593 590 break; 594 591 case KFD_IOCTL_SVM_ATTR_PREFETCH_LOC: 595 - if (attrs[i].value != KFD_IOCTL_SVM_LOCATION_SYSMEM && 596 - kfd_process_gpuidx_from_gpuid(p, 597 - attrs[i].value) < 0) { 598 - pr_debug("no GPU 0x%x found\n", attrs[i].value); 599 - return -EINVAL; 600 - } 592 + if (val != KFD_IOCTL_SVM_LOCATION_SYSMEM) 593 + gpuidx = kfd_process_gpuidx_from_gpuid(p, val); 601 594 break; 602 595 case KFD_IOCTL_SVM_ATTR_ACCESS: 603 596 case KFD_IOCTL_SVM_ATTR_ACCESS_IN_PLACE: 604 597 case KFD_IOCTL_SVM_ATTR_NO_ACCESS: 605 - gpuidx = kfd_process_gpuidx_from_gpuid(p, 606 - attrs[i].value); 607 - if (gpuidx < 0) { 608 - pr_debug("no GPU 0x%x found\n", attrs[i].value); 609 - return -EINVAL; 610 - } 598 + gpuidx = kfd_process_gpuidx_from_gpuid(p, val); 611 599 break; 612 600 case KFD_IOCTL_SVM_ATTR_SET_FLAGS: 613 601 break; ··· 606 616 break; 607 617 default: 608 618 pr_debug("unknown attr type 0x%x\n", attrs[i].type); 619 + return -EINVAL; 620 + } 621 + 622 + if (gpuidx < 0) { 623 + pr_debug("no GPU 0x%x found\n", val); 624 + return -EINVAL; 625 + } else if (gpuidx < MAX_GPU_INSTANCE && 626 + !test_bit(gpuidx, p->svms.bitmap_supported)) { 627 + pr_debug("GPU 0x%x not supported\n", val); 609 628 return -EINVAL; 610 629 } 611 630 } ··· 1854 1855 1855 1856 p = container_of(svms, struct kfd_process, svms); 1856 1857 1857 - for (i = 0; i < p->n_pdds; i++) { 1858 + for_each_set_bit(i, svms->bitmap_supported, p->n_pdds) { 1858 1859 pdd = p->pdds[i]; 1859 1860 if (!pdd) 1860 1861 continue; ··· 2324 2325 bool write_locked = false; 2325 2326 int r = 0; 2326 2327 2328 + if (!KFD_IS_SVM_API_SUPPORTED(adev->kfd.dev)) { 2329 + pr_debug("device does not support SVM\n"); 2330 + return -EFAULT; 2331 + } 2332 + 2327 2333 p = kfd_lookup_process_by_pasid(pasid); 2328 2334 if (!p) { 2329 2335 pr_debug("kfd process not founded pasid 0x%x\n", pasid); ··· 2476 2472 int svm_range_list_init(struct kfd_process *p) 2477 2473 { 2478 2474 struct svm_range_list *svms = &p->svms; 2475 + int i; 2479 2476 2480 2477 svms->objects = RB_ROOT_CACHED; 2481 2478 mutex_init(&svms->lock); ··· 2486 2481 INIT_WORK(&svms->deferred_list_work, svm_range_deferred_list_work); 2487 2482 INIT_LIST_HEAD(&svms->deferred_range_list); 2488 2483 spin_lock_init(&svms->deferred_list_lock); 2484 + 2485 + for (i = 0; i < p->n_pdds; i++) 2486 + if (KFD_IS_SVM_API_SUPPORTED(p->pdds[i]->dev)) 2487 + bitmap_set(svms->bitmap_supported, i, 1); 2489 2488 2490 2489 return 0; 2491 2490 } ··· 2987 2978 svm_range_set_default_attributes(&location, &prefetch_loc, 2988 2979 &granularity, &flags); 2989 2980 if (p->xnack_enabled) 2990 - bitmap_fill(bitmap_access, MAX_GPU_INSTANCE); 2981 + bitmap_copy(bitmap_access, svms->bitmap_supported, 2982 + MAX_GPU_INSTANCE); 2991 2983 else 2992 2984 bitmap_zero(bitmap_access, MAX_GPU_INSTANCE); 2993 2985 bitmap_zero(bitmap_aip, MAX_GPU_INSTANCE); 2994 2986 goto fill_values; 2995 2987 } 2996 - bitmap_fill(bitmap_access, MAX_GPU_INSTANCE); 2997 - bitmap_fill(bitmap_aip, MAX_GPU_INSTANCE); 2988 + bitmap_copy(bitmap_access, svms->bitmap_supported, MAX_GPU_INSTANCE); 2989 + bitmap_copy(bitmap_aip, svms->bitmap_supported, MAX_GPU_INSTANCE); 2998 2990 2999 2991 while (node) { 3000 2992 struct interval_tree_node *next;
+7
drivers/gpu/drm/amd/amdkfd/kfd_svm.h
··· 175 175 void svm_range_free_dma_mappings(struct svm_range *prange); 176 176 void svm_range_prefault(struct svm_range *prange, struct mm_struct *mm); 177 177 178 + /* SVM API and HMM page migration work together, device memory type 179 + * is initialized to not 0 when page migration register device memory. 180 + */ 181 + #define KFD_IS_SVM_API_SUPPORTED(dev) ((dev)->pgmap.type != 0) 182 + 178 183 #else 179 184 180 185 struct kfd_process; ··· 205 200 WARN_ONCE(1, "SVM eviction fence triggered, but SVM is disabled"); 206 201 return -EINVAL; 207 202 } 203 + 204 + #define KFD_IS_SVM_API_SUPPORTED(dev) false 208 205 209 206 #endif /* IS_ENABLED(CONFIG_HSA_AMD_SVM) */ 210 207
+2 -4
drivers/gpu/drm/amd/amdkfd/kfd_topology.c
··· 36 36 #include "kfd_topology.h" 37 37 #include "kfd_device_queue_manager.h" 38 38 #include "kfd_iommu.h" 39 + #include "kfd_svm.h" 39 40 #include "amdgpu_amdkfd.h" 40 41 #include "amdgpu_ras.h" 41 42 ··· 1442 1441 dev->node_props.capability |= (adev->ras_enabled != 0) ? 1443 1442 HSA_CAP_RASEVENTNOTIFY : 0; 1444 1443 1445 - /* SVM API and HMM page migration work together, device memory type 1446 - * is initialized to not 0 when page migration register device memory. 1447 - */ 1448 - if (adev->kfd.dev->pgmap.type != 0) 1444 + if (KFD_IS_SVM_API_SUPPORTED(adev->kfd.dev)) 1449 1445 dev->node_props.capability |= HSA_CAP_SVMAPI_SUPPORTED; 1450 1446 1451 1447 kfd_debug_print_topology();