[RFC PATCH] drm/gem: Warn on illegal use of the dumb buffer interface
Alex Deucher
alexdeucher at gmail.com
Fri Nov 14 13:16:47 PST 2014
On Thu, Nov 13, 2014 at 2:31 PM, Thomas Hellstrom <thellstrom at vmware.com> wrote:
> Hi!
>
> Could we perhaps get an ack from Radeon / Nouveau as well?
This needs to be rebased on a newer kernel to take into account the
userptr changes in radeon_mode_dumb_mmap() so they don't get lost.
With that fixed:
Acked-by: Alex Deucher <alexander.deucher at amd.com>
>
> Thanks,
> Thomas
>
>
> On 11/12/2014 12:55 PM, Thomas Hellstrom wrote:
>> It happens on occasion that developers of generic user-space applications
>> abuse the dumb buffer API to get hold of drm buffers that they can both
>> mmap() and use for GPU acceleration, using the assumptions that dumb buffers
>> and buffers available for GPU are
>> a) The same type and can be aribtrarily type-casted.
>> b) fully coherent.
>>
>> This patch makes the most widely used drivers warn nicely when that happens,
>> the next step will be to fail.
>>
>> Signed-off-by: Thomas Hellstrom <thellstrom at vmware.com>
>> ---
>> Patch is only compile-tested.
>> FWIW vmware should typically fail on these errors.
>>
>> ---
>> drivers/gpu/drm/i915/i915_drv.c | 2 +-
>> drivers/gpu/drm/i915/i915_drv.h | 5 +++--
>> drivers/gpu/drm/i915/i915_gem.c | 28 +++++++++++++++++++++++-----
>> drivers/gpu/drm/i915/i915_gem_execbuffer.c | 3 +++
>> drivers/gpu/drm/nouveau/nouveau_display.c | 9 +++++++++
>> drivers/gpu/drm/nouveau/nouveau_gem.c | 3 +++
>> drivers/gpu/drm/radeon/radeon_gem.c | 29 ++++++++++++++++++++++++++++-
>> drivers/gpu/drm/radeon/radeon_object.c | 3 +++
>> include/drm/drmP.h | 7 +++++++
>> 9 files changed, 80 insertions(+), 9 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
>> index e27cdbe..956b154 100644
>> --- a/drivers/gpu/drm/i915/i915_drv.c
>> +++ b/drivers/gpu/drm/i915/i915_drv.c
>> @@ -1593,7 +1593,7 @@ static struct drm_driver driver = {
>> .gem_prime_import = i915_gem_prime_import,
>>
>> .dumb_create = i915_gem_dumb_create,
>> - .dumb_map_offset = i915_gem_mmap_gtt,
>> + .dumb_map_offset = i915_gem_dumb_map_offset,
>> .dumb_destroy = drm_gem_dumb_destroy,
>> .ioctls = i915_ioctls,
>> .fops = &i915_driver_fops,
>> diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
>> index 7a830ea..669537c 100644
>> --- a/drivers/gpu/drm/i915/i915_drv.h
>> +++ b/drivers/gpu/drm/i915/i915_drv.h
>> @@ -2321,8 +2321,9 @@ void i915_vma_move_to_active(struct i915_vma *vma,
>> int i915_gem_dumb_create(struct drm_file *file_priv,
>> struct drm_device *dev,
>> struct drm_mode_create_dumb *args);
>> -int i915_gem_mmap_gtt(struct drm_file *file_priv, struct drm_device *dev,
>> - uint32_t handle, uint64_t *offset);
>> +int i915_gem_dumb_map_offset(struct drm_file *file_priv,
>> + struct drm_device *dev, uint32_t handle,
>> + uint64_t *offset);
>> /**
>> * Returns true if seq1 is later than seq2.
>> */
>> diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
>> index ba7f5c6..3d97a43 100644
>> --- a/drivers/gpu/drm/i915/i915_gem.c
>> +++ b/drivers/gpu/drm/i915/i915_gem.c
>> @@ -347,6 +347,7 @@ static int
>> i915_gem_create(struct drm_file *file,
>> struct drm_device *dev,
>> uint64_t size,
>> + bool dumb,
>> uint32_t *handle_p)
>> {
>> struct drm_i915_gem_object *obj;
>> @@ -362,6 +363,7 @@ i915_gem_create(struct drm_file *file,
>> if (obj == NULL)
>> return -ENOMEM;
>>
>> + obj->base.dumb = dumb;
>> ret = drm_gem_handle_create(file, &obj->base, &handle);
>> /* drop reference from allocate - handle holds it now */
>> drm_gem_object_unreference_unlocked(&obj->base);
>> @@ -381,7 +383,7 @@ i915_gem_dumb_create(struct drm_file *file,
>> args->pitch = ALIGN(args->width * DIV_ROUND_UP(args->bpp, 8), 64);
>> args->size = args->pitch * args->height;
>> return i915_gem_create(file, dev,
>> - args->size, &args->handle);
>> + args->size, true, &args->handle);
>> }
>>
>> /**
>> @@ -394,7 +396,7 @@ i915_gem_create_ioctl(struct drm_device *dev, void *data,
>> struct drm_i915_gem_create *args = data;
>>
>> return i915_gem_create(file, dev,
>> - args->size, &args->handle);
>> + args->size, false, &args->handle);
>> }
>>
>> static inline int
>> @@ -1750,10 +1752,10 @@ static void i915_gem_object_free_mmap_offset(struct drm_i915_gem_object *obj)
>> drm_gem_free_mmap_offset(&obj->base);
>> }
>>
>> -int
>> +static int
>> i915_gem_mmap_gtt(struct drm_file *file,
>> struct drm_device *dev,
>> - uint32_t handle,
>> + uint32_t handle, bool dumb,
>> uint64_t *offset)
>> {
>> struct drm_i915_private *dev_priv = dev->dev_private;
>> @@ -1770,6 +1772,13 @@ i915_gem_mmap_gtt(struct drm_file *file,
>> goto unlock;
>> }
>>
>> + /*
>> + * We don't allow dumb mmaps on objects created using another
>> + * interface.
>> + */
>> + WARN_ONCE(dumb && !(obj->base.dumb || obj->base.import_attach),
>> + "Illegal dumb map of accelerated buffer.\n");
>> +
>> if (obj->base.size > dev_priv->gtt.mappable_end) {
>> ret = -E2BIG;
>> goto out;
>> @@ -1794,6 +1803,15 @@ unlock:
>> return ret;
>> }
>>
>> +int
>> +i915_gem_dumb_map_offset(struct drm_file *file,
>> + struct drm_device *dev,
>> + uint32_t handle,
>> + uint64_t *offset)
>> +{
>> + return i915_gem_mmap_gtt(file, dev, handle, true, offset);
>> +}
>> +
>> /**
>> * i915_gem_mmap_gtt_ioctl - prepare an object for GTT mmap'ing
>> * @dev: DRM device
>> @@ -1815,7 +1833,7 @@ i915_gem_mmap_gtt_ioctl(struct drm_device *dev, void *data,
>> {
>> struct drm_i915_gem_mmap_gtt *args = data;
>>
>> - return i915_gem_mmap_gtt(file, dev, args->handle, &args->offset);
>> + return i915_gem_mmap_gtt(file, dev, args->handle, false, &args->offset);
>> }
>>
>> static inline int
>> diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c
>> index 60998fc..ba78ea0 100644
>> --- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c
>> +++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c
>> @@ -120,6 +120,9 @@ eb_lookup_vmas(struct eb_vmas *eb,
>> ret = -EINVAL;
>> goto err;
>> }
>> +
>> + WARN_ONCE(obj->base.dumb,
>> + "GPU use of dumb buffer is illegal.\n");
>>
>> drm_gem_object_reference(&obj->base);
>> list_add_tail(&obj->obj_exec_link, &objects);
>> diff --git a/drivers/gpu/drm/nouveau/nouveau_display.c b/drivers/gpu/drm/nouveau/nouveau_display.c
>> index 65b4fd5..63f746a 100644
>> --- a/drivers/gpu/drm/nouveau/nouveau_display.c
>> +++ b/drivers/gpu/drm/nouveau/nouveau_display.c
>> @@ -867,6 +867,7 @@ nouveau_display_dumb_create(struct drm_file *file_priv, struct drm_device *dev,
>> if (ret)
>> return ret;
>>
>> + bo->gem.dumb = true;
>> ret = drm_gem_handle_create(file_priv, &bo->gem, &args->handle);
>> drm_gem_object_unreference_unlocked(&bo->gem);
>> return ret;
>> @@ -882,6 +883,14 @@ nouveau_display_dumb_map_offset(struct drm_file *file_priv,
>> gem = drm_gem_object_lookup(dev, file_priv, handle);
>> if (gem) {
>> struct nouveau_bo *bo = nouveau_gem_object(gem);
>> +
>> + /*
>> + * We don't allow dumb mmaps on objects created using another
>> + * interface.
>> + */
>> + WARN_ONCE(!(gem->dumb || gem->import_attach),
>> + "Illegal dumb map of accelerated buffer.\n");
>> +
>> *poffset = drm_vma_node_offset_addr(&bo->bo.vma_node);
>> drm_gem_object_unreference_unlocked(gem);
>> return 0;
>> diff --git a/drivers/gpu/drm/nouveau/nouveau_gem.c b/drivers/gpu/drm/nouveau/nouveau_gem.c
>> index 292a677..92ba48e 100644
>> --- a/drivers/gpu/drm/nouveau/nouveau_gem.c
>> +++ b/drivers/gpu/drm/nouveau/nouveau_gem.c
>> @@ -459,6 +459,9 @@ validate_list(struct nouveau_channel *chan, struct nouveau_cli *cli,
>> list_for_each_entry(nvbo, list, entry) {
>> struct drm_nouveau_gem_pushbuf_bo *b = &pbbo[nvbo->pbbo_index];
>>
>> + WARN_ONCE(nvbo->gem.dumb,
>> + "GPU use of dumb buffer is illegal.\n");
>> +
>> ret = nouveau_gem_set_domain(&nvbo->gem, b->read_domains,
>> b->write_domains,
>> b->valid_domains);
>> diff --git a/drivers/gpu/drm/radeon/radeon_gem.c b/drivers/gpu/drm/radeon/radeon_gem.c
>> index bfd7e1b..cbfba17 100644
>> --- a/drivers/gpu/drm/radeon/radeon_gem.c
>> +++ b/drivers/gpu/drm/radeon/radeon_gem.c
>> @@ -303,6 +303,24 @@ int radeon_gem_set_domain_ioctl(struct drm_device *dev, void *data,
>> return r;
>> }
>>
>> +static int radeon_mode_mmap(struct drm_file *filp,
>> + struct drm_device *dev,
>> + uint32_t handle, uint64_t *offset_p)
>> +{
>> + struct drm_gem_object *gobj;
>> + struct radeon_bo *robj;
>> +
>> + gobj = drm_gem_object_lookup(dev, filp, handle);
>> + if (gobj == NULL) {
>> + return -ENOENT;
>> + }
>> +
>> + robj = gem_to_radeon_bo(gobj);
>> + *offset_p = radeon_bo_mmap_offset(robj);
>> + drm_gem_object_unreference_unlocked(gobj);
>> + return 0;
>> +}
>> +
>> int radeon_mode_dumb_mmap(struct drm_file *filp,
>> struct drm_device *dev,
>> uint32_t handle, uint64_t *offset_p)
>> @@ -314,6 +332,14 @@ int radeon_mode_dumb_mmap(struct drm_file *filp,
>> if (gobj == NULL) {
>> return -ENOENT;
>> }
>> +
>> + /*
>> + * We don't allow dumb mmaps on objects created using another
>> + * interface.
>> + */
>> + WARN_ONCE(!(gobj->dumb || gobj->import_attach),
>> + "Illegal dumb map of GPU buffer.\n");
>> +
>> robj = gem_to_radeon_bo(gobj);
>> *offset_p = radeon_bo_mmap_offset(robj);
>> drm_gem_object_unreference_unlocked(gobj);
>> @@ -325,7 +351,7 @@ int radeon_gem_mmap_ioctl(struct drm_device *dev, void *data,
>> {
>> struct drm_radeon_gem_mmap *args = data;
>>
>> - return radeon_mode_dumb_mmap(filp, dev, args->handle, &args->addr_ptr);
>> + return radeon_mode_mmap(filp, dev, args->handle, &args->addr_ptr);
>> }
>>
>> int radeon_gem_busy_ioctl(struct drm_device *dev, void *data,
>> @@ -575,6 +601,7 @@ int radeon_mode_dumb_create(struct drm_file *file_priv,
>> return -ENOMEM;
>>
>> r = drm_gem_handle_create(file_priv, gobj, &handle);
>> + gobj->dumb = true;
>> /* drop reference from allocate - handle holds it now */
>> drm_gem_object_unreference_unlocked(gobj);
>> if (r) {
>> diff --git a/drivers/gpu/drm/radeon/radeon_object.c b/drivers/gpu/drm/radeon/radeon_object.c
>> index 480c87d..1450ea0 100644
>> --- a/drivers/gpu/drm/radeon/radeon_object.c
>> +++ b/drivers/gpu/drm/radeon/radeon_object.c
>> @@ -471,6 +471,9 @@ int radeon_bo_list_validate(struct radeon_device *rdev,
>> u32 current_domain =
>> radeon_mem_type_to_domain(bo->tbo.mem.mem_type);
>>
>> + WARN_ONCE(bo->gem_base.dumb,
>> + "GPU use of dumb buffer is illegal.\n");
>> +
>> /* Check if this buffer will be moved and don't move it
>> * if we have moved too many buffers for this IB already.
>> *
>> diff --git a/include/drm/drmP.h b/include/drm/drmP.h
>> index 1968907..3d7908e 100644
>> --- a/include/drm/drmP.h
>> +++ b/include/drm/drmP.h
>> @@ -640,6 +640,13 @@ struct drm_gem_object {
>> * simply leave it as NULL.
>> */
>> struct dma_buf_attachment *import_attach;
>> +
>> + /**
>> + * dumb - created as dumb buffer
>> + * Whether the gem object was created using the dumb buffer interface
>> + * as such it may not be used for GPU rendering.
>> + */
>> + bool dumb;
>> };
>>
>> #include <drm/drm_crtc.h>
>
> _______________________________________________
> dri-devel mailing list
> dri-devel at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/dri-devel
More information about the dri-devel
mailing list