Fix a bunch of related crashes in amdgpu that occur when shadow page tables are kicked out of the GART.
One of the issues was that during command submission, we rely on a device-global evictions counter to skip some of the work of page-table validation. The driver was never informed of evictions from GART, so this series adds an evict parameter to ttm_bo_driver::move_notify.
There's still the evict parameter on ttm_bo_driver::move which is used by radeon and nouveau for the call to ttm_bo_move_accel_cleanup. The 'evict' parameter there should probably be more accurately called 'wait', but unless that wait can always be avoided, the evict parameter on ttm_bo_driver::move needs to stay.
Please review! Nicolai --- drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c | 20 ++++++++++++++------ drivers/gpu/drm/amd/amdgpu/amdgpu_object.c | 5 +++++ drivers/gpu/drm/amd/amdgpu/amdgpu_object.h | 12 +++++++++++- drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | 4 ---- drivers/gpu/drm/nouveau/nouveau_bo.c | 3 ++- drivers/gpu/drm/qxl/qxl_ttm.c | 1 + drivers/gpu/drm/radeon/radeon_object.c | 1 + drivers/gpu/drm/radeon/radeon_object.h | 1 + drivers/gpu/drm/ttm/ttm_bo.c | 8 ++++---- drivers/gpu/drm/virtio/virtgpu_ttm.c | 1 + drivers/gpu/drm/vmwgfx/vmwgfx_buffer.c | 1 + include/drm/ttm/ttm_bo_driver.h | 10 ++++++++-- 12 files changed, 49 insertions(+), 18 deletions(-)
From: Nicolai Hähnle nicolai.haehnle@amd.com
Ensure that the driver can listen to evictions even when they don't take the path through ttm_bo_driver::move.
This is crucial for amdgpu, which relies on an eviction counter to skip re-binding page tables when possible.
Signed-off-by: Nicolai Hähnle nicolai.haehnle@amd.com --- drivers/gpu/drm/amd/amdgpu/amdgpu_object.c | 1 + drivers/gpu/drm/amd/amdgpu/amdgpu_object.h | 3 ++- drivers/gpu/drm/nouveau/nouveau_bo.c | 3 ++- drivers/gpu/drm/qxl/qxl_ttm.c | 1 + drivers/gpu/drm/radeon/radeon_object.c | 1 + drivers/gpu/drm/radeon/radeon_object.h | 1 + drivers/gpu/drm/ttm/ttm_bo.c | 8 ++++---- drivers/gpu/drm/virtio/virtgpu_ttm.c | 1 + drivers/gpu/drm/vmwgfx/vmwgfx_buffer.c | 1 + include/drm/ttm/ttm_bo_driver.h | 10 ++++++++-- 10 files changed, 22 insertions(+), 8 deletions(-)
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c index bf79b73..c29db99 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c @@ -842,20 +842,21 @@ int amdgpu_bo_get_metadata(struct amdgpu_bo *bo, void *buffer,
if (metadata_size) *metadata_size = bo->metadata_size; if (flags) *flags = bo->metadata_flags;
return 0; }
void amdgpu_bo_move_notify(struct ttm_buffer_object *bo, + bool evict, struct ttm_mem_reg *new_mem) { struct amdgpu_device *adev = amdgpu_ttm_adev(bo->bdev); struct amdgpu_bo *abo; struct ttm_mem_reg *old_mem = &bo->mem;
if (!amdgpu_ttm_bo_is_amdgpu_bo(bo)) return;
abo = container_of(bo, struct amdgpu_bo, tbo); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h index 5cbf59e..4306b2f 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h @@ -148,21 +148,22 @@ void amdgpu_bo_fini(struct amdgpu_device *adev); int amdgpu_bo_fbdev_mmap(struct amdgpu_bo *bo, struct vm_area_struct *vma); int amdgpu_bo_set_tiling_flags(struct amdgpu_bo *bo, u64 tiling_flags); void amdgpu_bo_get_tiling_flags(struct amdgpu_bo *bo, u64 *tiling_flags); int amdgpu_bo_set_metadata (struct amdgpu_bo *bo, void *metadata, uint32_t metadata_size, uint64_t flags); int amdgpu_bo_get_metadata(struct amdgpu_bo *bo, void *buffer, size_t buffer_size, uint32_t *metadata_size, uint64_t *flags); void amdgpu_bo_move_notify(struct ttm_buffer_object *bo, - struct ttm_mem_reg *new_mem); + bool evict, + struct ttm_mem_reg *new_mem); int amdgpu_bo_fault_reserve_notify(struct ttm_buffer_object *bo); void amdgpu_bo_fence(struct amdgpu_bo *bo, struct dma_fence *fence, bool shared); u64 amdgpu_bo_gpu_offset(struct amdgpu_bo *bo); int amdgpu_bo_backup_to_shadow(struct amdgpu_device *adev, struct amdgpu_ring *ring, struct amdgpu_bo *bo, struct reservation_object *resv, struct dma_fence **fence, bool direct); int amdgpu_bo_restore_from_shadow(struct amdgpu_device *adev, diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.c b/drivers/gpu/drm/nouveau/nouveau_bo.c index e0c0007..6fa1521 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bo.c +++ b/drivers/gpu/drm/nouveau/nouveau_bo.c @@ -1187,21 +1187,22 @@ nouveau_bo_move_flips(struct ttm_buffer_object *bo, bool evict, bool intr, ret = nouveau_bo_move_m2mf(bo, true, intr, no_wait_gpu, new_mem); if (ret) goto out;
out: ttm_bo_mem_put(bo, &tmp_mem); return ret; }
static void -nouveau_bo_move_ntfy(struct ttm_buffer_object *bo, struct ttm_mem_reg *new_mem) +nouveau_bo_move_ntfy(struct ttm_buffer_object *bo, bool evict, + struct ttm_mem_reg *new_mem) { struct nouveau_bo *nvbo = nouveau_bo(bo); struct nvkm_vma *vma;
/* ttm can now (stupidly) pass the driver bos it didn't create... */ if (bo->destroy != nouveau_bo_del_ttm) return;
list_for_each_entry(vma, &nvbo->vma_list, head) { if (new_mem && new_mem->mem_type != TTM_PL_SYSTEM && diff --git a/drivers/gpu/drm/qxl/qxl_ttm.c b/drivers/gpu/drm/qxl/qxl_ttm.c index 1176133..f3939a9 100644 --- a/drivers/gpu/drm/qxl/qxl_ttm.c +++ b/drivers/gpu/drm/qxl/qxl_ttm.c @@ -360,20 +360,21 @@ static int qxl_bo_move(struct ttm_buffer_object *bo,
if (old_mem->mem_type == TTM_PL_SYSTEM && bo->ttm == NULL) { qxl_move_null(bo, new_mem); return 0; } return ttm_bo_move_memcpy(bo, interruptible, no_wait_gpu, new_mem); }
static void qxl_bo_move_notify(struct ttm_buffer_object *bo, + bool evict, struct ttm_mem_reg *new_mem) { struct qxl_bo *qbo; struct qxl_device *qdev;
if (!qxl_ttm_bo_is_qxl_bo(bo)) return; qbo = to_qxl_bo(bo); qdev = qbo->gem_base.dev->dev_private;
diff --git a/drivers/gpu/drm/radeon/radeon_object.c b/drivers/gpu/drm/radeon/radeon_object.c index 41b72ce..74b2760 100644 --- a/drivers/gpu/drm/radeon/radeon_object.c +++ b/drivers/gpu/drm/radeon/radeon_object.c @@ -758,20 +758,21 @@ int radeon_bo_check_tiling(struct radeon_bo *bo, bool has_moved, return 0; }
if ((bo->surface_reg >= 0) && !has_moved) return 0;
return radeon_bo_get_surface_reg(bo); }
void radeon_bo_move_notify(struct ttm_buffer_object *bo, + bool evict, struct ttm_mem_reg *new_mem) { struct radeon_bo *rbo;
if (!radeon_ttm_bo_is_radeon_bo(bo)) return;
rbo = container_of(bo, struct radeon_bo, tbo); radeon_bo_check_tiling(rbo, 0, 1); radeon_vm_bo_invalidate(rbo->rdev, rbo); diff --git a/drivers/gpu/drm/radeon/radeon_object.h b/drivers/gpu/drm/radeon/radeon_object.h index a10bb3d..9ffd821 100644 --- a/drivers/gpu/drm/radeon/radeon_object.h +++ b/drivers/gpu/drm/radeon/radeon_object.h @@ -143,20 +143,21 @@ extern void radeon_bo_fini(struct radeon_device *rdev); extern int radeon_bo_list_validate(struct radeon_device *rdev, struct ww_acquire_ctx *ticket, struct list_head *head, int ring); extern int radeon_bo_set_tiling_flags(struct radeon_bo *bo, u32 tiling_flags, u32 pitch); extern void radeon_bo_get_tiling_flags(struct radeon_bo *bo, u32 *tiling_flags, u32 *pitch); extern int radeon_bo_check_tiling(struct radeon_bo *bo, bool has_moved, bool force_drop); extern void radeon_bo_move_notify(struct ttm_buffer_object *bo, + bool evict, struct ttm_mem_reg *new_mem); extern int radeon_bo_fault_reserve_notify(struct ttm_buffer_object *bo); extern int radeon_bo_get_surface_reg(struct radeon_bo *bo); extern void radeon_bo_fence(struct radeon_bo *bo, struct radeon_fence *fence, bool shared);
/* * sub allocation */
diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c index d506361..d4973e9c 100644 --- a/drivers/gpu/drm/ttm/ttm_bo.c +++ b/drivers/gpu/drm/ttm/ttm_bo.c @@ -335,45 +335,45 @@ static int ttm_bo_handle_move_mem(struct ttm_buffer_object *bo, goto out_err;
if (mem->mem_type != TTM_PL_SYSTEM) { ret = ttm_tt_bind(bo->ttm, mem); if (ret) goto out_err; }
if (bo->mem.mem_type == TTM_PL_SYSTEM) { if (bdev->driver->move_notify) - bdev->driver->move_notify(bo, mem); + bdev->driver->move_notify(bo, evict, mem); bo->mem = *mem; mem->mm_node = NULL; goto moved; } }
if (bdev->driver->move_notify) - bdev->driver->move_notify(bo, mem); + bdev->driver->move_notify(bo, evict, mem);
if (!(old_man->flags & TTM_MEMTYPE_FLAG_FIXED) && !(new_man->flags & TTM_MEMTYPE_FLAG_FIXED)) ret = ttm_bo_move_ttm(bo, interruptible, no_wait_gpu, mem); else if (bdev->driver->move) ret = bdev->driver->move(bo, evict, interruptible, no_wait_gpu, mem); else ret = ttm_bo_move_memcpy(bo, interruptible, no_wait_gpu, mem);
if (ret) { if (bdev->driver->move_notify) { struct ttm_mem_reg tmp_mem = *mem; *mem = bo->mem; bo->mem = tmp_mem; - bdev->driver->move_notify(bo, mem); + bdev->driver->move_notify(bo, false, mem); bo->mem = *mem; *mem = tmp_mem; }
goto out_err; }
moved: if (bo->evicted) { if (bdev->driver->invalidate_caches) { @@ -407,21 +407,21 @@ static int ttm_bo_handle_move_mem(struct ttm_buffer_object *bo, * Call bo::reserved. * Will release GPU memory type usage on destruction. * This is the place to put in driver specific hooks to release * driver private resources. * Will release the bo::reserved lock. */
static void ttm_bo_cleanup_memtype_use(struct ttm_buffer_object *bo) { if (bo->bdev->driver->move_notify) - bo->bdev->driver->move_notify(bo, NULL); + bo->bdev->driver->move_notify(bo, false, NULL);
ttm_tt_destroy(bo->ttm); bo->ttm = NULL; ttm_bo_mem_put(bo, &bo->mem);
ww_mutex_unlock (&bo->resv->lock); }
static void ttm_bo_flush_all_fences(struct ttm_buffer_object *bo) { diff --git a/drivers/gpu/drm/virtio/virtgpu_ttm.c b/drivers/gpu/drm/virtio/virtgpu_ttm.c index 4a1de9f..10387d7 100644 --- a/drivers/gpu/drm/virtio/virtgpu_ttm.c +++ b/drivers/gpu/drm/virtio/virtgpu_ttm.c @@ -379,20 +379,21 @@ static int virtio_gpu_bo_move(struct ttm_buffer_object *bo,
ret = ttm_bo_wait(bo, interruptible, no_wait_gpu); if (ret) return ret;
virtio_gpu_move_null(bo, new_mem); return 0; }
static void virtio_gpu_bo_move_notify(struct ttm_buffer_object *tbo, + bool evict, struct ttm_mem_reg *new_mem) { struct virtio_gpu_object *bo; struct virtio_gpu_device *vgdev;
bo = container_of(tbo, struct virtio_gpu_object, tbo); vgdev = (struct virtio_gpu_device *)bo->gem_base.dev->dev_private;
if (!new_mem || (new_mem->placement & TTM_PL_FLAG_SYSTEM)) { if (bo->hw_res_handle) diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_buffer.c b/drivers/gpu/drm/vmwgfx/vmwgfx_buffer.c index c894a48..caa279b 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_buffer.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_buffer.c @@ -818,20 +818,21 @@ static int vmw_ttm_fault_reserve_notify(struct ttm_buffer_object *bo) * vmw_move_notify - TTM move_notify_callback * * @bo: The TTM buffer object about to move. * @mem: The struct ttm_mem_reg indicating to what memory * region the move is taking place. * * Calls move_notify for all subsystems needing it. * (currently only resources). */ static void vmw_move_notify(struct ttm_buffer_object *bo, + bool evict, struct ttm_mem_reg *mem) { vmw_resource_move_notify(bo, mem); vmw_query_move_notify(bo, mem); }
/** * vmw_swap_notify - TTM move_notify_callback * diff --git a/include/drm/ttm/ttm_bo_driver.h b/include/drm/ttm/ttm_bo_driver.h index cdbdb40..8b4bec7 100644 --- a/include/drm/ttm/ttm_bo_driver.h +++ b/include/drm/ttm/ttm_bo_driver.h @@ -424,23 +424,29 @@ struct ttm_bo_driver { * * Called from the map / write / read methods to verify that the * caller is permitted to access the buffer object. * This member may be set to NULL, which will refuse this kind of * access for all buffer objects. * This function should return 0 if access is granted, -EPERM otherwise. */ int (*verify_access)(struct ttm_buffer_object *bo, struct file *filp);
- /* hook to notify driver about a driver move so it - * can do tiling things */ + /** + * Hook to notify driver about a driver move so it + * can do tiling things and book-keeping. + * + * @evict: whether this move is evicting the buffer from the graphics + * address space + */ void (*move_notify)(struct ttm_buffer_object *bo, + bool evict, struct ttm_mem_reg *new_mem); /* notify the driver we are taking a fault on this BO * and have reserved it */ int (*fault_reserve_notify)(struct ttm_buffer_object *bo);
/** * notify the driver that we're about to swap out this bo */ void (*swap_notify)(struct ttm_buffer_object *bo);
On 2016年12月16日 01:10, Nicolai Hähnle wrote:
From: Nicolai Hähnle nicolai.haehnle@amd.com
Ensure that the driver can listen to evictions even when they don't take the path through ttm_bo_driver::move.
This is crucial for amdgpu, which relies on an eviction counter to skip re-binding page tables when possible.
Signed-off-by: Nicolai Hähnle nicolai.haehnle@amd.com
Acked-by: Chunming Zhou david1.zhou@amd.com
drivers/gpu/drm/amd/amdgpu/amdgpu_object.c | 1 + drivers/gpu/drm/amd/amdgpu/amdgpu_object.h | 3 ++- drivers/gpu/drm/nouveau/nouveau_bo.c | 3 ++- drivers/gpu/drm/qxl/qxl_ttm.c | 1 + drivers/gpu/drm/radeon/radeon_object.c | 1 + drivers/gpu/drm/radeon/radeon_object.h | 1 + drivers/gpu/drm/ttm/ttm_bo.c | 8 ++++---- drivers/gpu/drm/virtio/virtgpu_ttm.c | 1 + drivers/gpu/drm/vmwgfx/vmwgfx_buffer.c | 1 + include/drm/ttm/ttm_bo_driver.h | 10 ++++++++-- 10 files changed, 22 insertions(+), 8 deletions(-)
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c index bf79b73..c29db99 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c @@ -842,20 +842,21 @@ int amdgpu_bo_get_metadata(struct amdgpu_bo *bo, void *buffer,
if (metadata_size) *metadata_size = bo->metadata_size; if (flags) *flags = bo->metadata_flags;
return 0; }
void amdgpu_bo_move_notify(struct ttm_buffer_object *bo,
bool evict, struct ttm_mem_reg *new_mem)
{ struct amdgpu_device *adev = amdgpu_ttm_adev(bo->bdev); struct amdgpu_bo *abo; struct ttm_mem_reg *old_mem = &bo->mem;
if (!amdgpu_ttm_bo_is_amdgpu_bo(bo)) return;
abo = container_of(bo, struct amdgpu_bo, tbo);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h index 5cbf59e..4306b2f 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h @@ -148,21 +148,22 @@ void amdgpu_bo_fini(struct amdgpu_device *adev); int amdgpu_bo_fbdev_mmap(struct amdgpu_bo *bo, struct vm_area_struct *vma); int amdgpu_bo_set_tiling_flags(struct amdgpu_bo *bo, u64 tiling_flags); void amdgpu_bo_get_tiling_flags(struct amdgpu_bo *bo, u64 *tiling_flags); int amdgpu_bo_set_metadata (struct amdgpu_bo *bo, void *metadata, uint32_t metadata_size, uint64_t flags); int amdgpu_bo_get_metadata(struct amdgpu_bo *bo, void *buffer, size_t buffer_size, uint32_t *metadata_size, uint64_t *flags); void amdgpu_bo_move_notify(struct ttm_buffer_object *bo,
struct ttm_mem_reg *new_mem);
bool evict,
int amdgpu_bo_fault_reserve_notify(struct ttm_buffer_object *bo); void amdgpu_bo_fence(struct amdgpu_bo *bo, struct dma_fence *fence, bool shared); u64 amdgpu_bo_gpu_offset(struct amdgpu_bo *bo); int amdgpu_bo_backup_to_shadow(struct amdgpu_device *adev, struct amdgpu_ring *ring, struct amdgpu_bo *bo, struct reservation_object *resv, struct dma_fence **fence, bool direct); int amdgpu_bo_restore_from_shadow(struct amdgpu_device *adev,struct ttm_mem_reg *new_mem);
diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.c b/drivers/gpu/drm/nouveau/nouveau_bo.c index e0c0007..6fa1521 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bo.c +++ b/drivers/gpu/drm/nouveau/nouveau_bo.c @@ -1187,21 +1187,22 @@ nouveau_bo_move_flips(struct ttm_buffer_object *bo, bool evict, bool intr, ret = nouveau_bo_move_m2mf(bo, true, intr, no_wait_gpu, new_mem); if (ret) goto out;
out: ttm_bo_mem_put(bo, &tmp_mem); return ret; }
static void -nouveau_bo_move_ntfy(struct ttm_buffer_object *bo, struct ttm_mem_reg *new_mem) +nouveau_bo_move_ntfy(struct ttm_buffer_object *bo, bool evict,
struct ttm_mem_reg *new_mem)
{ struct nouveau_bo *nvbo = nouveau_bo(bo); struct nvkm_vma *vma;
/* ttm can now (stupidly) pass the driver bos it didn't create... */ if (bo->destroy != nouveau_bo_del_ttm) return;
list_for_each_entry(vma, &nvbo->vma_list, head) { if (new_mem && new_mem->mem_type != TTM_PL_SYSTEM &&
diff --git a/drivers/gpu/drm/qxl/qxl_ttm.c b/drivers/gpu/drm/qxl/qxl_ttm.c index 1176133..f3939a9 100644 --- a/drivers/gpu/drm/qxl/qxl_ttm.c +++ b/drivers/gpu/drm/qxl/qxl_ttm.c @@ -360,20 +360,21 @@ static int qxl_bo_move(struct ttm_buffer_object *bo,
if (old_mem->mem_type == TTM_PL_SYSTEM && bo->ttm == NULL) { qxl_move_null(bo, new_mem); return 0; } return ttm_bo_move_memcpy(bo, interruptible, no_wait_gpu, new_mem); }
static void qxl_bo_move_notify(struct ttm_buffer_object *bo,
bool evict, struct ttm_mem_reg *new_mem)
{ struct qxl_bo *qbo; struct qxl_device *qdev;
if (!qxl_ttm_bo_is_qxl_bo(bo)) return; qbo = to_qxl_bo(bo); qdev = qbo->gem_base.dev->dev_private;
diff --git a/drivers/gpu/drm/radeon/radeon_object.c b/drivers/gpu/drm/radeon/radeon_object.c index 41b72ce..74b2760 100644 --- a/drivers/gpu/drm/radeon/radeon_object.c +++ b/drivers/gpu/drm/radeon/radeon_object.c @@ -758,20 +758,21 @@ int radeon_bo_check_tiling(struct radeon_bo *bo, bool has_moved, return 0; }
if ((bo->surface_reg >= 0) && !has_moved) return 0;
return radeon_bo_get_surface_reg(bo); }
void radeon_bo_move_notify(struct ttm_buffer_object *bo,
bool evict, struct ttm_mem_reg *new_mem)
{ struct radeon_bo *rbo;
if (!radeon_ttm_bo_is_radeon_bo(bo)) return;
rbo = container_of(bo, struct radeon_bo, tbo); radeon_bo_check_tiling(rbo, 0, 1); radeon_vm_bo_invalidate(rbo->rdev, rbo);
diff --git a/drivers/gpu/drm/radeon/radeon_object.h b/drivers/gpu/drm/radeon/radeon_object.h index a10bb3d..9ffd821 100644 --- a/drivers/gpu/drm/radeon/radeon_object.h +++ b/drivers/gpu/drm/radeon/radeon_object.h @@ -143,20 +143,21 @@ extern void radeon_bo_fini(struct radeon_device *rdev); extern int radeon_bo_list_validate(struct radeon_device *rdev, struct ww_acquire_ctx *ticket, struct list_head *head, int ring); extern int radeon_bo_set_tiling_flags(struct radeon_bo *bo, u32 tiling_flags, u32 pitch); extern void radeon_bo_get_tiling_flags(struct radeon_bo *bo, u32 *tiling_flags, u32 *pitch); extern int radeon_bo_check_tiling(struct radeon_bo *bo, bool has_moved, bool force_drop); extern void radeon_bo_move_notify(struct ttm_buffer_object *bo,
bool evict, struct ttm_mem_reg *new_mem);
extern int radeon_bo_fault_reserve_notify(struct ttm_buffer_object *bo); extern int radeon_bo_get_surface_reg(struct radeon_bo *bo); extern void radeon_bo_fence(struct radeon_bo *bo, struct radeon_fence *fence, bool shared);
/*
- sub allocation
*/
diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c index d506361..d4973e9c 100644 --- a/drivers/gpu/drm/ttm/ttm_bo.c +++ b/drivers/gpu/drm/ttm/ttm_bo.c @@ -335,45 +335,45 @@ static int ttm_bo_handle_move_mem(struct ttm_buffer_object *bo, goto out_err;
if (mem->mem_type != TTM_PL_SYSTEM) { ret = ttm_tt_bind(bo->ttm, mem); if (ret) goto out_err; } if (bo->mem.mem_type == TTM_PL_SYSTEM) { if (bdev->driver->move_notify)
bdev->driver->move_notify(bo, mem);
bdev->driver->move_notify(bo, evict, mem); bo->mem = *mem; mem->mm_node = NULL; goto moved;
} }
if (bdev->driver->move_notify)
bdev->driver->move_notify(bo, mem);
bdev->driver->move_notify(bo, evict, mem);
if (!(old_man->flags & TTM_MEMTYPE_FLAG_FIXED) && !(new_man->flags & TTM_MEMTYPE_FLAG_FIXED)) ret = ttm_bo_move_ttm(bo, interruptible, no_wait_gpu, mem); else if (bdev->driver->move) ret = bdev->driver->move(bo, evict, interruptible, no_wait_gpu, mem); else ret = ttm_bo_move_memcpy(bo, interruptible, no_wait_gpu, mem);
if (ret) { if (bdev->driver->move_notify) { struct ttm_mem_reg tmp_mem = *mem; *mem = bo->mem; bo->mem = tmp_mem;
bdev->driver->move_notify(bo, mem);
bdev->driver->move_notify(bo, false, mem); bo->mem = *mem; *mem = tmp_mem;
}
goto out_err; }
moved: if (bo->evicted) { if (bdev->driver->invalidate_caches) {
@@ -407,21 +407,21 @@ static int ttm_bo_handle_move_mem(struct ttm_buffer_object *bo,
- Call bo::reserved.
- Will release GPU memory type usage on destruction.
- This is the place to put in driver specific hooks to release
- driver private resources.
- Will release the bo::reserved lock.
*/
static void ttm_bo_cleanup_memtype_use(struct ttm_buffer_object *bo) { if (bo->bdev->driver->move_notify)
bo->bdev->driver->move_notify(bo, NULL);
bo->bdev->driver->move_notify(bo, false, NULL);
ttm_tt_destroy(bo->ttm); bo->ttm = NULL; ttm_bo_mem_put(bo, &bo->mem);
ww_mutex_unlock (&bo->resv->lock); }
static void ttm_bo_flush_all_fences(struct ttm_buffer_object *bo) {
diff --git a/drivers/gpu/drm/virtio/virtgpu_ttm.c b/drivers/gpu/drm/virtio/virtgpu_ttm.c index 4a1de9f..10387d7 100644 --- a/drivers/gpu/drm/virtio/virtgpu_ttm.c +++ b/drivers/gpu/drm/virtio/virtgpu_ttm.c @@ -379,20 +379,21 @@ static int virtio_gpu_bo_move(struct ttm_buffer_object *bo,
ret = ttm_bo_wait(bo, interruptible, no_wait_gpu); if (ret) return ret;
virtio_gpu_move_null(bo, new_mem); return 0; }
static void virtio_gpu_bo_move_notify(struct ttm_buffer_object *tbo,
bool evict, struct ttm_mem_reg *new_mem)
{ struct virtio_gpu_object *bo; struct virtio_gpu_device *vgdev;
bo = container_of(tbo, struct virtio_gpu_object, tbo); vgdev = (struct virtio_gpu_device *)bo->gem_base.dev->dev_private;
if (!new_mem || (new_mem->placement & TTM_PL_FLAG_SYSTEM)) { if (bo->hw_res_handle)
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_buffer.c b/drivers/gpu/drm/vmwgfx/vmwgfx_buffer.c index c894a48..caa279b 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_buffer.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_buffer.c @@ -818,20 +818,21 @@ static int vmw_ttm_fault_reserve_notify(struct ttm_buffer_object *bo)
- vmw_move_notify - TTM move_notify_callback
- @bo: The TTM buffer object about to move.
- @mem: The struct ttm_mem_reg indicating to what memory
region the move is taking place.
- Calls move_notify for all subsystems needing it.
- (currently only resources).
*/ static void vmw_move_notify(struct ttm_buffer_object *bo,
bool evict, struct ttm_mem_reg *mem)
{ vmw_resource_move_notify(bo, mem); vmw_query_move_notify(bo, mem); }
/**
- vmw_swap_notify - TTM move_notify_callback
diff --git a/include/drm/ttm/ttm_bo_driver.h b/include/drm/ttm/ttm_bo_driver.h index cdbdb40..8b4bec7 100644 --- a/include/drm/ttm/ttm_bo_driver.h +++ b/include/drm/ttm/ttm_bo_driver.h @@ -424,23 +424,29 @@ struct ttm_bo_driver { * * Called from the map / write / read methods to verify that the * caller is permitted to access the buffer object. * This member may be set to NULL, which will refuse this kind of * access for all buffer objects. * This function should return 0 if access is granted, -EPERM otherwise. */ int (*verify_access)(struct ttm_buffer_object *bo, struct file *filp);
- /* hook to notify driver about a driver move so it
* can do tiling things */
/**
* Hook to notify driver about a driver move so it
* can do tiling things and book-keeping.
*
* @evict: whether this move is evicting the buffer from the graphics
* address space
*/
void (*move_notify)(struct ttm_buffer_object *bo,
bool evict, struct ttm_mem_reg *new_mem);
/* notify the driver we are taking a fault on this BO
- and have reserved it */
int (*fault_reserve_notify)(struct ttm_buffer_object *bo);
/**
- notify the driver that we're about to swap out this bo
*/ void (*swap_notify)(struct ttm_buffer_object *bo);
On 16.12.2016 03:49, zhoucm1 wrote:
On 2016年12月16日 01:10, Nicolai Hähnle wrote:
From: Nicolai Hähnle nicolai.haehnle@amd.com
Ensure that the driver can listen to evictions even when they don't take the path through ttm_bo_driver::move.
This is crucial for amdgpu, which relies on an eviction counter to skip re-binding page tables when possible.
Signed-off-by: Nicolai Hähnle nicolai.haehnle@amd.com
Acked-by: Chunming Zhou david1.zhou@amd.com
Thanks. Ping for feedback from non-AMD people?
Nicolai
drivers/gpu/drm/amd/amdgpu/amdgpu_object.c | 1 + drivers/gpu/drm/amd/amdgpu/amdgpu_object.h | 3 ++- drivers/gpu/drm/nouveau/nouveau_bo.c | 3 ++- drivers/gpu/drm/qxl/qxl_ttm.c | 1 + drivers/gpu/drm/radeon/radeon_object.c | 1 + drivers/gpu/drm/radeon/radeon_object.h | 1 + drivers/gpu/drm/ttm/ttm_bo.c | 8 ++++---- drivers/gpu/drm/virtio/virtgpu_ttm.c | 1 + drivers/gpu/drm/vmwgfx/vmwgfx_buffer.c | 1 + include/drm/ttm/ttm_bo_driver.h | 10 ++++++++-- 10 files changed, 22 insertions(+), 8 deletions(-)
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c index bf79b73..c29db99 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c @@ -842,20 +842,21 @@ int amdgpu_bo_get_metadata(struct amdgpu_bo *bo, void *buffer, if (metadata_size) *metadata_size = bo->metadata_size; if (flags) *flags = bo->metadata_flags; return 0; } void amdgpu_bo_move_notify(struct ttm_buffer_object *bo,
{ struct amdgpu_device *adev = amdgpu_ttm_adev(bo->bdev); struct amdgpu_bo *abo; struct ttm_mem_reg *old_mem = &bo->mem; if (!amdgpu_ttm_bo_is_amdgpu_bo(bo)) return; abo = container_of(bo, struct amdgpu_bo, tbo);bool evict, struct ttm_mem_reg *new_mem)
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h index 5cbf59e..4306b2f 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h @@ -148,21 +148,22 @@ void amdgpu_bo_fini(struct amdgpu_device *adev); int amdgpu_bo_fbdev_mmap(struct amdgpu_bo *bo, struct vm_area_struct *vma); int amdgpu_bo_set_tiling_flags(struct amdgpu_bo *bo, u64 tiling_flags); void amdgpu_bo_get_tiling_flags(struct amdgpu_bo *bo, u64 *tiling_flags); int amdgpu_bo_set_metadata (struct amdgpu_bo *bo, void *metadata, uint32_t metadata_size, uint64_t flags); int amdgpu_bo_get_metadata(struct amdgpu_bo *bo, void *buffer, size_t buffer_size, uint32_t *metadata_size, uint64_t *flags); void amdgpu_bo_move_notify(struct ttm_buffer_object *bo,
struct ttm_mem_reg *new_mem);
bool evict,
int amdgpu_bo_fault_reserve_notify(struct ttm_buffer_object *bo); void amdgpu_bo_fence(struct amdgpu_bo *bo, struct dma_fence *fence, bool shared); u64 amdgpu_bo_gpu_offset(struct amdgpu_bo *bo); int amdgpu_bo_backup_to_shadow(struct amdgpu_device *adev, struct amdgpu_ring *ring, struct amdgpu_bo *bo, struct reservation_object *resv, struct dma_fence **fence, bool direct); int amdgpu_bo_restore_from_shadow(struct amdgpu_device *adev,struct ttm_mem_reg *new_mem);
diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.c b/drivers/gpu/drm/nouveau/nouveau_bo.c index e0c0007..6fa1521 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bo.c +++ b/drivers/gpu/drm/nouveau/nouveau_bo.c @@ -1187,21 +1187,22 @@ nouveau_bo_move_flips(struct ttm_buffer_object *bo, bool evict, bool intr, ret = nouveau_bo_move_m2mf(bo, true, intr, no_wait_gpu, new_mem); if (ret) goto out; out: ttm_bo_mem_put(bo, &tmp_mem); return ret; } static void -nouveau_bo_move_ntfy(struct ttm_buffer_object *bo, struct ttm_mem_reg *new_mem) +nouveau_bo_move_ntfy(struct ttm_buffer_object *bo, bool evict,
{ struct nouveau_bo *nvbo = nouveau_bo(bo); struct nvkm_vma *vma; /* ttm can now (stupidly) pass the driver bos it didn'tstruct ttm_mem_reg *new_mem)
create... */ if (bo->destroy != nouveau_bo_del_ttm) return; list_for_each_entry(vma, &nvbo->vma_list, head) { if (new_mem && new_mem->mem_type != TTM_PL_SYSTEM && diff --git a/drivers/gpu/drm/qxl/qxl_ttm.c b/drivers/gpu/drm/qxl/qxl_ttm.c index 1176133..f3939a9 100644 --- a/drivers/gpu/drm/qxl/qxl_ttm.c +++ b/drivers/gpu/drm/qxl/qxl_ttm.c @@ -360,20 +360,21 @@ static int qxl_bo_move(struct ttm_buffer_object *bo, if (old_mem->mem_type == TTM_PL_SYSTEM && bo->ttm == NULL) { qxl_move_null(bo, new_mem); return 0; } return ttm_bo_move_memcpy(bo, interruptible, no_wait_gpu, new_mem); } static void qxl_bo_move_notify(struct ttm_buffer_object *bo,
{ struct qxl_bo *qbo; struct qxl_device *qdev; if (!qxl_ttm_bo_is_qxl_bo(bo)) return; qbo = to_qxl_bo(bo); qdev = qbo->gem_base.dev->dev_private; diff --git a/drivers/gpu/drm/radeon/radeon_object.cbool evict, struct ttm_mem_reg *new_mem)
b/drivers/gpu/drm/radeon/radeon_object.c index 41b72ce..74b2760 100644 --- a/drivers/gpu/drm/radeon/radeon_object.c +++ b/drivers/gpu/drm/radeon/radeon_object.c @@ -758,20 +758,21 @@ int radeon_bo_check_tiling(struct radeon_bo *bo, bool has_moved, return 0; } if ((bo->surface_reg >= 0) && !has_moved) return 0; return radeon_bo_get_surface_reg(bo); } void radeon_bo_move_notify(struct ttm_buffer_object *bo,
{ struct radeon_bo *rbo; if (!radeon_ttm_bo_is_radeon_bo(bo)) return; rbo = container_of(bo, struct radeon_bo, tbo); radeon_bo_check_tiling(rbo, 0, 1); radeon_vm_bo_invalidate(rbo->rdev, rbo);bool evict, struct ttm_mem_reg *new_mem)
diff --git a/drivers/gpu/drm/radeon/radeon_object.h b/drivers/gpu/drm/radeon/radeon_object.h index a10bb3d..9ffd821 100644 --- a/drivers/gpu/drm/radeon/radeon_object.h +++ b/drivers/gpu/drm/radeon/radeon_object.h @@ -143,20 +143,21 @@ extern void radeon_bo_fini(struct radeon_device *rdev); extern int radeon_bo_list_validate(struct radeon_device *rdev, struct ww_acquire_ctx *ticket, struct list_head *head, int ring); extern int radeon_bo_set_tiling_flags(struct radeon_bo *bo, u32 tiling_flags, u32 pitch); extern void radeon_bo_get_tiling_flags(struct radeon_bo *bo, u32 *tiling_flags, u32 *pitch); extern int radeon_bo_check_tiling(struct radeon_bo *bo, bool has_moved, bool force_drop); extern void radeon_bo_move_notify(struct ttm_buffer_object *bo,
extern int radeon_bo_fault_reserve_notify(struct ttm_buffer_objectbool evict, struct ttm_mem_reg *new_mem);
*bo); extern int radeon_bo_get_surface_reg(struct radeon_bo *bo); extern void radeon_bo_fence(struct radeon_bo *bo, struct radeon_fence *fence, bool shared); /*
- sub allocation
*/ diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c index d506361..d4973e9c 100644 --- a/drivers/gpu/drm/ttm/ttm_bo.c +++ b/drivers/gpu/drm/ttm/ttm_bo.c @@ -335,45 +335,45 @@ static int ttm_bo_handle_move_mem(struct ttm_buffer_object *bo, goto out_err; if (mem->mem_type != TTM_PL_SYSTEM) { ret = ttm_tt_bind(bo->ttm, mem); if (ret) goto out_err; } if (bo->mem.mem_type == TTM_PL_SYSTEM) { if (bdev->driver->move_notify)
bdev->driver->move_notify(bo, mem);
bdev->driver->move_notify(bo, evict, mem); bo->mem = *mem; mem->mm_node = NULL; goto moved; } } if (bdev->driver->move_notify)
bdev->driver->move_notify(bo, mem);
bdev->driver->move_notify(bo, evict, mem); if (!(old_man->flags & TTM_MEMTYPE_FLAG_FIXED) && !(new_man->flags & TTM_MEMTYPE_FLAG_FIXED)) ret = ttm_bo_move_ttm(bo, interruptible, no_wait_gpu, mem); else if (bdev->driver->move) ret = bdev->driver->move(bo, evict, interruptible, no_wait_gpu, mem); else ret = ttm_bo_move_memcpy(bo, interruptible, no_wait_gpu, mem); if (ret) { if (bdev->driver->move_notify) { struct ttm_mem_reg tmp_mem = *mem; *mem = bo->mem; bo->mem = tmp_mem;
bdev->driver->move_notify(bo, mem);
moved: if (bo->evicted) { if (bdev->driver->invalidate_caches) {bdev->driver->move_notify(bo, false, mem); bo->mem = *mem; *mem = tmp_mem; } goto out_err; }
@@ -407,21 +407,21 @@ static int ttm_bo_handle_move_mem(struct ttm_buffer_object *bo,
- Call bo::reserved.
- Will release GPU memory type usage on destruction.
- This is the place to put in driver specific hooks to release
- driver private resources.
- Will release the bo::reserved lock.
*/ static void ttm_bo_cleanup_memtype_use(struct ttm_buffer_object *bo) { if (bo->bdev->driver->move_notify)
bo->bdev->driver->move_notify(bo, NULL);
} static void ttm_bo_flush_all_fences(struct ttm_buffer_object *bo) {bo->bdev->driver->move_notify(bo, false, NULL); ttm_tt_destroy(bo->ttm); bo->ttm = NULL; ttm_bo_mem_put(bo, &bo->mem); ww_mutex_unlock (&bo->resv->lock);
diff --git a/drivers/gpu/drm/virtio/virtgpu_ttm.c b/drivers/gpu/drm/virtio/virtgpu_ttm.c index 4a1de9f..10387d7 100644 --- a/drivers/gpu/drm/virtio/virtgpu_ttm.c +++ b/drivers/gpu/drm/virtio/virtgpu_ttm.c @@ -379,20 +379,21 @@ static int virtio_gpu_bo_move(struct ttm_buffer_object *bo, ret = ttm_bo_wait(bo, interruptible, no_wait_gpu); if (ret) return ret; virtio_gpu_move_null(bo, new_mem); return 0; } static void virtio_gpu_bo_move_notify(struct ttm_buffer_object *tbo,
{ struct virtio_gpu_object *bo; struct virtio_gpu_device *vgdev; bo = container_of(tbo, struct virtio_gpu_object, tbo); vgdev = (struct virtio_gpu_device *)bo->gem_base.dev->dev_private; if (!new_mem || (new_mem->placement & TTM_PL_FLAG_SYSTEM)) { if (bo->hw_res_handle)bool evict, struct ttm_mem_reg *new_mem)
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_buffer.c b/drivers/gpu/drm/vmwgfx/vmwgfx_buffer.c index c894a48..caa279b 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_buffer.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_buffer.c @@ -818,20 +818,21 @@ static int vmw_ttm_fault_reserve_notify(struct ttm_buffer_object *bo)
- vmw_move_notify - TTM move_notify_callback
- @bo: The TTM buffer object about to move.
- @mem: The struct ttm_mem_reg indicating to what memory
region the move is taking place.
- Calls move_notify for all subsystems needing it.
- (currently only resources).
*/ static void vmw_move_notify(struct ttm_buffer_object *bo,
{ vmw_resource_move_notify(bo, mem); vmw_query_move_notify(bo, mem); } /**bool evict, struct ttm_mem_reg *mem)
- vmw_swap_notify - TTM move_notify_callback
diff --git a/include/drm/ttm/ttm_bo_driver.h b/include/drm/ttm/ttm_bo_driver.h index cdbdb40..8b4bec7 100644 --- a/include/drm/ttm/ttm_bo_driver.h +++ b/include/drm/ttm/ttm_bo_driver.h @@ -424,23 +424,29 @@ struct ttm_bo_driver { * * Called from the map / write / read methods to verify that the * caller is permitted to access the buffer object. * This member may be set to NULL, which will refuse this kind of * access for all buffer objects. * This function should return 0 if access is granted, -EPERM otherwise. */ int (*verify_access)(struct ttm_buffer_object *bo, struct file *filp);
- /* hook to notify driver about a driver move so it
* can do tiling things */
- /**
* Hook to notify driver about a driver move so it
* can do tiling things and book-keeping.
*
* @evict: whether this move is evicting the buffer from the
graphics
* address space
*/ void (*move_notify)(struct ttm_buffer_object *bo,
bool evict, struct ttm_mem_reg *new_mem); /* notify the driver we are taking a fault on this BO * and have reserved it */ int (*fault_reserve_notify)(struct ttm_buffer_object *bo); /** * notify the driver that we're about to swap out this bo */ void (*swap_notify)(struct ttm_buffer_object *bo);
Am 21.12.2016 um 16:12 schrieb Nicolai Hähnle:
On 16.12.2016 03:49, zhoucm1 wrote:
On 2016年12月16日 01:10, Nicolai Hähnle wrote:
From: Nicolai Hähnle nicolai.haehnle@amd.com
Ensure that the driver can listen to evictions even when they don't take the path through ttm_bo_driver::move.
This is crucial for amdgpu, which relies on an eviction counter to skip re-binding page tables when possible.
Signed-off-by: Nicolai Hähnle nicolai.haehnle@amd.com
Acked-by: Chunming Zhou david1.zhou@amd.com
Feel free to add my Reviewed-by: Christian König christian.koenig@amd.com to patch #1-#4 and V2 of patch #5 as well.
Thanks. Ping for feedback from non-AMD people?
Ping once more. Would be nice if somebody else can take a look as well.
Christian.
Nicolai
drivers/gpu/drm/amd/amdgpu/amdgpu_object.c | 1 + drivers/gpu/drm/amd/amdgpu/amdgpu_object.h | 3 ++- drivers/gpu/drm/nouveau/nouveau_bo.c | 3 ++- drivers/gpu/drm/qxl/qxl_ttm.c | 1 + drivers/gpu/drm/radeon/radeon_object.c | 1 + drivers/gpu/drm/radeon/radeon_object.h | 1 + drivers/gpu/drm/ttm/ttm_bo.c | 8 ++++---- drivers/gpu/drm/virtio/virtgpu_ttm.c | 1 + drivers/gpu/drm/vmwgfx/vmwgfx_buffer.c | 1 + include/drm/ttm/ttm_bo_driver.h | 10 ++++++++-- 10 files changed, 22 insertions(+), 8 deletions(-)
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c index bf79b73..c29db99 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c @@ -842,20 +842,21 @@ int amdgpu_bo_get_metadata(struct amdgpu_bo *bo, void *buffer, if (metadata_size) *metadata_size = bo->metadata_size; if (flags) *flags = bo->metadata_flags; return 0; } void amdgpu_bo_move_notify(struct ttm_buffer_object *bo,
{ struct amdgpu_device *adev = amdgpu_ttm_adev(bo->bdev); struct amdgpu_bo *abo; struct ttm_mem_reg *old_mem = &bo->mem; if (!amdgpu_ttm_bo_is_amdgpu_bo(bo)) return; abo = container_of(bo, struct amdgpu_bo, tbo);bool evict, struct ttm_mem_reg *new_mem)
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h index 5cbf59e..4306b2f 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h @@ -148,21 +148,22 @@ void amdgpu_bo_fini(struct amdgpu_device *adev); int amdgpu_bo_fbdev_mmap(struct amdgpu_bo *bo, struct vm_area_struct *vma); int amdgpu_bo_set_tiling_flags(struct amdgpu_bo *bo, u64 tiling_flags); void amdgpu_bo_get_tiling_flags(struct amdgpu_bo *bo, u64 *tiling_flags); int amdgpu_bo_set_metadata (struct amdgpu_bo *bo, void *metadata, uint32_t metadata_size, uint64_t flags); int amdgpu_bo_get_metadata(struct amdgpu_bo *bo, void *buffer, size_t buffer_size, uint32_t *metadata_size, uint64_t *flags); void amdgpu_bo_move_notify(struct ttm_buffer_object *bo,
struct ttm_mem_reg *new_mem);
bool evict,
int amdgpu_bo_fault_reserve_notify(struct ttm_buffer_object *bo); void amdgpu_bo_fence(struct amdgpu_bo *bo, struct dma_fence *fence, bool shared); u64 amdgpu_bo_gpu_offset(struct amdgpu_bo *bo); int amdgpu_bo_backup_to_shadow(struct amdgpu_device *adev, struct amdgpu_ring *ring, struct amdgpu_bo *bo, struct reservation_object *resv, struct dma_fence **fence, bool direct); int amdgpu_bo_restore_from_shadow(struct amdgpu_device *adev,struct ttm_mem_reg *new_mem);
diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.c b/drivers/gpu/drm/nouveau/nouveau_bo.c index e0c0007..6fa1521 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bo.c +++ b/drivers/gpu/drm/nouveau/nouveau_bo.c @@ -1187,21 +1187,22 @@ nouveau_bo_move_flips(struct ttm_buffer_object *bo, bool evict, bool intr, ret = nouveau_bo_move_m2mf(bo, true, intr, no_wait_gpu, new_mem); if (ret) goto out; out: ttm_bo_mem_put(bo, &tmp_mem); return ret; } static void -nouveau_bo_move_ntfy(struct ttm_buffer_object *bo, struct ttm_mem_reg *new_mem) +nouveau_bo_move_ntfy(struct ttm_buffer_object *bo, bool evict,
{ struct nouveau_bo *nvbo = nouveau_bo(bo); struct nvkm_vma *vma; /* ttm can now (stupidly) pass the driver bos it didn'tstruct ttm_mem_reg *new_mem)
create... */ if (bo->destroy != nouveau_bo_del_ttm) return; list_for_each_entry(vma, &nvbo->vma_list, head) { if (new_mem && new_mem->mem_type != TTM_PL_SYSTEM && diff --git a/drivers/gpu/drm/qxl/qxl_ttm.c b/drivers/gpu/drm/qxl/qxl_ttm.c index 1176133..f3939a9 100644 --- a/drivers/gpu/drm/qxl/qxl_ttm.c +++ b/drivers/gpu/drm/qxl/qxl_ttm.c @@ -360,20 +360,21 @@ static int qxl_bo_move(struct ttm_buffer_object *bo, if (old_mem->mem_type == TTM_PL_SYSTEM && bo->ttm == NULL) { qxl_move_null(bo, new_mem); return 0; } return ttm_bo_move_memcpy(bo, interruptible, no_wait_gpu, new_mem); } static void qxl_bo_move_notify(struct ttm_buffer_object *bo,
{ struct qxl_bo *qbo; struct qxl_device *qdev; if (!qxl_ttm_bo_is_qxl_bo(bo)) return; qbo = to_qxl_bo(bo); qdev = qbo->gem_base.dev->dev_private; diff --git a/drivers/gpu/drm/radeon/radeon_object.cbool evict, struct ttm_mem_reg *new_mem)
b/drivers/gpu/drm/radeon/radeon_object.c index 41b72ce..74b2760 100644 --- a/drivers/gpu/drm/radeon/radeon_object.c +++ b/drivers/gpu/drm/radeon/radeon_object.c @@ -758,20 +758,21 @@ int radeon_bo_check_tiling(struct radeon_bo *bo, bool has_moved, return 0; } if ((bo->surface_reg >= 0) && !has_moved) return 0; return radeon_bo_get_surface_reg(bo); } void radeon_bo_move_notify(struct ttm_buffer_object *bo,
{ struct radeon_bo *rbo; if (!radeon_ttm_bo_is_radeon_bo(bo)) return; rbo = container_of(bo, struct radeon_bo, tbo); radeon_bo_check_tiling(rbo, 0, 1); radeon_vm_bo_invalidate(rbo->rdev, rbo);bool evict, struct ttm_mem_reg *new_mem)
diff --git a/drivers/gpu/drm/radeon/radeon_object.h b/drivers/gpu/drm/radeon/radeon_object.h index a10bb3d..9ffd821 100644 --- a/drivers/gpu/drm/radeon/radeon_object.h +++ b/drivers/gpu/drm/radeon/radeon_object.h @@ -143,20 +143,21 @@ extern void radeon_bo_fini(struct radeon_device *rdev); extern int radeon_bo_list_validate(struct radeon_device *rdev, struct ww_acquire_ctx *ticket, struct list_head *head, int ring); extern int radeon_bo_set_tiling_flags(struct radeon_bo *bo, u32 tiling_flags, u32 pitch); extern void radeon_bo_get_tiling_flags(struct radeon_bo *bo, u32 *tiling_flags, u32 *pitch); extern int radeon_bo_check_tiling(struct radeon_bo *bo, bool has_moved, bool force_drop); extern void radeon_bo_move_notify(struct ttm_buffer_object *bo,
extern int radeon_bo_fault_reserve_notify(struct ttm_buffer_objectbool evict, struct ttm_mem_reg *new_mem);
*bo); extern int radeon_bo_get_surface_reg(struct radeon_bo *bo); extern void radeon_bo_fence(struct radeon_bo *bo, struct radeon_fence *fence, bool shared); /*
- sub allocation
*/ diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c index d506361..d4973e9c 100644 --- a/drivers/gpu/drm/ttm/ttm_bo.c +++ b/drivers/gpu/drm/ttm/ttm_bo.c @@ -335,45 +335,45 @@ static int ttm_bo_handle_move_mem(struct ttm_buffer_object *bo, goto out_err; if (mem->mem_type != TTM_PL_SYSTEM) { ret = ttm_tt_bind(bo->ttm, mem); if (ret) goto out_err; } if (bo->mem.mem_type == TTM_PL_SYSTEM) { if (bdev->driver->move_notify)
bdev->driver->move_notify(bo, mem);
bdev->driver->move_notify(bo, evict, mem); bo->mem = *mem; mem->mm_node = NULL; goto moved; } } if (bdev->driver->move_notify)
bdev->driver->move_notify(bo, mem);
bdev->driver->move_notify(bo, evict, mem); if (!(old_man->flags & TTM_MEMTYPE_FLAG_FIXED) && !(new_man->flags & TTM_MEMTYPE_FLAG_FIXED)) ret = ttm_bo_move_ttm(bo, interruptible, no_wait_gpu, mem); else if (bdev->driver->move) ret = bdev->driver->move(bo, evict, interruptible, no_wait_gpu, mem); else ret = ttm_bo_move_memcpy(bo, interruptible, no_wait_gpu,
mem); if (ret) { if (bdev->driver->move_notify) { struct ttm_mem_reg tmp_mem = *mem; *mem = bo->mem; bo->mem = tmp_mem;
bdev->driver->move_notify(bo, mem);
moved: if (bo->evicted) { if (bdev->driver->invalidate_caches) {bdev->driver->move_notify(bo, false, mem); bo->mem = *mem; *mem = tmp_mem; } goto out_err; }
@@ -407,21 +407,21 @@ static int ttm_bo_handle_move_mem(struct ttm_buffer_object *bo,
- Call bo::reserved.
- Will release GPU memory type usage on destruction.
- This is the place to put in driver specific hooks to release
- driver private resources.
- Will release the bo::reserved lock.
*/ static void ttm_bo_cleanup_memtype_use(struct ttm_buffer_object *bo) { if (bo->bdev->driver->move_notify)
bo->bdev->driver->move_notify(bo, NULL);
} static void ttm_bo_flush_all_fences(struct ttm_buffer_object *bo) {bo->bdev->driver->move_notify(bo, false, NULL); ttm_tt_destroy(bo->ttm); bo->ttm = NULL; ttm_bo_mem_put(bo, &bo->mem); ww_mutex_unlock (&bo->resv->lock);
diff --git a/drivers/gpu/drm/virtio/virtgpu_ttm.c b/drivers/gpu/drm/virtio/virtgpu_ttm.c index 4a1de9f..10387d7 100644 --- a/drivers/gpu/drm/virtio/virtgpu_ttm.c +++ b/drivers/gpu/drm/virtio/virtgpu_ttm.c @@ -379,20 +379,21 @@ static int virtio_gpu_bo_move(struct ttm_buffer_object *bo, ret = ttm_bo_wait(bo, interruptible, no_wait_gpu); if (ret) return ret; virtio_gpu_move_null(bo, new_mem); return 0; } static void virtio_gpu_bo_move_notify(struct ttm_buffer_object *tbo,
{ struct virtio_gpu_object *bo; struct virtio_gpu_device *vgdev; bo = container_of(tbo, struct virtio_gpu_object, tbo); vgdev = (struct virtio_gpu_devicebool evict, struct ttm_mem_reg *new_mem)
*)bo->gem_base.dev->dev_private; if (!new_mem || (new_mem->placement & TTM_PL_FLAG_SYSTEM)) { if (bo->hw_res_handle) diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_buffer.c b/drivers/gpu/drm/vmwgfx/vmwgfx_buffer.c index c894a48..caa279b 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_buffer.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_buffer.c @@ -818,20 +818,21 @@ static int vmw_ttm_fault_reserve_notify(struct ttm_buffer_object *bo)
- vmw_move_notify - TTM move_notify_callback
- @bo: The TTM buffer object about to move.
- @mem: The struct ttm_mem_reg indicating to what memory
region the move is taking place.
- Calls move_notify for all subsystems needing it.
- (currently only resources).
*/ static void vmw_move_notify(struct ttm_buffer_object *bo,
{ vmw_resource_move_notify(bo, mem); vmw_query_move_notify(bo, mem); } /**bool evict, struct ttm_mem_reg *mem)
- vmw_swap_notify - TTM move_notify_callback
diff --git a/include/drm/ttm/ttm_bo_driver.h b/include/drm/ttm/ttm_bo_driver.h index cdbdb40..8b4bec7 100644 --- a/include/drm/ttm/ttm_bo_driver.h +++ b/include/drm/ttm/ttm_bo_driver.h @@ -424,23 +424,29 @@ struct ttm_bo_driver { * * Called from the map / write / read methods to verify that the * caller is permitted to access the buffer object. * This member may be set to NULL, which will refuse this kind of * access for all buffer objects. * This function should return 0 if access is granted, -EPERM otherwise. */ int (*verify_access)(struct ttm_buffer_object *bo, struct file *filp);
- /* hook to notify driver about a driver move so it
* can do tiling things */
- /**
* Hook to notify driver about a driver move so it
* can do tiling things and book-keeping.
*
* @evict: whether this move is evicting the buffer from the
graphics
* address space
*/ void (*move_notify)(struct ttm_buffer_object *bo,
bool evict, struct ttm_mem_reg *new_mem); /* notify the driver we are taking a fault on this BO * and have reserved it */ int (*fault_reserve_notify)(struct ttm_buffer_object *bo); /** * notify the driver that we're about to swap out this bo */ void (*swap_notify)(struct ttm_buffer_object *bo);
amd-gfx mailing list amd-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/amd-gfx
From: Nicolai Hähnle nicolai.haehnle@amd.com
This catches evictions of shadow page tables from the GART. Since shadow page tables are always stored in system memory, amdgpu_bo_move is never called for them.
This fixes a crash during command submission that occurs when only a shadow page table and no other BOs were evicted since the last submission.
Fixes: 1baa439fb2f4e586 ("drm/amdgpu: allocate shadow for pd/pt bo V2") Signed-off-by: Nicolai Hähnle nicolai.haehnle@amd.com --- drivers/gpu/drm/amd/amdgpu/amdgpu_object.c | 4 ++++ drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | 4 ---- 2 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c index c29db99..d94cdef 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c @@ -855,20 +855,24 @@ void amdgpu_bo_move_notify(struct ttm_buffer_object *bo, struct amdgpu_device *adev = amdgpu_ttm_adev(bo->bdev); struct amdgpu_bo *abo; struct ttm_mem_reg *old_mem = &bo->mem;
if (!amdgpu_ttm_bo_is_amdgpu_bo(bo)) return;
abo = container_of(bo, struct amdgpu_bo, tbo); amdgpu_vm_bo_invalidate(adev, abo);
+ /* remember the eviction */ + if (evict) + atomic64_inc(&adev->num_evictions); + /* update statistics */ if (!new_mem) return;
/* move_notify is called before move happens */ amdgpu_update_memory_usage(adev, &bo->mem, new_mem);
trace_amdgpu_ttm_bo_move(abo, new_mem->mem_type, old_mem->mem_type); }
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c index 8f18b8e..80924c2 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c @@ -460,24 +460,20 @@ static int amdgpu_bo_move(struct ttm_buffer_object *bo, struct ttm_mem_reg *old_mem = &bo->mem; int r;
/* Can't move a pinned BO */ abo = container_of(bo, struct amdgpu_bo, tbo); if (WARN_ON_ONCE(abo->pin_count > 0)) return -EINVAL;
adev = amdgpu_ttm_adev(bo->bdev);
- /* remember the eviction */ - if (evict) - atomic64_inc(&adev->num_evictions); - if (old_mem->mem_type == TTM_PL_SYSTEM && bo->ttm == NULL) { amdgpu_move_null(bo, new_mem); return 0; } if ((old_mem->mem_type == TTM_PL_TT && new_mem->mem_type == TTM_PL_SYSTEM) || (old_mem->mem_type == TTM_PL_SYSTEM && new_mem->mem_type == TTM_PL_TT)) { /* bind is enough */ amdgpu_move_null(bo, new_mem);
On 2016年12月16日 01:10, Nicolai Hähnle wrote:
From: Nicolai Hähnle nicolai.haehnle@amd.com
This catches evictions of shadow page tables from the GART. Since shadow page tables are always stored in system memory, amdgpu_bo_move is never called for them.
This fixes a crash during command submission that occurs when only a shadow page table and no other BOs were evicted since the last submission.
Fixes: 1baa439fb2f4e586 ("drm/amdgpu: allocate shadow for pd/pt bo V2") Signed-off-by: Nicolai Hähnle nicolai.haehnle@amd.com
Acked-by: Chunming Zhou david1.zhou@amd.com
drivers/gpu/drm/amd/amdgpu/amdgpu_object.c | 4 ++++ drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | 4 ---- 2 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c index c29db99..d94cdef 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c @@ -855,20 +855,24 @@ void amdgpu_bo_move_notify(struct ttm_buffer_object *bo, struct amdgpu_device *adev = amdgpu_ttm_adev(bo->bdev); struct amdgpu_bo *abo; struct ttm_mem_reg *old_mem = &bo->mem;
if (!amdgpu_ttm_bo_is_amdgpu_bo(bo)) return;
abo = container_of(bo, struct amdgpu_bo, tbo); amdgpu_vm_bo_invalidate(adev, abo);
/* remember the eviction */
if (evict)
atomic64_inc(&adev->num_evictions);
/* update statistics */ if (!new_mem) return;
/* move_notify is called before move happens */ amdgpu_update_memory_usage(adev, &bo->mem, new_mem);
trace_amdgpu_ttm_bo_move(abo, new_mem->mem_type, old_mem->mem_type); }
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c index 8f18b8e..80924c2 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c @@ -460,24 +460,20 @@ static int amdgpu_bo_move(struct ttm_buffer_object *bo, struct ttm_mem_reg *old_mem = &bo->mem; int r;
/* Can't move a pinned BO */ abo = container_of(bo, struct amdgpu_bo, tbo); if (WARN_ON_ONCE(abo->pin_count > 0)) return -EINVAL;
adev = amdgpu_ttm_adev(bo->bdev);
- /* remember the eviction */
- if (evict)
atomic64_inc(&adev->num_evictions);
- if (old_mem->mem_type == TTM_PL_SYSTEM && bo->ttm == NULL) { amdgpu_move_null(bo, new_mem); return 0; } if ((old_mem->mem_type == TTM_PL_TT && new_mem->mem_type == TTM_PL_SYSTEM) || (old_mem->mem_type == TTM_PL_SYSTEM && new_mem->mem_type == TTM_PL_TT)) { /* bind is enough */ amdgpu_move_null(bo, new_mem);
From: Nicolai Hähnle nicolai.haehnle@amd.com
Signed-off-by: Nicolai Hähnle nicolai.haehnle@amd.com --- drivers/gpu/drm/amd/amdgpu/amdgpu_object.h | 9 +++++++++ 1 file changed, 9 insertions(+)
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h index 4306b2f..15a723a 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h @@ -107,20 +107,29 @@ static inline unsigned amdgpu_bo_gpu_page_alignment(struct amdgpu_bo *bo) * amdgpu_bo_mmap_offset - return mmap offset of bo * @bo: amdgpu object for which we query the offset * * Returns mmap offset of the object. */ static inline u64 amdgpu_bo_mmap_offset(struct amdgpu_bo *bo) { return drm_vma_node_offset_addr(&bo->tbo.vma_node); }
+/** + * amdgpu_bo_gpu_accessible - return whether the bo is currently in memory that + * is accessible to the GPU. + */ +static inline bool amdgpu_bo_gpu_accessible(struct amdgpu_bo *bo) +{ + return bo->tbo.mem.mem_type != TTM_PL_SYSTEM; +} + int amdgpu_bo_create(struct amdgpu_device *adev, unsigned long size, int byte_align, bool kernel, u32 domain, u64 flags, struct sg_table *sg, struct reservation_object *resv, struct amdgpu_bo **bo_ptr); int amdgpu_bo_create_restricted(struct amdgpu_device *adev, unsigned long size, int byte_align, bool kernel, u32 domain, u64 flags, struct sg_table *sg,
On 2016年12月16日 01:10, Nicolai Hähnle wrote:
From: Nicolai Hähnle nicolai.haehnle@amd.com
Signed-off-by: Nicolai Hähnle nicolai.haehnle@amd.com
Reviewed-by: Chunming Zhou david1.zhou@amd.com
drivers/gpu/drm/amd/amdgpu/amdgpu_object.h | 9 +++++++++ 1 file changed, 9 insertions(+)
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h index 4306b2f..15a723a 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h @@ -107,20 +107,29 @@ static inline unsigned amdgpu_bo_gpu_page_alignment(struct amdgpu_bo *bo)
- amdgpu_bo_mmap_offset - return mmap offset of bo
- @bo: amdgpu object for which we query the offset
- Returns mmap offset of the object.
*/ static inline u64 amdgpu_bo_mmap_offset(struct amdgpu_bo *bo) { return drm_vma_node_offset_addr(&bo->tbo.vma_node); }
+/**
- amdgpu_bo_gpu_accessible - return whether the bo is currently in memory that
- is accessible to the GPU.
- */
+static inline bool amdgpu_bo_gpu_accessible(struct amdgpu_bo *bo) +{
- return bo->tbo.mem.mem_type != TTM_PL_SYSTEM;
+}
- int amdgpu_bo_create(struct amdgpu_device *adev, unsigned long size, int byte_align, bool kernel, u32 domain, u64 flags, struct sg_table *sg, struct reservation_object *resv, struct amdgpu_bo **bo_ptr); int amdgpu_bo_create_restricted(struct amdgpu_device *adev, unsigned long size, int byte_align, bool kernel, u32 domain, u64 flags, struct sg_table *sg,
From: Nicolai Hähnle nicolai.haehnle@amd.com
Skip amdgpu_gem_va_update_vm when shadow the page directory is swapped out. Clean up the check for non-shadow BOs as well using the new helper function.
This fixes a crash with the stack trace:
amdgpu_gem_va_update_vm -> amdgpu_vm_update_page_directory -> amdgpu_ttm_bind -> amdgpu_gtt_mgr_alloc
Signed-off-by: Nicolai Hähnle nicolai.haehnle@amd.com --- drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-)
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c index cd62f6f..4e1eb05 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c @@ -489,44 +489,49 @@ static int amdgpu_gem_va_check(void *param, struct amdgpu_bo *bo) * vital here, so they are not reported back to userspace. */ static void amdgpu_gem_va_update_vm(struct amdgpu_device *adev, struct amdgpu_bo_va *bo_va, uint32_t operation) { struct ttm_validate_buffer tv, *entry; struct amdgpu_bo_list_entry vm_pd; struct ww_acquire_ctx ticket; struct list_head list, duplicates; - unsigned domain; int r;
INIT_LIST_HEAD(&list); 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) { - domain = amdgpu_mem_type_to_domain(entry->bo->mem.mem_type); + struct amdgpu_bo *bo = + container_of(entry->bo, struct amdgpu_bo, tbo); + /* if anything is swapped out don't swap it in here, just abort and wait for the next CS */ - if (domain == AMDGPU_GEM_DOMAIN_CPU) + if (!amdgpu_bo_gpu_accessible(bo)) + goto error_unreserve; + + if (bo->shadow && !amdgpu_bo_gpu_accessible(bo->shadow)) goto error_unreserve; } + r = amdgpu_vm_validate_pt_bos(adev, bo_va->vm, amdgpu_gem_va_check, NULL); if (r) goto error_unreserve;
r = amdgpu_vm_update_page_directory(adev, bo_va->vm); if (r) goto error_unreserve;
r = amdgpu_vm_clear_freed(adev, bo_va->vm);
On 2016年12月16日 01:10, Nicolai Hähnle wrote:
From: Nicolai Hähnle nicolai.haehnle@amd.com
Skip amdgpu_gem_va_update_vm when shadow the page directory is swapped out. Clean up the check for non-shadow BOs as well using the new helper function.
This fixes a crash with the stack trace:
amdgpu_gem_va_update_vm -> amdgpu_vm_update_page_directory -> amdgpu_ttm_bind -> amdgpu_gtt_mgr_alloc
Signed-off-by: Nicolai Hähnle nicolai.haehnle@amd.com
Reviewed-by: Chunming Zhou david1.zhou@amd.com
drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-)
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c index cd62f6f..4e1eb05 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c @@ -489,44 +489,49 @@ static int amdgpu_gem_va_check(void *param, struct amdgpu_bo *bo)
- vital here, so they are not reported back to userspace.
*/ static void amdgpu_gem_va_update_vm(struct amdgpu_device *adev, struct amdgpu_bo_va *bo_va, uint32_t operation) { struct ttm_validate_buffer tv, *entry; struct amdgpu_bo_list_entry vm_pd; struct ww_acquire_ctx ticket; struct list_head list, duplicates;
unsigned domain; int r;
INIT_LIST_HEAD(&list); 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) {
domain = amdgpu_mem_type_to_domain(entry->bo->mem.mem_type);
struct amdgpu_bo *bo =
container_of(entry->bo, struct amdgpu_bo, tbo);
- /* if anything is swapped out don't swap it in here, just abort and wait for the next CS */
if (domain == AMDGPU_GEM_DOMAIN_CPU)
if (!amdgpu_bo_gpu_accessible(bo))
goto error_unreserve;
if (bo->shadow && !amdgpu_bo_gpu_accessible(bo->shadow)) goto error_unreserve;
}
r = amdgpu_vm_validate_pt_bos(adev, bo_va->vm, amdgpu_gem_va_check, NULL); if (r) goto error_unreserve;
r = amdgpu_vm_update_page_directory(adev, bo_va->vm); if (r) goto error_unreserve;
r = amdgpu_vm_clear_freed(adev, bo_va->vm);
From: Nicolai Hähnle nicolai.haehnle@amd.com
Skip amdgpu_gem_va_update_vm otherwise. Also clean up the check for the non-shadow page tables using the new helper function.
This fixes a crash with the stack trace:
amdgpu_gem_va_update_vm -> amdgpu_vm_update_page_directory -> amdgpu_ttm_bind -> amdgpu_gtt_mgr_alloc
Signed-off-by: Nicolai Hähnle nicolai.haehnle@amd.com --- drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-)
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c index 4e1eb05..d91c80b 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c @@ -464,26 +464,29 @@ int amdgpu_gem_metadata_ioctl(struct drm_device *dev, void *data,
unreserve: amdgpu_bo_unreserve(robj); out: drm_gem_object_unreference_unlocked(gobj); return r; }
static int amdgpu_gem_va_check(void *param, struct amdgpu_bo *bo) { - unsigned domain = amdgpu_mem_type_to_domain(bo->tbo.mem.mem_type); - /* if anything is swapped out don't swap it in here, just abort and wait for the next CS */ + if (!amdgpu_bo_gpu_accessible(bo)) + return -ERESTARTSYS; + + if (bo->shadow && !amdgpu_bo_gpu_accessible(bo)) + return -ERESTARTSYS;
- return domain == AMDGPU_GEM_DOMAIN_CPU ? -ERESTARTSYS : 0; + return 0; }
/** * amdgpu_gem_va_update_vm -update the bo_va in its VM * * @adev: amdgpu_device pointer * @bo_va: bo_va to update * * Update the bo_va directly after setting it's address. Errors are not * vital here, so they are not reported back to userspace.
From: Nicolai Hähnle nicolai.haehnle@amd.com
Skip amdgpu_gem_va_update_vm otherwise. Also clean up the check for the non-shadow page tables using the new helper function.
This fixes a crash with the stack trace:
amdgpu_gem_va_update_vm -> amdgpu_vm_update_page_directory -> amdgpu_ttm_bind -> amdgpu_gtt_mgr_alloc
v2: actually check bo->shadow instead of just checking bo twice
Signed-off-by: Nicolai Hähnle nicolai.haehnle@amd.com --- drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-)
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c index 4e1eb05..9bd1b4e 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c @@ -464,26 +464,29 @@ int amdgpu_gem_metadata_ioctl(struct drm_device *dev, void *data,
unreserve: amdgpu_bo_unreserve(robj); out: drm_gem_object_unreference_unlocked(gobj); return r; }
static int amdgpu_gem_va_check(void *param, struct amdgpu_bo *bo) { - unsigned domain = amdgpu_mem_type_to_domain(bo->tbo.mem.mem_type); - /* if anything is swapped out don't swap it in here, just abort and wait for the next CS */ + if (!amdgpu_bo_gpu_accessible(bo)) + return -ERESTARTSYS; + + if (bo->shadow && !amdgpu_bo_gpu_accessible(bo->shadow)) + return -ERESTARTSYS;
- return domain == AMDGPU_GEM_DOMAIN_CPU ? -ERESTARTSYS : 0; + return 0; }
/** * amdgpu_gem_va_update_vm -update the bo_va in its VM * * @adev: amdgpu_device pointer * @bo_va: bo_va to update * * Update the bo_va directly after setting it's address. Errors are not * vital here, so they are not reported back to userspace.
On 2016年12月16日 01:59, Nicolai Hähnle wrote:
From: Nicolai Hähnle nicolai.haehnle@amd.com
Skip amdgpu_gem_va_update_vm otherwise. Also clean up the check for the non-shadow page tables using the new helper function.
This fixes a crash with the stack trace:
amdgpu_gem_va_update_vm -> amdgpu_vm_update_page_directory -> amdgpu_ttm_bind -> amdgpu_gtt_mgr_alloc
v2: actually check bo->shadow instead of just checking bo twice
Signed-off-by: Nicolai Hähnle nicolai.haehnle@amd.com
Reviewed-by: Chunming Zhou david1.zhou@amd.com
drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-)
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c index 4e1eb05..9bd1b4e 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c @@ -464,26 +464,29 @@ int amdgpu_gem_metadata_ioctl(struct drm_device *dev, void *data,
unreserve: amdgpu_bo_unreserve(robj); out: drm_gem_object_unreference_unlocked(gobj); return r; }
static int amdgpu_gem_va_check(void *param, struct amdgpu_bo *bo) {
- unsigned domain = amdgpu_mem_type_to_domain(bo->tbo.mem.mem_type);
- /* if anything is swapped out don't swap it in here, just abort and wait for the next CS */
- if (!amdgpu_bo_gpu_accessible(bo))
return -ERESTARTSYS;
- if (bo->shadow && !amdgpu_bo_gpu_accessible(bo->shadow))
return -ERESTARTSYS;
- return domain == AMDGPU_GEM_DOMAIN_CPU ? -ERESTARTSYS : 0;
return 0; }
/**
- amdgpu_gem_va_update_vm -update the bo_va in its VM
- @adev: amdgpu_device pointer
- @bo_va: bo_va to update
- Update the bo_va directly after setting it's address. Errors are not
- vital here, so they are not reported back to userspace.
On 2016年12月16日 01:10, Nicolai Hähnle wrote:
From: Nicolai Hähnle nicolai.haehnle@amd.com
Skip amdgpu_gem_va_update_vm otherwise. Also clean up the check for the non-shadow page tables using the new helper function.
This fixes a crash with the stack trace:
amdgpu_gem_va_update_vm -> amdgpu_vm_update_page_directory -> amdgpu_ttm_bind -> amdgpu_gtt_mgr_alloc
Signed-off-by: Nicolai Hähnle nicolai.haehnle@amd.com
drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-)
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c index 4e1eb05..d91c80b 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c @@ -464,26 +464,29 @@ int amdgpu_gem_metadata_ioctl(struct drm_device *dev, void *data,
unreserve: amdgpu_bo_unreserve(robj); out: drm_gem_object_unreference_unlocked(gobj); return r; }
static int amdgpu_gem_va_check(void *param, struct amdgpu_bo *bo) {
- unsigned domain = amdgpu_mem_type_to_domain(bo->tbo.mem.mem_type);
- /* if anything is swapped out don't swap it in here, just abort and wait for the next CS */
- if (!amdgpu_bo_gpu_accessible(bo))
return -ERESTARTSYS;
- if (bo->shadow && !amdgpu_bo_gpu_accessible(bo))
this should be 'if (bo->shadow && !amdgpu_bo_gpu_accessible(bo->shadow))'.
Regards, David Zhou
return -ERESTARTSYS;
- return domain == AMDGPU_GEM_DOMAIN_CPU ? -ERESTARTSYS : 0;
return 0; }
/**
- amdgpu_gem_va_update_vm -update the bo_va in its VM
- @adev: amdgpu_device pointer
- @bo_va: bo_va to update
- Update the bo_va directly after setting it's address. Errors are not
- vital here, so they are not reported back to userspace.
dri-devel@lists.freedesktop.org