[PATCH 4/4] drm/amdgpu: Add fence to the freed page table BOs
Philip Yang
Philip.Yang at amd.com
Thu Jun 1 19:31:17 UTC 2023
If updating page table free the page table BOs, add fence to the BOs to
ensure the page table BOs are not freed and reused before TLB is
flushed.
Signed-off-by: Philip Yang <Philip.Yang at amd.com>
---
drivers/gpu/drm/amd/amdgpu/amdgpu_vm_pt.c | 33 +++++++++++++++--------
1 file changed, 22 insertions(+), 11 deletions(-)
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm_pt.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm_pt.c
index dea1a64be44d..16eb9472d469 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm_pt.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm_pt.c
@@ -633,8 +633,10 @@ static int amdgpu_vm_pt_alloc(struct amdgpu_device *adev,
* amdgpu_vm_pt_free - free one PD/PT
*
* @entry: PDE to free
+ * @fence: fence added the freed page table BO
*/
-static void amdgpu_vm_pt_free(struct amdgpu_vm_bo_base *entry)
+static void amdgpu_vm_pt_free(struct amdgpu_vm_bo_base *entry,
+ struct dma_fence *fence)
{
struct amdgpu_bo *shadow;
@@ -643,6 +645,9 @@ static void amdgpu_vm_pt_free(struct amdgpu_vm_bo_base *entry)
shadow = amdgpu_bo_shadowed(entry->bo);
if (shadow) {
ttm_bo_set_bulk_move(&shadow->tbo, NULL);
+ if (fence && !dma_resv_reserve_fences(shadow->tbo.base.resv, 1))
+ dma_resv_add_fence(shadow->tbo.base.resv, fence,
+ DMA_RESV_USAGE_BOOKKEEP);
amdgpu_bo_unref(&shadow);
}
ttm_bo_set_bulk_move(&entry->bo->tbo, NULL);
@@ -651,6 +656,9 @@ static void amdgpu_vm_pt_free(struct amdgpu_vm_bo_base *entry)
spin_lock(&entry->vm->status_lock);
list_del(&entry->vm_status);
spin_unlock(&entry->vm->status_lock);
+ if (fence && !dma_resv_reserve_fences(entry->bo->tbo.base.resv, 1))
+ dma_resv_add_fence(entry->bo->tbo.base.resv, fence,
+ DMA_RESV_USAGE_BOOKKEEP);
amdgpu_bo_unref(&entry->bo);
}
@@ -670,7 +678,7 @@ void amdgpu_vm_pt_free_work(struct work_struct *work)
amdgpu_bo_reserve(vm->root.bo, true);
list_for_each_entry_safe(entry, next, &pt_freed, vm_status)
- amdgpu_vm_pt_free(entry);
+ amdgpu_vm_pt_free(entry, NULL);
amdgpu_bo_unreserve(vm->root.bo);
}
@@ -682,13 +690,15 @@ void amdgpu_vm_pt_free_work(struct work_struct *work)
* @vm: amdgpu vm structure
* @start: optional cursor where to start freeing PDs/PTs
* @unlocked: vm resv unlock status
+ * @fence: page table fence added to the freed BOs
*
* Free the page directory or page table level and all sub levels.
*/
static void amdgpu_vm_pt_free_dfs(struct amdgpu_device *adev,
struct amdgpu_vm *vm,
struct amdgpu_vm_pt_cursor *start,
- bool unlocked)
+ bool unlocked,
+ struct dma_fence *fence)
{
struct amdgpu_vm_pt_cursor cursor;
struct amdgpu_vm_bo_base *entry;
@@ -706,10 +716,10 @@ static void amdgpu_vm_pt_free_dfs(struct amdgpu_device *adev,
}
for_each_amdgpu_vm_pt_dfs_safe(adev, vm, start, cursor, entry)
- amdgpu_vm_pt_free(entry);
+ amdgpu_vm_pt_free(entry, fence);
if (start)
- amdgpu_vm_pt_free(start->entry);
+ amdgpu_vm_pt_free(start->entry, fence);
}
/**
@@ -721,7 +731,7 @@ static void amdgpu_vm_pt_free_dfs(struct amdgpu_device *adev,
*/
void amdgpu_vm_pt_free_root(struct amdgpu_device *adev, struct amdgpu_vm *vm)
{
- amdgpu_vm_pt_free_dfs(adev, vm, NULL, false);
+ amdgpu_vm_pt_free_dfs(adev, vm, NULL, false, NULL);
}
/**
@@ -905,6 +915,7 @@ int amdgpu_vm_ptes_update(struct amdgpu_vm_update_params *params,
struct amdgpu_device *adev = params->adev;
struct amdgpu_vm_pt_cursor cursor;
uint64_t frag_start = start, frag_end;
+ struct amdgpu_vm *vm = params->vm;
unsigned int frag;
int r;
@@ -913,7 +924,7 @@ int amdgpu_vm_ptes_update(struct amdgpu_vm_update_params *params,
&frag_end);
/* walk over the address space and update the PTs */
- amdgpu_vm_pt_start(adev, params->vm, start, &cursor);
+ amdgpu_vm_pt_start(adev, vm, start, &cursor);
while (cursor.pfn < end) {
unsigned int shift, parent_shift, mask;
uint64_t incr, entry_end, pe_start;
@@ -923,7 +934,7 @@ int amdgpu_vm_ptes_update(struct amdgpu_vm_update_params *params,
/* make sure that the page tables covering the
* address range are actually allocated
*/
- r = amdgpu_vm_pt_alloc(params->adev, params->vm,
+ r = amdgpu_vm_pt_alloc(params->adev, vm,
&cursor, params->immediate);
if (r)
return r;
@@ -986,7 +997,6 @@ int amdgpu_vm_ptes_update(struct amdgpu_vm_update_params *params,
entry_end = min(entry_end, end);
do {
- struct amdgpu_vm *vm = params->vm;
uint64_t upd_end = min(entry_end, frag_end);
unsigned int nptes = (upd_end - frag_start) >> shift;
uint64_t upd_flags = flags | AMDGPU_PTE_FRAG(frag);
@@ -1029,9 +1039,10 @@ int amdgpu_vm_ptes_update(struct amdgpu_vm_update_params *params,
/* Make sure previous mapping is freed */
if (cursor.entry->bo) {
params->table_freed = true;
- amdgpu_vm_pt_free_dfs(adev, params->vm,
+ amdgpu_vm_pt_free_dfs(adev, vm,
&cursor,
- params->unlocked);
+ params->unlocked,
+ vm->pt_fence);
}
amdgpu_vm_pt_next(adev, &cursor);
}
--
2.35.1
More information about the amd-gfx
mailing list