mirror of https://gitee.com/openkylin/linux.git
drm/amdgpu: fix race in GEM VA map IOCTL v2
Somebody could try to free the bo_va between mapping and updating it. v2: fix typos in comment Signed-off-by: Christian König <christian.koenig@amd.com> Reviewed-by: Nicolai Hähnle <nicolai.haehnle@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
This commit is contained in:
parent
18566acac1
commit
2ffdaafb5d
|
@ -487,67 +487,50 @@ static int amdgpu_gem_va_check(void *param, struct amdgpu_bo *bo)
|
||||||
*
|
*
|
||||||
* @adev: amdgpu_device pointer
|
* @adev: amdgpu_device pointer
|
||||||
* @bo_va: bo_va to update
|
* @bo_va: bo_va to update
|
||||||
|
* @list: validation list
|
||||||
|
* @operation: map or unmap
|
||||||
*
|
*
|
||||||
* Update the bo_va directly after setting it's address. Errors are not
|
* Update the bo_va directly after setting its address. Errors are not
|
||||||
* vital here, so they are not reported back to userspace.
|
* vital here, so they are not reported back to userspace.
|
||||||
*/
|
*/
|
||||||
static void amdgpu_gem_va_update_vm(struct amdgpu_device *adev,
|
static void amdgpu_gem_va_update_vm(struct amdgpu_device *adev,
|
||||||
struct amdgpu_bo_va *bo_va,
|
struct amdgpu_bo_va *bo_va,
|
||||||
|
struct list_head *list,
|
||||||
uint32_t operation)
|
uint32_t operation)
|
||||||
{
|
{
|
||||||
struct ttm_validate_buffer tv, *entry;
|
struct ttm_validate_buffer *entry;
|
||||||
struct amdgpu_bo_list_entry vm_pd;
|
int r = -ERESTARTSYS;
|
||||||
struct ww_acquire_ctx ticket;
|
|
||||||
struct list_head list, duplicates;
|
|
||||||
int r;
|
|
||||||
|
|
||||||
INIT_LIST_HEAD(&list);
|
list_for_each_entry(entry, list, head) {
|
||||||
INIT_LIST_HEAD(&duplicates);
|
|
||||||
|
|
||||||
tv.bo = &bo_va->bo->tbo;
|
|
||||||
tv.shared = true;
|
|
||||||
list_add(&tv.head, &list);
|
|
||||||
|
|
||||||
amdgpu_vm_get_pd_bo(bo_va->vm, &list, &vm_pd);
|
|
||||||
|
|
||||||
/* Provide duplicates to avoid -EALREADY */
|
|
||||||
r = ttm_eu_reserve_buffers(&ticket, &list, true, &duplicates);
|
|
||||||
if (r)
|
|
||||||
goto error_print;
|
|
||||||
|
|
||||||
list_for_each_entry(entry, &list, head) {
|
|
||||||
struct amdgpu_bo *bo =
|
struct amdgpu_bo *bo =
|
||||||
container_of(entry->bo, struct amdgpu_bo, tbo);
|
container_of(entry->bo, struct amdgpu_bo, tbo);
|
||||||
|
|
||||||
/* if anything is swapped out don't swap it in here,
|
/* if anything is swapped out don't swap it in here,
|
||||||
just abort and wait for the next CS */
|
just abort and wait for the next CS */
|
||||||
if (!amdgpu_bo_gpu_accessible(bo))
|
if (!amdgpu_bo_gpu_accessible(bo))
|
||||||
goto error_unreserve;
|
goto error;
|
||||||
|
|
||||||
if (bo->shadow && !amdgpu_bo_gpu_accessible(bo->shadow))
|
if (bo->shadow && !amdgpu_bo_gpu_accessible(bo->shadow))
|
||||||
goto error_unreserve;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
r = amdgpu_vm_validate_pt_bos(adev, bo_va->vm, amdgpu_gem_va_check,
|
r = amdgpu_vm_validate_pt_bos(adev, bo_va->vm, amdgpu_gem_va_check,
|
||||||
NULL);
|
NULL);
|
||||||
if (r)
|
if (r)
|
||||||
goto error_unreserve;
|
goto error;
|
||||||
|
|
||||||
r = amdgpu_vm_update_page_directory(adev, bo_va->vm);
|
r = amdgpu_vm_update_page_directory(adev, bo_va->vm);
|
||||||
if (r)
|
if (r)
|
||||||
goto error_unreserve;
|
goto error;
|
||||||
|
|
||||||
r = amdgpu_vm_clear_freed(adev, bo_va->vm);
|
r = amdgpu_vm_clear_freed(adev, bo_va->vm);
|
||||||
if (r)
|
if (r)
|
||||||
goto error_unreserve;
|
goto error;
|
||||||
|
|
||||||
if (operation == AMDGPU_VA_OP_MAP)
|
if (operation == AMDGPU_VA_OP_MAP)
|
||||||
r = amdgpu_vm_bo_update(adev, bo_va, false);
|
r = amdgpu_vm_bo_update(adev, bo_va, false);
|
||||||
|
|
||||||
error_unreserve:
|
error:
|
||||||
ttm_eu_backoff_reservation(&ticket, &list);
|
|
||||||
|
|
||||||
error_print:
|
|
||||||
if (r && r != -ERESTARTSYS)
|
if (r && r != -ERESTARTSYS)
|
||||||
DRM_ERROR("Couldn't update BO_VA (%d)\n", r);
|
DRM_ERROR("Couldn't update BO_VA (%d)\n", r);
|
||||||
}
|
}
|
||||||
|
@ -640,10 +623,10 @@ int amdgpu_gem_va_ioctl(struct drm_device *dev, void *data,
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
ttm_eu_backoff_reservation(&ticket, &list);
|
|
||||||
if (!r && !(args->flags & AMDGPU_VM_DELAY_UPDATE) &&
|
if (!r && !(args->flags & AMDGPU_VM_DELAY_UPDATE) &&
|
||||||
!amdgpu_vm_debug)
|
!amdgpu_vm_debug)
|
||||||
amdgpu_gem_va_update_vm(adev, bo_va, args->operation);
|
amdgpu_gem_va_update_vm(adev, bo_va, &list, args->operation);
|
||||||
|
ttm_eu_backoff_reservation(&ticket, &list);
|
||||||
|
|
||||||
drm_gem_object_unreference_unlocked(gobj);
|
drm_gem_object_unreference_unlocked(gobj);
|
||||||
return r;
|
return r;
|
||||||
|
|
Loading…
Reference in New Issue