From b4bcbe2a90a1127a6dad72fbda27e77705d9e0f4 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Tue, 18 Oct 2016 13:02:49 +0100 Subject: [PATCH] drm/i915: Document our internal limit on object size In many places, we try to count pages using a 32 bit integer. That implies if we are asked to create an object larger than 43bits, we will subtly crash much later. Catch this on the boundary, and add a warning to remind ourselves later on our exabyte systems. Signed-off-by: Chris Wilson Reviewed-by: Tvrtko Ursulin Link: http://patchwork.freedesktop.org/patch/msgid/20161018120251.25043-2-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_drv.h | 2 +- drivers/gpu/drm/i915/i915_gem.c | 19 +++++++++++++++++-- 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index cabcd06c84bd..33c44c631bab 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -3107,7 +3107,7 @@ void i915_gem_object_free(struct drm_i915_gem_object *obj); void i915_gem_object_init(struct drm_i915_gem_object *obj, const struct drm_i915_gem_object_ops *ops); struct drm_i915_gem_object *i915_gem_object_create(struct drm_device *dev, - size_t size); + u64 size); struct drm_i915_gem_object *i915_gem_object_create_from_data( struct drm_device *dev, const void *data, size_t size); void i915_gem_close_object(struct drm_gem_object *gem, struct drm_file *file); diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 838dc159a2d1..6165a3b0e3a4 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -4131,14 +4131,29 @@ static const struct drm_i915_gem_object_ops i915_gem_object_ops = { .put_pages = i915_gem_object_put_pages_gtt, }; -struct drm_i915_gem_object *i915_gem_object_create(struct drm_device *dev, - size_t size) +/* Note we don't consider signbits :| */ +#define overflows_type(x, T) \ + (sizeof(x) > sizeof(T) && (x) >> (sizeof(T) * BITS_PER_BYTE)) + +struct drm_i915_gem_object * +i915_gem_object_create(struct drm_device *dev, u64 size) { struct drm_i915_gem_object *obj; struct address_space *mapping; gfp_t mask; int ret; + /* There is a prevalence of the assumption that we fit the object's + * page count inside a 32bit _signed_ variable. Let's document this and + * catch if we ever need to fix it. In the meantime, if you do spot + * such a local variable, please consider fixing! + */ + if (WARN_ON(size >> PAGE_SHIFT > INT_MAX)) + return ERR_PTR(-E2BIG); + + if (overflows_type(size, obj->base.size)) + return ERR_PTR(-E2BIG); + obj = i915_gem_object_alloc(dev); if (obj == NULL) return ERR_PTR(-ENOMEM); -- 2.11.0