[PATCH 24/24] onstack
Chris Wilson
chris at chris-wilson.co.uk
Sat May 20 17:51:15 UTC 2017
---
drivers/gpu/drm/i915/i915_drv.c | 4 +-
drivers/gpu/drm/i915/i915_drv.h | 6 +-
drivers/gpu/drm/i915/i915_gem_execbuffer.c | 737 +++++++++++++----------------
3 files changed, 327 insertions(+), 420 deletions(-)
diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
index e3c6d052d1c9..1f26273bc4f6 100644
--- a/drivers/gpu/drm/i915/i915_drv.c
+++ b/drivers/gpu/drm/i915/i915_drv.c
@@ -2595,8 +2595,8 @@ static const struct drm_ioctl_desc i915_ioctls[] = {
DRM_IOCTL_DEF_DRV(I915_VBLANK_SWAP, drm_noop, DRM_AUTH),
DRM_IOCTL_DEF_DRV(I915_HWS_ADDR, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
DRM_IOCTL_DEF_DRV(I915_GEM_INIT, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
- DRM_IOCTL_DEF_DRV(I915_GEM_EXECBUFFER, i915_gem_execbuffer, DRM_AUTH),
- DRM_IOCTL_DEF_DRV(I915_GEM_EXECBUFFER2_WR, i915_gem_execbuffer2, DRM_AUTH|DRM_RENDER_ALLOW),
+ DRM_IOCTL_DEF_DRV(I915_GEM_EXECBUFFER, drm_noop, DRM_AUTH),
+ DRM_IOCTL_DEF_DRV(I915_GEM_EXECBUFFER2_WR, i915_gem_execbuffer2_ioctl, DRM_AUTH|DRM_RENDER_ALLOW),
DRM_IOCTL_DEF_DRV(I915_GEM_PIN, i915_gem_reject_pin_ioctl, DRM_AUTH|DRM_ROOT_ONLY),
DRM_IOCTL_DEF_DRV(I915_GEM_UNPIN, i915_gem_reject_pin_ioctl, DRM_AUTH|DRM_ROOT_ONLY),
DRM_IOCTL_DEF_DRV(I915_GEM_BUSY, i915_gem_busy_ioctl, DRM_AUTH|DRM_RENDER_ALLOW),
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 10beae1a13c8..973da1401fa1 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -3189,10 +3189,8 @@ int i915_gem_set_domain_ioctl(struct drm_device *dev, void *data,
struct drm_file *file_priv);
int i915_gem_sw_finish_ioctl(struct drm_device *dev, void *data,
struct drm_file *file_priv);
-int i915_gem_execbuffer(struct drm_device *dev, void *data,
- struct drm_file *file_priv);
-int i915_gem_execbuffer2(struct drm_device *dev, void *data,
- struct drm_file *file_priv);
+int i915_gem_execbuffer2_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv);
int i915_gem_busy_ioctl(struct drm_device *dev, void *data,
struct drm_file *file_priv);
int i915_gem_get_caching_ioctl(struct drm_device *dev, void *data,
diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c
index a98cc2a067f6..f602ac4a7ad8 100644
--- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c
+++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c
@@ -47,16 +47,16 @@ enum {
#define DBG_FORCE_RELOC 0 /* choose one of the above! */
};
-#define __EXEC_OBJECT_HAS_REF BIT(31)
-#define __EXEC_OBJECT_HAS_PIN BIT(30)
-#define __EXEC_OBJECT_HAS_FENCE BIT(29)
-#define __EXEC_OBJECT_NEEDS_MAP BIT(28)
-#define __EXEC_OBJECT_NEEDS_BIAS BIT(27)
-#define __EXEC_OBJECT_INTERNAL_FLAGS (~0u << 27) /* all of the above */
+#define __EXEC_OBJECT_VALIDATED BIT(31)
+#define __EXEC_OBJECT_HAS_REF BIT(30)
+#define __EXEC_OBJECT_HAS_PIN BIT(29)
+#define __EXEC_OBJECT_HAS_FENCE BIT(28)
+#define __EXEC_OBJECT_NEEDS_MAP BIT(27)
+#define __EXEC_OBJECT_NEEDS_BIAS BIT(26)
+#define __EXEC_OBJECT_INTERNAL_FLAGS (~0u << 26) /* all of the above */
#define __EXEC_OBJECT_RESERVED (__EXEC_OBJECT_HAS_PIN | __EXEC_OBJECT_HAS_FENCE)
#define __EXEC_HAS_RELOC BIT(31)
-#define __EXEC_VALIDATED BIT(30)
#define UPDATE PIN_OFFSET_FIXED
#define BATCH_OFFSET_BIAS (256*1024)
@@ -190,9 +190,9 @@ struct i915_execbuffer {
struct drm_i915_private *i915; /** i915 backpointer */
struct drm_file *file; /** per-file lookup tables and limits */
struct drm_i915_gem_execbuffer2 *args; /** ioctl parameters */
- struct drm_i915_gem_exec_object2 *exec; /** ioctl execobj[] */
struct i915_vma **vma;
unsigned int *flags;
+ u64 *offsets;
struct intel_engine_cs *engine; /** engine to queue the request to */
struct i915_gem_context *ctx; /** context for building the request */
@@ -309,7 +309,9 @@ static bool
eb_vma_misplaced(const struct drm_i915_gem_exec_object2 *entry,
const struct i915_vma *vma)
{
- if (!(*vma->exec_flags & __EXEC_OBJECT_HAS_PIN))
+ unsigned int flags = *vma->exec_flags;
+
+ if (!(flags & __EXEC_OBJECT_HAS_PIN))
return true;
if (vma->node.size < entry->pad_to_size)
@@ -318,15 +320,15 @@ eb_vma_misplaced(const struct drm_i915_gem_exec_object2 *entry,
if (entry->alignment && !IS_ALIGNED(vma->node.start, entry->alignment))
return true;
- if (entry->flags & EXEC_OBJECT_PINNED &&
+ if (flags & EXEC_OBJECT_PINNED &&
vma->node.start != entry->offset)
return true;
- if (entry->flags & __EXEC_OBJECT_NEEDS_BIAS &&
+ if (flags & __EXEC_OBJECT_NEEDS_BIAS &&
vma->node.start < BATCH_OFFSET_BIAS)
return true;
- if (!(entry->flags & EXEC_OBJECT_SUPPORTS_48B_ADDRESS) &&
+ if (!(flags & EXEC_OBJECT_SUPPORTS_48B_ADDRESS) &&
(vma->node.start + vma->node.size - 1) >> 32)
return true;
@@ -338,6 +340,7 @@ eb_pin_vma(struct i915_execbuffer *eb,
const struct drm_i915_gem_exec_object2 *entry,
struct i915_vma *vma)
{
+ unsigned int ctl = *vma->exec_flags;
u64 flags;
if (vma->node.size)
@@ -346,13 +349,13 @@ eb_pin_vma(struct i915_execbuffer *eb,
flags = entry->offset & PIN_OFFSET_MASK;
flags |= PIN_USER | PIN_NOEVICT | PIN_OFFSET_FIXED;
- if (unlikely(entry->flags & EXEC_OBJECT_NEEDS_GTT))
+ if (unlikely(ctl & EXEC_OBJECT_NEEDS_GTT))
flags |= PIN_GLOBAL;
if (unlikely(i915_vma_pin(vma, 0, 0, flags)))
return;
- if (unlikely(entry->flags & EXEC_OBJECT_NEEDS_FENCE)) {
+ if (unlikely(ctl & EXEC_OBJECT_NEEDS_FENCE)) {
if (unlikely(i915_vma_get_fence(vma))) {
i915_vma_unpin(vma);
return;
@@ -422,8 +425,8 @@ eb_validate_vma(struct i915_execbuffer *eb,
}
if (unlikely(vma->exec_flags)) {
- DRM_DEBUG("Object [handle %d, index %d] appears more than once in object list\n",
- entry->handle, (int)(entry - eb->exec));
+ DRM_DEBUG("Object [handle %d] appears more than once in object list\n",
+ entry->handle);
return -EINVAL;
}
@@ -431,14 +434,16 @@ eb_validate_vma(struct i915_execbuffer *eb,
}
static int
-eb_add_vma(struct i915_execbuffer *eb, unsigned int i, struct i915_vma *vma)
+eb_add_vma(struct i915_execbuffer *eb,
+ unsigned int i, struct i915_vma *vma,
+ struct drm_i915_gem_exec_object2 *entry,
+ unsigned int flags)
{
- struct drm_i915_gem_exec_object2 *entry = &eb->exec[i];
int err;
GEM_BUG_ON(i915_vma_is_closed(vma));
- if (!(eb->args->flags & __EXEC_VALIDATED)) {
+ if (!(flags & __EXEC_OBJECT_VALIDATED)) {
err = eb_validate_vma(eb, entry, vma);
if (unlikely(err))
return err;
@@ -473,7 +478,8 @@ eb_add_vma(struct i915_execbuffer *eb, unsigned int i, struct i915_vma *vma)
* to find the right target VMA when doing relocations.
*/
eb->vma[i] = vma;
- eb->flags[i] = entry->flags;
+ eb->offsets[i] = 0;
+ eb->flags[i] = entry->flags | flags;
vma->exec_flags = &eb->flags[i];
err = 0;
@@ -486,8 +492,8 @@ eb_add_vma(struct i915_execbuffer *eb, unsigned int i, struct i915_vma *vma)
err = i915_vma_unbind(vma);
} else {
if (entry->offset != vma->node.start) {
- entry->offset = vma->node.start | UPDATE;
eb->args->flags |= __EXEC_HAS_RELOC;
+ eb->offsets[i] = vma->node.start | UPDATE;
}
}
return err;
@@ -510,15 +516,22 @@ static inline int use_cpu_reloc(const struct reloc_cache *cache,
obj->cache_level != I915_CACHE_NONE);
}
-static int eb_reserve_vma(struct i915_execbuffer *eb, struct i915_vma *vma)
+static int eb_reserve_vma(const struct i915_execbuffer *eb,
+ struct i915_vma *vma)
{
- struct drm_i915_gem_exec_object2 *entry =
- &eb->exec[vma->exec_flags - eb->flags];
+ unsigned long idx = vma->exec_flags - eb->flags;
+ const struct drm_i915_gem_exec_object2 *user =
+ u64_to_user_ptr(eb->args->buffers_ptr);
+ struct drm_i915_gem_exec_object2 entry;
+ unsigned int ctl = *vma->exec_flags;
u64 flags;
int err;
+ if (__copy_from_user(&entry, &user[idx], sizeof(entry)))
+ return -EFAULT;
+
flags = PIN_USER | PIN_NONBLOCK;
- if (entry->flags & EXEC_OBJECT_NEEDS_GTT)
+ if (ctl & EXEC_OBJECT_NEEDS_GTT)
flags |= PIN_GLOBAL;
if (!drm_mm_node_allocated(&vma->node)) {
@@ -526,34 +539,35 @@ static int eb_reserve_vma(struct i915_execbuffer *eb, struct i915_vma *vma)
* Wa32bitGeneralStateOffset & Wa32bitInstructionBaseOffset,
* limit address to the first 4GBs for unflagged objects.
*/
- if (!(entry->flags & EXEC_OBJECT_SUPPORTS_48B_ADDRESS))
+ if (!(ctl & EXEC_OBJECT_SUPPORTS_48B_ADDRESS))
flags |= PIN_ZONE_4G;
- if (entry->flags & __EXEC_OBJECT_NEEDS_MAP)
+ if (ctl & __EXEC_OBJECT_NEEDS_MAP)
flags |= PIN_MAPPABLE;
- if (entry->flags & EXEC_OBJECT_PINNED) {
- flags |= entry->offset | PIN_OFFSET_FIXED;
+ if (ctl & EXEC_OBJECT_PINNED) {
+ flags |= entry.offset | PIN_OFFSET_FIXED;
/* force overlapping PINNED checks */
flags &= ~PIN_NONBLOCK;
- } else if (entry->flags & __EXEC_OBJECT_NEEDS_BIAS) {
+ } else if (ctl & __EXEC_OBJECT_NEEDS_BIAS) {
flags |= BATCH_OFFSET_BIAS | PIN_OFFSET_BIAS;
}
}
- err = i915_vma_pin(vma, entry->pad_to_size, entry->alignment, flags);
+ err = i915_vma_pin(vma, entry.pad_to_size, entry.alignment, flags);
if (err)
return err;
- if (entry->offset != vma->node.start) {
- entry->offset = vma->node.start | UPDATE;
+ eb->offsets[idx] = 0;
+ if (entry.offset != vma->node.start) {
eb->args->flags |= __EXEC_HAS_RELOC;
+ eb->offsets[idx] = vma->node.start | UPDATE;
}
*vma->exec_flags |= __EXEC_OBJECT_HAS_PIN;
- GEM_BUG_ON(eb_vma_misplaced(entry, vma));
+ GEM_BUG_ON(eb_vma_misplaced(&entry, vma));
- if (unlikely(entry->flags & EXEC_OBJECT_NEEDS_FENCE)) {
+ if (unlikely(ctl & EXEC_OBJECT_NEEDS_FENCE)) {
err = i915_vma_get_fence(vma);
if (unlikely(err)) {
i915_vma_unpin(vma);
@@ -685,15 +699,15 @@ static int eb_select_context(struct i915_execbuffer *eb)
return 0;
}
-static int eb_lookup_vmas(struct i915_execbuffer *eb)
+static int eb_lookup_vmas(struct i915_execbuffer *eb, unsigned int flags)
{
-#define INTERMEDIATE BIT(0)
- const unsigned int count = eb->buffer_count;
+#define N_EXEC(x) ((x) / sizeof(struct drm_i915_gem_exec_object2))
+ struct drm_i915_gem_exec_object2 stack[N_EXEC(768)];
+ const struct drm_i915_gem_exec_object2 *user =
+ u64_to_user_ptr(eb->args->buffers_ptr);
struct i915_gem_context_vma_lut *lut = &eb->ctx->vma_lut;
- struct i915_vma *vma;
- struct idr *idr;
- unsigned int i;
- int slow_pass = -1;
+ struct drm_i915_gem_object *uninitialized_var(obj);
+ unsigned int i, remain;
int err;
INIT_LIST_HEAD(&eb->relocs);
@@ -703,105 +717,74 @@ static int eb_lookup_vmas(struct i915_execbuffer *eb)
flush_work(&lut->resize);
GEM_BUG_ON(lut->ht_size & I915_CTX_RESIZE_IN_PROGRESS);
- for (i = 0; i < count; i++) {
- hlist_for_each_entry(vma,
- ht_head(lut, eb->exec[i].handle),
- ctx_node) {
- if (vma->ctx_handle != eb->exec[i].handle)
- continue;
-
- err = eb_add_vma(eb, i, vma);
- if (unlikely(err))
- return err;
- goto next_vma;
- }
-
- if (slow_pass < 0)
- slow_pass = i;
-
- eb->vma[i] = NULL;
+ i = 0;
+ remain = eb->buffer_count;
+ do {
+ struct drm_i915_gem_exec_object2 *exec = stack;
+ unsigned int count =
+ min_t(unsigned int, remain, ARRAY_SIZE(stack));
-next_vma: ;
- }
+ GEM_BUG_ON(!count);
- if (slow_pass < 0)
- goto out;
+ if (__copy_from_user(exec, user, count * sizeof(exec[0]))) {
+ err = -EFAULT;
+ goto err;
+ }
- spin_lock(&eb->file->table_lock);
- /*
- * Grab a reference to the object and release the lock so we can lookup
- * or create the VMA without using GFP_ATOMIC
- */
- idr = &eb->file->object_idr;
- for (i = slow_pass; i < count; i++) {
- struct drm_i915_gem_object *obj;
+ user += count;
+ remain -= count;
- if (eb->vma[i])
- continue;
+ do {
+ struct hlist_head *hl = ht_head(lut, exec->handle);
+ struct i915_vma *vma;
- obj = to_intel_bo(idr_find(idr, eb->exec[i].handle));
- if (unlikely(!obj)) {
- spin_unlock(&eb->file->table_lock);
- DRM_DEBUG("Invalid object handle %d at index %d\n",
- eb->exec[i].handle, i);
- err = -ENOENT;
- goto err;
- }
+ hlist_for_each_entry(vma, hl, ctx_node) {
+ GEM_BUG_ON(vma->ctx != eb->ctx);
- eb->vma[i] =
- (struct i915_vma *)ptr_pack_bits(obj, INTERMEDIATE, 1);
- }
- spin_unlock(&eb->file->table_lock);
+ if (vma->ctx_handle != exec->handle)
+ continue;
- for (i = slow_pass; i < count; i++) {
- struct drm_i915_gem_object *obj;
- unsigned int is_obj;
+ goto add_vma;
+ }
- obj = (typeof(obj))ptr_unpack_bits(eb->vma[i], &is_obj, 1);
- if (!is_obj)
- continue;
+ obj = i915_gem_object_lookup(eb->file, exec->handle);
+ if (unlikely(!obj)) {
+ err = -ENOENT;
+ goto err;
+ }
- /*
- * NOTE: We can leak any vmas created here when something fails
- * later on. But that's no issue since vma_unbind can deal with
- * vmas which are not actually bound. And since only
- * lookup_or_create exists as an interface to get at the vma
- * from the (obj, vm) we don't run the risk of creating
- * duplicated vmas for the same vm.
- */
- vma = i915_vma_instance(obj, eb->vm, NULL);
- if (unlikely(IS_ERR(vma))) {
- DRM_DEBUG("Failed to lookup VMA\n");
- err = PTR_ERR(vma);
- goto err;
- }
+ flags |= __EXEC_OBJECT_HAS_REF;
- /* First come, first served */
- if (!vma->ctx) {
- vma->ctx = eb->ctx;
- vma->ctx_handle = eb->exec[i].handle;
- hlist_add_head(&vma->ctx_node,
- ht_head(lut, eb->exec[i].handle));
- lut->ht_count++;
- lut->ht_size |= I915_CTX_RESIZE_IN_PROGRESS;
- if (i915_vma_is_ggtt(vma)) {
- GEM_BUG_ON(obj->vma_hashed);
- obj->vma_hashed = vma;
+ vma = i915_vma_instance(obj, eb->vm, NULL);
+ if (unlikely(IS_ERR(vma))) {
+ err = PTR_ERR(vma);
+ goto err;
}
- i915_vma_get(vma);
- }
+ /* First come, first served */
+ if (!vma->ctx) {
+ vma->ctx = eb->ctx;
+ vma->ctx_handle = exec->handle;
+ hlist_add_head(&vma->ctx_node, hl);
+ lut->ht_count++;
+ lut->ht_size |= I915_CTX_RESIZE_IN_PROGRESS;
+ if (i915_vma_is_ggtt(vma)) {
+ GEM_BUG_ON(obj->vma_hashed);
+ obj->vma_hashed = vma;
+ }
+
+ /* transfer ref to ctx */
+ flags &= ~__EXEC_OBJECT_HAS_REF;
+ }
- err = eb_add_vma(eb, i, vma);
- if (unlikely(err))
- goto err;
+add_vma:
+ err = eb_add_vma(eb, i, vma, exec, flags);
+ if (unlikely(err))
+ goto err;
- /* Only after we validated the user didn't use our bits */
- if (vma->ctx != eb->ctx) {
- i915_vma_get(vma);
- eb->flags[i] |= __EXEC_OBJECT_HAS_REF;
- }
- }
+ flags &= ~__EXEC_OBJECT_HAS_REF;
+ } while (i++, exec++, --count);
+ } while (remain);
if (lut->ht_size & I915_CTX_RESIZE_IN_PROGRESS) {
if (ht_needs_resize(lut))
@@ -810,7 +793,6 @@ next_vma: ;
lut->ht_size &= ~I915_CTX_RESIZE_IN_PROGRESS;
}
-out:
/* take note of the batch buffer before we might reorder the lists */
i = eb_batch_index(eb);
eb->batch = eb->vma[i];
@@ -825,22 +807,19 @@ next_vma: ;
* Note that actual hangs have only been observed on gen7, but for
* paranoia do it everywhere.
*/
- if (!(eb->exec[i].flags & EXEC_OBJECT_PINNED))
- eb->exec[i].flags |= __EXEC_OBJECT_NEEDS_BIAS;
+ if (!(eb->flags[i] & EXEC_OBJECT_PINNED))
+ eb->flags[i] |= __EXEC_OBJECT_NEEDS_BIAS;
if (eb->reloc_cache.has_fence)
- eb->exec[i].flags |= EXEC_OBJECT_NEEDS_FENCE;
+ eb->flags[i] |= EXEC_OBJECT_NEEDS_FENCE;
- eb->args->flags |= __EXEC_VALIDATED;
return eb_reserve(eb);
err:
- for (i = slow_pass; i < count; i++) {
- if (ptr_unmask_bits(eb->vma[i], 1))
- eb->vma[i] = NULL;
- }
+ if (flags & __EXEC_OBJECT_HAS_REF)
+ i915_gem_object_put(obj);
lut->ht_size &= ~I915_CTX_RESIZE_IN_PROGRESS;
+ eb->vma[i] = NULL;
return err;
-#undef INTERMEDIATE
}
static struct i915_vma *
@@ -872,6 +851,9 @@ static void eb_reset_vmas(const struct i915_execbuffer *eb)
struct i915_vma *vma = eb->vma[i];
unsigned int *flags = &eb->flags[i];
+ if (!vma)
+ break;
+
eb_unreserve_vma(vma, flags);
vma->exec_flags = NULL;
@@ -891,17 +873,14 @@ static void eb_release_vmas(const struct i915_execbuffer *eb)
const unsigned int count = eb->buffer_count;
unsigned int i;
- if (!eb->exec)
- return;
-
for (i = 0; i < count; i++) {
struct i915_vma *vma = eb->vma[i];
unsigned int *flags = &eb->flags[i];
if (!vma)
- continue;
+ break;
- GEM_BUG_ON(vma->exec_flags != &eb->flags[i]);
+ GEM_BUG_ON(vma->exec_flags != flags);
eb_unreserve_vma(vma, flags);
vma->exec_flags = NULL;
@@ -1451,12 +1430,21 @@ static int eb_relocate_vma(struct i915_execbuffer *eb, struct i915_vma *vma)
#define N_RELOC(x) ((x) / sizeof(struct drm_i915_gem_relocation_entry))
struct drm_i915_gem_relocation_entry stack[N_RELOC(512)];
struct drm_i915_gem_relocation_entry __user *urelocs;
- const struct drm_i915_gem_exec_object2 *entry =
- &eb->exec[vma->exec_flags - eb->flags];
+ const struct drm_i915_gem_exec_object2 *exec =
+ u64_to_user_ptr(eb->args->buffers_ptr);
+ unsigned int idx = vma->exec_flags - eb->flags;
unsigned int remain;
+ u64 uptr;
+ int err;
+
+ err = __get_user(uptr, &exec[idx].relocs_ptr);
+ if (unlikely(err))
+ return err;
+
+ err = __get_user(remain, &exec[idx].relocation_count);
+ if (unlikely(err))
+ return err;
- urelocs = u64_to_user_ptr(entry->relocs_ptr);
- remain = entry->relocation_count;
if (unlikely(remain > N_RELOC(ULONG_MAX)))
return -EINVAL;
@@ -1466,6 +1454,7 @@ static int eb_relocate_vma(struct i915_execbuffer *eb, struct i915_vma *vma)
* the updated relocation values.
*/
+ urelocs = u64_to_user_ptr(uptr);
do {
struct drm_i915_gem_relocation_entry *r = stack;
unsigned int count =
@@ -1532,18 +1521,21 @@ static int eb_relocate_vma(struct i915_execbuffer *eb, struct i915_vma *vma)
return remain;
}
+struct eb_relocs {
+ struct drm_i915_gem_relocation_entry *relocs;
+ unsigned int count;
+};
+
static int
-eb_relocate_vma_slow(struct i915_execbuffer *eb, struct i915_vma *vma)
+eb_relocate_vma_slow(struct i915_execbuffer *eb, struct i915_vma *vma,
+ struct eb_relocs *r)
{
- const struct drm_i915_gem_exec_object2 *entry =
- &eb->exec[vma->exec_flags - eb->flags];
- struct drm_i915_gem_relocation_entry *relocs =
- u64_to_ptr(typeof(*relocs), entry->relocs_ptr);
- unsigned int i;
+ struct drm_i915_gem_relocation_entry *relocs = r->relocs;
+ unsigned int count = r->count;
int err;
- for (i = 0; i < entry->relocation_count; i++) {
- u64 offset = eb_relocate_entry(eb, vma, &relocs[i]);
+ while (count--) {
+ u64 offset = eb_relocate_entry(eb, vma, relocs++);
if ((s64)offset < 0) {
err = (int)offset;
@@ -1570,59 +1562,67 @@ static int eb_relocate(struct i915_execbuffer *eb)
return 0;
}
-static int check_relocations(const struct drm_i915_gem_exec_object2 *entry)
+static int check_relocations(unsigned int count, const void __user *addr)
{
- const char __user *addr, *end;
+ const void __user *end;
unsigned long size;
char __maybe_unused c;
- size = entry->relocation_count;
- if (size == 0)
- return 0;
-
- if (size > N_RELOC(ULONG_MAX))
+ if (count > N_RELOC(ULONG_MAX))
return -EINVAL;
- addr = u64_to_user_ptr(entry->relocs_ptr);
- size *= sizeof(struct drm_i915_gem_relocation_entry);
- if (!access_ok(VERIFY_WRITE, addr, size))
+ size = count * sizeof(struct drm_i915_gem_relocation_entry);
+ if (!access_ok(VERIFY_READ, addr, size))
return -EFAULT;
end = addr + size;
for (; addr < end; addr += PAGE_SIZE) {
- int err = __get_user(c, addr);
+ int err = __get_user(c, (const char __user *)addr);
if (err)
return err;
}
- return __get_user(c, end - 1);
+ return __get_user(c, (const char __user *)end - 1);
}
-static int eb_copy_relocations(const struct i915_execbuffer *eb)
+static struct eb_relocs *eb_copy_relocations(const struct i915_execbuffer *eb)
{
+ const struct drm_i915_gem_exec_object2 *exec =
+ u64_to_user_ptr(eb->args->buffers_ptr);
const unsigned int count = eb->buffer_count;
+ struct eb_relocs *r;
unsigned int i;
int err;
+ r = kvmalloc_array(count, sizeof(*r), GFP_TEMPORARY | __GFP_ZERO);
+ if (!r)
+ return ERR_PTR(-ENOMEM);
+
for (i = 0; i < count; i++) {
- const unsigned int nreloc = eb->exec[i].relocation_count;
struct drm_i915_gem_relocation_entry __user *urelocs;
- struct drm_i915_gem_relocation_entry *relocs;
- unsigned long size;
- unsigned long copied;
+ unsigned int copied;
+ unsigned int nreloc;
+ u64 uptr;
+
+ err = __get_user(nreloc, &exec[i].relocation_count);
+ if (unlikely(err))
+ goto err;
if (nreloc == 0)
continue;
- err = check_relocations(&eb->exec[i]);
- if (err)
+ err = __get_user(uptr, &exec[i].relocs_ptr);
+ if (unlikely(err))
goto err;
- urelocs = u64_to_user_ptr(eb->exec[i].relocs_ptr);
- size = nreloc * sizeof(*relocs);
+ urelocs = u64_to_user_ptr(uptr);
+ err = check_relocations(nreloc, urelocs);
+ if (err)
+ goto err;
- relocs = kvmalloc_array(size, 1, GFP_TEMPORARY);
- if (!relocs) {
- kvfree(relocs);
+ r[i].relocs = kvmalloc_array(nreloc,
+ sizeof(*r->relocs),
+ GFP_TEMPORARY);
+ if (!r[i].relocs) {
err = -ENOMEM;
goto err;
}
@@ -1631,18 +1631,20 @@ static int eb_copy_relocations(const struct i915_execbuffer *eb)
copied = 0;
do {
unsigned int len =
- min_t(u64, BIT_ULL(31), size - copied);
-
- if (__copy_from_user((char *)relocs + copied,
- (char *)urelocs + copied,
- len)) {
- kvfree(relocs);
+ min_t(u64,
+ BIT_ULL(31) / sizeof(*r->relocs),
+ nreloc - copied);
+
+ if (__copy_from_user(r[i].relocs + copied,
+ urelocs + copied,
+ len * sizeof(*r->relocs))) {
+ kvfree(r[i].relocs);
err = -EFAULT;
goto err;
}
copied += len;
- } while (copied < size);
+ } while (copied < nreloc);
/*
* As we do not update the known relocation offsets after
@@ -1662,33 +1664,43 @@ static int eb_copy_relocations(const struct i915_execbuffer *eb)
end_user:
user_access_end();
- eb->exec[i].relocs_ptr = (uintptr_t)relocs;
+ r[i].count = nreloc;
}
- return 0;
+ return r;
err:
- while (i--) {
- struct drm_i915_gem_relocation_entry *relocs =
- u64_to_ptr(typeof(*relocs), eb->exec[i].relocs_ptr);
- if (eb->exec[i].relocation_count)
- kvfree(relocs);
- }
- return err;
+ while (i--)
+ kvfree(r[i].relocs);
+ kvfree(r);
+ return ERR_PTR(err);
}
static int eb_prefault_relocations(const struct i915_execbuffer *eb)
{
+ const struct drm_i915_gem_exec_object2 *exec =
+ u64_to_user_ptr(eb->args->buffers_ptr);
const unsigned int count = eb->buffer_count;
unsigned int i;
+ int err;
if (unlikely(i915.prefault_disable))
return 0;
for (i = 0; i < count; i++) {
- int err;
+ unsigned int nreloc;
+ u64 uptr;
+
+ if (__get_user(nreloc, &exec[i].relocation_count))
+ return -EFAULT;
- err = check_relocations(&eb->exec[i]);
+ if (nreloc == 0)
+ continue;
+
+ if (__get_user(uptr, &exec[i].relocs_ptr))
+ return -EFAULT;
+
+ err = check_relocations(nreloc, u64_to_user_ptr(uptr));
if (err)
return err;
}
@@ -1699,7 +1711,7 @@ static int eb_prefault_relocations(const struct i915_execbuffer *eb)
static int eb_relocate_slow(struct i915_execbuffer *eb)
{
struct drm_device *dev = &eb->i915->drm;
- bool have_copy = false;
+ struct eb_relocs *r = NULL;
struct i915_vma *vma;
int err = 0;
@@ -1728,9 +1740,11 @@ static int eb_relocate_slow(struct i915_execbuffer *eb)
*/
if (!err) {
err = eb_prefault_relocations(eb);
- } else if (!have_copy) {
- err = eb_copy_relocations(eb);
- have_copy = err == 0;
+ } else if (!r) {
+ err = 0;
+ r = eb_copy_relocations(eb);
+ if (IS_ERR(r))
+ err = PTR_ERR(r);
} else {
cond_resched();
err = 0;
@@ -1750,21 +1764,22 @@ static int eb_relocate_slow(struct i915_execbuffer *eb)
}
/* reacquire the objects */
- err = eb_lookup_vmas(eb);
+ err = eb_lookup_vmas(eb, __EXEC_OBJECT_VALIDATED);
if (err)
goto err;
GEM_BUG_ON(!eb->batch);
list_for_each_entry(vma, &eb->relocs, reloc_link) {
- if (!have_copy) {
+ if (!r) {
pagefault_disable();
err = eb_relocate_vma(eb, vma);
pagefault_enable();
if (err)
goto repeat;
} else {
- err = eb_relocate_vma_slow(eb, vma);
+ err = eb_relocate_vma_slow(eb, vma,
+ &r[vma->exec_flags - eb->flags]);
if (err)
goto err;
}
@@ -1782,24 +1797,16 @@ static int eb_relocate_slow(struct i915_execbuffer *eb)
goto repeat;
out:
- if (have_copy) {
+ if (r) {
const unsigned int count = eb->buffer_count;
unsigned int i;
- for (i = 0; i < count; i++) {
- const struct drm_i915_gem_exec_object2 *entry =
- &eb->exec[i];
- struct drm_i915_gem_relocation_entry *relocs;
-
- if (!entry->relocation_count)
- continue;
-
- relocs = u64_to_ptr(typeof(*relocs), entry->relocs_ptr);
- kvfree(relocs);
- }
+ for (i = 0; i < count; i++)
+ kvfree(r[i].relocs);
+ kvfree(r);
}
- return err ?: have_copy;
+ return err ?: !!r;
}
static void eb_export_fence(struct i915_vma *vma,
@@ -1869,7 +1876,7 @@ static int eb_move_to_gpu(struct i915_execbuffer *eb)
if (unlikely(flags & __EXEC_OBJECT_HAS_REF))
i915_vma_put(vma);
}
- eb->exec = NULL;
+ eb->buffer_count = 0;
/* Unconditionally flush any chipset caches (for streaming writes). */
i915_gem_chipset_flush(eb->i915);
@@ -1878,26 +1885,34 @@ static int eb_move_to_gpu(struct i915_execbuffer *eb)
return eb->engine->emit_flush(eb->request, EMIT_INVALIDATE);
}
-static bool i915_gem_check_execbuffer(struct drm_i915_gem_execbuffer2 *exec)
+static int eb_check_args(struct drm_i915_gem_execbuffer2 *args)
{
- if (exec->flags & __I915_EXEC_ILLEGAL_FLAGS)
- return false;
+ if (args->flags & __I915_EXEC_ILLEGAL_FLAGS)
+ return -EINVAL;
/* Kernel clipping was a DRI1 misfeature */
- if (exec->num_cliprects || exec->cliprects_ptr)
- return false;
+ if (args->num_cliprects | args->cliprects_ptr)
+ return -EINVAL;
- if (exec->DR4 == 0xffffffff) {
+ if (args->DR4 == 0xffffffff) {
DRM_DEBUG("UXA submitting garbage DR4, fixing up\n");
- exec->DR4 = 0;
+ args->DR4 = 0;
}
- if (exec->DR1 || exec->DR4)
- return false;
+ if (args->DR1 | args->DR4)
+ return -EINVAL;
- if ((exec->batch_start_offset | exec->batch_len) & 0x7)
- return false;
+ if ((args->batch_start_offset | args->batch_len) & 0x7)
+ return -EINVAL;
- return true;
+ if (args->buffer_count < 1 || args->buffer_count > N_EXEC(SIZE_MAX) - 1)
+ return -EINVAL;
+
+ if (!access_ok(VERIFY_READ,
+ args->buffers_ptr,
+ args->buffer_count * sizeof(struct drm_i915_gem_exec_object2)))
+ return -EFAULT;
+
+ return 0;
}
void i915_vma_move_to_active(struct i915_vma *vma,
@@ -2117,16 +2132,18 @@ eb_select_engine(struct drm_i915_private *dev_priv,
return engine;
}
-static int
-i915_gem_do_execbuffer(struct drm_device *dev,
- struct drm_file *file,
- struct drm_i915_gem_execbuffer2 *args,
- struct drm_i915_gem_exec_object2 *exec)
+int
+i915_gem_execbuffer2_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file)
{
+ const size_t sz = (sizeof(struct i915_vma *) +
+ sizeof(unsigned int) +
+ sizeof(u64));
struct i915_execbuffer eb;
struct dma_fence *in_fence = NULL;
struct sync_file *out_fence = NULL;
int out_fence_fd = -1;
+ char onstack[900 - sizeof(eb)];
int err;
BUILD_BUG_ON(__EXEC_OBJECT_INTERNAL_FLAGS &
@@ -2134,56 +2151,81 @@ i915_gem_do_execbuffer(struct drm_device *dev,
eb.i915 = to_i915(dev);
eb.file = file;
- eb.args = args;
- if (DBG_FORCE_RELOC || !(args->flags & I915_EXEC_NO_RELOC))
- args->flags |= __EXEC_HAS_RELOC;
- eb.exec = exec;
- eb.vma = (struct i915_vma **)(exec + args->buffer_count + 1);
- eb.flags = (unsigned int *)(eb.vma + args->buffer_count + 1);
+ eb.args = data;
+
+ err = eb_check_args(eb.args);
+ if (unlikely(err))
+ return err;
+
+ /* Allocate an extra slot for use by the command parser */
+ if (eb.args->buffer_count + 1 > sizeof(onstack) / sz) {
+ eb.vma = kvmalloc_array(eb.args->buffer_count + 1, sz,
+ __GFP_NOWARN | GFP_TEMPORARY);
+ if (!eb.vma) {
+ DRM_DEBUG("Failed to allocate exec list for %d buffers\n",
+ eb.args->buffer_count);
+ return -ENOMEM;
+ }
+ } else {
+ eb.vma = (typeof(eb.vma))onstack;
+ }
+
+ if (DBG_FORCE_RELOC || !(eb.args->flags & I915_EXEC_NO_RELOC))
+ eb.args->flags |= __EXEC_HAS_RELOC;
+ eb.flags = (unsigned int *)(eb.vma + eb.args->buffer_count + 1);
+ eb.offsets = (u64 *)(eb.flags + eb.args->buffer_count + 1);
eb.invalid_flags = __EXEC_OBJECT_UNKNOWN_FLAGS;
if (USES_FULL_PPGTT(eb.i915))
eb.invalid_flags |= EXEC_OBJECT_NEEDS_GTT;
reloc_cache_init(&eb.reloc_cache, eb.i915);
- eb.buffer_count = args->buffer_count;
- eb.batch_start_offset = args->batch_start_offset;
- eb.batch_len = args->batch_len;
+ eb.buffer_count = eb.args->buffer_count;
+ eb.batch_start_offset = eb.args->batch_start_offset;
+ eb.batch_len = eb.args->batch_len;
eb.batch_flags = 0;
- if (args->flags & I915_EXEC_SECURE) {
- if (!drm_is_current_master(file) || !capable(CAP_SYS_ADMIN))
- return -EPERM;
+ if (eb.args->flags & I915_EXEC_SECURE) {
+ if (!drm_is_current_master(file) || !capable(CAP_SYS_ADMIN)) {
+ err = -EPERM;
+ goto out;
+ }
eb.batch_flags |= I915_DISPATCH_SECURE;
}
- if (args->flags & I915_EXEC_IS_PINNED)
+ if (eb.args->flags & I915_EXEC_IS_PINNED)
eb.batch_flags |= I915_DISPATCH_PINNED;
- eb.engine = eb_select_engine(eb.i915, file, args);
- if (!eb.engine)
- return -EINVAL;
+ eb.engine = eb_select_engine(eb.i915, file, eb.args);
+ if (!eb.engine) {
+ err = -EINVAL;
+ goto out;
+ }
- if (args->flags & I915_EXEC_RESOURCE_STREAMER) {
+ if (eb.args->flags & I915_EXEC_RESOURCE_STREAMER) {
if (!HAS_RESOURCE_STREAMER(eb.i915)) {
DRM_DEBUG("RS is only allowed for Haswell, Gen8 and above\n");
- return -EINVAL;
+ err = -EINVAL;
+ goto out;
}
if (eb.engine->id != RCS) {
DRM_DEBUG("RS is not available on %s\n",
eb.engine->name);
- return -EINVAL;
+ err = -EINVAL;
+ goto out;
}
eb.batch_flags |= I915_DISPATCH_RS;
}
- if (args->flags & I915_EXEC_FENCE_IN) {
- in_fence = sync_file_get_fence(lower_32_bits(args->rsvd2));
- if (!in_fence)
- return -EINVAL;
+ if (eb.args->flags & I915_EXEC_FENCE_IN) {
+ in_fence = sync_file_get_fence(lower_32_bits(eb.args->rsvd2));
+ if (!in_fence) {
+ err = -EINVAL;
+ goto out;
+ }
}
- if (args->flags & I915_EXEC_FENCE_OUT) {
+ if (eb.args->flags & I915_EXEC_FENCE_OUT) {
out_fence_fd = get_unused_fd_flags(O_CLOEXEC);
if (out_fence_fd < 0) {
err = out_fence_fd;
@@ -2191,8 +2233,10 @@ i915_gem_do_execbuffer(struct drm_device *dev,
}
}
- if (eb_create(&eb))
- return -ENOMEM;
+ if (eb_create(&eb)) {
+ err = -ENOMEM;
+ goto out;
+ }
err = eb_select_context(&eb);
if (unlikely(err))
@@ -2211,12 +2255,12 @@ i915_gem_do_execbuffer(struct drm_device *dev,
if (err)
goto err_rpm;
- err = eb_lookup_vmas(&eb);
- if (likely(!err && args->flags & __EXEC_HAS_RELOC))
+ err = eb_lookup_vmas(&eb, 0);
+ if (likely(!err && eb.args->flags & __EXEC_HAS_RELOC))
err = eb_relocate(&eb);
if (err == -EAGAIN || err == -EFAULT)
err = eb_relocate_slow(&eb);
- if (err && args->flags & I915_EXEC_NO_RELOC)
+ if (err && eb.args->flags & I915_EXEC_NO_RELOC)
/*
* If the user expects the execobject.offset and
* reloc.presumed_offset to be an exact match,
@@ -2224,7 +2268,7 @@ i915_gem_do_execbuffer(struct drm_device *dev,
* the execobject.offset until we have completed
* relocation.
*/
- args->flags &= ~__EXEC_HAS_RELOC;
+ eb.args->flags &= ~__EXEC_HAS_RELOC;
if (err < 0)
goto err_vma;
@@ -2336,8 +2380,8 @@ i915_gem_do_execbuffer(struct drm_device *dev,
if (out_fence) {
if (err == 0) {
fd_install(out_fence_fd, out_fence->file);
- args->rsvd2 &= GENMASK_ULL(0, 31); /* keep in-fence */
- args->rsvd2 |= (u64)out_fence_fd << 32;
+ eb.args->rsvd2 &= GENMASK_ULL(0, 31); /* keep in-fence */
+ eb.args->rsvd2 |= (u64)out_fence_fd << 32;
out_fence_fd = -1;
} else {
fput(out_fence->file);
@@ -2359,142 +2403,6 @@ i915_gem_do_execbuffer(struct drm_device *dev,
put_unused_fd(out_fence_fd);
err_in_fence:
dma_fence_put(in_fence);
- return err;
-}
-
-/*
- * Legacy execbuffer just creates an exec2 list from the original exec object
- * list array and passes it to the real function.
- */
-int
-i915_gem_execbuffer(struct drm_device *dev, void *data,
- struct drm_file *file)
-{
- const size_t sz = (sizeof(struct drm_i915_gem_exec_object2) +
- sizeof(struct i915_vma *) +
- sizeof(unsigned int));
- struct drm_i915_gem_execbuffer *args = data;
- struct drm_i915_gem_execbuffer2 exec2;
- struct drm_i915_gem_exec_object *exec_list = NULL;
- struct drm_i915_gem_exec_object2 *exec2_list = NULL;
- unsigned int i;
- int err;
-
- if (args->buffer_count < 1 || args->buffer_count > SIZE_MAX / sz - 1) {
- DRM_DEBUG("execbuf2 with %d buffers\n", args->buffer_count);
- return -EINVAL;
- }
-
- exec2.buffers_ptr = args->buffers_ptr;
- exec2.buffer_count = args->buffer_count;
- exec2.batch_start_offset = args->batch_start_offset;
- exec2.batch_len = args->batch_len;
- exec2.DR1 = args->DR1;
- exec2.DR4 = args->DR4;
- exec2.num_cliprects = args->num_cliprects;
- exec2.cliprects_ptr = args->cliprects_ptr;
- exec2.flags = I915_EXEC_RENDER;
- i915_execbuffer2_set_context_id(exec2, 0);
-
- if (!i915_gem_check_execbuffer(&exec2))
- return -EINVAL;
-
- /* Copy in the exec list from userland */
- exec_list = kvmalloc_array(args->buffer_count, sizeof(*exec_list),
- __GFP_NOWARN | GFP_TEMPORARY);
- exec2_list = kvmalloc_array(args->buffer_count + 1, sz,
- __GFP_NOWARN | GFP_TEMPORARY);
- if (exec_list == NULL || exec2_list == NULL) {
- DRM_DEBUG("Failed to allocate exec list for %d buffers\n",
- args->buffer_count);
- kvfree(exec_list);
- kvfree(exec2_list);
- return -ENOMEM;
- }
- err = copy_from_user(exec_list,
- u64_to_user_ptr(args->buffers_ptr),
- sizeof(*exec_list) * args->buffer_count);
- if (err) {
- DRM_DEBUG("copy %d exec entries failed %d\n",
- args->buffer_count, err);
- kvfree(exec_list);
- kvfree(exec2_list);
- return -EFAULT;
- }
-
- for (i = 0; i < args->buffer_count; i++) {
- exec2_list[i].handle = exec_list[i].handle;
- exec2_list[i].relocation_count = exec_list[i].relocation_count;
- exec2_list[i].relocs_ptr = exec_list[i].relocs_ptr;
- exec2_list[i].alignment = exec_list[i].alignment;
- exec2_list[i].offset = exec_list[i].offset;
- if (INTEL_GEN(to_i915(dev)) < 4)
- exec2_list[i].flags = EXEC_OBJECT_NEEDS_FENCE;
- else
- exec2_list[i].flags = 0;
- }
-
- err = i915_gem_do_execbuffer(dev, file, &exec2, exec2_list);
- if (exec2.flags & __EXEC_HAS_RELOC) {
- struct drm_i915_gem_exec_object __user *user_exec_list =
- u64_to_user_ptr(args->buffers_ptr);
-
- /* Copy the new buffer offsets back to the user's exec list. */
- for (i = 0; i < args->buffer_count; i++) {
- if (!(exec2_list[i].offset & UPDATE))
- continue;
-
- exec2_list[i].offset =
- gen8_canonical_addr(exec2_list[i].offset & PIN_OFFSET_MASK);
- exec2_list[i].offset &= PIN_OFFSET_MASK;
- if (__copy_to_user(&user_exec_list[i].offset,
- &exec2_list[i].offset,
- sizeof(user_exec_list[i].offset)))
- break;
- }
- }
-
- kvfree(exec_list);
- kvfree(exec2_list);
- return err;
-}
-
-int
-i915_gem_execbuffer2(struct drm_device *dev, void *data,
- struct drm_file *file)
-{
- const size_t sz = (sizeof(struct drm_i915_gem_exec_object2) +
- sizeof(struct i915_vma *) +
- sizeof(unsigned int));
- struct drm_i915_gem_execbuffer2 *args = data;
- struct drm_i915_gem_exec_object2 *exec2_list;
- int err;
-
- if (args->buffer_count < 1 || args->buffer_count > SIZE_MAX / sz - 1) {
- DRM_DEBUG("execbuf2 with %d buffers\n", args->buffer_count);
- return -EINVAL;
- }
-
- if (!i915_gem_check_execbuffer(args))
- return -EINVAL;
-
- /* Allocate an extra slot for use by the command parser */
- exec2_list = kvmalloc_array(args->buffer_count + 1, sz,
- __GFP_NOWARN | GFP_TEMPORARY);
- if (exec2_list == NULL) {
- DRM_DEBUG("Failed to allocate exec list for %d buffers\n",
- args->buffer_count);
- return -ENOMEM;
- }
- if (copy_from_user(exec2_list,
- u64_to_user_ptr(args->buffers_ptr),
- sizeof(*exec2_list) * args->buffer_count)) {
- DRM_DEBUG("copy %d exec entries failed\n", args->buffer_count);
- kvfree(exec2_list);
- return -EFAULT;
- }
-
- err = i915_gem_do_execbuffer(dev, file, args, exec2_list);
/*
* Now that we have begun execution of the batchbuffer, we ignore
@@ -2502,28 +2410,29 @@ i915_gem_execbuffer2(struct drm_device *dev, void *data,
* updated the associated relocations, we try to write out the current
* object locations irrespective of any error.
*/
- if (args->flags & __EXEC_HAS_RELOC) {
- struct drm_i915_gem_exec_object2 __user *user_exec_list =
- u64_to_user_ptr(args->buffers_ptr);
+ if (eb.args->flags & __EXEC_HAS_RELOC) {
+ struct drm_i915_gem_exec_object2 __user *user =
+ u64_to_user_ptr(eb.args->buffers_ptr);
unsigned int i;
/* Copy the new buffer offsets back to the user's exec list. */
user_access_begin();
- for (i = 0; i < args->buffer_count; i++) {
- if (!(exec2_list[i].offset & UPDATE))
+ for (i = 0; i < eb.args->buffer_count; i++) {
+ u64 offset;
+
+ if (!(eb.offsets[i] & UPDATE))
continue;
- exec2_list[i].offset =
- gen8_canonical_addr(exec2_list[i].offset & PIN_OFFSET_MASK);
- unsafe_put_user(exec2_list[i].offset,
- &user_exec_list[i].offset,
- end_user);
+ offset = gen8_canonical_addr(eb.offsets[i] & ~UPDATE);
+ unsafe_put_user(offset, &user[i].offset, end_user);
}
end_user:
user_access_end();
}
- args->flags &= ~__I915_EXEC_UNKNOWN_FLAGS;
- kvfree(exec2_list);
+out:
+ eb.args->flags &= ~__I915_EXEC_UNKNOWN_FLAGS;
+ if (eb.vma != (typeof(eb.vma))onstack)
+ kvfree(eb.vma);
return err;
}
--
2.11.0
More information about the Intel-gfx-trybot
mailing list