From: Yu Huang <[email protected]>

amdgpu_vm_pt_leaves() can redirect a fault to the preallocated dummy
page-table hierarchy when the walk stops above the PTE level. The
entry written in this case must point to the next-level dummy PD/PT.

amdgpu_vm_pte_update_flags() treats entries above PTB as leaf mappings
and applies AMDGPU_PDE_PTE_FLAG() before the ASIC-specific conversion.
This is not appropriate for a pointer to another page table and can
produce an incorrectly encoded dummy PDE.

Build the dummy PDE address and flags with amdgpu_gmc_get_pde_for_bo()
and pass them directly to the update callback. Keep the existing PTE
flag handling for other updates, including unmaps with a NULL
destination.

Authored-by: Yu Huang <[email protected]>
Signed-off-by: Yu Huang <[email protected]>
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_vm_pt.c | 39 ++++++++++++++++-------
 1 file changed, 27 insertions(+), 12 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm_pt.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm_pt.c
index 06492358d85a..0c3ecd3eb740 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm_pt.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm_pt.c
@@ -950,19 +950,19 @@ int amdgpu_vm_ptes_update(struct amdgpu_vm_update_params 
*params,
  * Returns:
  * 0 for success, negative error code for failure.
  */
-void amdgpu_vm_pt_leaves(struct amdgpu_vm_update_params *params,
-                        uint64_t start, uint64_t end,
-                        int64_t *dst, uint64_t flags)
+void amdgpu_vm_pt_leaves(struct amdgpu_vm_update_params *params, uint64_t 
start,
+                        uint64_t end, int64_t *dst, uint64_t flags)
 {
        struct amdgpu_device *adev = params->adev;
        struct amdgpu_vm_pt_cursor cursor;
 
        amdgpu_vm_pt_start(adev, params->vm, start, &cursor);
        while (cursor.pfn < end) {
-               uint64_t entry_end, pe_start, val;
-               unsigned int shift, mask;
+               uint64_t entry_end, pe_start, val, update_flags = flags;
+               unsigned int level, shift, mask;
                struct amdgpu_bo *pt;
                unsigned int nptes;
+               bool dummy_pde;
 
                /* Walk to the leave entries */
                if (amdgpu_vm_pt_descendant(adev, &cursor))
@@ -993,15 +993,30 @@ void amdgpu_vm_pt_leaves(struct amdgpu_vm_update_params 
*params,
                 */
                nptes = max(nptes, 1u);
 
+               level = pt == cursor.parent->bo ? cursor.level - 1 :
+                                                 cursor.level;
+               dummy_pde = dst && level != AMDGPU_VM_PTB;
+
                val = dst ? dst[cursor.level] : 0;
+               if (dummy_pde)
+                       amdgpu_gmc_get_pde_for_bo(
+                               adev->vm_manager.dummy_pd[level + 1], level,
+                               &val, &update_flags);
                trace_amdgpu_vm_update_ptes(params, cursor.pfn, entry_end,
-                                           min(nptes, 32u), val, 0, flags);
-
-               amdgpu_vm_pte_update_flags(params, to_amdgpu_bo_vm(pt),
-                                          pt == cursor.parent->bo ?
-                                                  cursor.level - 1 :
-                                                  cursor.level,
-                                          pe_start, val, nptes, 0, flags);
+                                           min(nptes, 32u), val, 0,
+                                           update_flags);
+               if (dummy_pde)
+                       params->vm->update_funcs->update(params,
+                                                        to_amdgpu_bo_vm(pt),
+                                                        pe_start, val, nptes,
+                                                        0, update_flags);
+               else
+                       amdgpu_vm_pte_update_flags(params, to_amdgpu_bo_vm(pt),
+                                                  pt == cursor.parent->bo ?
+                                                          cursor.level - 1 :
+                                                          cursor.level,
+                                                  pe_start, val, nptes, 0,
+                                                  flags);
                amdgpu_vm_pt_next(adev, &cursor);
        }
 }
-- 
2.53.0

Reply via email to