From: Felix Kuehling <[email protected]>

With latest POR, remote importers aren't guaranteed to support
instruction replay-on-fault. Therefore, we cannot support unpinned
exports or unpinned page-tables in the exporter mappings into NPA space.

Signed-off-by: Felix Kuehling <[email protected]>
Reviewed-by: Mukul Joshi <[email protected]>
Signed-off-by: Alex Deucher <[email protected]>
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_ualink.c |  4 +--
 drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c     | 40 ++++++++++++++++++++++
 drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h     |  3 ++
 drivers/gpu/drm/amd/amdgpu/amdgpu_vm_pt.c  | 25 +++++++++++++-
 4 files changed, 69 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ualink.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_ualink.c
index 5811218b35d33..0f57a7e2c3341 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ualink.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ualink.c
@@ -3444,8 +3444,8 @@ int amdgpu_ualink_manager_start(struct amdgpu_device 
*adev)
        if (r)
                goto out;
 
-       /* For using CPU for page table updates. */
-       r = amdgpu_vm_make_compute(adev, &adev->ualink.npa_vm);
+       /* For pinning page tables and using CPU for page table updates. */
+       r = amdgpu_vm_make_npa(adev, &adev->ualink.npa_vm);
        if (r)
                goto uninit_vm;
 
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
index fc928c2d8b21e..47cde54594693 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
@@ -2752,6 +2752,46 @@ int amdgpu_vm_make_compute(struct amdgpu_device *adev, 
struct amdgpu_vm *vm)
        return r;
 }
 
+/**
+ * amdgpu_vm_make_npa - Turn a GFX VM into an NPA VM
+ *
+ * @adev: amdgpu_device pointer
+ * @vm: requested vm
+ *
+ * This only works on GFX VMs that don't have any BOs added and no
+ * page tables allocated yet.
+ *
+ * Changes the following VM parameters:
+ * - use_cpu_for_update
+ * - pins page tables
+ * - initializes PTEs to no-retry encoding
+ *
+ * Reinitializes the page directory to reflect the changed ATS
+ * setting.
+ *
+ * Returns:
+ * 0 for success, -errno for errors.
+ */
+int amdgpu_vm_make_npa(struct amdgpu_device *adev, struct amdgpu_vm *vm)
+{
+       int r = amdgpu_vm_make_compute(adev, vm);
+
+       if (r)
+               return r;
+       vm->is_npa = true;
+       r = amdgpu_bo_reserve(vm->root.bo, false);
+       if (r)
+               return r;
+       r = amdgpu_bo_pin(vm->root.bo, AMDGPU_GEM_DOMAIN_VRAM);
+       amdgpu_bo_unreserve(vm->root.bo);
+       if (r)
+               return r;
+
+       vm->is_npa = true;
+
+       return 0;
+}
+
 static int amdgpu_vm_stats_is_zero(struct amdgpu_vm *vm)
 {
        for (int i = 0; i < __AMDGPU_PL_NUM; ++i) {
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h
index 7a0ee19a12b18..0f6634b749746 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h
@@ -369,6 +369,8 @@ struct amdgpu_vm {
        struct ttm_lru_bulk_move lru_bulk_move;
        /* Flag to indicate if VM is used for compute */
        bool                    is_compute_context;
+       /* Flag to indicate that page tables are for NPA mappings */
+       bool                    is_npa;
        /* Flag to indicate if VM needs a TLB fence (KFD or KGD) */
        bool                    need_tlb_fence;
 
@@ -429,6 +431,7 @@ void amdgpu_vm_manager_fini(struct amdgpu_device *adev);
 long amdgpu_vm_wait_idle(struct amdgpu_vm *vm, long timeout);
 int amdgpu_vm_init(struct amdgpu_device *adev, struct amdgpu_vm *vm, int32_t 
xcp_id);
 int amdgpu_vm_make_compute(struct amdgpu_device *adev, struct amdgpu_vm *vm);
+int amdgpu_vm_make_npa(struct amdgpu_device *adev, struct amdgpu_vm *vm);
 void amdgpu_vm_fini(struct amdgpu_device *adev, struct amdgpu_vm *vm);
 int amdgpu_vm_lock_pd(struct amdgpu_vm *vm, struct drm_exec *exec,
                      unsigned int num_fences);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm_pt.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm_pt.c
index b85b70a1a428d..b9831a5f85d8b 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm_pt.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm_pt.c
@@ -445,6 +445,7 @@ int amdgpu_vm_pt_create(struct amdgpu_device *adev, struct 
amdgpu_vm *vm,
 {
        struct amdgpu_bo_param bp;
        unsigned int num_entries;
+       int r;
 
        memset(&bp, 0, sizeof(bp));
 
@@ -477,7 +478,24 @@ int amdgpu_vm_pt_create(struct amdgpu_device *adev, struct 
amdgpu_vm *vm,
        if (vm->root.bo)
                bp.resv = vm->root.bo->tbo.base.resv;
 
-       return amdgpu_bo_create_vm(adev, &bp, vmbo);
+       r = amdgpu_bo_create_vm(adev, &bp, vmbo);
+       if (r)
+               return r;
+
+       /* Assumes that reservation is shared with the VM root and that the
+        * reservation is locked
+        */
+       if (vm->root.bo && vm->is_npa) {
+               struct amdgpu_bo *pt_bo = &(*vmbo)->bo;
+
+               r = amdgpu_bo_pin(pt_bo, AMDGPU_GEM_DOMAIN_VRAM);
+               if (r) {
+                       amdgpu_bo_unref(&pt_bo);
+                       return r;
+               }
+       }
+
+       return 0;
 }
 
 /**
@@ -527,6 +545,8 @@ static int amdgpu_vm_pt_alloc(struct amdgpu_device *adev,
        return 0;
 
 error_free_pt:
+       if (vm->is_npa)
+               amdgpu_bo_unpin(pt_bo);
        amdgpu_bo_unref(&pt_bo);
        return r;
 }
@@ -541,6 +561,9 @@ static void amdgpu_vm_pt_free(struct amdgpu_vm_bo_base 
*entry)
        if (!entry->bo)
                return;
 
+       if (entry->vm->is_npa)
+               amdgpu_bo_unpin(entry->bo);
+
        amdgpu_vm_update_stats(entry, entry->bo->tbo.resource, -1);
        entry->bo->vm_bo = NULL;
        ttm_bo_set_bulk_move(&entry->bo->tbo, NULL);
-- 
2.55.0

Reply via email to