Commit 0ed704d0 authored by Kent Russell's avatar Kent Russell Committed by Alex Deucher
Browse files

drm/amdkfd: Handle lack of READ permissions in SVM mapping



HMM assumes that pages have READ permissions by default. Inside
svm_range_validate_and_map, we add READ permissions then add WRITE
permissions if the VMA isn't read-only. This will conflict with regions
that only have PROT_WRITE or have PROT_NONE. When that happens,
svm_range_restore_work will continue to retry, silently, giving the
impression of a hang if pr_debug isn't enabled to show the retries..

If pages don't have READ permissions, simply unmap them and continue. If
they weren't mapped in the first place, this would be a no-op. Since x86
doesn't support write-only, and PROT_NONE doesn't allow reads or writes
anyways, this will allow the svm range validation to continue without
getting stuck in a loop forever on mappings we can't use with HMM.

Signed-off-by: default avatarKent Russell <kent.russell@amd.com>
Reviewed-by: default avatarFelix Kuehling <felix.kuehling@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent 9d20f37a
Loading
Loading
Loading
Loading
+23 −0
Original line number Diff line number Diff line
@@ -1713,6 +1713,29 @@ static int svm_range_validate_and_map(struct mm_struct *mm,

			next = min(vma->vm_end, end);
			npages = (next - addr) >> PAGE_SHIFT;
			/* HMM requires at least READ permissions. If provided with PROT_NONE,
			 * unmap the memory. If it's not already mapped, this is a no-op
			 * If PROT_WRITE is provided without READ, warn first then unmap
			 */
			if (!(vma->vm_flags & VM_READ)) {
				unsigned long e, s;

				svm_range_lock(prange);
				if (vma->vm_flags & VM_WRITE)
					pr_debug("VM_WRITE without VM_READ is not supported");
				s = max(start, prange->start);
				e = min(end, prange->last);
				if (e >= s)
					r = svm_range_unmap_from_gpus(prange, s, e,
						       KFD_SVM_UNMAP_TRIGGER_UNMAP_FROM_CPU);
				svm_range_unlock(prange);
				/* If unmap returns non-zero, we'll bail on the next for loop
				 * iteration, so just leave r and continue
				 */
				addr = next;
				continue;
			}

			WRITE_ONCE(p->svms.faulting_task, current);
			r = amdgpu_hmm_range_get_pages(&prange->notifier, addr, npages,
						       readonly, owner, NULL,