Implement mmap via struct drm_gem_object_functions.mmap for amdgpu, radeon and nouveau. This allows for using common DRM helpers for the mmap-related callbacks in struct file_operations and struct drm_driver. The drivers have their own vm_ops, which are now set automatically by the DRM core functions. The code in each driver's verify_access becomes part of the driver's new mmap implementation.
With the GEM drivers converted, vmwgfx is the only user of ttm_bo_mmap() and related infrastructure. So move everything into vmwgfx and delete the rsp code from TTM.
This touches several drivers. Preferably everything would be merged at once via drm-misc-next.
Thomas Zimmermann (8): drm/ttm: Don't override vm_ops callbacks, if set drm/amdgpu: Remove unused function amdgpu_bo_fbdev_mmap() drm/amdgpu: Implement mmap as GEM object function drm/radeon: Implement mmap as GEM object function drm/nouveau: Implement mmap as GEM object function drm/vmwgfx: Inline ttm_bo_mmap() into vmwgfx driver drm/vmwgfx: Inline vmw_verify_access() drm/ttm: Remove ttm_bo_mmap() and friends
drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c | 46 ------------- drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.h | 2 - drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c | 4 +- drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c | 64 +++++++++++++++++++ drivers/gpu/drm/amd/amdgpu/amdgpu_object.c | 19 ------ drivers/gpu/drm/amd/amdgpu/amdgpu_object.h | 2 - drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | 71 --------------------- drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h | 1 - drivers/gpu/drm/nouveau/nouveau_bo.c | 10 --- drivers/gpu/drm/nouveau/nouveau_drm.c | 3 +- drivers/gpu/drm/nouveau/nouveau_gem.c | 36 +++++++++++ drivers/gpu/drm/nouveau/nouveau_ttm.c | 49 -------------- drivers/gpu/drm/nouveau/nouveau_ttm.h | 1 - drivers/gpu/drm/radeon/radeon_drv.c | 3 +- drivers/gpu/drm/radeon/radeon_gem.c | 52 +++++++++++++++ drivers/gpu/drm/radeon/radeon_ttm.c | 65 ------------------- drivers/gpu/drm/radeon/radeon_ttm.h | 1 - drivers/gpu/drm/ttm/ttm_bo_vm.c | 60 ++--------------- drivers/gpu/drm/vmwgfx/vmwgfx_ttm_buffer.c | 9 --- drivers/gpu/drm/vmwgfx/vmwgfx_ttm_glue.c | 51 ++++++++++++++- include/drm/ttm/ttm_bo_api.h | 13 ---- include/drm/ttm/ttm_device.h | 15 ----- 22 files changed, 212 insertions(+), 365 deletions(-)
-- 2.30.2
Drivers may want to set their own callbacks for a VM area. Only set TTM's callbacks if the vm_ops field is clear.
Signed-off-by: Thomas Zimmermann tzimmermann@suse.de --- drivers/gpu/drm/ttm/ttm_bo_vm.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/ttm/ttm_bo_vm.c b/drivers/gpu/drm/ttm/ttm_bo_vm.c index b31b18058965..bf4a213bc66c 100644 --- a/drivers/gpu/drm/ttm/ttm_bo_vm.c +++ b/drivers/gpu/drm/ttm/ttm_bo_vm.c @@ -534,7 +534,12 @@ static struct ttm_buffer_object *ttm_bo_vm_lookup(struct ttm_device *bdev,
static void ttm_bo_mmap_vma_setup(struct ttm_buffer_object *bo, struct vm_area_struct *vma) { - vma->vm_ops = &ttm_bo_vm_ops; + /* + * Drivers may want to override the vm_ops field. Otherwise we + * use TTM's default callbacks. + */ + if (!vma->vm_ops) + vma->vm_ops = &ttm_bo_vm_ops;
/* * Note: We're transferring the bo reference to
Remove an unused function. Mapping the fbdev framebuffer is apparently not supported.
Signed-off-by: Thomas Zimmermann tzimmermann@suse.de --- drivers/gpu/drm/amd/amdgpu/amdgpu_object.c | 19 ------------------- drivers/gpu/drm/amd/amdgpu/amdgpu_object.h | 2 -- 2 files changed, 21 deletions(-)
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c index b99e9d8736c2..cfc89164dee8 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c @@ -1092,25 +1092,6 @@ void amdgpu_bo_fini(struct amdgpu_device *adev) } }
-/** - * amdgpu_bo_fbdev_mmap - mmap fbdev memory - * @bo: &amdgpu_bo buffer object - * @vma: vma as input from the fbdev mmap method - * - * Calls ttm_fbdev_mmap() to mmap fbdev memory if it is backed by a bo. - * - * Returns: - * 0 for success or a negative error code on failure. - */ -int amdgpu_bo_fbdev_mmap(struct amdgpu_bo *bo, - struct vm_area_struct *vma) -{ - if (vma->vm_pgoff != 0) - return -EACCES; - - return ttm_bo_mmap_obj(vma, &bo->tbo); -} - /** * amdgpu_bo_set_tiling_flags - set tiling flags * @bo: &amdgpu_bo buffer object diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h index 54ceb065e546..46e94d413c5c 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h @@ -268,8 +268,6 @@ void amdgpu_bo_unpin(struct amdgpu_bo *bo); int amdgpu_bo_evict_vram(struct amdgpu_device *adev); int amdgpu_bo_init(struct amdgpu_device *adev); 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,
Am 06.04.21 um 11:08 schrieb Thomas Zimmermann:
Remove an unused function. Mapping the fbdev framebuffer is apparently not supported.
Signed-off-by: Thomas Zimmermann tzimmermann@suse.de
Reviewed-by: Christian König christian.koenig@amd.com
Should I just upstream this through our internal branches?
Thanks, Christian.
drivers/gpu/drm/amd/amdgpu/amdgpu_object.c | 19 ------------------- drivers/gpu/drm/amd/amdgpu/amdgpu_object.h | 2 -- 2 files changed, 21 deletions(-)
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c index b99e9d8736c2..cfc89164dee8 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c @@ -1092,25 +1092,6 @@ void amdgpu_bo_fini(struct amdgpu_device *adev) } }
-/**
- amdgpu_bo_fbdev_mmap - mmap fbdev memory
- @bo: &amdgpu_bo buffer object
- @vma: vma as input from the fbdev mmap method
- Calls ttm_fbdev_mmap() to mmap fbdev memory if it is backed by a bo.
- Returns:
- 0 for success or a negative error code on failure.
- */
-int amdgpu_bo_fbdev_mmap(struct amdgpu_bo *bo,
struct vm_area_struct *vma)
-{
- if (vma->vm_pgoff != 0)
return -EACCES;
- return ttm_bo_mmap_obj(vma, &bo->tbo);
-}
- /**
- amdgpu_bo_set_tiling_flags - set tiling flags
- @bo: &amdgpu_bo buffer object
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h index 54ceb065e546..46e94d413c5c 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h @@ -268,8 +268,6 @@ void amdgpu_bo_unpin(struct amdgpu_bo *bo); int amdgpu_bo_evict_vram(struct amdgpu_device *adev); int amdgpu_bo_init(struct amdgpu_device *adev); void amdgpu_bo_fini(struct amdgpu_device *adev); -int amdgpu_bo_fbdev_mmap(struct amdgpu_bo *bo,
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,struct vm_area_struct *vma);
Hi
Am 06.04.21 um 11:43 schrieb Christian König:
Am 06.04.21 um 11:08 schrieb Thomas Zimmermann:
Remove an unused function. Mapping the fbdev framebuffer is apparently not supported.
Signed-off-by: Thomas Zimmermann tzimmermann@suse.de
Reviewed-by: Christian König christian.koenig@amd.com
Should I just upstream this through our internal branches?
I guess you can pick up this patch into your branches if that's easier for you. For the other patches, I'd like to merge them via drm-misc-next.
Best regards Thomas
Thanks, Christian.
drivers/gpu/drm/amd/amdgpu/amdgpu_object.c | 19 ------------------- drivers/gpu/drm/amd/amdgpu/amdgpu_object.h | 2 -- 2 files changed, 21 deletions(-)
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c index b99e9d8736c2..cfc89164dee8 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c @@ -1092,25 +1092,6 @@ void amdgpu_bo_fini(struct amdgpu_device *adev) } } -/**
- amdgpu_bo_fbdev_mmap - mmap fbdev memory
- @bo: &amdgpu_bo buffer object
- @vma: vma as input from the fbdev mmap method
- Calls ttm_fbdev_mmap() to mmap fbdev memory if it is backed by a bo.
- Returns:
- 0 for success or a negative error code on failure.
- */
-int amdgpu_bo_fbdev_mmap(struct amdgpu_bo *bo, - struct vm_area_struct *vma) -{ - if (vma->vm_pgoff != 0) - return -EACCES;
- return ttm_bo_mmap_obj(vma, &bo->tbo); -}
/** * amdgpu_bo_set_tiling_flags - set tiling flags * @bo: &amdgpu_bo buffer object diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h index 54ceb065e546..46e94d413c5c 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h @@ -268,8 +268,6 @@ void amdgpu_bo_unpin(struct amdgpu_bo *bo); int amdgpu_bo_evict_vram(struct amdgpu_device *adev); int amdgpu_bo_init(struct amdgpu_device *adev); 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,
Moving the driver-specific mmap code into a GEM object function allows for using DRM helpers for various mmap callbacks.
This change resolves several inconsistencies between regular mmap and prime-based mmap. The vm_ops field in vma is now set for all mmap'ed areas. Previously it way only set for regular mmap calls, prime-based mmap used TTM's default vm_ops. The check for kfd_bo has been taken from amdgpu_verify_access(), which is not called any longer and has been removed.
As a side effect, amdgpu_ttm_vm_ops and amdgpu_ttm_fault() are now implemented in amdgpu's GEM code.
Signed-off-by: Thomas Zimmermann tzimmermann@suse.de --- drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c | 46 ------------- drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.h | 2 - drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c | 4 +- drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c | 64 +++++++++++++++++++ drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | 71 --------------------- drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h | 1 - 6 files changed, 66 insertions(+), 122 deletions(-)
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c index e0c4f7c7f1b9..19c5ab08d9ec 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c @@ -42,52 +42,6 @@ #include <linux/pci-p2pdma.h> #include <linux/pm_runtime.h>
-/** - * amdgpu_gem_prime_mmap - &drm_driver.gem_prime_mmap implementation - * @obj: GEM BO - * @vma: Virtual memory area - * - * Sets up a userspace mapping of the BO's memory in the given - * virtual memory area. - * - * Returns: - * 0 on success or a negative error code on failure. - */ -int amdgpu_gem_prime_mmap(struct drm_gem_object *obj, - struct vm_area_struct *vma) -{ - struct amdgpu_bo *bo = gem_to_amdgpu_bo(obj); - struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev); - unsigned asize = amdgpu_bo_size(bo); - int ret; - - if (!vma->vm_file) - return -ENODEV; - - if (adev == NULL) - return -ENODEV; - - /* Check for valid size. */ - if (asize < vma->vm_end - vma->vm_start) - return -EINVAL; - - if (amdgpu_ttm_tt_get_usermm(bo->tbo.ttm) || - (bo->flags & AMDGPU_GEM_CREATE_NO_CPU_ACCESS)) { - return -EPERM; - } - vma->vm_pgoff += amdgpu_bo_mmap_offset(bo) >> PAGE_SHIFT; - - /* prime mmap does not need to check access, so allow here */ - ret = drm_vma_node_allow(&obj->vma_node, vma->vm_file->private_data); - if (ret) - return ret; - - ret = ttm_bo_mmap(vma->vm_file, vma, &adev->mman.bdev); - drm_vma_node_revoke(&obj->vma_node, vma->vm_file->private_data); - - return ret; -} - static int __dma_resv_make_exclusive(struct dma_resv *obj) { diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.h index 39b5b9616fd8..3e93b9b407a9 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.h @@ -31,8 +31,6 @@ struct drm_gem_object *amdgpu_gem_prime_import(struct drm_device *dev, struct dma_buf *dma_buf); bool amdgpu_dmabuf_is_xgmi_accessible(struct amdgpu_device *adev, struct amdgpu_bo *bo); -int amdgpu_gem_prime_mmap(struct drm_gem_object *obj, - struct vm_area_struct *vma);
extern const struct dma_buf_ops amdgpu_dmabuf_ops;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c index 76f48f79c70b..e96d2758f4bb 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c @@ -1656,7 +1656,7 @@ static const struct file_operations amdgpu_driver_kms_fops = { .flush = amdgpu_flush, .release = drm_release, .unlocked_ioctl = amdgpu_drm_ioctl, - .mmap = amdgpu_mmap, + .mmap = drm_gem_mmap, .poll = drm_poll, .read = drm_read, #ifdef CONFIG_COMPAT @@ -1719,7 +1719,7 @@ static const struct drm_driver amdgpu_kms_driver = { .prime_handle_to_fd = drm_gem_prime_handle_to_fd, .prime_fd_to_handle = drm_gem_prime_fd_to_handle, .gem_prime_import = amdgpu_gem_prime_import, - .gem_prime_mmap = amdgpu_gem_prime_mmap, + .gem_prime_mmap = drm_gem_prime_mmap,
.name = DRIVER_NAME, .desc = DRIVER_DESC, diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c index fb7171e5507c..fe93faad05f2 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c @@ -41,6 +41,36 @@
static const struct drm_gem_object_funcs amdgpu_gem_object_funcs;
+static vm_fault_t amdgpu_ttm_fault(struct vm_fault *vmf) +{ + struct ttm_buffer_object *bo = vmf->vma->vm_private_data; + vm_fault_t ret; + + ret = ttm_bo_vm_reserve(bo, vmf); + if (ret) + return ret; + + ret = amdgpu_bo_fault_reserve_notify(bo); + if (ret) + goto unlock; + + ret = ttm_bo_vm_fault_reserved(vmf, vmf->vma->vm_page_prot, + TTM_BO_VM_NUM_PREFAULT, 1); + if (ret == VM_FAULT_RETRY && !(vmf->flags & FAULT_FLAG_RETRY_NOWAIT)) + return ret; + +unlock: + dma_resv_unlock(bo->base.resv); + return ret; +} + +static const struct vm_operations_struct amdgpu_ttm_vm_ops = { + .fault = amdgpu_ttm_fault, + .open = ttm_bo_vm_open, + .close = ttm_bo_vm_close, + .access = ttm_bo_vm_access +}; + static void amdgpu_gem_object_free(struct drm_gem_object *gobj) { struct amdgpu_bo *robj = gem_to_amdgpu_bo(gobj); @@ -201,6 +231,38 @@ static void amdgpu_gem_object_close(struct drm_gem_object *obj, ttm_eu_backoff_reservation(&ticket, &list); }
+static int amdgpu_gem_prime_mmap(struct drm_gem_object *obj, struct vm_area_struct *vma) +{ + struct amdgpu_bo *bo = gem_to_amdgpu_bo(obj); + struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev); + unsigned long asize = amdgpu_bo_size(bo); + + if (!vma->vm_file) + return -ENODEV; + + if (!adev) + return -ENODEV; + + /* Check for valid size. */ + if (asize < vma->vm_end - vma->vm_start) + return -EINVAL; + + /* + * Don't verify access for KFD BOs. They don't have a GEM + * object associated with them. + */ + if (bo->kfd_bo) + goto out; + + if (amdgpu_ttm_tt_get_usermm(bo->tbo.ttm) || + (bo->flags & AMDGPU_GEM_CREATE_NO_CPU_ACCESS)) { + return -EPERM; + } + +out: + return drm_gem_ttm_mmap(obj, vma); +} + static const struct drm_gem_object_funcs amdgpu_gem_object_funcs = { .free = amdgpu_gem_object_free, .open = amdgpu_gem_object_open, @@ -208,6 +270,8 @@ static const struct drm_gem_object_funcs amdgpu_gem_object_funcs = { .export = amdgpu_gem_prime_export, .vmap = drm_gem_ttm_vmap, .vunmap = drm_gem_ttm_vunmap, + .mmap = amdgpu_gem_prime_mmap, + .vm_ops = &amdgpu_ttm_vm_ops, };
/* diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c index 1c6131489a85..d9de91a517c6 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c @@ -152,32 +152,6 @@ static void amdgpu_evict_flags(struct ttm_buffer_object *bo, *placement = abo->placement; }
-/** - * amdgpu_verify_access - Verify access for a mmap call - * - * @bo: The buffer object to map - * @filp: The file pointer from the process performing the mmap - * - * This is called by ttm_bo_mmap() to verify whether a process - * has the right to mmap a BO to their process space. - */ -static int amdgpu_verify_access(struct ttm_buffer_object *bo, struct file *filp) -{ - struct amdgpu_bo *abo = ttm_to_amdgpu_bo(bo); - - /* - * Don't verify access for KFD BOs. They don't have a GEM - * object associated with them. - */ - if (abo->kfd_bo) - return 0; - - if (amdgpu_ttm_tt_get_usermm(bo->ttm)) - return -EPERM; - return drm_vma_node_verify_access(&abo->tbo.base.vma_node, - filp->private_data); -} - /** * amdgpu_ttm_map_buffer - Map memory into the GART windows * @bo: buffer object to map @@ -1531,7 +1505,6 @@ static struct ttm_device_funcs amdgpu_bo_driver = { .eviction_valuable = amdgpu_ttm_bo_eviction_valuable, .evict_flags = &amdgpu_evict_flags, .move = &amdgpu_bo_move, - .verify_access = &amdgpu_verify_access, .delete_mem_notify = &amdgpu_bo_delete_mem_notify, .release_notify = &amdgpu_bo_release_notify, .io_mem_reserve = &amdgpu_ttm_io_mem_reserve, @@ -1906,50 +1879,6 @@ void amdgpu_ttm_set_buffer_funcs_status(struct amdgpu_device *adev, bool enable) adev->mman.buffer_funcs_enabled = enable; }
-static vm_fault_t amdgpu_ttm_fault(struct vm_fault *vmf) -{ - struct ttm_buffer_object *bo = vmf->vma->vm_private_data; - vm_fault_t ret; - - ret = ttm_bo_vm_reserve(bo, vmf); - if (ret) - return ret; - - ret = amdgpu_bo_fault_reserve_notify(bo); - if (ret) - goto unlock; - - ret = ttm_bo_vm_fault_reserved(vmf, vmf->vma->vm_page_prot, - TTM_BO_VM_NUM_PREFAULT, 1); - if (ret == VM_FAULT_RETRY && !(vmf->flags & FAULT_FLAG_RETRY_NOWAIT)) - return ret; - -unlock: - dma_resv_unlock(bo->base.resv); - return ret; -} - -static const struct vm_operations_struct amdgpu_ttm_vm_ops = { - .fault = amdgpu_ttm_fault, - .open = ttm_bo_vm_open, - .close = ttm_bo_vm_close, - .access = ttm_bo_vm_access -}; - -int amdgpu_mmap(struct file *filp, struct vm_area_struct *vma) -{ - struct drm_file *file_priv = filp->private_data; - struct amdgpu_device *adev = drm_to_adev(file_priv->minor->dev); - int r; - - r = ttm_bo_mmap(filp, vma, &adev->mman.bdev); - if (unlikely(r != 0)) - return r; - - vma->vm_ops = &amdgpu_ttm_vm_ops; - return 0; -} - int amdgpu_copy_buffer(struct amdgpu_ring *ring, uint64_t src_offset, uint64_t dst_offset, uint32_t byte_count, struct dma_resv *resv, diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h index dec0db8b0b13..6e51faad7371 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h @@ -146,7 +146,6 @@ int amdgpu_fill_buffer(struct amdgpu_bo *bo, struct dma_resv *resv, struct dma_fence **fence);
-int amdgpu_mmap(struct file *filp, struct vm_area_struct *vma); int amdgpu_ttm_alloc_gart(struct ttm_buffer_object *bo); int amdgpu_ttm_recover_gart(struct ttm_buffer_object *tbo); uint64_t amdgpu_ttm_domain_start(struct amdgpu_device *adev, uint32_t type);
Am 06.04.21 um 11:08 schrieb Thomas Zimmermann:
Moving the driver-specific mmap code into a GEM object function allows for using DRM helpers for various mmap callbacks.
This change resolves several inconsistencies between regular mmap and prime-based mmap. The vm_ops field in vma is now set for all mmap'ed areas. Previously it way only set for regular mmap calls, prime-based mmap used TTM's default vm_ops. The check for kfd_bo has been taken from amdgpu_verify_access(), which is not called any longer and has been removed.
As a side effect, amdgpu_ttm_vm_ops and amdgpu_ttm_fault() are now implemented in amdgpu's GEM code.
Signed-off-by: Thomas Zimmermann tzimmermann@suse.de
drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c | 46 ------------- drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.h | 2 - drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c | 4 +- drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c | 64 +++++++++++++++++++ drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | 71 --------------------- drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h | 1 - 6 files changed, 66 insertions(+), 122 deletions(-)
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c index e0c4f7c7f1b9..19c5ab08d9ec 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c @@ -42,52 +42,6 @@ #include <linux/pci-p2pdma.h> #include <linux/pm_runtime.h>
-/**
- amdgpu_gem_prime_mmap - &drm_driver.gem_prime_mmap implementation
- @obj: GEM BO
- @vma: Virtual memory area
- Sets up a userspace mapping of the BO's memory in the given
- virtual memory area.
- Returns:
- 0 on success or a negative error code on failure.
- */
-int amdgpu_gem_prime_mmap(struct drm_gem_object *obj,
struct vm_area_struct *vma)
-{
- struct amdgpu_bo *bo = gem_to_amdgpu_bo(obj);
- struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev);
- unsigned asize = amdgpu_bo_size(bo);
- int ret;
- if (!vma->vm_file)
return -ENODEV;
- if (adev == NULL)
return -ENODEV;
- /* Check for valid size. */
- if (asize < vma->vm_end - vma->vm_start)
return -EINVAL;
- if (amdgpu_ttm_tt_get_usermm(bo->tbo.ttm) ||
(bo->flags & AMDGPU_GEM_CREATE_NO_CPU_ACCESS)) {
return -EPERM;
- }
- vma->vm_pgoff += amdgpu_bo_mmap_offset(bo) >> PAGE_SHIFT;
- /* prime mmap does not need to check access, so allow here */
- ret = drm_vma_node_allow(&obj->vma_node, vma->vm_file->private_data);
- if (ret)
return ret;
- ret = ttm_bo_mmap(vma->vm_file, vma, &adev->mman.bdev);
- drm_vma_node_revoke(&obj->vma_node, vma->vm_file->private_data);
- return ret;
-}
- static int __dma_resv_make_exclusive(struct dma_resv *obj) {
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.h index 39b5b9616fd8..3e93b9b407a9 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.h @@ -31,8 +31,6 @@ struct drm_gem_object *amdgpu_gem_prime_import(struct drm_device *dev, struct dma_buf *dma_buf); bool amdgpu_dmabuf_is_xgmi_accessible(struct amdgpu_device *adev, struct amdgpu_bo *bo); -int amdgpu_gem_prime_mmap(struct drm_gem_object *obj,
struct vm_area_struct *vma);
extern const struct dma_buf_ops amdgpu_dmabuf_ops;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c index 76f48f79c70b..e96d2758f4bb 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c @@ -1656,7 +1656,7 @@ static const struct file_operations amdgpu_driver_kms_fops = { .flush = amdgpu_flush, .release = drm_release, .unlocked_ioctl = amdgpu_drm_ioctl,
- .mmap = amdgpu_mmap,
- .mmap = drm_gem_mmap, .poll = drm_poll, .read = drm_read, #ifdef CONFIG_COMPAT
@@ -1719,7 +1719,7 @@ static const struct drm_driver amdgpu_kms_driver = { .prime_handle_to_fd = drm_gem_prime_handle_to_fd, .prime_fd_to_handle = drm_gem_prime_fd_to_handle, .gem_prime_import = amdgpu_gem_prime_import,
- .gem_prime_mmap = amdgpu_gem_prime_mmap,
.gem_prime_mmap = drm_gem_prime_mmap,
.name = DRIVER_NAME, .desc = DRIVER_DESC,
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c index fb7171e5507c..fe93faad05f2 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c @@ -41,6 +41,36 @@
static const struct drm_gem_object_funcs amdgpu_gem_object_funcs;
+static vm_fault_t amdgpu_ttm_fault(struct vm_fault *vmf)
Please name that function amdgpu_gem_fault or amdgpu_gem_object_fault
+{
- struct ttm_buffer_object *bo = vmf->vma->vm_private_data;
- vm_fault_t ret;
- ret = ttm_bo_vm_reserve(bo, vmf);
- if (ret)
return ret;
- ret = amdgpu_bo_fault_reserve_notify(bo);
- if (ret)
goto unlock;
- ret = ttm_bo_vm_fault_reserved(vmf, vmf->vma->vm_page_prot,
TTM_BO_VM_NUM_PREFAULT, 1);
- if (ret == VM_FAULT_RETRY && !(vmf->flags & FAULT_FLAG_RETRY_NOWAIT))
return ret;
+unlock:
- dma_resv_unlock(bo->base.resv);
- return ret;
+}
+static const struct vm_operations_struct amdgpu_ttm_vm_ops = {
- .fault = amdgpu_ttm_fault,
- .open = ttm_bo_vm_open,
- .close = ttm_bo_vm_close,
- .access = ttm_bo_vm_access
+};
- static void amdgpu_gem_object_free(struct drm_gem_object *gobj) { struct amdgpu_bo *robj = gem_to_amdgpu_bo(gobj);
@@ -201,6 +231,38 @@ static void amdgpu_gem_object_close(struct drm_gem_object *obj, ttm_eu_backoff_reservation(&ticket, &list); }
+static int amdgpu_gem_prime_mmap(struct drm_gem_object *obj, struct vm_area_struct *vma) +{
- struct amdgpu_bo *bo = gem_to_amdgpu_bo(obj);
- struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev);
- unsigned long asize = amdgpu_bo_size(bo);
- if (!vma->vm_file)
return -ENODEV;
- if (!adev)
return -ENODEV;
- /* Check for valid size. */
- if (asize < vma->vm_end - vma->vm_start)
return -EINVAL;
- /*
* Don't verify access for KFD BOs. They don't have a GEM
* object associated with them.
*/
- if (bo->kfd_bo)
goto out;
Who does the access verification now?
Christian.
- if (amdgpu_ttm_tt_get_usermm(bo->tbo.ttm) ||
(bo->flags & AMDGPU_GEM_CREATE_NO_CPU_ACCESS)) {
return -EPERM;
- }
+out:
- return drm_gem_ttm_mmap(obj, vma);
+}
- static const struct drm_gem_object_funcs amdgpu_gem_object_funcs = { .free = amdgpu_gem_object_free, .open = amdgpu_gem_object_open,
@@ -208,6 +270,8 @@ static const struct drm_gem_object_funcs amdgpu_gem_object_funcs = { .export = amdgpu_gem_prime_export, .vmap = drm_gem_ttm_vmap, .vunmap = drm_gem_ttm_vunmap,
.mmap = amdgpu_gem_prime_mmap,
.vm_ops = &amdgpu_ttm_vm_ops, };
/*
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c index 1c6131489a85..d9de91a517c6 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c @@ -152,32 +152,6 @@ static void amdgpu_evict_flags(struct ttm_buffer_object *bo, *placement = abo->placement; }
-/**
- amdgpu_verify_access - Verify access for a mmap call
- @bo: The buffer object to map
- @filp: The file pointer from the process performing the mmap
- This is called by ttm_bo_mmap() to verify whether a process
- has the right to mmap a BO to their process space.
- */
-static int amdgpu_verify_access(struct ttm_buffer_object *bo, struct file *filp) -{
- struct amdgpu_bo *abo = ttm_to_amdgpu_bo(bo);
- /*
* Don't verify access for KFD BOs. They don't have a GEM
* object associated with them.
*/
- if (abo->kfd_bo)
return 0;
- if (amdgpu_ttm_tt_get_usermm(bo->ttm))
return -EPERM;
- return drm_vma_node_verify_access(&abo->tbo.base.vma_node,
filp->private_data);
-}
- /**
- amdgpu_ttm_map_buffer - Map memory into the GART windows
- @bo: buffer object to map
@@ -1531,7 +1505,6 @@ static struct ttm_device_funcs amdgpu_bo_driver = { .eviction_valuable = amdgpu_ttm_bo_eviction_valuable, .evict_flags = &amdgpu_evict_flags, .move = &amdgpu_bo_move,
- .verify_access = &amdgpu_verify_access, .delete_mem_notify = &amdgpu_bo_delete_mem_notify, .release_notify = &amdgpu_bo_release_notify, .io_mem_reserve = &amdgpu_ttm_io_mem_reserve,
@@ -1906,50 +1879,6 @@ void amdgpu_ttm_set_buffer_funcs_status(struct amdgpu_device *adev, bool enable) adev->mman.buffer_funcs_enabled = enable; }
-static vm_fault_t amdgpu_ttm_fault(struct vm_fault *vmf) -{
- struct ttm_buffer_object *bo = vmf->vma->vm_private_data;
- vm_fault_t ret;
- ret = ttm_bo_vm_reserve(bo, vmf);
- if (ret)
return ret;
- ret = amdgpu_bo_fault_reserve_notify(bo);
- if (ret)
goto unlock;
- ret = ttm_bo_vm_fault_reserved(vmf, vmf->vma->vm_page_prot,
TTM_BO_VM_NUM_PREFAULT, 1);
- if (ret == VM_FAULT_RETRY && !(vmf->flags & FAULT_FLAG_RETRY_NOWAIT))
return ret;
-unlock:
- dma_resv_unlock(bo->base.resv);
- return ret;
-}
-static const struct vm_operations_struct amdgpu_ttm_vm_ops = {
- .fault = amdgpu_ttm_fault,
- .open = ttm_bo_vm_open,
- .close = ttm_bo_vm_close,
- .access = ttm_bo_vm_access
-};
-int amdgpu_mmap(struct file *filp, struct vm_area_struct *vma) -{
- struct drm_file *file_priv = filp->private_data;
- struct amdgpu_device *adev = drm_to_adev(file_priv->minor->dev);
- int r;
- r = ttm_bo_mmap(filp, vma, &adev->mman.bdev);
- if (unlikely(r != 0))
return r;
- vma->vm_ops = &amdgpu_ttm_vm_ops;
- return 0;
-}
- int amdgpu_copy_buffer(struct amdgpu_ring *ring, uint64_t src_offset, uint64_t dst_offset, uint32_t byte_count, struct dma_resv *resv,
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h index dec0db8b0b13..6e51faad7371 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h @@ -146,7 +146,6 @@ int amdgpu_fill_buffer(struct amdgpu_bo *bo, struct dma_resv *resv, struct dma_fence **fence);
-int amdgpu_mmap(struct file *filp, struct vm_area_struct *vma); int amdgpu_ttm_alloc_gart(struct ttm_buffer_object *bo); int amdgpu_ttm_recover_gart(struct ttm_buffer_object *tbo); uint64_t amdgpu_ttm_domain_start(struct amdgpu_device *adev, uint32_t type);
Hi
Am 06.04.21 um 11:35 schrieb Christian König:
Am 06.04.21 um 11:08 schrieb Thomas Zimmermann:
Moving the driver-specific mmap code into a GEM object function allows for using DRM helpers for various mmap callbacks.
This change resolves several inconsistencies between regular mmap and prime-based mmap. The vm_ops field in vma is now set for all mmap'ed areas. Previously it way only set for regular mmap calls, prime-based mmap used TTM's default vm_ops. The check for kfd_bo has been taken from amdgpu_verify_access(), which is not called any longer and has been removed.
As a side effect, amdgpu_ttm_vm_ops and amdgpu_ttm_fault() are now implemented in amdgpu's GEM code.
Signed-off-by: Thomas Zimmermann tzimmermann@suse.de
drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c | 46 ------------- drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.h | 2 - drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c | 4 +- drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c | 64 +++++++++++++++++++ drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | 71 --------------------- drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h | 1 - 6 files changed, 66 insertions(+), 122 deletions(-)
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c index e0c4f7c7f1b9..19c5ab08d9ec 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c @@ -42,52 +42,6 @@ #include <linux/pci-p2pdma.h> #include <linux/pm_runtime.h> -/**
- amdgpu_gem_prime_mmap - &drm_driver.gem_prime_mmap implementation
- @obj: GEM BO
- @vma: Virtual memory area
- Sets up a userspace mapping of the BO's memory in the given
- virtual memory area.
- Returns:
- 0 on success or a negative error code on failure.
- */
-int amdgpu_gem_prime_mmap(struct drm_gem_object *obj, - struct vm_area_struct *vma) -{ - struct amdgpu_bo *bo = gem_to_amdgpu_bo(obj); - struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev); - unsigned asize = amdgpu_bo_size(bo); - int ret;
- if (!vma->vm_file) - return -ENODEV;
- if (adev == NULL) - return -ENODEV;
- /* Check for valid size. */ - if (asize < vma->vm_end - vma->vm_start) - return -EINVAL;
- if (amdgpu_ttm_tt_get_usermm(bo->tbo.ttm) || - (bo->flags & AMDGPU_GEM_CREATE_NO_CPU_ACCESS)) { - return -EPERM; - } - vma->vm_pgoff += amdgpu_bo_mmap_offset(bo) >> PAGE_SHIFT;
- /* prime mmap does not need to check access, so allow here */ - ret = drm_vma_node_allow(&obj->vma_node, vma->vm_file->private_data); - if (ret) - return ret;
- ret = ttm_bo_mmap(vma->vm_file, vma, &adev->mman.bdev); - drm_vma_node_revoke(&obj->vma_node, vma->vm_file->private_data);
- return ret; -}
static int __dma_resv_make_exclusive(struct dma_resv *obj) { diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.h index 39b5b9616fd8..3e93b9b407a9 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.h @@ -31,8 +31,6 @@ struct drm_gem_object *amdgpu_gem_prime_import(struct drm_device *dev, struct dma_buf *dma_buf); bool amdgpu_dmabuf_is_xgmi_accessible(struct amdgpu_device *adev, struct amdgpu_bo *bo); -int amdgpu_gem_prime_mmap(struct drm_gem_object *obj, - struct vm_area_struct *vma); extern const struct dma_buf_ops amdgpu_dmabuf_ops; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c index 76f48f79c70b..e96d2758f4bb 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c @@ -1656,7 +1656,7 @@ static const struct file_operations amdgpu_driver_kms_fops = { .flush = amdgpu_flush, .release = drm_release, .unlocked_ioctl = amdgpu_drm_ioctl, - .mmap = amdgpu_mmap, + .mmap = drm_gem_mmap, .poll = drm_poll, .read = drm_read, #ifdef CONFIG_COMPAT @@ -1719,7 +1719,7 @@ static const struct drm_driver amdgpu_kms_driver = { .prime_handle_to_fd = drm_gem_prime_handle_to_fd, .prime_fd_to_handle = drm_gem_prime_fd_to_handle, .gem_prime_import = amdgpu_gem_prime_import, - .gem_prime_mmap = amdgpu_gem_prime_mmap, + .gem_prime_mmap = drm_gem_prime_mmap, .name = DRIVER_NAME, .desc = DRIVER_DESC, diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c index fb7171e5507c..fe93faad05f2 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c @@ -41,6 +41,36 @@ static const struct drm_gem_object_funcs amdgpu_gem_object_funcs; +static vm_fault_t amdgpu_ttm_fault(struct vm_fault *vmf)
Please name that function amdgpu_gem_fault or amdgpu_gem_object_fault
+{ + struct ttm_buffer_object *bo = vmf->vma->vm_private_data; + vm_fault_t ret;
+ ret = ttm_bo_vm_reserve(bo, vmf); + if (ret) + return ret;
+ ret = amdgpu_bo_fault_reserve_notify(bo); + if (ret) + goto unlock;
+ ret = ttm_bo_vm_fault_reserved(vmf, vmf->vma->vm_page_prot, + TTM_BO_VM_NUM_PREFAULT, 1); + if (ret == VM_FAULT_RETRY && !(vmf->flags & FAULT_FLAG_RETRY_NOWAIT)) + return ret;
+unlock: + dma_resv_unlock(bo->base.resv); + return ret; +}
+static const struct vm_operations_struct amdgpu_ttm_vm_ops = { + .fault = amdgpu_ttm_fault, + .open = ttm_bo_vm_open, + .close = ttm_bo_vm_close, + .access = ttm_bo_vm_access +};
static void amdgpu_gem_object_free(struct drm_gem_object *gobj) { struct amdgpu_bo *robj = gem_to_amdgpu_bo(gobj); @@ -201,6 +231,38 @@ static void amdgpu_gem_object_close(struct drm_gem_object *obj, ttm_eu_backoff_reservation(&ticket, &list); } +static int amdgpu_gem_prime_mmap(struct drm_gem_object *obj, struct vm_area_struct *vma) +{ + struct amdgpu_bo *bo = gem_to_amdgpu_bo(obj); + struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev); + unsigned long asize = amdgpu_bo_size(bo);
+ if (!vma->vm_file) + return -ENODEV;
+ if (!adev) + return -ENODEV;
+ /* Check for valid size. */ + if (asize < vma->vm_end - vma->vm_start) + return -EINVAL;
+ /* + * Don't verify access for KFD BOs. They don't have a GEM + * object associated with them. + */ + if (bo->kfd_bo) + goto out;
Who does the access verification now?
This is somewhat confusing.
I took this check as-is, including the comment, from amdgpu's verify_access function. The verify_access function was called by ttm_bo_mmap. It returned 0 and ttm_bo_mmap did the mapping.
Christian.
+ if (amdgpu_ttm_tt_get_usermm(bo->tbo.ttm) || + (bo->flags & AMDGPU_GEM_CREATE_NO_CPU_ACCESS)) { + return -EPERM; + }
+out: + return drm_gem_ttm_mmap(obj, vma); +}
static const struct drm_gem_object_funcs amdgpu_gem_object_funcs = { .free = amdgpu_gem_object_free, .open = amdgpu_gem_object_open, @@ -208,6 +270,8 @@ static const struct drm_gem_object_funcs amdgpu_gem_object_funcs = { .export = amdgpu_gem_prime_export, .vmap = drm_gem_ttm_vmap, .vunmap = drm_gem_ttm_vunmap, + .mmap = amdgpu_gem_prime_mmap, + .vm_ops = &amdgpu_ttm_vm_ops, }; /* diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c index 1c6131489a85..d9de91a517c6 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c @@ -152,32 +152,6 @@ static void amdgpu_evict_flags(struct ttm_buffer_object *bo, *placement = abo->placement; } -/**
- amdgpu_verify_access - Verify access for a mmap call
- @bo: The buffer object to map
- @filp: The file pointer from the process performing the mmap
- This is called by ttm_bo_mmap() to verify whether a process
- has the right to mmap a BO to their process space.
- */
-static int amdgpu_verify_access(struct ttm_buffer_object *bo, struct file *filp) -{ - struct amdgpu_bo *abo = ttm_to_amdgpu_bo(bo);
- /* - * Don't verify access for KFD BOs. They don't have a GEM - * object associated with them. - */ - if (abo->kfd_bo) - return 0;
- if (amdgpu_ttm_tt_get_usermm(bo->ttm)) - return -EPERM; - return drm_vma_node_verify_access(&abo->tbo.base.vma_node, - filp->private_data); -}
Here's the orignal verification code. It gives a free pass to KFD.
/** * amdgpu_ttm_map_buffer - Map memory into the GART windows * @bo: buffer object to map @@ -1531,7 +1505,6 @@ static struct ttm_device_funcs amdgpu_bo_driver = { .eviction_valuable = amdgpu_ttm_bo_eviction_valuable, .evict_flags = &amdgpu_evict_flags, .move = &amdgpu_bo_move, - .verify_access = &amdgpu_verify_access, .delete_mem_notify = &amdgpu_bo_delete_mem_notify, .release_notify = &amdgpu_bo_release_notify, .io_mem_reserve = &amdgpu_ttm_io_mem_reserve, @@ -1906,50 +1879,6 @@ void amdgpu_ttm_set_buffer_funcs_status(struct amdgpu_device *adev, bool enable) adev->mman.buffer_funcs_enabled = enable; } -static vm_fault_t amdgpu_ttm_fault(struct vm_fault *vmf) -{ - struct ttm_buffer_object *bo = vmf->vma->vm_private_data; - vm_fault_t ret;
- ret = ttm_bo_vm_reserve(bo, vmf); - if (ret) - return ret;
- ret = amdgpu_bo_fault_reserve_notify(bo); - if (ret) - goto unlock;
- ret = ttm_bo_vm_fault_reserved(vmf, vmf->vma->vm_page_prot, - TTM_BO_VM_NUM_PREFAULT, 1); - if (ret == VM_FAULT_RETRY && !(vmf->flags & FAULT_FLAG_RETRY_NOWAIT)) - return ret;
-unlock: - dma_resv_unlock(bo->base.resv); - return ret; -}
-static const struct vm_operations_struct amdgpu_ttm_vm_ops = { - .fault = amdgpu_ttm_fault, - .open = ttm_bo_vm_open, - .close = ttm_bo_vm_close, - .access = ttm_bo_vm_access -};
-int amdgpu_mmap(struct file *filp, struct vm_area_struct *vma) -{ - struct drm_file *file_priv = filp->private_data; - struct amdgpu_device *adev = drm_to_adev(file_priv->minor->dev); - int r;
- r = ttm_bo_mmap(filp, vma, &adev->mman.bdev); - if (unlikely(r != 0)) - return r;
- vma->vm_ops = &amdgpu_ttm_vm_ops; - return 0; -}
And this was the mmap callback in struct file_operations. It calls ttm_bo_mmap(), which skips verification for KFD BOs. To the best of my knowledge, there was no additional verification for these KFD BOs.
The original code in amdgpu_gem_prime_mmap() did seom verification, but didn't handle KFD specially. I guess, PRIME needs GEM and KFD BOs wouldn't quailify.
In the end I went with the semantics I found in amdgpu_mmap() and handled KFD specially. Let me know if this requires to be changed.
Best regards Thomas
int amdgpu_copy_buffer(struct amdgpu_ring *ring, uint64_t src_offset, uint64_t dst_offset, uint32_t byte_count, struct dma_resv *resv, diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h index dec0db8b0b13..6e51faad7371 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h @@ -146,7 +146,6 @@ int amdgpu_fill_buffer(struct amdgpu_bo *bo, struct dma_resv *resv, struct dma_fence **fence); -int amdgpu_mmap(struct file *filp, struct vm_area_struct *vma); int amdgpu_ttm_alloc_gart(struct ttm_buffer_object *bo); int amdgpu_ttm_recover_gart(struct ttm_buffer_object *tbo); uint64_t amdgpu_ttm_domain_start(struct amdgpu_device *adev, uint32_t type);
dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Hi Thomas,
Am 06.04.21 um 12:38 schrieb Thomas Zimmermann:
Hi
Am 06.04.21 um 11:35 schrieb Christian König:
Am 06.04.21 um 11:08 schrieb Thomas Zimmermann:
Moving the driver-specific mmap code into a GEM object function allows for using DRM helpers for various mmap callbacks.
This change resolves several inconsistencies between regular mmap and prime-based mmap. The vm_ops field in vma is now set for all mmap'ed areas. Previously it way only set for regular mmap calls, prime-based mmap used TTM's default vm_ops. The check for kfd_bo has been taken from amdgpu_verify_access(), which is not called any longer and has been removed.
As a side effect, amdgpu_ttm_vm_ops and amdgpu_ttm_fault() are now implemented in amdgpu's GEM code.
Signed-off-by: Thomas Zimmermann tzimmermann@suse.de
drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c | 46 ------------- drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.h | 2 - drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c | 4 +- drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c | 64 +++++++++++++++++++ drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | 71
drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h | 1 - 6 files changed, 66 insertions(+), 122 deletions(-)
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c index e0c4f7c7f1b9..19c5ab08d9ec 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c @@ -42,52 +42,6 @@ #include <linux/pci-p2pdma.h> #include <linux/pm_runtime.h> -/**
- amdgpu_gem_prime_mmap - &drm_driver.gem_prime_mmap implementation
- @obj: GEM BO
- @vma: Virtual memory area
- Sets up a userspace mapping of the BO's memory in the given
- virtual memory area.
- Returns:
- 0 on success or a negative error code on failure.
- */
-int amdgpu_gem_prime_mmap(struct drm_gem_object *obj, - struct vm_area_struct *vma) -{ - struct amdgpu_bo *bo = gem_to_amdgpu_bo(obj); - struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev); - unsigned asize = amdgpu_bo_size(bo); - int ret;
- if (!vma->vm_file) - return -ENODEV;
- if (adev == NULL) - return -ENODEV;
- /* Check for valid size. */ - if (asize < vma->vm_end - vma->vm_start) - return -EINVAL;
- if (amdgpu_ttm_tt_get_usermm(bo->tbo.ttm) || - (bo->flags & AMDGPU_GEM_CREATE_NO_CPU_ACCESS)) { - return -EPERM; - } - vma->vm_pgoff += amdgpu_bo_mmap_offset(bo) >> PAGE_SHIFT;
- /* prime mmap does not need to check access, so allow here */ - ret = drm_vma_node_allow(&obj->vma_node, vma->vm_file->private_data); - if (ret) - return ret;
- ret = ttm_bo_mmap(vma->vm_file, vma, &adev->mman.bdev); - drm_vma_node_revoke(&obj->vma_node, vma->vm_file->private_data);
- return ret; -}
static int __dma_resv_make_exclusive(struct dma_resv *obj) { diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.h index 39b5b9616fd8..3e93b9b407a9 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.h @@ -31,8 +31,6 @@ struct drm_gem_object *amdgpu_gem_prime_import(struct drm_device *dev, struct dma_buf *dma_buf); bool amdgpu_dmabuf_is_xgmi_accessible(struct amdgpu_device *adev, struct amdgpu_bo *bo); -int amdgpu_gem_prime_mmap(struct drm_gem_object *obj, - struct vm_area_struct *vma); extern const struct dma_buf_ops amdgpu_dmabuf_ops; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c index 76f48f79c70b..e96d2758f4bb 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c @@ -1656,7 +1656,7 @@ static const struct file_operations amdgpu_driver_kms_fops = { .flush = amdgpu_flush, .release = drm_release, .unlocked_ioctl = amdgpu_drm_ioctl, - .mmap = amdgpu_mmap, + .mmap = drm_gem_mmap, .poll = drm_poll, .read = drm_read, #ifdef CONFIG_COMPAT @@ -1719,7 +1719,7 @@ static const struct drm_driver amdgpu_kms_driver = { .prime_handle_to_fd = drm_gem_prime_handle_to_fd, .prime_fd_to_handle = drm_gem_prime_fd_to_handle, .gem_prime_import = amdgpu_gem_prime_import, - .gem_prime_mmap = amdgpu_gem_prime_mmap, + .gem_prime_mmap = drm_gem_prime_mmap, .name = DRIVER_NAME, .desc = DRIVER_DESC, diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c index fb7171e5507c..fe93faad05f2 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c @@ -41,6 +41,36 @@ static const struct drm_gem_object_funcs amdgpu_gem_object_funcs; +static vm_fault_t amdgpu_ttm_fault(struct vm_fault *vmf)
Please name that function amdgpu_gem_fault or amdgpu_gem_object_fault
+{ + struct ttm_buffer_object *bo = vmf->vma->vm_private_data; + vm_fault_t ret;
+ ret = ttm_bo_vm_reserve(bo, vmf); + if (ret) + return ret;
+ ret = amdgpu_bo_fault_reserve_notify(bo); + if (ret) + goto unlock;
+ ret = ttm_bo_vm_fault_reserved(vmf, vmf->vma->vm_page_prot, + TTM_BO_VM_NUM_PREFAULT, 1); + if (ret == VM_FAULT_RETRY && !(vmf->flags & FAULT_FLAG_RETRY_NOWAIT)) + return ret;
+unlock: + dma_resv_unlock(bo->base.resv); + return ret; +}
+static const struct vm_operations_struct amdgpu_ttm_vm_ops = { + .fault = amdgpu_ttm_fault, + .open = ttm_bo_vm_open, + .close = ttm_bo_vm_close, + .access = ttm_bo_vm_access +};
static void amdgpu_gem_object_free(struct drm_gem_object *gobj) { struct amdgpu_bo *robj = gem_to_amdgpu_bo(gobj); @@ -201,6 +231,38 @@ static void amdgpu_gem_object_close(struct drm_gem_object *obj, ttm_eu_backoff_reservation(&ticket, &list); } +static int amdgpu_gem_prime_mmap(struct drm_gem_object *obj, struct vm_area_struct *vma) +{ + struct amdgpu_bo *bo = gem_to_amdgpu_bo(obj); + struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev); + unsigned long asize = amdgpu_bo_size(bo);
+ if (!vma->vm_file) + return -ENODEV;
+ if (!adev) + return -ENODEV;
+ /* Check for valid size. */ + if (asize < vma->vm_end - vma->vm_start) + return -EINVAL;
+ /* + * Don't verify access for KFD BOs. They don't have a GEM + * object associated with them. + */ + if (bo->kfd_bo) + goto out;
Who does the access verification now?
This is somewhat confusing.
I took this check as-is, including the comment, from amdgpu's verify_access function. The verify_access function was called by ttm_bo_mmap. It returned 0 and ttm_bo_mmap did the mapping.
Christian.
+ if (amdgpu_ttm_tt_get_usermm(bo->tbo.ttm) || + (bo->flags & AMDGPU_GEM_CREATE_NO_CPU_ACCESS)) { + return -EPERM; + }
+out: + return drm_gem_ttm_mmap(obj, vma); +}
static const struct drm_gem_object_funcs amdgpu_gem_object_funcs = { .free = amdgpu_gem_object_free, .open = amdgpu_gem_object_open, @@ -208,6 +270,8 @@ static const struct drm_gem_object_funcs amdgpu_gem_object_funcs = { .export = amdgpu_gem_prime_export, .vmap = drm_gem_ttm_vmap, .vunmap = drm_gem_ttm_vunmap, + .mmap = amdgpu_gem_prime_mmap, + .vm_ops = &amdgpu_ttm_vm_ops, }; /* diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c index 1c6131489a85..d9de91a517c6 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c @@ -152,32 +152,6 @@ static void amdgpu_evict_flags(struct ttm_buffer_object *bo, *placement = abo->placement; } -/**
- amdgpu_verify_access - Verify access for a mmap call
- @bo: The buffer object to map
- @filp: The file pointer from the process performing the mmap
- This is called by ttm_bo_mmap() to verify whether a process
- has the right to mmap a BO to their process space.
- */
-static int amdgpu_verify_access(struct ttm_buffer_object *bo, struct file *filp) -{ - struct amdgpu_bo *abo = ttm_to_amdgpu_bo(bo);
- /* - * Don't verify access for KFD BOs. They don't have a GEM - * object associated with them. - */ - if (abo->kfd_bo) - return 0;
- if (amdgpu_ttm_tt_get_usermm(bo->ttm)) - return -EPERM; - return drm_vma_node_verify_access(&abo->tbo.base.vma_node, - filp->private_data); -}
Here's the orignal verification code. It gives a free pass to KFD.
/** * amdgpu_ttm_map_buffer - Map memory into the GART windows * @bo: buffer object to map @@ -1531,7 +1505,6 @@ static struct ttm_device_funcs amdgpu_bo_driver = { .eviction_valuable = amdgpu_ttm_bo_eviction_valuable, .evict_flags = &amdgpu_evict_flags, .move = &amdgpu_bo_move, - .verify_access = &amdgpu_verify_access, .delete_mem_notify = &amdgpu_bo_delete_mem_notify, .release_notify = &amdgpu_bo_release_notify, .io_mem_reserve = &amdgpu_ttm_io_mem_reserve, @@ -1906,50 +1879,6 @@ void amdgpu_ttm_set_buffer_funcs_status(struct amdgpu_device *adev, bool enable) adev->mman.buffer_funcs_enabled = enable; } -static vm_fault_t amdgpu_ttm_fault(struct vm_fault *vmf) -{ - struct ttm_buffer_object *bo = vmf->vma->vm_private_data; - vm_fault_t ret;
- ret = ttm_bo_vm_reserve(bo, vmf); - if (ret) - return ret;
- ret = amdgpu_bo_fault_reserve_notify(bo); - if (ret) - goto unlock;
- ret = ttm_bo_vm_fault_reserved(vmf, vmf->vma->vm_page_prot, - TTM_BO_VM_NUM_PREFAULT, 1); - if (ret == VM_FAULT_RETRY && !(vmf->flags & FAULT_FLAG_RETRY_NOWAIT)) - return ret;
-unlock: - dma_resv_unlock(bo->base.resv); - return ret; -}
-static const struct vm_operations_struct amdgpu_ttm_vm_ops = { - .fault = amdgpu_ttm_fault, - .open = ttm_bo_vm_open, - .close = ttm_bo_vm_close, - .access = ttm_bo_vm_access -};
-int amdgpu_mmap(struct file *filp, struct vm_area_struct *vma) -{ - struct drm_file *file_priv = filp->private_data; - struct amdgpu_device *adev = drm_to_adev(file_priv->minor->dev); - int r;
- r = ttm_bo_mmap(filp, vma, &adev->mman.bdev); - if (unlikely(r != 0)) - return r;
- vma->vm_ops = &amdgpu_ttm_vm_ops; - return 0; -}
And this was the mmap callback in struct file_operations. It calls ttm_bo_mmap(), which skips verification for KFD BOs. To the best of my knowledge, there was no additional verification for these KFD BOs.
The original code in amdgpu_gem_prime_mmap() did seom verification, but didn't handle KFD specially. I guess, PRIME needs GEM and KFD BOs wouldn't quailify.
In the end I went with the semantics I found in amdgpu_mmap() and handled KFD specially. Let me know if this requires to be changed.
Well the question is where is the call to drm_vma_node_verify_access() now? Cause that needs to be skipped for KFD BOs.
Regards, Christian.
Best regards Thomas
int amdgpu_copy_buffer(struct amdgpu_ring *ring, uint64_t src_offset, uint64_t dst_offset, uint32_t byte_count, struct dma_resv *resv, diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h index dec0db8b0b13..6e51faad7371 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h @@ -146,7 +146,6 @@ int amdgpu_fill_buffer(struct amdgpu_bo *bo, struct dma_resv *resv, struct dma_fence **fence); -int amdgpu_mmap(struct file *filp, struct vm_area_struct *vma); int amdgpu_ttm_alloc_gart(struct ttm_buffer_object *bo); int amdgpu_ttm_recover_gart(struct ttm_buffer_object *tbo); uint64_t amdgpu_ttm_domain_start(struct amdgpu_device *adev, uint32_t type);
dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Hi
Am 06.04.21 um 12:56 schrieb Christian König:
In the end I went with the semantics I found in amdgpu_mmap() and handled KFD specially. Let me know if this requires to be changed.
Well the question is where is the call to drm_vma_node_verify_access() now? Cause that needs to be skipped for KFD BOs.
I see. It's now drm_vma_node_is_allowed(); called by drm_gem_mmap(). [1] So drm_gem_mmap() cannot be used by amdgpu.
If I understand the code at [2] correctly, KFD objects don't use the GEM ioctl interfaces, but they still use the internal GEM object that is part of the TTM BO. In this case, amdgpu could have its own version of drm_gem_mmap(), which calls drm_gem_mmap_obj(), [3] which in turn handles the mmap details via GEM object functions.
drm_gem_prime_mmap() doesn't do any additional verification.
Best regards Thomas
[1] https://elixir.bootlin.com/linux/v5.11.11/source/drivers/gpu/drm/drm_gem.c#L... [2] https://elixir.bootlin.com/linux/v5.11.11/source/drivers/gpu/drm/amd/amdgpu/... [3] https://elixir.bootlin.com/linux/v5.12-rc6/source/drivers/gpu/drm/drm_gem.c#...
Regards, Christian.
Best regards Thomas
int amdgpu_copy_buffer(struct amdgpu_ring *ring, uint64_t src_offset, uint64_t dst_offset, uint32_t byte_count, struct dma_resv *resv, diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h index dec0db8b0b13..6e51faad7371 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h @@ -146,7 +146,6 @@ int amdgpu_fill_buffer(struct amdgpu_bo *bo, struct dma_resv *resv, struct dma_fence **fence); -int amdgpu_mmap(struct file *filp, struct vm_area_struct *vma); int amdgpu_ttm_alloc_gart(struct ttm_buffer_object *bo); int amdgpu_ttm_recover_gart(struct ttm_buffer_object *tbo); uint64_t amdgpu_ttm_domain_start(struct amdgpu_device *adev, uint32_t type);
dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Hi Thomas,
Am 06.04.21 um 13:55 schrieb Thomas Zimmermann:
Hi
Am 06.04.21 um 12:56 schrieb Christian König:
In the end I went with the semantics I found in amdgpu_mmap() and handled KFD specially. Let me know if this requires to be changed.
Well the question is where is the call to drm_vma_node_verify_access() now? Cause that needs to be skipped for KFD BOs.
I see. It's now drm_vma_node_is_allowed(); called by drm_gem_mmap(). [1] So drm_gem_mmap() cannot be used by amdgpu.
If I understand the code at [2] correctly, KFD objects don't use the GEM ioctl interfaces, but they still use the internal GEM object that is part of the TTM BO. In this case, amdgpu could have its own version of drm_gem_mmap(), which calls drm_gem_mmap_obj(), [3] which in turn handles the mmap details via GEM object functions.
Correct, well we could cleanup the KFD to use the GEM functions as well.
Felix what exactly was your objections to using this?
Regards, Christian.
drm_gem_prime_mmap() doesn't do any additional verification.
Best regards Thomas
[1] https://elixir.bootlin.com/linux/v5.11.11/source/drivers/gpu/drm/drm_gem.c#L... [2] https://elixir.bootlin.com/linux/v5.11.11/source/drivers/gpu/drm/amd/amdgpu/... [3] https://elixir.bootlin.com/linux/v5.12-rc6/source/drivers/gpu/drm/drm_gem.c#...
Regards, Christian.
Best regards Thomas
int amdgpu_copy_buffer(struct amdgpu_ring *ring, uint64_t src_offset, uint64_t dst_offset, uint32_t byte_count, struct dma_resv *resv, diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h index dec0db8b0b13..6e51faad7371 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h @@ -146,7 +146,6 @@ int amdgpu_fill_buffer(struct amdgpu_bo *bo, struct dma_resv *resv, struct dma_fence **fence); -int amdgpu_mmap(struct file *filp, struct vm_area_struct *vma); int amdgpu_ttm_alloc_gart(struct ttm_buffer_object *bo); int amdgpu_ttm_recover_gart(struct ttm_buffer_object *tbo); uint64_t amdgpu_ttm_domain_start(struct amdgpu_device *adev, uint32_t type);
dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Hi
Am 06.04.21 um 14:42 schrieb Christian König:
Hi Thomas,
Am 06.04.21 um 13:55 schrieb Thomas Zimmermann:
Hi
Am 06.04.21 um 12:56 schrieb Christian König:
In the end I went with the semantics I found in amdgpu_mmap() and handled KFD specially. Let me know if this requires to be changed.
Well the question is where is the call to drm_vma_node_verify_access() now? Cause that needs to be skipped for KFD BOs.
I see. It's now drm_vma_node_is_allowed(); called by drm_gem_mmap(). [1] So drm_gem_mmap() cannot be used by amdgpu.
If I understand the code at [2] correctly, KFD objects don't use the GEM ioctl interfaces, but they still use the internal GEM object that is part of the TTM BO. In this case, amdgpu could have its own version of drm_gem_mmap(), which calls drm_gem_mmap_obj(), [3] which in turn handles the mmap details via GEM object functions.
Correct, well we could cleanup the KFD to use the GEM functions as well.
The KFD code already calls amdgpu_gem_object_create(). It should have the object-functions pointer set for use with mmap. Not sure what the use of drm_vma_node_is_allowed() would involve.
Best regards Thomas
Felix what exactly was your objections to using this?
Regards, Christian.
drm_gem_prime_mmap() doesn't do any additional verification.
Best regards Thomas
[1] https://elixir.bootlin.com/linux/v5.11.11/source/drivers/gpu/drm/drm_gem.c#L...
[2] https://elixir.bootlin.com/linux/v5.11.11/source/drivers/gpu/drm/amd/amdgpu/...
[3] https://elixir.bootlin.com/linux/v5.12-rc6/source/drivers/gpu/drm/drm_gem.c#...
Regards, Christian.
Best regards Thomas
int amdgpu_copy_buffer(struct amdgpu_ring *ring, uint64_t src_offset, uint64_t dst_offset, uint32_t byte_count, struct dma_resv *resv, diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h index dec0db8b0b13..6e51faad7371 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h @@ -146,7 +146,6 @@ int amdgpu_fill_buffer(struct amdgpu_bo *bo, struct dma_resv *resv, struct dma_fence **fence); -int amdgpu_mmap(struct file *filp, struct vm_area_struct *vma); int amdgpu_ttm_alloc_gart(struct ttm_buffer_object *bo); int amdgpu_ttm_recover_gart(struct ttm_buffer_object *tbo); uint64_t amdgpu_ttm_domain_start(struct amdgpu_device *adev, uint32_t type);
dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Am 06.04.21 um 14:52 schrieb Thomas Zimmermann:
Hi
Am 06.04.21 um 14:42 schrieb Christian König:
Hi Thomas,
Am 06.04.21 um 13:55 schrieb Thomas Zimmermann:
Hi
Am 06.04.21 um 12:56 schrieb Christian König:
In the end I went with the semantics I found in amdgpu_mmap() and handled KFD specially. Let me know if this requires to be changed.
Well the question is where is the call to drm_vma_node_verify_access() now? Cause that needs to be skipped for KFD BOs.
I see. It's now drm_vma_node_is_allowed(); called by drm_gem_mmap(). [1] So drm_gem_mmap() cannot be used by amdgpu.
If I understand the code at [2] correctly, KFD objects don't use the GEM ioctl interfaces, but they still use the internal GEM object that is part of the TTM BO. In this case, amdgpu could have its own version of drm_gem_mmap(), which calls drm_gem_mmap_obj(), [3] which in turn handles the mmap details via GEM object functions.
Correct, well we could cleanup the KFD to use the GEM functions as well.
The KFD code already calls amdgpu_gem_object_create(). It should have the object-functions pointer set for use with mmap. Not sure what the use of drm_vma_node_is_allowed() would involve.
The KFD allows BOs to be mmaped with different offsets than what's used in the DRM node.
So drm_vma_node_is_allowed() would return false as far as I know.
Regards, Christian.
Best regards Thomas
Felix what exactly was your objections to using this?
Regards, Christian.
drm_gem_prime_mmap() doesn't do any additional verification.
Best regards Thomas
[1] https://elixir.bootlin.com/linux/v5.11.11/source/drivers/gpu/drm/drm_gem.c#L...
[2] https://elixir.bootlin.com/linux/v5.11.11/source/drivers/gpu/drm/amd/amdgpu/...
[3] https://elixir.bootlin.com/linux/v5.12-rc6/source/drivers/gpu/drm/drm_gem.c#...
Regards, Christian.
Best regards Thomas
> - > int amdgpu_copy_buffer(struct amdgpu_ring *ring, uint64_t > src_offset, > uint64_t dst_offset, uint32_t byte_count, > struct dma_resv *resv, > diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h > b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h > index dec0db8b0b13..6e51faad7371 100644 > --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h > +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h > @@ -146,7 +146,6 @@ int amdgpu_fill_buffer(struct amdgpu_bo *bo, > struct dma_resv *resv, > struct dma_fence **fence); > -int amdgpu_mmap(struct file *filp, struct vm_area_struct *vma); > int amdgpu_ttm_alloc_gart(struct ttm_buffer_object *bo); > int amdgpu_ttm_recover_gart(struct ttm_buffer_object *tbo); > uint64_t amdgpu_ttm_domain_start(struct amdgpu_device *adev, > uint32_t type);
dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Am 2021-04-06 um 9:04 a.m. schrieb Christian König:
Am 06.04.21 um 14:52 schrieb Thomas Zimmermann:
Hi
Am 06.04.21 um 14:42 schrieb Christian König:
Hi Thomas,
Am 06.04.21 um 13:55 schrieb Thomas Zimmermann:
Hi
Am 06.04.21 um 12:56 schrieb Christian König:
In the end I went with the semantics I found in amdgpu_mmap() and handled KFD specially. Let me know if this requires to be changed.
Well the question is where is the call to drm_vma_node_verify_access() now? Cause that needs to be skipped for KFD BOs.
I see. It's now drm_vma_node_is_allowed(); called by drm_gem_mmap(). [1] So drm_gem_mmap() cannot be used by amdgpu.
If I understand the code at [2] correctly, KFD objects don't use the GEM ioctl interfaces, but they still use the internal GEM object that is part of the TTM BO. In this case, amdgpu could have its own version of drm_gem_mmap(), which calls drm_gem_mmap_obj(), [3] which in turn handles the mmap details via GEM object functions.
Correct, well we could cleanup the KFD to use the GEM functions as well.
The KFD code already calls amdgpu_gem_object_create(). It should have the object-functions pointer set for use with mmap. Not sure what the use of drm_vma_node_is_allowed() would involve.
The KFD allows BOs to be mmaped with different offsets than what's used in the DRM node.
So drm_vma_node_is_allowed() would return false as far as I know.
We used to mmap KFD BOs through the /dev/kfd file descriptor. We moved that to using the /dev/dri/renderD* file descriptors a long time ago. If there is some KFD special casing left in the code for BO mmap, it's probably an oversight and we should be able to remove it.
We still have a few special mmaps in /dev/kfd, but they are for things that don't involve GEM BOs that could be mmapped through the render node: doorbells, MMIO pages and CWSR trap-handler mappings for APUs.
Regards, Felix
Regards, Christian.
Best regards Thomas
Felix what exactly was your objections to using this?
Regards, Christian.
drm_gem_prime_mmap() doesn't do any additional verification.
Best regards Thomas
[1] https://elixir.bootlin.com/linux/v5.11.11/source/drivers/gpu/drm/drm_gem.c#L...
[2] https://elixir.bootlin.com/linux/v5.11.11/source/drivers/gpu/drm/amd/amdgpu/...
[3] https://elixir.bootlin.com/linux/v5.12-rc6/source/drivers/gpu/drm/drm_gem.c#...
Regards, Christian.
Best regards Thomas
>> - >> int amdgpu_copy_buffer(struct amdgpu_ring *ring, uint64_t >> src_offset, >> uint64_t dst_offset, uint32_t byte_count, >> struct dma_resv *resv, >> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h >> b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h >> index dec0db8b0b13..6e51faad7371 100644 >> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h >> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h >> @@ -146,7 +146,6 @@ int amdgpu_fill_buffer(struct amdgpu_bo *bo, >> struct dma_resv *resv, >> struct dma_fence **fence); >> -int amdgpu_mmap(struct file *filp, struct vm_area_struct *vma); >> int amdgpu_ttm_alloc_gart(struct ttm_buffer_object *bo); >> int amdgpu_ttm_recover_gart(struct ttm_buffer_object *tbo); >> uint64_t amdgpu_ttm_domain_start(struct amdgpu_device *adev, >> uint32_t type); > > _______________________________________________ > dri-devel mailing list > dri-devel@lists.freedesktop.org > https://lists.freedesktop.org/mailman/listinfo/dri-devel
dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Am 2021-04-06 um 6:38 a.m. schrieb Thomas Zimmermann:
Hi
Am 06.04.21 um 11:35 schrieb Christian König:
Am 06.04.21 um 11:08 schrieb Thomas Zimmermann:
Moving the driver-specific mmap code into a GEM object function allows for using DRM helpers for various mmap callbacks.
This change resolves several inconsistencies between regular mmap and prime-based mmap. The vm_ops field in vma is now set for all mmap'ed areas. Previously it way only set for regular mmap calls, prime-based mmap used TTM's default vm_ops. The check for kfd_bo has been taken from amdgpu_verify_access(), which is not called any longer and has been removed.
As a side effect, amdgpu_ttm_vm_ops and amdgpu_ttm_fault() are now implemented in amdgpu's GEM code.
Signed-off-by: Thomas Zimmermann tzimmermann@suse.de
drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c | 46 ------------- drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.h | 2 - drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c | 4 +- drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c | 64 +++++++++++++++++++ drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | 71
drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h | 1 - 6 files changed, 66 insertions(+), 122 deletions(-)
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c index e0c4f7c7f1b9..19c5ab08d9ec 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c @@ -42,52 +42,6 @@ #include <linux/pci-p2pdma.h> #include <linux/pm_runtime.h> -/**
- amdgpu_gem_prime_mmap - &drm_driver.gem_prime_mmap implementation
- @obj: GEM BO
- @vma: Virtual memory area
- Sets up a userspace mapping of the BO's memory in the given
- virtual memory area.
- Returns:
- 0 on success or a negative error code on failure.
- */
-int amdgpu_gem_prime_mmap(struct drm_gem_object *obj, - struct vm_area_struct *vma) -{ - struct amdgpu_bo *bo = gem_to_amdgpu_bo(obj); - struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev); - unsigned asize = amdgpu_bo_size(bo); - int ret;
- if (!vma->vm_file) - return -ENODEV;
- if (adev == NULL) - return -ENODEV;
- /* Check for valid size. */ - if (asize < vma->vm_end - vma->vm_start) - return -EINVAL;
- if (amdgpu_ttm_tt_get_usermm(bo->tbo.ttm) || - (bo->flags & AMDGPU_GEM_CREATE_NO_CPU_ACCESS)) { - return -EPERM; - } - vma->vm_pgoff += amdgpu_bo_mmap_offset(bo) >> PAGE_SHIFT;
- /* prime mmap does not need to check access, so allow here */ - ret = drm_vma_node_allow(&obj->vma_node, vma->vm_file->private_data); - if (ret) - return ret;
- ret = ttm_bo_mmap(vma->vm_file, vma, &adev->mman.bdev); - drm_vma_node_revoke(&obj->vma_node, vma->vm_file->private_data);
- return ret; -}
static int __dma_resv_make_exclusive(struct dma_resv *obj) { diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.h index 39b5b9616fd8..3e93b9b407a9 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.h @@ -31,8 +31,6 @@ struct drm_gem_object *amdgpu_gem_prime_import(struct drm_device *dev, struct dma_buf *dma_buf); bool amdgpu_dmabuf_is_xgmi_accessible(struct amdgpu_device *adev, struct amdgpu_bo *bo); -int amdgpu_gem_prime_mmap(struct drm_gem_object *obj, - struct vm_area_struct *vma); extern const struct dma_buf_ops amdgpu_dmabuf_ops; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c index 76f48f79c70b..e96d2758f4bb 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c @@ -1656,7 +1656,7 @@ static const struct file_operations amdgpu_driver_kms_fops = { .flush = amdgpu_flush, .release = drm_release, .unlocked_ioctl = amdgpu_drm_ioctl, - .mmap = amdgpu_mmap, + .mmap = drm_gem_mmap, .poll = drm_poll, .read = drm_read, #ifdef CONFIG_COMPAT @@ -1719,7 +1719,7 @@ static const struct drm_driver amdgpu_kms_driver = { .prime_handle_to_fd = drm_gem_prime_handle_to_fd, .prime_fd_to_handle = drm_gem_prime_fd_to_handle, .gem_prime_import = amdgpu_gem_prime_import, - .gem_prime_mmap = amdgpu_gem_prime_mmap, + .gem_prime_mmap = drm_gem_prime_mmap, .name = DRIVER_NAME, .desc = DRIVER_DESC, diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c index fb7171e5507c..fe93faad05f2 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c @@ -41,6 +41,36 @@ static const struct drm_gem_object_funcs amdgpu_gem_object_funcs; +static vm_fault_t amdgpu_ttm_fault(struct vm_fault *vmf)
Please name that function amdgpu_gem_fault or amdgpu_gem_object_fault
+{ + struct ttm_buffer_object *bo = vmf->vma->vm_private_data; + vm_fault_t ret;
+ ret = ttm_bo_vm_reserve(bo, vmf); + if (ret) + return ret;
+ ret = amdgpu_bo_fault_reserve_notify(bo); + if (ret) + goto unlock;
+ ret = ttm_bo_vm_fault_reserved(vmf, vmf->vma->vm_page_prot, + TTM_BO_VM_NUM_PREFAULT, 1); + if (ret == VM_FAULT_RETRY && !(vmf->flags & FAULT_FLAG_RETRY_NOWAIT)) + return ret;
+unlock: + dma_resv_unlock(bo->base.resv); + return ret; +}
+static const struct vm_operations_struct amdgpu_ttm_vm_ops = { + .fault = amdgpu_ttm_fault, + .open = ttm_bo_vm_open, + .close = ttm_bo_vm_close, + .access = ttm_bo_vm_access +};
static void amdgpu_gem_object_free(struct drm_gem_object *gobj) { struct amdgpu_bo *robj = gem_to_amdgpu_bo(gobj); @@ -201,6 +231,38 @@ static void amdgpu_gem_object_close(struct drm_gem_object *obj, ttm_eu_backoff_reservation(&ticket, &list); } +static int amdgpu_gem_prime_mmap(struct drm_gem_object *obj, struct vm_area_struct *vma) +{ + struct amdgpu_bo *bo = gem_to_amdgpu_bo(obj); + struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev); + unsigned long asize = amdgpu_bo_size(bo);
+ if (!vma->vm_file) + return -ENODEV;
+ if (!adev) + return -ENODEV;
+ /* Check for valid size. */ + if (asize < vma->vm_end - vma->vm_start) + return -EINVAL;
+ /* + * Don't verify access for KFD BOs. They don't have a GEM + * object associated with them. + */ + if (bo->kfd_bo) + goto out;
Who does the access verification now?
This is somewhat confusing.
I took this check as-is, including the comment, from amdgpu's verify_access function. The verify_access function was called by ttm_bo_mmap. It returned 0 and ttm_bo_mmap did the mapping.
This is probably a left-over from when we mapped BOs using /dev/kfd. We changed this to use /dev/dri/renderD* a long time ago to fix CPU mapping invalidations on memory evictions. I think we can let GEM do the access check.
Regards, Felix
Christian.
+ if (amdgpu_ttm_tt_get_usermm(bo->tbo.ttm) || + (bo->flags & AMDGPU_GEM_CREATE_NO_CPU_ACCESS)) { + return -EPERM; + }
+out: + return drm_gem_ttm_mmap(obj, vma); +}
static const struct drm_gem_object_funcs amdgpu_gem_object_funcs = { .free = amdgpu_gem_object_free, .open = amdgpu_gem_object_open, @@ -208,6 +270,8 @@ static const struct drm_gem_object_funcs amdgpu_gem_object_funcs = { .export = amdgpu_gem_prime_export, .vmap = drm_gem_ttm_vmap, .vunmap = drm_gem_ttm_vunmap, + .mmap = amdgpu_gem_prime_mmap, + .vm_ops = &amdgpu_ttm_vm_ops, }; /* diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c index 1c6131489a85..d9de91a517c6 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c @@ -152,32 +152,6 @@ static void amdgpu_evict_flags(struct ttm_buffer_object *bo, *placement = abo->placement; } -/**
- amdgpu_verify_access - Verify access for a mmap call
- @bo: The buffer object to map
- @filp: The file pointer from the process performing the mmap
- This is called by ttm_bo_mmap() to verify whether a process
- has the right to mmap a BO to their process space.
- */
-static int amdgpu_verify_access(struct ttm_buffer_object *bo, struct file *filp) -{ - struct amdgpu_bo *abo = ttm_to_amdgpu_bo(bo);
- /* - * Don't verify access for KFD BOs. They don't have a GEM - * object associated with them. - */ - if (abo->kfd_bo) - return 0;
- if (amdgpu_ttm_tt_get_usermm(bo->ttm)) - return -EPERM; - return drm_vma_node_verify_access(&abo->tbo.base.vma_node, - filp->private_data); -}
Here's the orignal verification code. It gives a free pass to KFD.
/** * amdgpu_ttm_map_buffer - Map memory into the GART windows * @bo: buffer object to map @@ -1531,7 +1505,6 @@ static struct ttm_device_funcs amdgpu_bo_driver = { .eviction_valuable = amdgpu_ttm_bo_eviction_valuable, .evict_flags = &amdgpu_evict_flags, .move = &amdgpu_bo_move, - .verify_access = &amdgpu_verify_access, .delete_mem_notify = &amdgpu_bo_delete_mem_notify, .release_notify = &amdgpu_bo_release_notify, .io_mem_reserve = &amdgpu_ttm_io_mem_reserve, @@ -1906,50 +1879,6 @@ void amdgpu_ttm_set_buffer_funcs_status(struct amdgpu_device *adev, bool enable) adev->mman.buffer_funcs_enabled = enable; } -static vm_fault_t amdgpu_ttm_fault(struct vm_fault *vmf) -{ - struct ttm_buffer_object *bo = vmf->vma->vm_private_data; - vm_fault_t ret;
- ret = ttm_bo_vm_reserve(bo, vmf); - if (ret) - return ret;
- ret = amdgpu_bo_fault_reserve_notify(bo); - if (ret) - goto unlock;
- ret = ttm_bo_vm_fault_reserved(vmf, vmf->vma->vm_page_prot, - TTM_BO_VM_NUM_PREFAULT, 1); - if (ret == VM_FAULT_RETRY && !(vmf->flags & FAULT_FLAG_RETRY_NOWAIT)) - return ret;
-unlock: - dma_resv_unlock(bo->base.resv); - return ret; -}
-static const struct vm_operations_struct amdgpu_ttm_vm_ops = { - .fault = amdgpu_ttm_fault, - .open = ttm_bo_vm_open, - .close = ttm_bo_vm_close, - .access = ttm_bo_vm_access -};
-int amdgpu_mmap(struct file *filp, struct vm_area_struct *vma) -{ - struct drm_file *file_priv = filp->private_data; - struct amdgpu_device *adev = drm_to_adev(file_priv->minor->dev); - int r;
- r = ttm_bo_mmap(filp, vma, &adev->mman.bdev); - if (unlikely(r != 0)) - return r;
- vma->vm_ops = &amdgpu_ttm_vm_ops; - return 0; -}
And this was the mmap callback in struct file_operations. It calls ttm_bo_mmap(), which skips verification for KFD BOs. To the best of my knowledge, there was no additional verification for these KFD BOs.
The original code in amdgpu_gem_prime_mmap() did seom verification, but didn't handle KFD specially. I guess, PRIME needs GEM and KFD BOs wouldn't quailify.
In the end I went with the semantics I found in amdgpu_mmap() and handled KFD specially. Let me know if this requires to be changed.
Best regards Thomas
int amdgpu_copy_buffer(struct amdgpu_ring *ring, uint64_t src_offset, uint64_t dst_offset, uint32_t byte_count, struct dma_resv *resv, diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h index dec0db8b0b13..6e51faad7371 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h @@ -146,7 +146,6 @@ int amdgpu_fill_buffer(struct amdgpu_bo *bo, struct dma_resv *resv, struct dma_fence **fence); -int amdgpu_mmap(struct file *filp, struct vm_area_struct *vma); int amdgpu_ttm_alloc_gart(struct ttm_buffer_object *bo); int amdgpu_ttm_recover_gart(struct ttm_buffer_object *tbo); uint64_t amdgpu_ttm_domain_start(struct amdgpu_device *adev, uint32_t type);
dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Hi,
Am 06.04.21 um 17:27 schrieb Felix Kuehling:
Am 2021-04-06 um 6:38 a.m. schrieb Thomas Zimmermann:
Hi
Am 06.04.21 um 11:35 schrieb Christian König:
Am 06.04.21 um 11:08 schrieb Thomas Zimmermann:
Moving the driver-specific mmap code into a GEM object function allows for using DRM helpers for various mmap callbacks.
This change resolves several inconsistencies between regular mmap and prime-based mmap. The vm_ops field in vma is now set for all mmap'ed areas. Previously it way only set for regular mmap calls, prime-based mmap used TTM's default vm_ops. The check for kfd_bo has been taken from amdgpu_verify_access(), which is not called any longer and has been removed.
As a side effect, amdgpu_ttm_vm_ops and amdgpu_ttm_fault() are now implemented in amdgpu's GEM code.
Signed-off-by: Thomas Zimmermann tzimmermann@suse.de
drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c | 46 ------------- drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.h | 2 - drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c | 4 +- drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c | 64 +++++++++++++++++++ drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | 71
drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h | 1 - 6 files changed, 66 insertions(+), 122 deletions(-)
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c index e0c4f7c7f1b9..19c5ab08d9ec 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c @@ -42,52 +42,6 @@ #include <linux/pci-p2pdma.h> #include <linux/pm_runtime.h> -/**
- amdgpu_gem_prime_mmap - &drm_driver.gem_prime_mmap implementation
- @obj: GEM BO
- @vma: Virtual memory area
- Sets up a userspace mapping of the BO's memory in the given
- virtual memory area.
- Returns:
- 0 on success or a negative error code on failure.
- */
-int amdgpu_gem_prime_mmap(struct drm_gem_object *obj, - struct vm_area_struct *vma) -{ - struct amdgpu_bo *bo = gem_to_amdgpu_bo(obj); - struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev); - unsigned asize = amdgpu_bo_size(bo); - int ret;
- if (!vma->vm_file) - return -ENODEV;
- if (adev == NULL) - return -ENODEV;
- /* Check for valid size. */ - if (asize < vma->vm_end - vma->vm_start) - return -EINVAL;
- if (amdgpu_ttm_tt_get_usermm(bo->tbo.ttm) || - (bo->flags & AMDGPU_GEM_CREATE_NO_CPU_ACCESS)) { - return -EPERM; - } - vma->vm_pgoff += amdgpu_bo_mmap_offset(bo) >> PAGE_SHIFT;
- /* prime mmap does not need to check access, so allow here */ - ret = drm_vma_node_allow(&obj->vma_node, vma->vm_file->private_data); - if (ret) - return ret;
- ret = ttm_bo_mmap(vma->vm_file, vma, &adev->mman.bdev); - drm_vma_node_revoke(&obj->vma_node, vma->vm_file->private_data);
- return ret; -}
static int __dma_resv_make_exclusive(struct dma_resv *obj) { diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.h index 39b5b9616fd8..3e93b9b407a9 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.h @@ -31,8 +31,6 @@ struct drm_gem_object *amdgpu_gem_prime_import(struct drm_device *dev, struct dma_buf *dma_buf); bool amdgpu_dmabuf_is_xgmi_accessible(struct amdgpu_device *adev, struct amdgpu_bo *bo); -int amdgpu_gem_prime_mmap(struct drm_gem_object *obj, - struct vm_area_struct *vma); extern const struct dma_buf_ops amdgpu_dmabuf_ops; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c index 76f48f79c70b..e96d2758f4bb 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c @@ -1656,7 +1656,7 @@ static const struct file_operations amdgpu_driver_kms_fops = { .flush = amdgpu_flush, .release = drm_release, .unlocked_ioctl = amdgpu_drm_ioctl, - .mmap = amdgpu_mmap, + .mmap = drm_gem_mmap, .poll = drm_poll, .read = drm_read, #ifdef CONFIG_COMPAT @@ -1719,7 +1719,7 @@ static const struct drm_driver amdgpu_kms_driver = { .prime_handle_to_fd = drm_gem_prime_handle_to_fd, .prime_fd_to_handle = drm_gem_prime_fd_to_handle, .gem_prime_import = amdgpu_gem_prime_import, - .gem_prime_mmap = amdgpu_gem_prime_mmap, + .gem_prime_mmap = drm_gem_prime_mmap, .name = DRIVER_NAME, .desc = DRIVER_DESC, diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c index fb7171e5507c..fe93faad05f2 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c @@ -41,6 +41,36 @@ static const struct drm_gem_object_funcs amdgpu_gem_object_funcs; +static vm_fault_t amdgpu_ttm_fault(struct vm_fault *vmf)
Please name that function amdgpu_gem_fault or amdgpu_gem_object_fault
+{ + struct ttm_buffer_object *bo = vmf->vma->vm_private_data; + vm_fault_t ret;
+ ret = ttm_bo_vm_reserve(bo, vmf); + if (ret) + return ret;
+ ret = amdgpu_bo_fault_reserve_notify(bo); + if (ret) + goto unlock;
+ ret = ttm_bo_vm_fault_reserved(vmf, vmf->vma->vm_page_prot, + TTM_BO_VM_NUM_PREFAULT, 1); + if (ret == VM_FAULT_RETRY && !(vmf->flags & FAULT_FLAG_RETRY_NOWAIT)) + return ret;
+unlock: + dma_resv_unlock(bo->base.resv); + return ret; +}
+static const struct vm_operations_struct amdgpu_ttm_vm_ops = { + .fault = amdgpu_ttm_fault, + .open = ttm_bo_vm_open, + .close = ttm_bo_vm_close, + .access = ttm_bo_vm_access +};
static void amdgpu_gem_object_free(struct drm_gem_object *gobj) { struct amdgpu_bo *robj = gem_to_amdgpu_bo(gobj); @@ -201,6 +231,38 @@ static void amdgpu_gem_object_close(struct drm_gem_object *obj, ttm_eu_backoff_reservation(&ticket, &list); } +static int amdgpu_gem_prime_mmap(struct drm_gem_object *obj, struct vm_area_struct *vma) +{ + struct amdgpu_bo *bo = gem_to_amdgpu_bo(obj); + struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev); + unsigned long asize = amdgpu_bo_size(bo);
+ if (!vma->vm_file) + return -ENODEV;
+ if (!adev) + return -ENODEV;
+ /* Check for valid size. */ + if (asize < vma->vm_end - vma->vm_start) + return -EINVAL;
+ /* + * Don't verify access for KFD BOs. They don't have a GEM + * object associated with them. + */ + if (bo->kfd_bo) + goto out;
Who does the access verification now?
This is somewhat confusing.
I took this check as-is, including the comment, from amdgpu's verify_access function. The verify_access function was called by ttm_bo_mmap. It returned 0 and ttm_bo_mmap did the mapping.
This is probably a left-over from when we mapped BOs using /dev/kfd. We changed this to use /dev/dri/renderD* a long time ago to fix CPU mapping invalidations on memory evictions. I think we can let GEM do the access check.
Ok, good to know.
Thomas can you remove the extra handling in a separate prerequisite patch?
If anybody then bisects to this patch we at least know what to do to get it working again.
Regards, Christian.
Regards, Felix
Christian.
+ if (amdgpu_ttm_tt_get_usermm(bo->tbo.ttm) || + (bo->flags & AMDGPU_GEM_CREATE_NO_CPU_ACCESS)) { + return -EPERM; + }
+out: + return drm_gem_ttm_mmap(obj, vma); +}
static const struct drm_gem_object_funcs amdgpu_gem_object_funcs = { .free = amdgpu_gem_object_free, .open = amdgpu_gem_object_open, @@ -208,6 +270,8 @@ static const struct drm_gem_object_funcs amdgpu_gem_object_funcs = { .export = amdgpu_gem_prime_export, .vmap = drm_gem_ttm_vmap, .vunmap = drm_gem_ttm_vunmap, + .mmap = amdgpu_gem_prime_mmap, + .vm_ops = &amdgpu_ttm_vm_ops, }; /* diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c index 1c6131489a85..d9de91a517c6 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c @@ -152,32 +152,6 @@ static void amdgpu_evict_flags(struct ttm_buffer_object *bo, *placement = abo->placement; } -/**
- amdgpu_verify_access - Verify access for a mmap call
- @bo: The buffer object to map
- @filp: The file pointer from the process performing the mmap
- This is called by ttm_bo_mmap() to verify whether a process
- has the right to mmap a BO to their process space.
- */
-static int amdgpu_verify_access(struct ttm_buffer_object *bo, struct file *filp) -{ - struct amdgpu_bo *abo = ttm_to_amdgpu_bo(bo);
- /* - * Don't verify access for KFD BOs. They don't have a GEM - * object associated with them. - */ - if (abo->kfd_bo) - return 0;
- if (amdgpu_ttm_tt_get_usermm(bo->ttm)) - return -EPERM; - return drm_vma_node_verify_access(&abo->tbo.base.vma_node, - filp->private_data); -}
Here's the orignal verification code. It gives a free pass to KFD.
/** * amdgpu_ttm_map_buffer - Map memory into the GART windows * @bo: buffer object to map @@ -1531,7 +1505,6 @@ static struct ttm_device_funcs amdgpu_bo_driver = { .eviction_valuable = amdgpu_ttm_bo_eviction_valuable, .evict_flags = &amdgpu_evict_flags, .move = &amdgpu_bo_move, - .verify_access = &amdgpu_verify_access, .delete_mem_notify = &amdgpu_bo_delete_mem_notify, .release_notify = &amdgpu_bo_release_notify, .io_mem_reserve = &amdgpu_ttm_io_mem_reserve, @@ -1906,50 +1879,6 @@ void amdgpu_ttm_set_buffer_funcs_status(struct amdgpu_device *adev, bool enable) adev->mman.buffer_funcs_enabled = enable; } -static vm_fault_t amdgpu_ttm_fault(struct vm_fault *vmf) -{ - struct ttm_buffer_object *bo = vmf->vma->vm_private_data; - vm_fault_t ret;
- ret = ttm_bo_vm_reserve(bo, vmf); - if (ret) - return ret;
- ret = amdgpu_bo_fault_reserve_notify(bo); - if (ret) - goto unlock;
- ret = ttm_bo_vm_fault_reserved(vmf, vmf->vma->vm_page_prot, - TTM_BO_VM_NUM_PREFAULT, 1); - if (ret == VM_FAULT_RETRY && !(vmf->flags & FAULT_FLAG_RETRY_NOWAIT)) - return ret;
-unlock: - dma_resv_unlock(bo->base.resv); - return ret; -}
-static const struct vm_operations_struct amdgpu_ttm_vm_ops = { - .fault = amdgpu_ttm_fault, - .open = ttm_bo_vm_open, - .close = ttm_bo_vm_close, - .access = ttm_bo_vm_access -};
-int amdgpu_mmap(struct file *filp, struct vm_area_struct *vma) -{ - struct drm_file *file_priv = filp->private_data; - struct amdgpu_device *adev = drm_to_adev(file_priv->minor->dev); - int r;
- r = ttm_bo_mmap(filp, vma, &adev->mman.bdev); - if (unlikely(r != 0)) - return r;
- vma->vm_ops = &amdgpu_ttm_vm_ops; - return 0; -}
And this was the mmap callback in struct file_operations. It calls ttm_bo_mmap(), which skips verification for KFD BOs. To the best of my knowledge, there was no additional verification for these KFD BOs.
The original code in amdgpu_gem_prime_mmap() did seom verification, but didn't handle KFD specially. I guess, PRIME needs GEM and KFD BOs wouldn't quailify.
In the end I went with the semantics I found in amdgpu_mmap() and handled KFD specially. Let me know if this requires to be changed.
Best regards Thomas
int amdgpu_copy_buffer(struct amdgpu_ring *ring, uint64_t src_offset, uint64_t dst_offset, uint32_t byte_count, struct dma_resv *resv, diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h index dec0db8b0b13..6e51faad7371 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h @@ -146,7 +146,6 @@ int amdgpu_fill_buffer(struct amdgpu_bo *bo, struct dma_resv *resv, struct dma_fence **fence); -int amdgpu_mmap(struct file *filp, struct vm_area_struct *vma); int amdgpu_ttm_alloc_gart(struct ttm_buffer_object *bo); int amdgpu_ttm_recover_gart(struct ttm_buffer_object *tbo); uint64_t amdgpu_ttm_domain_start(struct amdgpu_device *adev, uint32_t type);
dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
On 2021-04-07 7:25 a.m., Christian König wrote:
+ /* + * Don't verify access for KFD BOs. They don't have a GEM + * object associated with them. + */ + if (bo->kfd_bo) + goto out;
Who does the access verification now?
This is somewhat confusing.
I took this check as-is, including the comment, from amdgpu's verify_access function. The verify_access function was called by ttm_bo_mmap. It returned 0 and ttm_bo_mmap did the mapping.
This is probably a left-over from when we mapped BOs using /dev/kfd. We changed this to use /dev/dri/renderD* a long time ago to fix CPU mapping invalidations on memory evictions. I think we can let GEM do the access check.
Ok, good to know.
Thomas can you remove the extra handling in a separate prerequisite patch?
If anybody then bisects to this patch we at least know what to do to get it working again.
FWIW, I ran KFDTest test with this shortcut removed on current amd-staging-drm-next + my HMM patch series, and it didn't seem to cause any issues.
Regards, Felix
Regards, Christian.
On 2021-04-07 3:34 p.m., Felix Kuehling wrote:
On 2021-04-07 7:25 a.m., Christian König wrote:
+ /* + * Don't verify access for KFD BOs. They don't have a GEM + * object associated with them. + */ + if (bo->kfd_bo) + goto out;
Who does the access verification now?
This is somewhat confusing.
I took this check as-is, including the comment, from amdgpu's verify_access function. The verify_access function was called by ttm_bo_mmap. It returned 0 and ttm_bo_mmap did the mapping.
This is probably a left-over from when we mapped BOs using /dev/kfd. We changed this to use /dev/dri/renderD* a long time ago to fix CPU mapping invalidations on memory evictions. I think we can let GEM do the access check.
Ok, good to know.
Thomas can you remove the extra handling in a separate prerequisite patch?
If anybody then bisects to this patch we at least know what to do to get it working again.
FWIW, I ran KFDTest test with this shortcut removed on current amd-staging-drm-next + my HMM patch series, and it didn't seem to cause any issues.
Wait, I celebrated too soon. I was running the wrong kernel. I do see some failures where access is being denied. I need to do more debugging to figure out what's causing that.
Regards, Felix
Regards, Felix
Regards, Christian.
Hi
Am 07.04.21 um 21:49 schrieb Felix Kuehling:
On 2021-04-07 3:34 p.m., Felix Kuehling wrote:
On 2021-04-07 7:25 a.m., Christian König wrote:
> + /* > + * Don't verify access for KFD BOs. They don't have a GEM > + * object associated with them. > + */ > + if (bo->kfd_bo) > + goto out; Who does the access verification now?
This is somewhat confusing.
I took this check as-is, including the comment, from amdgpu's verify_access function. The verify_access function was called by ttm_bo_mmap. It returned 0 and ttm_bo_mmap did the mapping.
This is probably a left-over from when we mapped BOs using /dev/kfd. We changed this to use /dev/dri/renderD* a long time ago to fix CPU mapping invalidations on memory evictions. I think we can let GEM do the access check.
Ok, good to know.
Thomas can you remove the extra handling in a separate prerequisite patch?
If anybody then bisects to this patch we at least know what to do to get it working again.
FWIW, I ran KFDTest test with this shortcut removed on current amd-staging-drm-next + my HMM patch series, and it didn't seem to cause any issues.
Wait, I celebrated too soon. I was running the wrong kernel. I do see some failures where access is being denied. I need to do more debugging to figure out what's causing that.
OK, thanks for looking into this. I'll wait a bit before sending out the new patchset.
Best regards Thomas
Regards, Felix
Regards, Felix
Regards, Christian.
Hi
Am 07.04.21 um 21:49 schrieb Felix Kuehling:
On 2021-04-07 3:34 p.m., Felix Kuehling wrote:
On 2021-04-07 7:25 a.m., Christian König wrote:
> + /* > + * Don't verify access for KFD BOs. They
don't have a GEM
> + * object associated with them. > + */ > + if (bo->kfd_bo) > + goto out; Who does the access verification now?
This is somewhat confusing.
I took this check as-is, including the comment, from amdgpu's verify_access function. The verify_access function was called by ttm_bo_mmap. It returned 0 and ttm_bo_mmap did the mapping.
This is probably a left-over from when we mapped BOs using /dev/kfd.
We
changed this to use /dev/dri/renderD* a long time ago to fix CPU mapping invalidations on memory evictions. I think we can let GEM do the access check.
Ok, good to know.
Thomas can you remove the extra handling in a separate prerequisite patch?
If anybody then bisects to this patch we at least know what to do to get it working again.
FWIW, I ran KFDTest test with this shortcut removed on current amd-staging-drm-next + my HMM patch series, and it didn't seem to cause any issues.
Wait, I celebrated too soon. I was running the wrong kernel. I do see some failures where access is being denied. I need to do more debugging
to figure out what's causing that.
Any news here? I saw the patch at [1], which removes the kfd_bo test. Can I assume that the series addresses the issue?
Best regards Thomas
[1] https://patchwork.freedesktop.org/patch/427516/?series=88822&rev=1
Regards, Felix
Regards, Felix
Regards, Christian.
dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Am 2021-04-14 um 3:44 a.m. schrieb Thomas Zimmermann:
Hi
Am 07.04.21 um 21:49 schrieb Felix Kuehling:
On 2021-04-07 3:34 p.m., Felix Kuehling wrote:
On 2021-04-07 7:25 a.m., Christian König wrote:
>> + /* >> + * Don't verify access for KFD BOs. They
don't have a GEM
>> + * object associated with them. >> + */ >> + if (bo->kfd_bo) >> + goto out; > Who does the access verification now? This is somewhat confusing.
I took this check as-is, including the comment, from amdgpu's verify_access function. The verify_access function was called by ttm_bo_mmap. It returned 0 and ttm_bo_mmap did the mapping.
This is probably a left-over from when we mapped BOs using /dev/kfd.
We
changed this to use /dev/dri/renderD* a long time ago to fix CPU mapping invalidations on memory evictions. I think we can let GEM do the access check.
Ok, good to know.
Thomas can you remove the extra handling in a separate prerequisite patch?
If anybody then bisects to this patch we at least know what to do to get it working again.
FWIW, I ran KFDTest test with this shortcut removed on current amd-staging-drm-next + my HMM patch series, and it didn't seem to cause any issues.
Wait, I celebrated too soon. I was running the wrong kernel. I do see some failures where access is being denied. I need to do more debugging
to figure out what's causing that.
Any news here? I saw the patch at [1], which removes the kfd_bo test. Can I assume that the series addresses the issue?
Yes, that series fixes the problem. I need to pester more people to review it.
Regards, Felix
Best regards Thomas
[1] https://patchwork.freedesktop.org/patch/427516/?series=88822&rev=1
Regards, Felix
Regards, Felix
Regards, Christian.
dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Moving the driver-specific mmap code into a GEM object function allows for using DRM helpers for various mmap callbacks.
This change also allows to support prime-based mmap via DRM's helper drm_gem_prime_mmap().
Permission checks are implemented by drm_gem_mmap(), with an additional check for radeon_ttm_tt_has_userptr() in the GEM object function. The function radeon_verify_access() is now unused and has thus been removed.
As a side effect, amdgpu_ttm_vm_ops and amdgpu_ttm_fault() are now implemented in amdgpu's GEM code.
Signed-off-by: Thomas Zimmermann tzimmermann@suse.de --- drivers/gpu/drm/radeon/radeon_drv.c | 3 +- drivers/gpu/drm/radeon/radeon_gem.c | 52 +++++++++++++++++++++++ drivers/gpu/drm/radeon/radeon_ttm.c | 65 ----------------------------- drivers/gpu/drm/radeon/radeon_ttm.h | 1 - 4 files changed, 54 insertions(+), 67 deletions(-)
diff --git a/drivers/gpu/drm/radeon/radeon_drv.c b/drivers/gpu/drm/radeon/radeon_drv.c index efeb115ae70e..4039b6d71aa2 100644 --- a/drivers/gpu/drm/radeon/radeon_drv.c +++ b/drivers/gpu/drm/radeon/radeon_drv.c @@ -557,7 +557,7 @@ static const struct file_operations radeon_driver_kms_fops = { .open = drm_open, .release = drm_release, .unlocked_ioctl = radeon_drm_ioctl, - .mmap = radeon_mmap, + .mmap = drm_gem_mmap, .poll = drm_poll, .read = drm_read, #ifdef CONFIG_COMPAT @@ -632,6 +632,7 @@ static const struct drm_driver kms_driver = { .prime_handle_to_fd = drm_gem_prime_handle_to_fd, .prime_fd_to_handle = drm_gem_prime_fd_to_handle, .gem_prime_import_sg_table = radeon_gem_prime_import_sg_table, + .gem_prime_mmap = drm_gem_prime_mmap,
.name = DRIVER_NAME, .desc = DRIVER_DESC, diff --git a/drivers/gpu/drm/radeon/radeon_gem.c b/drivers/gpu/drm/radeon/radeon_gem.c index 05ea2f39f626..71e8737bce01 100644 --- a/drivers/gpu/drm/radeon/radeon_gem.c +++ b/drivers/gpu/drm/radeon/radeon_gem.c @@ -44,6 +44,42 @@ void radeon_gem_prime_unpin(struct drm_gem_object *obj);
const struct drm_gem_object_funcs radeon_gem_object_funcs;
+static vm_fault_t radeon_ttm_fault(struct vm_fault *vmf) +{ + struct ttm_buffer_object *bo = vmf->vma->vm_private_data; + struct radeon_device *rdev = radeon_get_rdev(bo->bdev); + vm_fault_t ret; + + down_read(&rdev->pm.mclk_lock); + + ret = ttm_bo_vm_reserve(bo, vmf); + if (ret) + goto unlock_mclk; + + ret = radeon_bo_fault_reserve_notify(bo); + if (ret) + goto unlock_resv; + + ret = ttm_bo_vm_fault_reserved(vmf, vmf->vma->vm_page_prot, + TTM_BO_VM_NUM_PREFAULT, 1); + if (ret == VM_FAULT_RETRY && !(vmf->flags & FAULT_FLAG_RETRY_NOWAIT)) + goto unlock_mclk; + +unlock_resv: + dma_resv_unlock(bo->base.resv); + +unlock_mclk: + up_read(&rdev->pm.mclk_lock); + return ret; +} + +static const struct vm_operations_struct radeon_ttm_vm_ops = { + .fault = radeon_ttm_fault, + .open = ttm_bo_vm_open, + .close = ttm_bo_vm_close, + .access = ttm_bo_vm_access +}; + static void radeon_gem_object_free(struct drm_gem_object *gobj) { struct radeon_bo *robj = gem_to_radeon_bo(gobj); @@ -226,6 +262,20 @@ static int radeon_gem_handle_lockup(struct radeon_device *rdev, int r) return r; }
+static int radeon_gem_object_mmap(struct drm_gem_object *obj, struct vm_area_struct *vma) +{ + struct radeon_bo *bo = gem_to_radeon_bo(obj); + struct radeon_device *rdev = radeon_get_rdev(bo->tbo.bdev); + + if (!rdev) + return -EINVAL; + + if (radeon_ttm_tt_has_userptr(rdev, bo->tbo.ttm)) + return -EPERM; + + return drm_gem_ttm_mmap(obj, vma); +} + const struct drm_gem_object_funcs radeon_gem_object_funcs = { .free = radeon_gem_object_free, .open = radeon_gem_object_open, @@ -236,6 +286,8 @@ const struct drm_gem_object_funcs radeon_gem_object_funcs = { .get_sg_table = radeon_gem_prime_get_sg_table, .vmap = drm_gem_ttm_vmap, .vunmap = drm_gem_ttm_vunmap, + .mmap = radeon_gem_object_mmap, + .vm_ops = &radeon_ttm_vm_ops, };
/* diff --git a/drivers/gpu/drm/radeon/radeon_ttm.c b/drivers/gpu/drm/radeon/radeon_ttm.c index 476ce9c24b9f..a5ce43a909a2 100644 --- a/drivers/gpu/drm/radeon/radeon_ttm.c +++ b/drivers/gpu/drm/radeon/radeon_ttm.c @@ -136,17 +136,6 @@ static void radeon_evict_flags(struct ttm_buffer_object *bo, *placement = rbo->placement; }
-static int radeon_verify_access(struct ttm_buffer_object *bo, struct file *filp) -{ - struct radeon_bo *rbo = container_of(bo, struct radeon_bo, tbo); - struct radeon_device *rdev = radeon_get_rdev(bo->bdev); - - if (radeon_ttm_tt_has_userptr(rdev, bo->ttm)) - return -EPERM; - return drm_vma_node_verify_access(&rbo->tbo.base.vma_node, - filp->private_data); -} - static int radeon_move_blit(struct ttm_buffer_object *bo, bool evict, struct ttm_resource *new_mem, @@ -704,7 +693,6 @@ static struct ttm_device_funcs radeon_bo_driver = { .eviction_valuable = ttm_bo_eviction_valuable, .evict_flags = &radeon_evict_flags, .move = &radeon_bo_move, - .verify_access = &radeon_verify_access, .delete_mem_notify = &radeon_bo_delete_mem_notify, .io_mem_reserve = &radeon_ttm_io_mem_reserve, }; @@ -801,59 +789,6 @@ void radeon_ttm_set_active_vram_size(struct radeon_device *rdev, u64 size) man->size = size >> PAGE_SHIFT; }
-static vm_fault_t radeon_ttm_fault(struct vm_fault *vmf) -{ - struct ttm_buffer_object *bo = vmf->vma->vm_private_data; - struct radeon_device *rdev = radeon_get_rdev(bo->bdev); - vm_fault_t ret; - - down_read(&rdev->pm.mclk_lock); - - ret = ttm_bo_vm_reserve(bo, vmf); - if (ret) - goto unlock_mclk; - - ret = radeon_bo_fault_reserve_notify(bo); - if (ret) - goto unlock_resv; - - ret = ttm_bo_vm_fault_reserved(vmf, vmf->vma->vm_page_prot, - TTM_BO_VM_NUM_PREFAULT, 1); - if (ret == VM_FAULT_RETRY && !(vmf->flags & FAULT_FLAG_RETRY_NOWAIT)) - goto unlock_mclk; - -unlock_resv: - dma_resv_unlock(bo->base.resv); - -unlock_mclk: - up_read(&rdev->pm.mclk_lock); - return ret; -} - -static const struct vm_operations_struct radeon_ttm_vm_ops = { - .fault = radeon_ttm_fault, - .open = ttm_bo_vm_open, - .close = ttm_bo_vm_close, - .access = ttm_bo_vm_access -}; - -int radeon_mmap(struct file *filp, struct vm_area_struct *vma) -{ - int r; - struct drm_file *file_priv = filp->private_data; - struct radeon_device *rdev = file_priv->minor->dev->dev_private; - - if (rdev == NULL) - return -EINVAL; - - r = ttm_bo_mmap(filp, vma, &rdev->mman.bdev); - if (unlikely(r != 0)) - return r; - - vma->vm_ops = &radeon_ttm_vm_ops; - return 0; -} - #if defined(CONFIG_DEBUG_FS)
static int radeon_mm_vram_dump_table_show(struct seq_file *m, void *unused) diff --git a/drivers/gpu/drm/radeon/radeon_ttm.h b/drivers/gpu/drm/radeon/radeon_ttm.h index 4d7b90ee2774..91ea7141bc81 100644 --- a/drivers/gpu/drm/radeon/radeon_ttm.h +++ b/drivers/gpu/drm/radeon/radeon_ttm.h @@ -32,6 +32,5 @@ struct radeon_device;
int radeon_ttm_init(struct radeon_device *rdev); void radeon_ttm_fini(struct radeon_device *rdev); -int radeon_mmap(struct file *filp, struct vm_area_struct *vma);
#endif /* __RADEON_TTM_H__ */
Am 06.04.21 um 11:08 schrieb Thomas Zimmermann:
Moving the driver-specific mmap code into a GEM object function allows for using DRM helpers for various mmap callbacks.
This change also allows to support prime-based mmap via DRM's helper drm_gem_prime_mmap().
Permission checks are implemented by drm_gem_mmap(), with an additional check for radeon_ttm_tt_has_userptr() in the GEM object function. The function radeon_verify_access() is now unused and has thus been removed.
As a side effect, amdgpu_ttm_vm_ops and amdgpu_ttm_fault() are now implemented in amdgpu's GEM code.
Signed-off-by: Thomas Zimmermann tzimmermann@suse.de
drivers/gpu/drm/radeon/radeon_drv.c | 3 +- drivers/gpu/drm/radeon/radeon_gem.c | 52 +++++++++++++++++++++++ drivers/gpu/drm/radeon/radeon_ttm.c | 65 ----------------------------- drivers/gpu/drm/radeon/radeon_ttm.h | 1 - 4 files changed, 54 insertions(+), 67 deletions(-)
diff --git a/drivers/gpu/drm/radeon/radeon_drv.c b/drivers/gpu/drm/radeon/radeon_drv.c index efeb115ae70e..4039b6d71aa2 100644 --- a/drivers/gpu/drm/radeon/radeon_drv.c +++ b/drivers/gpu/drm/radeon/radeon_drv.c @@ -557,7 +557,7 @@ static const struct file_operations radeon_driver_kms_fops = { .open = drm_open, .release = drm_release, .unlocked_ioctl = radeon_drm_ioctl,
- .mmap = radeon_mmap,
- .mmap = drm_gem_mmap, .poll = drm_poll, .read = drm_read, #ifdef CONFIG_COMPAT
@@ -632,6 +632,7 @@ static const struct drm_driver kms_driver = { .prime_handle_to_fd = drm_gem_prime_handle_to_fd, .prime_fd_to_handle = drm_gem_prime_fd_to_handle, .gem_prime_import_sg_table = radeon_gem_prime_import_sg_table,
.gem_prime_mmap = drm_gem_prime_mmap,
.name = DRIVER_NAME, .desc = DRIVER_DESC,
diff --git a/drivers/gpu/drm/radeon/radeon_gem.c b/drivers/gpu/drm/radeon/radeon_gem.c index 05ea2f39f626..71e8737bce01 100644 --- a/drivers/gpu/drm/radeon/radeon_gem.c +++ b/drivers/gpu/drm/radeon/radeon_gem.c @@ -44,6 +44,42 @@ void radeon_gem_prime_unpin(struct drm_gem_object *obj);
const struct drm_gem_object_funcs radeon_gem_object_funcs;
+static vm_fault_t radeon_ttm_fault(struct vm_fault *vmf)
Please name this radeon_gem_fault or radeon_gem_object_fault.
Apart from that looks good to me.
Christian.
+{
- struct ttm_buffer_object *bo = vmf->vma->vm_private_data;
- struct radeon_device *rdev = radeon_get_rdev(bo->bdev);
- vm_fault_t ret;
- down_read(&rdev->pm.mclk_lock);
- ret = ttm_bo_vm_reserve(bo, vmf);
- if (ret)
goto unlock_mclk;
- ret = radeon_bo_fault_reserve_notify(bo);
- if (ret)
goto unlock_resv;
- ret = ttm_bo_vm_fault_reserved(vmf, vmf->vma->vm_page_prot,
TTM_BO_VM_NUM_PREFAULT, 1);
- if (ret == VM_FAULT_RETRY && !(vmf->flags & FAULT_FLAG_RETRY_NOWAIT))
goto unlock_mclk;
+unlock_resv:
- dma_resv_unlock(bo->base.resv);
+unlock_mclk:
- up_read(&rdev->pm.mclk_lock);
- return ret;
+}
+static const struct vm_operations_struct radeon_ttm_vm_ops = {
- .fault = radeon_ttm_fault,
- .open = ttm_bo_vm_open,
- .close = ttm_bo_vm_close,
- .access = ttm_bo_vm_access
+};
- static void radeon_gem_object_free(struct drm_gem_object *gobj) { struct radeon_bo *robj = gem_to_radeon_bo(gobj);
@@ -226,6 +262,20 @@ static int radeon_gem_handle_lockup(struct radeon_device *rdev, int r) return r; }
+static int radeon_gem_object_mmap(struct drm_gem_object *obj, struct vm_area_struct *vma) +{
- struct radeon_bo *bo = gem_to_radeon_bo(obj);
- struct radeon_device *rdev = radeon_get_rdev(bo->tbo.bdev);
- if (!rdev)
return -EINVAL;
- if (radeon_ttm_tt_has_userptr(rdev, bo->tbo.ttm))
return -EPERM;
- return drm_gem_ttm_mmap(obj, vma);
+}
- const struct drm_gem_object_funcs radeon_gem_object_funcs = { .free = radeon_gem_object_free, .open = radeon_gem_object_open,
@@ -236,6 +286,8 @@ const struct drm_gem_object_funcs radeon_gem_object_funcs = { .get_sg_table = radeon_gem_prime_get_sg_table, .vmap = drm_gem_ttm_vmap, .vunmap = drm_gem_ttm_vunmap,
.mmap = radeon_gem_object_mmap,
.vm_ops = &radeon_ttm_vm_ops, };
/*
diff --git a/drivers/gpu/drm/radeon/radeon_ttm.c b/drivers/gpu/drm/radeon/radeon_ttm.c index 476ce9c24b9f..a5ce43a909a2 100644 --- a/drivers/gpu/drm/radeon/radeon_ttm.c +++ b/drivers/gpu/drm/radeon/radeon_ttm.c @@ -136,17 +136,6 @@ static void radeon_evict_flags(struct ttm_buffer_object *bo, *placement = rbo->placement; }
-static int radeon_verify_access(struct ttm_buffer_object *bo, struct file *filp) -{
- struct radeon_bo *rbo = container_of(bo, struct radeon_bo, tbo);
- struct radeon_device *rdev = radeon_get_rdev(bo->bdev);
- if (radeon_ttm_tt_has_userptr(rdev, bo->ttm))
return -EPERM;
- return drm_vma_node_verify_access(&rbo->tbo.base.vma_node,
filp->private_data);
-}
- static int radeon_move_blit(struct ttm_buffer_object *bo, bool evict, struct ttm_resource *new_mem,
@@ -704,7 +693,6 @@ static struct ttm_device_funcs radeon_bo_driver = { .eviction_valuable = ttm_bo_eviction_valuable, .evict_flags = &radeon_evict_flags, .move = &radeon_bo_move,
- .verify_access = &radeon_verify_access, .delete_mem_notify = &radeon_bo_delete_mem_notify, .io_mem_reserve = &radeon_ttm_io_mem_reserve, };
@@ -801,59 +789,6 @@ void radeon_ttm_set_active_vram_size(struct radeon_device *rdev, u64 size) man->size = size >> PAGE_SHIFT; }
-static vm_fault_t radeon_ttm_fault(struct vm_fault *vmf) -{
- struct ttm_buffer_object *bo = vmf->vma->vm_private_data;
- struct radeon_device *rdev = radeon_get_rdev(bo->bdev);
- vm_fault_t ret;
- down_read(&rdev->pm.mclk_lock);
- ret = ttm_bo_vm_reserve(bo, vmf);
- if (ret)
goto unlock_mclk;
- ret = radeon_bo_fault_reserve_notify(bo);
- if (ret)
goto unlock_resv;
- ret = ttm_bo_vm_fault_reserved(vmf, vmf->vma->vm_page_prot,
TTM_BO_VM_NUM_PREFAULT, 1);
- if (ret == VM_FAULT_RETRY && !(vmf->flags & FAULT_FLAG_RETRY_NOWAIT))
goto unlock_mclk;
-unlock_resv:
- dma_resv_unlock(bo->base.resv);
-unlock_mclk:
- up_read(&rdev->pm.mclk_lock);
- return ret;
-}
-static const struct vm_operations_struct radeon_ttm_vm_ops = {
- .fault = radeon_ttm_fault,
- .open = ttm_bo_vm_open,
- .close = ttm_bo_vm_close,
- .access = ttm_bo_vm_access
-};
-int radeon_mmap(struct file *filp, struct vm_area_struct *vma) -{
- int r;
- struct drm_file *file_priv = filp->private_data;
- struct radeon_device *rdev = file_priv->minor->dev->dev_private;
- if (rdev == NULL)
return -EINVAL;
- r = ttm_bo_mmap(filp, vma, &rdev->mman.bdev);
- if (unlikely(r != 0))
return r;
- vma->vm_ops = &radeon_ttm_vm_ops;
- return 0;
-}
#if defined(CONFIG_DEBUG_FS)
static int radeon_mm_vram_dump_table_show(struct seq_file *m, void *unused)
diff --git a/drivers/gpu/drm/radeon/radeon_ttm.h b/drivers/gpu/drm/radeon/radeon_ttm.h index 4d7b90ee2774..91ea7141bc81 100644 --- a/drivers/gpu/drm/radeon/radeon_ttm.h +++ b/drivers/gpu/drm/radeon/radeon_ttm.h @@ -32,6 +32,5 @@ struct radeon_device;
int radeon_ttm_init(struct radeon_device *rdev); void radeon_ttm_fini(struct radeon_device *rdev); -int radeon_mmap(struct file *filp, struct vm_area_struct *vma);
#endif /* __RADEON_TTM_H__ */
On Tue, Apr 6, 2021 at 5:09 AM Thomas Zimmermann tzimmermann@suse.de wrote:
Moving the driver-specific mmap code into a GEM object function allows for using DRM helpers for various mmap callbacks.
This change also allows to support prime-based mmap via DRM's helper drm_gem_prime_mmap().
Permission checks are implemented by drm_gem_mmap(), with an additional check for radeon_ttm_tt_has_userptr() in the GEM object function. The function radeon_verify_access() is now unused and has thus been removed.
As a side effect, amdgpu_ttm_vm_ops and amdgpu_ttm_fault() are now implemented in amdgpu's GEM code.
s/amdgpu/radeon/
Alex
Signed-off-by: Thomas Zimmermann tzimmermann@suse.de
drivers/gpu/drm/radeon/radeon_drv.c | 3 +- drivers/gpu/drm/radeon/radeon_gem.c | 52 +++++++++++++++++++++++ drivers/gpu/drm/radeon/radeon_ttm.c | 65 ----------------------------- drivers/gpu/drm/radeon/radeon_ttm.h | 1 - 4 files changed, 54 insertions(+), 67 deletions(-)
diff --git a/drivers/gpu/drm/radeon/radeon_drv.c b/drivers/gpu/drm/radeon/radeon_drv.c index efeb115ae70e..4039b6d71aa2 100644 --- a/drivers/gpu/drm/radeon/radeon_drv.c +++ b/drivers/gpu/drm/radeon/radeon_drv.c @@ -557,7 +557,7 @@ static const struct file_operations radeon_driver_kms_fops = { .open = drm_open, .release = drm_release, .unlocked_ioctl = radeon_drm_ioctl,
.mmap = radeon_mmap,
.mmap = drm_gem_mmap, .poll = drm_poll, .read = drm_read,
#ifdef CONFIG_COMPAT @@ -632,6 +632,7 @@ static const struct drm_driver kms_driver = { .prime_handle_to_fd = drm_gem_prime_handle_to_fd, .prime_fd_to_handle = drm_gem_prime_fd_to_handle, .gem_prime_import_sg_table = radeon_gem_prime_import_sg_table,
.gem_prime_mmap = drm_gem_prime_mmap, .name = DRIVER_NAME, .desc = DRIVER_DESC,
diff --git a/drivers/gpu/drm/radeon/radeon_gem.c b/drivers/gpu/drm/radeon/radeon_gem.c index 05ea2f39f626..71e8737bce01 100644 --- a/drivers/gpu/drm/radeon/radeon_gem.c +++ b/drivers/gpu/drm/radeon/radeon_gem.c @@ -44,6 +44,42 @@ void radeon_gem_prime_unpin(struct drm_gem_object *obj);
const struct drm_gem_object_funcs radeon_gem_object_funcs;
+static vm_fault_t radeon_ttm_fault(struct vm_fault *vmf) +{
struct ttm_buffer_object *bo = vmf->vma->vm_private_data;
struct radeon_device *rdev = radeon_get_rdev(bo->bdev);
vm_fault_t ret;
down_read(&rdev->pm.mclk_lock);
ret = ttm_bo_vm_reserve(bo, vmf);
if (ret)
goto unlock_mclk;
ret = radeon_bo_fault_reserve_notify(bo);
if (ret)
goto unlock_resv;
ret = ttm_bo_vm_fault_reserved(vmf, vmf->vma->vm_page_prot,
TTM_BO_VM_NUM_PREFAULT, 1);
if (ret == VM_FAULT_RETRY && !(vmf->flags & FAULT_FLAG_RETRY_NOWAIT))
goto unlock_mclk;
+unlock_resv:
dma_resv_unlock(bo->base.resv);
+unlock_mclk:
up_read(&rdev->pm.mclk_lock);
return ret;
+}
+static const struct vm_operations_struct radeon_ttm_vm_ops = {
.fault = radeon_ttm_fault,
.open = ttm_bo_vm_open,
.close = ttm_bo_vm_close,
.access = ttm_bo_vm_access
+};
static void radeon_gem_object_free(struct drm_gem_object *gobj) { struct radeon_bo *robj = gem_to_radeon_bo(gobj); @@ -226,6 +262,20 @@ static int radeon_gem_handle_lockup(struct radeon_device *rdev, int r) return r; }
+static int radeon_gem_object_mmap(struct drm_gem_object *obj, struct vm_area_struct *vma) +{
struct radeon_bo *bo = gem_to_radeon_bo(obj);
struct radeon_device *rdev = radeon_get_rdev(bo->tbo.bdev);
if (!rdev)
return -EINVAL;
if (radeon_ttm_tt_has_userptr(rdev, bo->tbo.ttm))
return -EPERM;
return drm_gem_ttm_mmap(obj, vma);
+}
const struct drm_gem_object_funcs radeon_gem_object_funcs = { .free = radeon_gem_object_free, .open = radeon_gem_object_open, @@ -236,6 +286,8 @@ const struct drm_gem_object_funcs radeon_gem_object_funcs = { .get_sg_table = radeon_gem_prime_get_sg_table, .vmap = drm_gem_ttm_vmap, .vunmap = drm_gem_ttm_vunmap,
.mmap = radeon_gem_object_mmap,
.vm_ops = &radeon_ttm_vm_ops,
};
/* diff --git a/drivers/gpu/drm/radeon/radeon_ttm.c b/drivers/gpu/drm/radeon/radeon_ttm.c index 476ce9c24b9f..a5ce43a909a2 100644 --- a/drivers/gpu/drm/radeon/radeon_ttm.c +++ b/drivers/gpu/drm/radeon/radeon_ttm.c @@ -136,17 +136,6 @@ static void radeon_evict_flags(struct ttm_buffer_object *bo, *placement = rbo->placement; }
-static int radeon_verify_access(struct ttm_buffer_object *bo, struct file *filp) -{
struct radeon_bo *rbo = container_of(bo, struct radeon_bo, tbo);
struct radeon_device *rdev = radeon_get_rdev(bo->bdev);
if (radeon_ttm_tt_has_userptr(rdev, bo->ttm))
return -EPERM;
return drm_vma_node_verify_access(&rbo->tbo.base.vma_node,
filp->private_data);
-}
static int radeon_move_blit(struct ttm_buffer_object *bo, bool evict, struct ttm_resource *new_mem, @@ -704,7 +693,6 @@ static struct ttm_device_funcs radeon_bo_driver = { .eviction_valuable = ttm_bo_eviction_valuable, .evict_flags = &radeon_evict_flags, .move = &radeon_bo_move,
.verify_access = &radeon_verify_access, .delete_mem_notify = &radeon_bo_delete_mem_notify, .io_mem_reserve = &radeon_ttm_io_mem_reserve,
}; @@ -801,59 +789,6 @@ void radeon_ttm_set_active_vram_size(struct radeon_device *rdev, u64 size) man->size = size >> PAGE_SHIFT; }
-static vm_fault_t radeon_ttm_fault(struct vm_fault *vmf) -{
struct ttm_buffer_object *bo = vmf->vma->vm_private_data;
struct radeon_device *rdev = radeon_get_rdev(bo->bdev);
vm_fault_t ret;
down_read(&rdev->pm.mclk_lock);
ret = ttm_bo_vm_reserve(bo, vmf);
if (ret)
goto unlock_mclk;
ret = radeon_bo_fault_reserve_notify(bo);
if (ret)
goto unlock_resv;
ret = ttm_bo_vm_fault_reserved(vmf, vmf->vma->vm_page_prot,
TTM_BO_VM_NUM_PREFAULT, 1);
if (ret == VM_FAULT_RETRY && !(vmf->flags & FAULT_FLAG_RETRY_NOWAIT))
goto unlock_mclk;
-unlock_resv:
dma_resv_unlock(bo->base.resv);
-unlock_mclk:
up_read(&rdev->pm.mclk_lock);
return ret;
-}
-static const struct vm_operations_struct radeon_ttm_vm_ops = {
.fault = radeon_ttm_fault,
.open = ttm_bo_vm_open,
.close = ttm_bo_vm_close,
.access = ttm_bo_vm_access
-};
-int radeon_mmap(struct file *filp, struct vm_area_struct *vma) -{
int r;
struct drm_file *file_priv = filp->private_data;
struct radeon_device *rdev = file_priv->minor->dev->dev_private;
if (rdev == NULL)
return -EINVAL;
r = ttm_bo_mmap(filp, vma, &rdev->mman.bdev);
if (unlikely(r != 0))
return r;
vma->vm_ops = &radeon_ttm_vm_ops;
return 0;
-}
#if defined(CONFIG_DEBUG_FS)
static int radeon_mm_vram_dump_table_show(struct seq_file *m, void *unused) diff --git a/drivers/gpu/drm/radeon/radeon_ttm.h b/drivers/gpu/drm/radeon/radeon_ttm.h index 4d7b90ee2774..91ea7141bc81 100644 --- a/drivers/gpu/drm/radeon/radeon_ttm.h +++ b/drivers/gpu/drm/radeon/radeon_ttm.h @@ -32,6 +32,5 @@ struct radeon_device;
int radeon_ttm_init(struct radeon_device *rdev); void radeon_ttm_fini(struct radeon_device *rdev); -int radeon_mmap(struct file *filp, struct vm_area_struct *vma);
#endif /* __RADEON_TTM_H__ */
2.30.2
dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Moving the driver-specific mmap code into a GEM object function allows for using DRM helpers for various mmap callbacks.
The GEM object function is provided by GEM TTM helpers. Nouveau's implementation of verify_access is unused and has been removed. Access permissions are validated by the DRM helpers.
As a side effect, nouveau_ttm_vm_ops and nouveau_ttm_fault() are now implemented in nouveau's GEM code.
Signed-off-by: Thomas Zimmermann tzimmermann@suse.de --- drivers/gpu/drm/nouveau/nouveau_bo.c | 10 ------ drivers/gpu/drm/nouveau/nouveau_drm.c | 3 +- drivers/gpu/drm/nouveau/nouveau_gem.c | 36 ++++++++++++++++++++ drivers/gpu/drm/nouveau/nouveau_ttm.c | 49 --------------------------- drivers/gpu/drm/nouveau/nouveau_ttm.h | 1 - 5 files changed, 38 insertions(+), 61 deletions(-)
diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.c b/drivers/gpu/drm/nouveau/nouveau_bo.c index 3e09df0472ce..bc67cbccc83b 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bo.c +++ b/drivers/gpu/drm/nouveau/nouveau_bo.c @@ -1051,15 +1051,6 @@ nouveau_bo_move(struct ttm_buffer_object *bo, bool evict, return ret; }
-static int -nouveau_bo_verify_access(struct ttm_buffer_object *bo, struct file *filp) -{ - struct nouveau_bo *nvbo = nouveau_bo(bo); - - return drm_vma_node_verify_access(&nvbo->bo.base.vma_node, - filp->private_data); -} - static void nouveau_ttm_io_mem_free_locked(struct nouveau_drm *drm, struct ttm_resource *reg) @@ -1332,7 +1323,6 @@ struct ttm_device_funcs nouveau_bo_driver = { .evict_flags = nouveau_bo_evict_flags, .delete_mem_notify = nouveau_bo_delete_mem_notify, .move = nouveau_bo_move, - .verify_access = nouveau_bo_verify_access, .io_mem_reserve = &nouveau_ttm_io_mem_reserve, .io_mem_free = &nouveau_ttm_io_mem_free, }; diff --git a/drivers/gpu/drm/nouveau/nouveau_drm.c b/drivers/gpu/drm/nouveau/nouveau_drm.c index 885815ea917f..7586328c1de5 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drm.c +++ b/drivers/gpu/drm/nouveau/nouveau_drm.c @@ -1177,7 +1177,7 @@ nouveau_driver_fops = { .open = drm_open, .release = drm_release, .unlocked_ioctl = nouveau_drm_ioctl, - .mmap = nouveau_ttm_mmap, + .mmap = drm_gem_mmap, .poll = drm_poll, .read = drm_read, #if defined(CONFIG_COMPAT) @@ -1210,6 +1210,7 @@ driver_stub = { .prime_handle_to_fd = drm_gem_prime_handle_to_fd, .prime_fd_to_handle = drm_gem_prime_fd_to_handle, .gem_prime_import_sg_table = nouveau_gem_prime_import_sg_table, + .gem_prime_mmap = drm_gem_prime_mmap,
.dumb_create = nouveau_display_dumb_create, .dumb_map_offset = nouveau_display_dumb_map_offset, diff --git a/drivers/gpu/drm/nouveau/nouveau_gem.c b/drivers/gpu/drm/nouveau/nouveau_gem.c index c88cbb85f101..71dfac820c4d 100644 --- a/drivers/gpu/drm/nouveau/nouveau_gem.c +++ b/drivers/gpu/drm/nouveau/nouveau_gem.c @@ -39,6 +39,40 @@ #include <nvif/class.h> #include <nvif/push206e.h>
+static vm_fault_t nouveau_ttm_fault(struct vm_fault *vmf) +{ + struct vm_area_struct *vma = vmf->vma; + struct ttm_buffer_object *bo = vma->vm_private_data; + pgprot_t prot; + vm_fault_t ret; + + ret = ttm_bo_vm_reserve(bo, vmf); + if (ret) + return ret; + + ret = nouveau_ttm_fault_reserve_notify(bo); + if (ret) + goto error_unlock; + + nouveau_bo_del_io_reserve_lru(bo); + prot = vm_get_page_prot(vma->vm_flags); + ret = ttm_bo_vm_fault_reserved(vmf, prot, TTM_BO_VM_NUM_PREFAULT, 1); + nouveau_bo_add_io_reserve_lru(bo); + if (ret == VM_FAULT_RETRY && !(vmf->flags & FAULT_FLAG_RETRY_NOWAIT)) + return ret; + +error_unlock: + dma_resv_unlock(bo->base.resv); + return ret; +} + +static const struct vm_operations_struct nouveau_ttm_vm_ops = { + .fault = nouveau_ttm_fault, + .open = ttm_bo_vm_open, + .close = ttm_bo_vm_close, + .access = ttm_bo_vm_access +}; + void nouveau_gem_object_del(struct drm_gem_object *gem) { @@ -180,6 +214,8 @@ const struct drm_gem_object_funcs nouveau_gem_object_funcs = { .get_sg_table = nouveau_gem_prime_get_sg_table, .vmap = drm_gem_ttm_vmap, .vunmap = drm_gem_ttm_vunmap, + .mmap = drm_gem_ttm_mmap, + .vm_ops = &nouveau_ttm_vm_ops, };
int diff --git a/drivers/gpu/drm/nouveau/nouveau_ttm.c b/drivers/gpu/drm/nouveau/nouveau_ttm.c index b81ae90b8449..e511a26379da 100644 --- a/drivers/gpu/drm/nouveau/nouveau_ttm.c +++ b/drivers/gpu/drm/nouveau/nouveau_ttm.c @@ -127,55 +127,6 @@ const struct ttm_resource_manager_func nv04_gart_manager = { .free = nouveau_manager_del, };
-static vm_fault_t nouveau_ttm_fault(struct vm_fault *vmf) -{ - struct vm_area_struct *vma = vmf->vma; - struct ttm_buffer_object *bo = vma->vm_private_data; - pgprot_t prot; - vm_fault_t ret; - - ret = ttm_bo_vm_reserve(bo, vmf); - if (ret) - return ret; - - ret = nouveau_ttm_fault_reserve_notify(bo); - if (ret) - goto error_unlock; - - nouveau_bo_del_io_reserve_lru(bo); - prot = vm_get_page_prot(vma->vm_flags); - ret = ttm_bo_vm_fault_reserved(vmf, prot, TTM_BO_VM_NUM_PREFAULT, 1); - nouveau_bo_add_io_reserve_lru(bo); - if (ret == VM_FAULT_RETRY && !(vmf->flags & FAULT_FLAG_RETRY_NOWAIT)) - return ret; - -error_unlock: - dma_resv_unlock(bo->base.resv); - return ret; -} - -static const struct vm_operations_struct nouveau_ttm_vm_ops = { - .fault = nouveau_ttm_fault, - .open = ttm_bo_vm_open, - .close = ttm_bo_vm_close, - .access = ttm_bo_vm_access -}; - -int -nouveau_ttm_mmap(struct file *filp, struct vm_area_struct *vma) -{ - struct drm_file *file_priv = filp->private_data; - struct nouveau_drm *drm = nouveau_drm(file_priv->minor->dev); - int ret; - - ret = ttm_bo_mmap(filp, vma, &drm->ttm.bdev); - if (ret) - return ret; - - vma->vm_ops = &nouveau_ttm_vm_ops; - return 0; -} - static int nouveau_ttm_init_host(struct nouveau_drm *drm, u8 kind) { diff --git a/drivers/gpu/drm/nouveau/nouveau_ttm.h b/drivers/gpu/drm/nouveau/nouveau_ttm.h index dbf6dc238efd..2f0efda7ccdb 100644 --- a/drivers/gpu/drm/nouveau/nouveau_ttm.h +++ b/drivers/gpu/drm/nouveau/nouveau_ttm.h @@ -17,7 +17,6 @@ struct ttm_tt *nouveau_sgdma_create_ttm(struct ttm_buffer_object *bo,
int nouveau_ttm_init(struct nouveau_drm *drm); void nouveau_ttm_fini(struct nouveau_drm *drm); -int nouveau_ttm_mmap(struct file *, struct vm_area_struct *);
int nouveau_ttm_global_init(struct nouveau_drm *); void nouveau_ttm_global_release(struct nouveau_drm *);
The vmwgfx driver is the only remaining user of ttm_bo_mmap(). Inline the code. The internal helper ttm_bo_vm_lookup() is now also part of vmwgfx as vmw_bo_vm_lookup().
Signed-off-by: Thomas Zimmermann tzimmermann@suse.de --- drivers/gpu/drm/vmwgfx/vmwgfx_ttm_glue.c | 54 ++++++++++++++++++++++-- 1 file changed, 51 insertions(+), 3 deletions(-)
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_ttm_glue.c b/drivers/gpu/drm/vmwgfx/vmwgfx_ttm_glue.c index cb9975889e2f..3eaad00668f2 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_ttm_glue.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_ttm_glue.c @@ -27,6 +27,30 @@
#include "vmwgfx_drv.h"
+static struct ttm_buffer_object *vmw_bo_vm_lookup(struct ttm_device *bdev, + unsigned long offset, + unsigned long pages) +{ + struct drm_vma_offset_node *node; + struct ttm_buffer_object *bo = NULL; + + drm_vma_offset_lock_lookup(bdev->vma_manager); + + node = drm_vma_offset_lookup_locked(bdev->vma_manager, offset, pages); + if (likely(node)) { + bo = container_of(node, struct ttm_buffer_object, + base.vma_node); + bo = ttm_bo_get_unless_zero(bo); + } + + drm_vma_offset_unlock_lookup(bdev->vma_manager); + + if (!bo) + pr_err("Could not find buffer object to map\n"); + + return bo; +} + int vmw_mmap(struct file *filp, struct vm_area_struct *vma) { static const struct vm_operations_struct vmw_vm_ops = { @@ -41,10 +65,28 @@ int vmw_mmap(struct file *filp, struct vm_area_struct *vma) }; struct drm_file *file_priv = filp->private_data; struct vmw_private *dev_priv = vmw_priv(file_priv->minor->dev); - int ret = ttm_bo_mmap(filp, vma, &dev_priv->bdev); + struct ttm_device *bdev = &dev_priv->bdev; + struct ttm_buffer_object *bo; + int ret; + + if (unlikely(vma->vm_pgoff < DRM_FILE_PAGE_OFFSET_START)) + return -EINVAL; + + bo = vmw_bo_vm_lookup(bdev, vma->vm_pgoff, vma_pages(vma)); + if (unlikely(!bo)) + return -EINVAL;
- if (ret) - return ret; + if (unlikely(!bo->bdev->funcs->verify_access)) { + ret = -EPERM; + goto out_unref; + } + ret = bo->bdev->funcs->verify_access(bo, filp); + if (unlikely(ret != 0)) + goto out_unref; + + ret = ttm_bo_mmap_obj(vma, bo); + if (unlikely(ret != 0)) + goto out_unref;
vma->vm_ops = &vmw_vm_ops;
@@ -52,7 +94,13 @@ int vmw_mmap(struct file *filp, struct vm_area_struct *vma) if (!is_cow_mapping(vma->vm_flags)) vma->vm_flags = (vma->vm_flags & ~VM_MIXEDMAP) | VM_PFNMAP;
+ ttm_bo_put(bo); /* release extra ref taken by ttm_bo_mmap_obj() */ + return 0; + +out_unref: + ttm_bo_put(bo); + return ret; }
/* struct vmw_validation_mem callback */
On 4/6/21 5:09 AM, Thomas Zimmermann wrote:
The vmwgfx driver is the only remaining user of ttm_bo_mmap(). Inline the code. The internal helper ttm_bo_vm_lookup() is now also part of vmwgfx as vmw_bo_vm_lookup().
Signed-off-by: Thomas Zimmermann tzimmermann@suse.de
drivers/gpu/drm/vmwgfx/vmwgfx_ttm_glue.c | 54 ++++++++++++++++++++++-- 1 file changed, 51 insertions(+), 3 deletions(-)
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_ttm_glue.c b/drivers/gpu/drm/vmwgfx/vmwgfx_ttm_glue.c index cb9975889e2f..3eaad00668f2 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_ttm_glue.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_ttm_glue.c @@ -27,6 +27,30 @@
#include "vmwgfx_drv.h"
+static struct ttm_buffer_object *vmw_bo_vm_lookup(struct ttm_device *bdev,
unsigned long offset,
unsigned long pages)
+{
- struct drm_vma_offset_node *node;
- struct ttm_buffer_object *bo = NULL;
- drm_vma_offset_lock_lookup(bdev->vma_manager);
- node = drm_vma_offset_lookup_locked(bdev->vma_manager, offset, pages);
- if (likely(node)) {
bo = container_of(node, struct ttm_buffer_object,
base.vma_node);
bo = ttm_bo_get_unless_zero(bo);
- }
- drm_vma_offset_unlock_lookup(bdev->vma_manager);
- if (!bo)
pr_err("Could not find buffer object to map\n");
It's not a big deal and I know it's been in the original, but since you're already in there if you could change this to DRM_ERR that'd be great. Either way: Reviewed-by: Zack Rusin zackr@vmware.com
z
Vmwgfx is the only user of the TTM's verify_access callback. Inline the call and avoid the indirection through the function pointer.
Signed-off-by: Thomas Zimmermann tzimmermann@suse.de --- drivers/gpu/drm/vmwgfx/vmwgfx_ttm_buffer.c | 9 --------- drivers/gpu/drm/vmwgfx/vmwgfx_ttm_glue.c | 7 ++----- 2 files changed, 2 insertions(+), 14 deletions(-)
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_ttm_buffer.c b/drivers/gpu/drm/vmwgfx/vmwgfx_ttm_buffer.c index 2dc031fe4a90..a079734f9d68 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_ttm_buffer.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_ttm_buffer.c @@ -658,14 +658,6 @@ static void vmw_evict_flags(struct ttm_buffer_object *bo, *placement = vmw_sys_placement; }
-static int vmw_verify_access(struct ttm_buffer_object *bo, struct file *filp) -{ - struct ttm_object_file *tfile = - vmw_fpriv((struct drm_file *)filp->private_data)->tfile; - - return vmw_user_bo_verify_access(bo, tfile); -} - static int vmw_ttm_io_mem_reserve(struct ttm_device *bdev, struct ttm_resource *mem) { struct vmw_private *dev_priv = container_of(bdev, struct vmw_private, bdev); @@ -768,7 +760,6 @@ struct ttm_device_funcs vmw_bo_driver = { .eviction_valuable = ttm_bo_eviction_valuable, .evict_flags = vmw_evict_flags, .move = vmw_move, - .verify_access = vmw_verify_access, .swap_notify = vmw_swap_notify, .io_mem_reserve = &vmw_ttm_io_mem_reserve, }; diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_ttm_glue.c b/drivers/gpu/drm/vmwgfx/vmwgfx_ttm_glue.c index 3eaad00668f2..2574d4707407 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_ttm_glue.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_ttm_glue.c @@ -65,6 +65,7 @@ int vmw_mmap(struct file *filp, struct vm_area_struct *vma) }; struct drm_file *file_priv = filp->private_data; struct vmw_private *dev_priv = vmw_priv(file_priv->minor->dev); + struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile; struct ttm_device *bdev = &dev_priv->bdev; struct ttm_buffer_object *bo; int ret; @@ -76,11 +77,7 @@ int vmw_mmap(struct file *filp, struct vm_area_struct *vma) if (unlikely(!bo)) return -EINVAL;
- if (unlikely(!bo->bdev->funcs->verify_access)) { - ret = -EPERM; - goto out_unref; - } - ret = bo->bdev->funcs->verify_access(bo, filp); + ret = vmw_user_bo_verify_access(bo, tfile); if (unlikely(ret != 0)) goto out_unref;
On 4/6/21 5:09 AM, Thomas Zimmermann wrote:
Vmwgfx is the only user of the TTM's verify_access callback. Inline the call and avoid the indirection through the function pointer.
Signed-off-by: Thomas Zimmermann tzimmermann@suse.de
drivers/gpu/drm/vmwgfx/vmwgfx_ttm_buffer.c | 9 --------- drivers/gpu/drm/vmwgfx/vmwgfx_ttm_glue.c | 7 ++----- 2 files changed, 2 insertions(+), 14 deletions(-)
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_ttm_buffer.c b/drivers/gpu/drm/vmwgfx/vmwgfx_ttm_buffer.c index 2dc031fe4a90..a079734f9d68 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_ttm_buffer.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_ttm_buffer.c @@ -658,14 +658,6 @@ static void vmw_evict_flags(struct ttm_buffer_object *bo, *placement = vmw_sys_placement; }
-static int vmw_verify_access(struct ttm_buffer_object *bo, struct file *filp) -{
- struct ttm_object_file *tfile =
vmw_fpriv((struct drm_file *)filp->private_data)->tfile;
- return vmw_user_bo_verify_access(bo, tfile);
-}
- static int vmw_ttm_io_mem_reserve(struct ttm_device *bdev, struct ttm_resource *mem) { struct vmw_private *dev_priv = container_of(bdev, struct vmw_private, bdev);
@@ -768,7 +760,6 @@ struct ttm_device_funcs vmw_bo_driver = { .eviction_valuable = ttm_bo_eviction_valuable, .evict_flags = vmw_evict_flags, .move = vmw_move,
- .verify_access = vmw_verify_access, .swap_notify = vmw_swap_notify, .io_mem_reserve = &vmw_ttm_io_mem_reserve, };
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_ttm_glue.c b/drivers/gpu/drm/vmwgfx/vmwgfx_ttm_glue.c index 3eaad00668f2..2574d4707407 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_ttm_glue.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_ttm_glue.c @@ -65,6 +65,7 @@ int vmw_mmap(struct file *filp, struct vm_area_struct *vma) }; struct drm_file *file_priv = filp->private_data; struct vmw_private *dev_priv = vmw_priv(file_priv->minor->dev);
- struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile; struct ttm_device *bdev = &dev_priv->bdev; struct ttm_buffer_object *bo; int ret;
@@ -76,11 +77,7 @@ int vmw_mmap(struct file *filp, struct vm_area_struct *vma) if (unlikely(!bo)) return -EINVAL;
- if (unlikely(!bo->bdev->funcs->verify_access)) {
ret = -EPERM;
goto out_unref;
- }
- ret = bo->bdev->funcs->verify_access(bo, filp);
- ret = vmw_user_bo_verify_access(bo, tfile); if (unlikely(ret != 0)) goto out_unref;
Looks great.
Reviewed-by: Zack Rusin zackr@vmware.com
z
The function ttm_bo_mmap is unused. Remove it and it's helpers; including the verify_access callback in struct ttm_device_funcs.
Signed-off-by: Thomas Zimmermann tzimmermann@suse.de --- drivers/gpu/drm/ttm/ttm_bo_vm.c | 53 --------------------------------- include/drm/ttm/ttm_bo_api.h | 13 -------- include/drm/ttm/ttm_device.h | 15 ---------- 3 files changed, 81 deletions(-)
diff --git a/drivers/gpu/drm/ttm/ttm_bo_vm.c b/drivers/gpu/drm/ttm/ttm_bo_vm.c index bf4a213bc66c..6cd352399941 100644 --- a/drivers/gpu/drm/ttm/ttm_bo_vm.c +++ b/drivers/gpu/drm/ttm/ttm_bo_vm.c @@ -508,30 +508,6 @@ static const struct vm_operations_struct ttm_bo_vm_ops = { .access = ttm_bo_vm_access, };
-static struct ttm_buffer_object *ttm_bo_vm_lookup(struct ttm_device *bdev, - unsigned long offset, - unsigned long pages) -{ - struct drm_vma_offset_node *node; - struct ttm_buffer_object *bo = NULL; - - drm_vma_offset_lock_lookup(bdev->vma_manager); - - node = drm_vma_offset_lookup_locked(bdev->vma_manager, offset, pages); - if (likely(node)) { - bo = container_of(node, struct ttm_buffer_object, - base.vma_node); - bo = ttm_bo_get_unless_zero(bo); - } - - drm_vma_offset_unlock_lookup(bdev->vma_manager); - - if (!bo) - pr_err("Could not find buffer object to map\n"); - - return bo; -} - static void ttm_bo_mmap_vma_setup(struct ttm_buffer_object *bo, struct vm_area_struct *vma) { /* @@ -559,35 +535,6 @@ static void ttm_bo_mmap_vma_setup(struct ttm_buffer_object *bo, struct vm_area_s vma->vm_flags |= VM_IO | VM_DONTEXPAND | VM_DONTDUMP; }
-int ttm_bo_mmap(struct file *filp, struct vm_area_struct *vma, - struct ttm_device *bdev) -{ - struct ttm_buffer_object *bo; - int ret; - - if (unlikely(vma->vm_pgoff < DRM_FILE_PAGE_OFFSET_START)) - return -EINVAL; - - bo = ttm_bo_vm_lookup(bdev, vma->vm_pgoff, vma_pages(vma)); - if (unlikely(!bo)) - return -EINVAL; - - if (unlikely(!bo->bdev->funcs->verify_access)) { - ret = -EPERM; - goto out_unref; - } - ret = bo->bdev->funcs->verify_access(bo, filp); - if (unlikely(ret != 0)) - goto out_unref; - - ttm_bo_mmap_vma_setup(bo, vma); - return 0; -out_unref: - ttm_bo_put(bo); - return ret; -} -EXPORT_SYMBOL(ttm_bo_mmap); - int ttm_bo_mmap_obj(struct vm_area_struct *vma, struct ttm_buffer_object *bo) { ttm_bo_get(bo); diff --git a/include/drm/ttm/ttm_bo_api.h b/include/drm/ttm/ttm_bo_api.h index 2155e2e38aec..6e35680ac01b 100644 --- a/include/drm/ttm/ttm_bo_api.h +++ b/include/drm/ttm/ttm_bo_api.h @@ -522,19 +522,6 @@ void ttm_bo_vunmap(struct ttm_buffer_object *bo, struct dma_buf_map *map); */ int ttm_bo_mmap_obj(struct vm_area_struct *vma, struct ttm_buffer_object *bo);
-/** - * ttm_bo_mmap - mmap out of the ttm device address space. - * - * @filp: filp as input from the mmap method. - * @vma: vma as input from the mmap method. - * @bdev: Pointer to the ttm_device with the address space manager. - * - * This function is intended to be called by the device mmap method. - * if the device address space is to be backed by the bo manager. - */ -int ttm_bo_mmap(struct file *filp, struct vm_area_struct *vma, - struct ttm_device *bdev); - /** * ttm_bo_io * diff --git a/include/drm/ttm/ttm_device.h b/include/drm/ttm/ttm_device.h index 7c8f87bd52d3..cd592f8e941b 100644 --- a/include/drm/ttm/ttm_device.h +++ b/include/drm/ttm/ttm_device.h @@ -161,21 +161,6 @@ struct ttm_device_funcs { struct ttm_resource *new_mem, struct ttm_place *hop);
- /** - * struct ttm_bo_driver_member verify_access - * - * @bo: Pointer to a buffer object. - * @filp: Pointer to a struct file trying to access the object. - * - * 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 resource delete. */
Am 06.04.21 um 11:09 schrieb Thomas Zimmermann:
The function ttm_bo_mmap is unused. Remove it and it's helpers; including the verify_access callback in struct ttm_device_funcs.
Signed-off-by: Thomas Zimmermann tzimmermann@suse.de
Reviewed-by: Christian König christian.koenig@amd.com
drivers/gpu/drm/ttm/ttm_bo_vm.c | 53 --------------------------------- include/drm/ttm/ttm_bo_api.h | 13 -------- include/drm/ttm/ttm_device.h | 15 ---------- 3 files changed, 81 deletions(-)
diff --git a/drivers/gpu/drm/ttm/ttm_bo_vm.c b/drivers/gpu/drm/ttm/ttm_bo_vm.c index bf4a213bc66c..6cd352399941 100644 --- a/drivers/gpu/drm/ttm/ttm_bo_vm.c +++ b/drivers/gpu/drm/ttm/ttm_bo_vm.c @@ -508,30 +508,6 @@ static const struct vm_operations_struct ttm_bo_vm_ops = { .access = ttm_bo_vm_access, };
-static struct ttm_buffer_object *ttm_bo_vm_lookup(struct ttm_device *bdev,
unsigned long offset,
unsigned long pages)
-{
- struct drm_vma_offset_node *node;
- struct ttm_buffer_object *bo = NULL;
- drm_vma_offset_lock_lookup(bdev->vma_manager);
- node = drm_vma_offset_lookup_locked(bdev->vma_manager, offset, pages);
- if (likely(node)) {
bo = container_of(node, struct ttm_buffer_object,
base.vma_node);
bo = ttm_bo_get_unless_zero(bo);
- }
- drm_vma_offset_unlock_lookup(bdev->vma_manager);
- if (!bo)
pr_err("Could not find buffer object to map\n");
- return bo;
-}
- static void ttm_bo_mmap_vma_setup(struct ttm_buffer_object *bo, struct vm_area_struct *vma) { /*
@@ -559,35 +535,6 @@ static void ttm_bo_mmap_vma_setup(struct ttm_buffer_object *bo, struct vm_area_s vma->vm_flags |= VM_IO | VM_DONTEXPAND | VM_DONTDUMP; }
-int ttm_bo_mmap(struct file *filp, struct vm_area_struct *vma,
struct ttm_device *bdev)
-{
- struct ttm_buffer_object *bo;
- int ret;
- if (unlikely(vma->vm_pgoff < DRM_FILE_PAGE_OFFSET_START))
return -EINVAL;
- bo = ttm_bo_vm_lookup(bdev, vma->vm_pgoff, vma_pages(vma));
- if (unlikely(!bo))
return -EINVAL;
- if (unlikely(!bo->bdev->funcs->verify_access)) {
ret = -EPERM;
goto out_unref;
- }
- ret = bo->bdev->funcs->verify_access(bo, filp);
- if (unlikely(ret != 0))
goto out_unref;
- ttm_bo_mmap_vma_setup(bo, vma);
- return 0;
-out_unref:
- ttm_bo_put(bo);
- return ret;
-} -EXPORT_SYMBOL(ttm_bo_mmap);
- int ttm_bo_mmap_obj(struct vm_area_struct *vma, struct ttm_buffer_object *bo) { ttm_bo_get(bo);
diff --git a/include/drm/ttm/ttm_bo_api.h b/include/drm/ttm/ttm_bo_api.h index 2155e2e38aec..6e35680ac01b 100644 --- a/include/drm/ttm/ttm_bo_api.h +++ b/include/drm/ttm/ttm_bo_api.h @@ -522,19 +522,6 @@ void ttm_bo_vunmap(struct ttm_buffer_object *bo, struct dma_buf_map *map); */ int ttm_bo_mmap_obj(struct vm_area_struct *vma, struct ttm_buffer_object *bo);
-/**
- ttm_bo_mmap - mmap out of the ttm device address space.
- @filp: filp as input from the mmap method.
- @vma: vma as input from the mmap method.
- @bdev: Pointer to the ttm_device with the address space manager.
- This function is intended to be called by the device mmap method.
- if the device address space is to be backed by the bo manager.
- */
-int ttm_bo_mmap(struct file *filp, struct vm_area_struct *vma,
struct ttm_device *bdev);
- /**
- ttm_bo_io
diff --git a/include/drm/ttm/ttm_device.h b/include/drm/ttm/ttm_device.h index 7c8f87bd52d3..cd592f8e941b 100644 --- a/include/drm/ttm/ttm_device.h +++ b/include/drm/ttm/ttm_device.h @@ -161,21 +161,6 @@ struct ttm_device_funcs { struct ttm_resource *new_mem, struct ttm_place *hop);
- /**
* struct ttm_bo_driver_member verify_access
*
* @bo: Pointer to a buffer object.
* @filp: Pointer to a struct file trying to access the object.
*
* 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 resource delete.
On Tue, Apr 06, 2021 at 11:08:55AM +0200, Thomas Zimmermann wrote:
Implement mmap via struct drm_gem_object_functions.mmap for amdgpu, radeon and nouveau. This allows for using common DRM helpers for the mmap-related callbacks in struct file_operations and struct drm_driver. The drivers have their own vm_ops, which are now set automatically by the DRM core functions. The code in each driver's verify_access becomes part of the driver's new mmap implementation.
Is there anything left in there which isn't already handled by the gem checks? Iirc there was some custom limit for ttm drivers once to allow co-existing with ums drivers, but that's never really been a thing since forever ... -Daniel
With the GEM drivers converted, vmwgfx is the only user of ttm_bo_mmap() and related infrastructure. So move everything into vmwgfx and delete the rsp code from TTM.
This touches several drivers. Preferably everything would be merged at once via drm-misc-next.
Thomas Zimmermann (8): drm/ttm: Don't override vm_ops callbacks, if set drm/amdgpu: Remove unused function amdgpu_bo_fbdev_mmap() drm/amdgpu: Implement mmap as GEM object function drm/radeon: Implement mmap as GEM object function drm/nouveau: Implement mmap as GEM object function drm/vmwgfx: Inline ttm_bo_mmap() into vmwgfx driver drm/vmwgfx: Inline vmw_verify_access() drm/ttm: Remove ttm_bo_mmap() and friends
drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c | 46 ------------- drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.h | 2 - drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c | 4 +- drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c | 64 +++++++++++++++++++ drivers/gpu/drm/amd/amdgpu/amdgpu_object.c | 19 ------ drivers/gpu/drm/amd/amdgpu/amdgpu_object.h | 2 - drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | 71 --------------------- drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h | 1 - drivers/gpu/drm/nouveau/nouveau_bo.c | 10 --- drivers/gpu/drm/nouveau/nouveau_drm.c | 3 +- drivers/gpu/drm/nouveau/nouveau_gem.c | 36 +++++++++++ drivers/gpu/drm/nouveau/nouveau_ttm.c | 49 -------------- drivers/gpu/drm/nouveau/nouveau_ttm.h | 1 - drivers/gpu/drm/radeon/radeon_drv.c | 3 +- drivers/gpu/drm/radeon/radeon_gem.c | 52 +++++++++++++++ drivers/gpu/drm/radeon/radeon_ttm.c | 65 ------------------- drivers/gpu/drm/radeon/radeon_ttm.h | 1 - drivers/gpu/drm/ttm/ttm_bo_vm.c | 60 ++--------------- drivers/gpu/drm/vmwgfx/vmwgfx_ttm_buffer.c | 9 --- drivers/gpu/drm/vmwgfx/vmwgfx_ttm_glue.c | 51 ++++++++++++++- include/drm/ttm/ttm_bo_api.h | 13 ---- include/drm/ttm/ttm_device.h | 15 ----- 22 files changed, 212 insertions(+), 365 deletions(-)
-- 2.30.2
Hi
Am 08.04.21 um 13:19 schrieb Daniel Vetter:
On Tue, Apr 06, 2021 at 11:08:55AM +0200, Thomas Zimmermann wrote:
Implement mmap via struct drm_gem_object_functions.mmap for amdgpu, radeon and nouveau. This allows for using common DRM helpers for the mmap-related callbacks in struct file_operations and struct drm_driver. The drivers have their own vm_ops, which are now set automatically by the DRM core functions. The code in each driver's verify_access becomes part of the driver's new mmap implementation.
Is there anything left in there which isn't already handled by the gem checks? Iirc there was some custom limit for ttm drivers once to allow co-existing with ums drivers, but that's never really been a thing since forever ...
Vmwgfx does its own thing. radeon and amdgpu have some checks (userptr). But it's all very small. The general tests will be in the GEM helpers.
Best regards Thomas
-Daniel
With the GEM drivers converted, vmwgfx is the only user of ttm_bo_mmap() and related infrastructure. So move everything into vmwgfx and delete the rsp code from TTM.
This touches several drivers. Preferably everything would be merged at once via drm-misc-next.
Thomas Zimmermann (8): drm/ttm: Don't override vm_ops callbacks, if set drm/amdgpu: Remove unused function amdgpu_bo_fbdev_mmap() drm/amdgpu: Implement mmap as GEM object function drm/radeon: Implement mmap as GEM object function drm/nouveau: Implement mmap as GEM object function drm/vmwgfx: Inline ttm_bo_mmap() into vmwgfx driver drm/vmwgfx: Inline vmw_verify_access() drm/ttm: Remove ttm_bo_mmap() and friends
drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c | 46 ------------- drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.h | 2 - drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c | 4 +- drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c | 64 +++++++++++++++++++ drivers/gpu/drm/amd/amdgpu/amdgpu_object.c | 19 ------ drivers/gpu/drm/amd/amdgpu/amdgpu_object.h | 2 - drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | 71 --------------------- drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h | 1 - drivers/gpu/drm/nouveau/nouveau_bo.c | 10 --- drivers/gpu/drm/nouveau/nouveau_drm.c | 3 +- drivers/gpu/drm/nouveau/nouveau_gem.c | 36 +++++++++++ drivers/gpu/drm/nouveau/nouveau_ttm.c | 49 -------------- drivers/gpu/drm/nouveau/nouveau_ttm.h | 1 - drivers/gpu/drm/radeon/radeon_drv.c | 3 +- drivers/gpu/drm/radeon/radeon_gem.c | 52 +++++++++++++++ drivers/gpu/drm/radeon/radeon_ttm.c | 65 ------------------- drivers/gpu/drm/radeon/radeon_ttm.h | 1 - drivers/gpu/drm/ttm/ttm_bo_vm.c | 60 ++--------------- drivers/gpu/drm/vmwgfx/vmwgfx_ttm_buffer.c | 9 --- drivers/gpu/drm/vmwgfx/vmwgfx_ttm_glue.c | 51 ++++++++++++++- include/drm/ttm/ttm_bo_api.h | 13 ---- include/drm/ttm/ttm_device.h | 15 ----- 22 files changed, 212 insertions(+), 365 deletions(-)
-- 2.30.2
On Thu, Apr 08, 2021 at 01:38:59PM +0200, Thomas Zimmermann wrote:
Hi
Am 08.04.21 um 13:19 schrieb Daniel Vetter:
On Tue, Apr 06, 2021 at 11:08:55AM +0200, Thomas Zimmermann wrote:
Implement mmap via struct drm_gem_object_functions.mmap for amdgpu, radeon and nouveau. This allows for using common DRM helpers for the mmap-related callbacks in struct file_operations and struct drm_driver. The drivers have their own vm_ops, which are now set automatically by the DRM core functions. The code in each driver's verify_access becomes part of the driver's new mmap implementation.
Is there anything left in there which isn't already handled by the gem checks? Iirc there was some custom limit for ttm drivers once to allow co-existing with ums drivers, but that's never really been a thing since forever ...
Vmwgfx does its own thing. radeon and amdgpu have some checks (userptr). But it's all very small. The general tests will be in the GEM helpers.
Ah userptr makes tons of sense. I think that should be rejected when creating the mmap offset, and then a WARN_ON to bail out.
But that means we'd need to lift the basic userptr scaffolding to drm_gem_object. Which would make tons of sense imo (all the various semi-broken copypasta versions aren't great), but that's definitely for another time. -Daniel
Best regards Thomas
-Daniel
With the GEM drivers converted, vmwgfx is the only user of ttm_bo_mmap() and related infrastructure. So move everything into vmwgfx and delete the rsp code from TTM.
This touches several drivers. Preferably everything would be merged at once via drm-misc-next.
Thomas Zimmermann (8): drm/ttm: Don't override vm_ops callbacks, if set drm/amdgpu: Remove unused function amdgpu_bo_fbdev_mmap() drm/amdgpu: Implement mmap as GEM object function drm/radeon: Implement mmap as GEM object function drm/nouveau: Implement mmap as GEM object function drm/vmwgfx: Inline ttm_bo_mmap() into vmwgfx driver drm/vmwgfx: Inline vmw_verify_access() drm/ttm: Remove ttm_bo_mmap() and friends
drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c | 46 ------------- drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.h | 2 - drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c | 4 +- drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c | 64 +++++++++++++++++++ drivers/gpu/drm/amd/amdgpu/amdgpu_object.c | 19 ------ drivers/gpu/drm/amd/amdgpu/amdgpu_object.h | 2 - drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | 71 --------------------- drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h | 1 - drivers/gpu/drm/nouveau/nouveau_bo.c | 10 --- drivers/gpu/drm/nouveau/nouveau_drm.c | 3 +- drivers/gpu/drm/nouveau/nouveau_gem.c | 36 +++++++++++ drivers/gpu/drm/nouveau/nouveau_ttm.c | 49 -------------- drivers/gpu/drm/nouveau/nouveau_ttm.h | 1 - drivers/gpu/drm/radeon/radeon_drv.c | 3 +- drivers/gpu/drm/radeon/radeon_gem.c | 52 +++++++++++++++ drivers/gpu/drm/radeon/radeon_ttm.c | 65 ------------------- drivers/gpu/drm/radeon/radeon_ttm.h | 1 - drivers/gpu/drm/ttm/ttm_bo_vm.c | 60 ++--------------- drivers/gpu/drm/vmwgfx/vmwgfx_ttm_buffer.c | 9 --- drivers/gpu/drm/vmwgfx/vmwgfx_ttm_glue.c | 51 ++++++++++++++- include/drm/ttm/ttm_bo_api.h | 13 ---- include/drm/ttm/ttm_device.h | 15 ----- 22 files changed, 212 insertions(+), 365 deletions(-)
-- 2.30.2
-- Thomas Zimmermann Graphics Driver Developer SUSE Software Solutions Germany GmbH Maxfeldstr. 5, 90409 Nürnberg, Germany (HRB 36809, AG Nürnberg) Geschäftsführer: Felix Imendörffer
dri-devel@lists.freedesktop.org