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
