drm/i915: Restrict L3 remapping sysfs interface to dwords
authorChris Wilson <chris@chris-wilson.co.uk>
Fri, 4 Oct 2019 10:59:58 +0000 (11:59 +0100)
committerChris Wilson <chris@chris-wilson.co.uk>
Fri, 4 Oct 2019 13:24:32 +0000 (14:24 +0100)
The L3 cache remapping is stored as u32 elements, and we should ensure
that the user only supplies complete slice information(u32).

Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Cc: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
Reviewed-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20191004105958.1741-1-chris@chris-wilson.co.uk
drivers/gpu/drm/i915/i915_sysfs.c

index 034b8abc50624adde890790510d8557c8865f88b..1e08c5961535b19922a22e593a38c03f4316d735 100644 (file)
@@ -144,12 +144,12 @@ static const struct attribute_group media_rc6_attr_group = {
 };
 #endif
 
-static int l3_access_valid(struct drm_i915_private *dev_priv, loff_t offset)
+static int l3_access_valid(struct drm_i915_private *i915, loff_t offset)
 {
-       if (!HAS_L3_DPF(dev_priv))
+       if (!HAS_L3_DPF(i915))
                return -EPERM;
 
-       if (offset % 4 != 0)
+       if (!IS_ALIGNED(offset, sizeof(u32)))
                return -EINVAL;
 
        if (offset >= GEN7_L3LOG_SIZE)
@@ -164,31 +164,28 @@ i915_l3_read(struct file *filp, struct kobject *kobj,
             loff_t offset, size_t count)
 {
        struct device *kdev = kobj_to_dev(kobj);
-       struct drm_i915_private *dev_priv = kdev_minor_to_i915(kdev);
-       struct drm_device *dev = &dev_priv->drm;
+       struct drm_i915_private *i915 = kdev_minor_to_i915(kdev);
        int slice = (int)(uintptr_t)attr->private;
        int ret;
 
-       count = round_down(count, 4);
-
-       ret = l3_access_valid(dev_priv, offset);
+       ret = l3_access_valid(i915, offset);
        if (ret)
                return ret;
 
+       count = round_down(count, sizeof(u32));
        count = min_t(size_t, GEN7_L3LOG_SIZE - offset, count);
+       memset(buf, 0, count);
 
-       ret = i915_mutex_lock_interruptible(dev);
+       ret = i915_mutex_lock_interruptible(&i915->drm);
        if (ret)
                return ret;
 
-       if (dev_priv->l3_parity.remap_info[slice])
+       if (i915->l3_parity.remap_info[slice])
                memcpy(buf,
-                      dev_priv->l3_parity.remap_info[slice] + (offset/4),
+                      i915->l3_parity.remap_info[slice] + offset / sizeof(u32),
                       count);
-       else
-               memset(buf, 0, count);
 
-       mutex_unlock(&dev->struct_mutex);
+       mutex_unlock(&i915->drm.struct_mutex);
 
        return count;
 }
@@ -199,22 +196,24 @@ i915_l3_write(struct file *filp, struct kobject *kobj,
              loff_t offset, size_t count)
 {
        struct device *kdev = kobj_to_dev(kobj);
-       struct drm_i915_private *dev_priv = kdev_minor_to_i915(kdev);
-       struct drm_device *dev = &dev_priv->drm;
-       struct i915_gem_context *ctx;
+       struct drm_i915_private *i915 = kdev_minor_to_i915(kdev);
        int slice = (int)(uintptr_t)attr->private;
+       struct i915_gem_context *ctx;
        u32 **remap_info;
        int ret;
 
-       ret = l3_access_valid(dev_priv, offset);
+       ret = l3_access_valid(i915, offset);
        if (ret)
                return ret;
 
-       ret = i915_mutex_lock_interruptible(dev);
+       if (count < sizeof(u32))
+               return -EINVAL;
+
+       ret = i915_mutex_lock_interruptible(&i915->drm);
        if (ret)
                return ret;
 
-       remap_info = &dev_priv->l3_parity.remap_info[slice];
+       remap_info = &i915->l3_parity.remap_info[slice];
        if (!*remap_info) {
                *remap_info = kzalloc(GEN7_L3LOG_SIZE, GFP_KERNEL);
                if (!*remap_info) {
@@ -223,20 +222,22 @@ i915_l3_write(struct file *filp, struct kobject *kobj,
                }
        }
 
-       /* TODO: Ideally we really want a GPU reset here to make sure errors
+       count = round_down(count, sizeof(u32));
+       memcpy(*remap_info + offset / sizeof(u32), buf, count);
+
+       /* NB: We defer the remapping until we switch to the context */
+       list_for_each_entry(ctx, &i915->contexts.list, link)
+               ctx->remap_slice |= BIT(slice);
+
+       /*
+        * TODO: Ideally we really want a GPU reset here to make sure errors
         * aren't propagated. Since I cannot find a stable way to reset the GPU
         * at this point it is left as a TODO.
        */
-       memcpy(*remap_info + (offset/4), buf, count);
-
-       /* NB: We defer the remapping until we switch to the context */
-       list_for_each_entry(ctx, &dev_priv->contexts.list, link)
-               ctx->remap_slice |= (1<<slice);
 
        ret = count;
-
 out:
-       mutex_unlock(&dev->struct_mutex);
+       mutex_unlock(&i915->drm.struct_mutex);
 
        return ret;
 }