mirror of
https://github.com/torvalds/linux.git
synced 2026-06-01 11:03:43 +02:00
drm/amdgpu: flush TLB if valid PDE turns into PTE
Mapping huge page, 2MB aligned address with 2MB size, uses PDE0 as PTE. If previously valid PDE0, PDE0.V=1 and PDE0.P=0 turns into PTE, this requires TLB flush, otherwise page table walker will not read updated PDE0. Change page table update mapping to return table_freed flag to indicate the previously valid PDE may have turned into a PTE if page table is freed. Signed-off-by: Philip Yang <Philip.Yang@amd.com> Reviewed-by: Felix Kuehling <Felix.Kuehling@amd.com> Reviewed-by: Christian König <christian.koenig@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
This commit is contained in:
parent
a6ce1e1aab
commit
bf546940d5
|
|
@ -1583,6 +1583,7 @@ static int amdgpu_vm_update_ptes(struct amdgpu_vm_update_params *params,
|
|||
while (cursor.pfn < frag_start) {
|
||||
amdgpu_vm_free_pts(adev, params->vm, &cursor);
|
||||
amdgpu_vm_pt_next(adev, &cursor);
|
||||
params->table_freed = true;
|
||||
}
|
||||
|
||||
} else if (frag >= shift) {
|
||||
|
|
@ -1610,6 +1611,7 @@ static int amdgpu_vm_update_ptes(struct amdgpu_vm_update_params *params,
|
|||
* @res: ttm_resource to map
|
||||
* @pages_addr: DMA addresses to use for mapping
|
||||
* @fence: optional resulting fence
|
||||
* @table_freed: return true if page table is freed
|
||||
*
|
||||
* Fill in the page table entries between @start and @last.
|
||||
*
|
||||
|
|
@ -1624,7 +1626,8 @@ int amdgpu_vm_bo_update_mapping(struct amdgpu_device *adev,
|
|||
uint64_t flags, uint64_t offset,
|
||||
struct ttm_resource *res,
|
||||
dma_addr_t *pages_addr,
|
||||
struct dma_fence **fence)
|
||||
struct dma_fence **fence,
|
||||
bool *table_freed)
|
||||
{
|
||||
struct amdgpu_vm_update_params params;
|
||||
struct amdgpu_res_cursor cursor;
|
||||
|
|
@ -1719,6 +1722,9 @@ int amdgpu_vm_bo_update_mapping(struct amdgpu_device *adev,
|
|||
|
||||
r = vm->update_funcs->commit(¶ms, fence);
|
||||
|
||||
if (table_freed)
|
||||
*table_freed = params.table_freed;
|
||||
|
||||
error_unlock:
|
||||
amdgpu_vm_eviction_unlock(vm);
|
||||
return r;
|
||||
|
|
@ -1815,7 +1821,7 @@ int amdgpu_vm_bo_update(struct amdgpu_device *adev, struct amdgpu_bo_va *bo_va,
|
|||
resv, mapping->start,
|
||||
mapping->last, update_flags,
|
||||
mapping->offset, mem,
|
||||
pages_addr, last_update);
|
||||
pages_addr, last_update, NULL);
|
||||
if (r)
|
||||
return r;
|
||||
}
|
||||
|
|
@ -2026,7 +2032,7 @@ int amdgpu_vm_clear_freed(struct amdgpu_device *adev,
|
|||
r = amdgpu_vm_bo_update_mapping(adev, adev, vm, false, false,
|
||||
resv, mapping->start,
|
||||
mapping->last, init_pte_value,
|
||||
0, NULL, NULL, &f);
|
||||
0, NULL, NULL, &f, NULL);
|
||||
amdgpu_vm_free_mapping(adev, vm, mapping, f);
|
||||
if (r) {
|
||||
dma_fence_put(f);
|
||||
|
|
@ -3364,7 +3370,7 @@ bool amdgpu_vm_handle_fault(struct amdgpu_device *adev, u32 pasid,
|
|||
}
|
||||
|
||||
r = amdgpu_vm_bo_update_mapping(adev, adev, vm, true, false, NULL, addr,
|
||||
addr, flags, value, NULL, NULL,
|
||||
addr, flags, value, NULL, NULL, NULL,
|
||||
NULL);
|
||||
if (r)
|
||||
goto error_unlock;
|
||||
|
|
|
|||
|
|
@ -231,6 +231,11 @@ struct amdgpu_vm_update_params {
|
|||
* @num_dw_left: number of dw left for the IB
|
||||
*/
|
||||
unsigned int num_dw_left;
|
||||
|
||||
/**
|
||||
* @table_freed: return true if page table is freed when updating
|
||||
*/
|
||||
bool table_freed;
|
||||
};
|
||||
|
||||
struct amdgpu_vm_update_funcs {
|
||||
|
|
@ -404,7 +409,7 @@ int amdgpu_vm_bo_update_mapping(struct amdgpu_device *adev,
|
|||
uint64_t flags, uint64_t offset,
|
||||
struct ttm_resource *res,
|
||||
dma_addr_t *pages_addr,
|
||||
struct dma_fence **fence);
|
||||
struct dma_fence **fence, bool *free_table);
|
||||
int amdgpu_vm_bo_update(struct amdgpu_device *adev,
|
||||
struct amdgpu_bo_va *bo_va,
|
||||
bool clear);
|
||||
|
|
|
|||
|
|
@ -1086,7 +1086,7 @@ svm_range_unmap_from_gpu(struct amdgpu_device *adev, struct amdgpu_vm *vm,
|
|||
|
||||
return amdgpu_vm_bo_update_mapping(adev, adev, vm, false, true, NULL,
|
||||
start, last, init_pte_value, 0,
|
||||
NULL, NULL, fence);
|
||||
NULL, NULL, fence, NULL);
|
||||
}
|
||||
|
||||
static int
|
||||
|
|
@ -1139,6 +1139,7 @@ svm_range_map_to_gpu(struct amdgpu_device *adev, struct amdgpu_vm *vm,
|
|||
struct amdgpu_device *bo_adev, struct dma_fence **fence)
|
||||
{
|
||||
struct amdgpu_bo_va bo_va;
|
||||
bool table_freed = false;
|
||||
uint64_t pte_flags;
|
||||
int r = 0;
|
||||
|
||||
|
|
@ -1160,7 +1161,8 @@ svm_range_map_to_gpu(struct amdgpu_device *adev, struct amdgpu_vm *vm,
|
|||
prange->mapping.last, pte_flags,
|
||||
prange->mapping.offset,
|
||||
prange->ttm_res,
|
||||
dma_addr, &vm->last_update);
|
||||
dma_addr, &vm->last_update,
|
||||
&table_freed);
|
||||
if (r) {
|
||||
pr_debug("failed %d to map to gpu 0x%lx\n", r, prange->start);
|
||||
goto out;
|
||||
|
|
@ -1176,6 +1178,13 @@ svm_range_map_to_gpu(struct amdgpu_device *adev, struct amdgpu_vm *vm,
|
|||
if (fence)
|
||||
*fence = dma_fence_get(vm->last_update);
|
||||
|
||||
if (table_freed) {
|
||||
struct kfd_process *p;
|
||||
|
||||
p = container_of(prange->svms, struct kfd_process, svms);
|
||||
amdgpu_amdkfd_flush_gpu_tlb_pasid((struct kgd_dev *)adev,
|
||||
p->pasid);
|
||||
}
|
||||
out:
|
||||
prange->mapping.bo_va = NULL;
|
||||
return r;
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user