svm_range_restore_pages() receives a CPU page number, but passes it
unchanged to amdgpu_gmc_filter_faults_remove() when recovery is deferred
or returns -EAGAIN. The software fault filter uses a byte address and
PASID as its key, so this can leave the fault filtered until the entry
ages out.

Pass the original byte address to svm_range_restore_pages() and derive
the CPU page number locally for range operations. Use the original
address for both filter removals. This also preserves the GPU subpage
offset when CPU pages are larger than the 4 KiB GPU page size.

Fixes: b3dc91f97317 ("drm/amdkfd: enable subsequent retry fault")
Reported-by: Sashiko <[email protected]>
Closes: https://lore.kernel.org/r/[email protected]
Signed-off-by: Aveline Noir <[email protected]>
---
No testing on AMD hardware. Any test will be appreciated.
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c | 2 +-
 drivers/gpu/drm/amd/amdkfd/kfd_svm.c   | 7 ++++---
 drivers/gpu/drm/amd/amdkfd/kfd_svm.h   | 4 ++--
 3 files changed, 7 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
index c41e9c0916b7..86ef849097fa 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
@@ -3092,7 +3092,7 @@ bool amdgpu_vm_handle_fault(struct amdgpu_device *adev, 
u32 pasid,
                drm_exec_fini(&exec);
 
                if (!svm_range_restore_pages(adev, pasid, vmid,
-                                            node_id, addr >> PAGE_SHIFT, ts, 
write_fault))
+                                            node_id, addr, ts, write_fault))
                        return true;
 
                /* Re-acquire the VM lock, could be that the VM was freed in 
between. */
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c 
b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c
index 79455e23a030..c85d6bb73629 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c
@@ -3130,8 +3130,9 @@ svm_fault_allowed(struct vm_area_struct *vma, bool 
write_fault)
 int
 svm_range_restore_pages(struct amdgpu_device *adev, unsigned int pasid,
                        uint32_t vmid, uint32_t node_id,
-                       uint64_t addr, uint64_t ts, bool write_fault)
+                       uint64_t fault_addr, uint64_t ts, bool write_fault)
 {
+       uint64_t addr = fault_addr >> PAGE_SHIFT;
        unsigned long start, last, size;
        struct mm_struct *mm = NULL;
        struct svm_range_list *svms;
@@ -3249,7 +3250,7 @@ svm_range_restore_pages(struct amdgpu_device *adev, 
unsigned int pasid,
        mutex_lock(&prange->migrate_mutex);
 
        if (svm_range_skip_recover(prange)) {
-               amdgpu_gmc_filter_faults_remove(node->adev, addr, pasid);
+               amdgpu_gmc_filter_faults_remove(node->adev, fault_addr, pasid);
                r = 0;
                goto out_unlock_range;
        }
@@ -3353,7 +3354,7 @@ svm_range_restore_pages(struct amdgpu_device *adev, 
unsigned int pasid,
 
        if (r == -EAGAIN) {
                pr_debug("recover vm fault later\n");
-               amdgpu_gmc_filter_faults_remove(node->adev, addr, pasid);
+               amdgpu_gmc_filter_faults_remove(node->adev, fault_addr, pasid);
                r = 0;
        }
        return r;
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_svm.h 
b/drivers/gpu/drm/amd/amdkfd/kfd_svm.h
index c7d7adae4476..38744e716f74 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_svm.h
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_svm.h
@@ -178,7 +178,7 @@ int svm_range_vram_node_new(struct kfd_node *node, struct 
svm_range *prange,
                            bool clear);
 void svm_range_vram_node_free(struct svm_range *prange);
 int svm_range_restore_pages(struct amdgpu_device *adev, unsigned int pasid,
-                           uint32_t vmid, uint32_t node_id, uint64_t addr, 
uint64_t ts,
+                           uint32_t vmid, uint32_t node_id, uint64_t 
fault_addr, uint64_t ts,
                            bool write_fault);
 int svm_range_evict_svm_bo(struct amdgpu_bo *bo);
 
@@ -230,7 +230,7 @@ static inline void svm_range_list_fini(struct kfd_process 
*p)
 static inline int svm_range_restore_pages(struct amdgpu_device *adev,
                                          unsigned int pasid,
                                          uint32_t client_id, uint32_t node_id,
-                                         uint64_t addr, uint64_t ts, bool 
write_fault)
+                                         uint64_t fault_addr, uint64_t ts, 
bool write_fault)
 {
        return -EFAULT;
 }

---
base-commit: 403b3d68346d7ba25f474f0686ad1d05feb65b7c
change-id: 20261108-kfd-fault-filter-address-20261108-4f096f2b2a1a

Best regards,
--  
Aveline Noir <[email protected]>

Reply via email to