KFD SVM ranges on processes without XNACK, and ranges requested as GPU_ALWAYS_MAPPED, cannot rely on replayable GPU faults after a CPU THP remap of the registered VA range. Keep those ranges backed by base pages while their interval notifier is active.
Opt those SVM interval notifiers into MMU_INTERVAL_NOTIFIER_BLOCK_THP and update the flag when SVM attributes change. XNACK-enabled ranges that can handle remaps through replayable faults remain eligible for THP unless GPU_ALWAYS_MAPPED is requested. Assisted-by: OpenAI-Codex:GPT-5.5 Signed-off-by: Yitao Jiang <[email protected]> --- drivers/gpu/drm/amd/amdkfd/kfd_svm.c | 36 ++++++++++++++++++++++++---- 1 file changed, 32 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c index 3841943da..0d0feba7b 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c @@ -22,6 +22,7 @@ */ #include <linux/types.h> +#include <linux/mm.h> #include <linux/sched/task.h> #include <linux/dynamic_debug.h> #include <drm/ttm/ttm_tt.h> @@ -81,6 +82,26 @@ static const struct mmu_interval_notifier_ops svm_range_mn_ops = { .invalidate = svm_range_cpu_invalidate_pagetables, }; +static unsigned int +svm_range_mn_flags(struct svm_range *prange) +{ + struct kfd_process *p = container_of(prange->svms, struct kfd_process, + svms); + + if (!p->xnack_enabled || + (prange->flags & KFD_IOCTL_SVM_FLAG_GPU_ALWAYS_MAPPED)) + return MMU_INTERVAL_NOTIFIER_BLOCK_THP; + + return 0; +} + +static int +svm_range_update_mn_flags_locked(struct svm_range *prange) +{ + return mmu_interval_notifier_set_flags_locked(&prange->notifier, + svm_range_mn_flags(prange)); +} + /** * svm_range_unlink - unlink svm_range from lists and interval tree * @prange: svm range structure to be removed @@ -112,10 +133,11 @@ svm_range_add_notifier_locked(struct mm_struct *mm, struct svm_range *prange) pr_debug("svms 0x%p prange 0x%p [0x%lx 0x%lx]\n", prange->svms, prange, prange->start, prange->last); - mmu_interval_notifier_insert_locked(&prange->notifier, mm, - prange->start << PAGE_SHIFT, - prange->npages << PAGE_SHIFT, - &svm_range_mn_ops); + mmu_interval_notifier_insert_locked_flags(&prange->notifier, mm, + prange->start << PAGE_SHIFT, + prange->npages << PAGE_SHIFT, + &svm_range_mn_ops, + svm_range_mn_flags(prange)); } /** @@ -3763,6 +3785,12 @@ svm_range_set_attr(struct kfd_process *p, struct mm_struct *mm, } list_for_each_entry(prange, &update_list, update_list) { svm_range_apply_attrs(p, prange, nattr, attrs, &update_mapping); + r = svm_range_update_mn_flags_locked(prange); + if (r) { + mutex_unlock(&svms->lock); + mmap_write_unlock(mm); + goto out; + } /* TODO: unmap ranges from GPU that lost access */ } update_mapping |= !p->xnack_enabled && !list_empty(&remap_list); -- 2.53.0
