---
v2: Addressed code review comments from Sashiko
---
drivers/gpu/drm/amd/amdkfd/kfd_svm.c | 24 +++++++++++++++++++++++-
1 file changed, 23 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c
b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c
index 876476046926..2aade0183578 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c
@@ -156,6 +156,18 @@ svm_is_valid_dma_mapping_addr(struct device *dev,
dma_addr_t dma_addr)
!(dma_addr & SVM_RANGE_VRAM_DOMAIN);
}
+static bool svm_page_is_range_owned(struct page *page, struct svm_range *prange)
+{
+ bool is_owned;
+
+ mutex_lock(&prange->lock);
+ is_owned = is_zone_device_page(page) && prange->ttm_res &&
+ page->zone_device_data == prange->svm_bo;
+ mutex_unlock(&prange->lock);
+
+ return is_owned;
+}
+
static int
svm_range_dma_map_dev(struct amdgpu_device *adev, struct svm_range *prange,
unsigned long offset, unsigned long npages,
@@ -180,7 +192,7 @@ svm_range_dma_map_dev(struct amdgpu_device *adev, struct
svm_range *prange,
dma_unmap_page(dev, addr[i], PAGE_SIZE, dir);
page = hmm_pfn_to_page(hmm_pfns[i]);
- if (is_zone_device_page(page)) {
+ if (svm_page_is_range_owned(page, prange)) {
struct amdgpu_device *bo_adev =
prange->svm_bo->node->adev;
addr[i] = (hmm_pfns[i] << PAGE_SHIFT) +
@@ -189,6 +201,16 @@ svm_range_dma_map_dev(struct amdgpu_device *adev, struct
svm_range *prange,
addr[i] |= SVM_RANGE_VRAM_DOMAIN;
pr_debug_ratelimited("vram address: 0x%llx\n", addr[i]);
continue;
+ } else if (is_device_private_page(page)) {
+ /* Device private memory from another driver or range.
+ * This should never happen in practice but it's
+ * theoretically possible for read-only VMAs after a
+ * process forks, creates a new KFD context and maps
+ * the same page.
+ */
+ pr_debug("Trying to map device private page from another
device or range\n");
+ addr[i] = 0;
+ return -EINVAL;
}
addr[i] = dma_map_page(dev, page, 0, PAGE_SIZE, dir);
r = dma_mapping_error(dev, addr[i]);