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;
 
        struct intel_engine_cs *engine; /** engine to queue the request to */
        struct i915_gem_context *ctx; /** context for building the request */
        struct hlist_head *buckets; /** ht for relocation handles */
 };
 
-/*
- * As an alternative to creating a hashtable of handle-to-vma for a batch,
- * we used the last available reserved field in the execobject[] and stash
- * a link from the execobj to its vma.
- */
-#define __exec_to_vma(ee) (ee)->rsvd2
-#define exec_to_vma(ee) u64_to_ptr(struct i915_vma, __exec_to_vma(ee))
+#define exec_entry(EB, VMA) (&(EB)->exec[(VMA)->exec_flags - (EB)->flags])
 
 /*
  * Used to convert any address to canonical form.
 
 static bool
 eb_vma_misplaced(const struct drm_i915_gem_exec_object2 *entry,
-                const struct i915_vma *vma)
+                const struct i915_vma *vma,
+                unsigned int flags)
 {
-       if (!(entry->flags & __EXEC_OBJECT_HAS_PIN))
-               return true;
-
        if (vma->node.size < entry->pad_to_size)
                return true;
 
        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;
 
        return false;
 }
 
-static inline void
+static inline bool
 eb_pin_vma(struct i915_execbuffer *eb,
-          struct drm_i915_gem_exec_object2 *entry,
+          const struct drm_i915_gem_exec_object2 *entry,
           struct i915_vma *vma)
 {
-       u64 flags;
+       unsigned int exec_flags = *vma->exec_flags;
+       u64 pin_flags;
 
        if (vma->node.size)
-               flags = vma->node.start;
+               pin_flags = vma->node.start;
        else
-               flags = entry->offset & PIN_OFFSET_MASK;
+               pin_flags = entry->offset & PIN_OFFSET_MASK;
 
-       flags |= PIN_USER | PIN_NOEVICT | PIN_OFFSET_FIXED;
-       if (unlikely(entry->flags & EXEC_OBJECT_NEEDS_GTT))
-               flags |= PIN_GLOBAL;
+       pin_flags |= PIN_USER | PIN_NOEVICT | PIN_OFFSET_FIXED;
+       if (unlikely(exec_flags & EXEC_OBJECT_NEEDS_GTT))
+               pin_flags |= PIN_GLOBAL;
 
-       if (unlikely(i915_vma_pin(vma, 0, 0, flags)))
-               return;
+       if (unlikely(i915_vma_pin(vma, 0, 0, pin_flags)))
+               return false;
 
-       if (unlikely(entry->flags & EXEC_OBJECT_NEEDS_FENCE)) {
+       if (unlikely(exec_flags & EXEC_OBJECT_NEEDS_FENCE)) {
                if (unlikely(i915_vma_get_fence(vma))) {
                        i915_vma_unpin(vma);
-                       return;
+                       return false;
                }
 
                if (i915_vma_pin_fence(vma))
-                       entry->flags |= __EXEC_OBJECT_HAS_FENCE;
+                       exec_flags |= __EXEC_OBJECT_HAS_FENCE;
        }
 
-       entry->flags |= __EXEC_OBJECT_HAS_PIN;
+       *vma->exec_flags = exec_flags | __EXEC_OBJECT_HAS_PIN;
+       return !eb_vma_misplaced(entry, vma, exec_flags);
 }
 
-static inline void
-__eb_unreserve_vma(struct i915_vma *vma,
-                  const struct drm_i915_gem_exec_object2 *entry)
+static inline void __eb_unreserve_vma(struct i915_vma *vma, unsigned int flags)
 {
-       GEM_BUG_ON(!(entry->flags & __EXEC_OBJECT_HAS_PIN));
+       GEM_BUG_ON(!(flags & __EXEC_OBJECT_HAS_PIN));
 
-       if (unlikely(entry->flags & __EXEC_OBJECT_HAS_FENCE))
+       if (unlikely(flags & __EXEC_OBJECT_HAS_FENCE))
                i915_vma_unpin_fence(vma);
 
        __i915_vma_unpin(vma);
 }
 
 static inline void
-eb_unreserve_vma(struct i915_vma *vma,
-                struct drm_i915_gem_exec_object2 *entry)
+eb_unreserve_vma(struct i915_vma *vma, unsigned int *flags)
 {
-       if (!(entry->flags & __EXEC_OBJECT_HAS_PIN))
+       if (!(*flags & __EXEC_OBJECT_HAS_PIN))
                return;
 
-       __eb_unreserve_vma(vma, entry);
-       entry->flags &= ~__EXEC_OBJECT_RESERVED;
+       __eb_unreserve_vma(vma, *flags);
+       *flags &= ~__EXEC_OBJECT_RESERVED;
 }
 
 static int
                entry->pad_to_size = 0;
        }
 
-       if (unlikely(vma->exec_entry)) {
+       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));
                return -EINVAL;
         */
        entry->offset = gen8_noncanonical_addr(entry->offset);
 
+       if (!eb->reloc_cache.has_fence) {
+               entry->flags &= ~EXEC_OBJECT_NEEDS_FENCE;
+       } else {
+               if ((entry->flags & EXEC_OBJECT_NEEDS_FENCE ||
+                    eb->reloc_cache.needs_unfenced) &&
+                   i915_gem_object_is_tiled(vma->obj))
+                       entry->flags |= EXEC_OBJECT_NEEDS_GTT | __EXEC_OBJECT_NEEDS_MAP;
+       }
+
+       if (!(entry->flags & EXEC_OBJECT_PINNED))
+               entry->flags |= eb->context_flags;
+
        return 0;
 }
 
 static int
-eb_add_vma(struct i915_execbuffer *eb,
-          struct drm_i915_gem_exec_object2 *entry,
-          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 = &eb->exec[i];
        int err;
 
        GEM_BUG_ON(i915_vma_is_closed(vma));
        if (entry->relocation_count)
                list_add_tail(&vma->reloc_link, &eb->relocs);
 
-       if (!eb->reloc_cache.has_fence) {
-               entry->flags &= ~EXEC_OBJECT_NEEDS_FENCE;
-       } else {
-               if ((entry->flags & EXEC_OBJECT_NEEDS_FENCE ||
-                    eb->reloc_cache.needs_unfenced) &&
-                   i915_gem_object_is_tiled(vma->obj))
-                       entry->flags |= EXEC_OBJECT_NEEDS_GTT | __EXEC_OBJECT_NEEDS_MAP;
-       }
-
-       if (!(entry->flags & EXEC_OBJECT_PINNED))
-               entry->flags |= eb->context_flags;
-
        /*
         * Stash a pointer from the vma to execobj, so we can query its flags,
         * size, alignment etc as provided by the user. Also we stash a pointer
         * to the vma inside the execobj so that we can use a direct lookup
         * to find the right target VMA when doing relocations.
         */
-       vma->exec_entry = entry;
-       __exec_to_vma(entry) = (uintptr_t)vma;
+       eb->vma[i] = vma;
+       eb->flags[i] = entry->flags;
+       vma->exec_flags = &eb->flags[i];
 
        err = 0;
-       eb_pin_vma(eb, entry, vma);
-       if (eb_vma_misplaced(entry, vma)) {
-               eb_unreserve_vma(vma, entry);
-
-               list_add_tail(&vma->exec_link, &eb->unbound);
-               if (drm_mm_node_allocated(&vma->node))
-                       err = i915_vma_unbind(vma);
-       } else {
+       if (eb_pin_vma(eb, entry, vma)) {
                if (entry->offset != vma->node.start) {
                        entry->offset = vma->node.start | UPDATE;
                        eb->args->flags |= __EXEC_HAS_RELOC;
                }
+       } else {
+               eb_unreserve_vma(vma, vma->exec_flags);
+
+               list_add_tail(&vma->exec_link, &eb->unbound);
+               if (drm_mm_node_allocated(&vma->node))
+                       err = i915_vma_unbind(vma);
        }
        return err;
 }
 static int eb_reserve_vma(const struct i915_execbuffer *eb,
                          struct i915_vma *vma)
 {
-       struct drm_i915_gem_exec_object2 *entry = vma->exec_entry;
-       u64 flags;
+       struct drm_i915_gem_exec_object2 *entry = exec_entry(eb, vma);
+       unsigned int exec_flags = *vma->exec_flags;
+       u64 pin_flags;
        int err;
 
-       flags = PIN_USER | PIN_NONBLOCK;
-       if (entry->flags & EXEC_OBJECT_NEEDS_GTT)
-               flags |= PIN_GLOBAL;
+       pin_flags = PIN_USER | PIN_NONBLOCK;
+       if (exec_flags & EXEC_OBJECT_NEEDS_GTT)
+               pin_flags |= PIN_GLOBAL;
 
        /*
         * Wa32bitGeneralStateOffset & Wa32bitInstructionBaseOffset,
         * limit address to the first 4GBs for unflagged objects.
         */
-       if (!(entry->flags & EXEC_OBJECT_SUPPORTS_48B_ADDRESS))
-               flags |= PIN_ZONE_4G;
+       if (!(exec_flags & EXEC_OBJECT_SUPPORTS_48B_ADDRESS))
+               pin_flags |= PIN_ZONE_4G;
 
-       if (entry->flags & __EXEC_OBJECT_NEEDS_MAP)
-               flags |= PIN_MAPPABLE;
+       if (exec_flags & __EXEC_OBJECT_NEEDS_MAP)
+               pin_flags |= PIN_MAPPABLE;
 
-       if (entry->flags & EXEC_OBJECT_PINNED) {
-               flags |= entry->offset | PIN_OFFSET_FIXED;
-               flags &= ~PIN_NONBLOCK; /* force overlapping PINNED checks */
-       } else if (entry->flags & __EXEC_OBJECT_NEEDS_BIAS) {
-               flags |= BATCH_OFFSET_BIAS | PIN_OFFSET_BIAS;
+       if (exec_flags & EXEC_OBJECT_PINNED) {
+               pin_flags |= entry->offset | PIN_OFFSET_FIXED;
+               pin_flags &= ~PIN_NONBLOCK; /* force overlapping checks */
+       } else if (exec_flags & __EXEC_OBJECT_NEEDS_BIAS) {
+               pin_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,
+                          pin_flags);
        if (err)
                return err;
 
                eb->args->flags |= __EXEC_HAS_RELOC;
        }
 
-       if (unlikely(entry->flags & EXEC_OBJECT_NEEDS_FENCE)) {
+       if (unlikely(exec_flags & EXEC_OBJECT_NEEDS_FENCE)) {
                err = i915_vma_get_fence(vma);
                if (unlikely(err)) {
                        i915_vma_unpin(vma);
                }
 
                if (i915_vma_pin_fence(vma))
-                       entry->flags |= __EXEC_OBJECT_HAS_FENCE;
+                       exec_flags |= __EXEC_OBJECT_HAS_FENCE;
        }
 
-       entry->flags |= __EXEC_OBJECT_HAS_PIN;
-       GEM_BUG_ON(eb_vma_misplaced(entry, vma));
+       *vma->exec_flags = exec_flags | __EXEC_OBJECT_HAS_PIN;
+       GEM_BUG_ON(eb_vma_misplaced(entry, vma, exec_flags));
 
        return 0;
 }
                INIT_LIST_HEAD(&eb->unbound);
                INIT_LIST_HEAD(&last);
                for (i = 0; i < count; i++) {
-                       struct drm_i915_gem_exec_object2 *entry = &eb->exec[i];
+                       unsigned int flags = eb->flags[i];
+                       struct i915_vma *vma = eb->vma[i];
 
-                       if (entry->flags & EXEC_OBJECT_PINNED &&
-                           entry->flags & __EXEC_OBJECT_HAS_PIN)
+                       if (flags & EXEC_OBJECT_PINNED &&
+                           flags & __EXEC_OBJECT_HAS_PIN)
                                continue;
 
-                       vma = exec_to_vma(entry);
-                       eb_unreserve_vma(vma, entry);
+                       eb_unreserve_vma(vma, &eb->flags[i]);
 
-                       if (entry->flags & EXEC_OBJECT_PINNED)
+                       if (flags & EXEC_OBJECT_PINNED)
                                list_add(&vma->exec_link, &eb->unbound);
-                       else if (entry->flags & __EXEC_OBJECT_NEEDS_MAP)
+                       else if (flags & __EXEC_OBJECT_NEEDS_MAP)
                                list_add_tail(&vma->exec_link, &eb->unbound);
                        else
                                list_add_tail(&vma->exec_link, &last);
        GEM_BUG_ON(lut->ht_size & I915_CTX_RESIZE_IN_PROGRESS);
 
        for (i = 0; i < count; i++) {
-               __exec_to_vma(&eb->exec[i]) = 0;
-
                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, &eb->exec[i], vma);
+                       err = eb_add_vma(eb, i, vma);
                        if (unlikely(err))
                                return err;
-
                        goto next_vma;
                }
 
        for (i = slow_pass; i < count; i++) {
                struct drm_i915_gem_object *obj;
 
-               if (__exec_to_vma(&eb->exec[i]))
+               if (eb->vma[i])
                        continue;
 
                obj = to_intel_bo(idr_find(idr, eb->exec[i].handle));
                        goto err;
                }
 
-               __exec_to_vma(&eb->exec[i]) = INTERMEDIATE | (uintptr_t)obj;
+               eb->vma[i] = (struct i915_vma *)
+                       ptr_pack_bits(obj, INTERMEDIATE, 1);
        }
        spin_unlock(&eb->file->table_lock);
 
        for (i = slow_pass; i < count; i++) {
                struct drm_i915_gem_object *obj;
+               unsigned int is_obj;
 
-               if (!(__exec_to_vma(&eb->exec[i]) & INTERMEDIATE))
+               obj = (typeof(obj))ptr_unpack_bits(eb->vma[i], &is_obj, 1);
+               if (!is_obj)
                        continue;
 
                /*
                 * from the (obj, vm) we don't run the risk of creating
                 * duplicated vmas for the same vm.
                 */
-               obj = u64_to_ptr(typeof(*obj),
-                                __exec_to_vma(&eb->exec[i]) & ~INTERMEDIATE);
                vma = i915_vma_instance(obj, eb->vm, NULL);
                if (unlikely(IS_ERR(vma))) {
                        DRM_DEBUG("Failed to lookup VMA\n");
                        i915_vma_get(vma);
                }
 
-               err = eb_add_vma(eb, &eb->exec[i], vma);
+               err = eb_add_vma(eb, i, vma);
                if (unlikely(err))
                        goto err;
 
+               GEM_BUG_ON(vma != eb->vma[i]);
+               GEM_BUG_ON(vma->exec_flags != &eb->flags[i]);
+
                /* Only after we validated the user didn't use our bits */
                if (vma->ctx != eb->ctx) {
                        i915_vma_get(vma);
-                       eb->exec[i].flags |= __EXEC_OBJECT_HAS_REF;
+                       *vma->exec_flags |= __EXEC_OBJECT_HAS_REF;
                }
        }
 
 out:
        /* take note of the batch buffer before we might reorder the lists */
        i = eb_batch_index(eb);
-       eb->batch = exec_to_vma(&eb->exec[i]);
+       eb->batch = eb->vma[i];
+       GEM_BUG_ON(eb->batch->exec_flags != &eb->flags[i]);
 
        /*
         * SNA is doing fancy tricks with compressing batch buffers, which leads
         * 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 (__exec_to_vma(&eb->exec[i]) & INTERMEDIATE)
-                       __exec_to_vma(&eb->exec[i]) = 0;
+               if (ptr_unmask_bits(eb->vma[i], 1))
+                       eb->vma[i] = NULL;
        }
        lut->ht_size &= ~I915_CTX_RESIZE_IN_PROGRESS;
        return err;
        if (eb->lut_size < 0) {
                if (handle >= -eb->lut_size)
                        return NULL;
-               return exec_to_vma(&eb->exec[handle]);
+               return eb->vma[handle];
        } else {
                struct hlist_head *head;
                struct i915_vma *vma;
        unsigned int i;
 
        for (i = 0; i < count; i++) {
-               struct drm_i915_gem_exec_object2 *entry = &eb->exec[i];
-               struct i915_vma *vma = exec_to_vma(entry);
+               struct i915_vma *vma = eb->vma[i];
+               unsigned int flags = eb->flags[i];
 
                if (!vma)
                        continue;
 
-               GEM_BUG_ON(vma->exec_entry != entry);
-               vma->exec_entry = NULL;
-               __exec_to_vma(entry) = 0;
+               GEM_BUG_ON(vma->exec_flags != &eb->flags[i]);
+               vma->exec_flags = NULL;
+               eb->vma[i] = NULL;
 
-               if (entry->flags & __EXEC_OBJECT_HAS_PIN)
-                       __eb_unreserve_vma(vma, entry);
+               if (flags & __EXEC_OBJECT_HAS_PIN)
+                       __eb_unreserve_vma(vma, flags);
 
-               if (entry->flags & __EXEC_OBJECT_HAS_REF)
+               if (flags & __EXEC_OBJECT_HAS_REF)
                        i915_vma_put(vma);
-
-               entry->flags &=
-                       ~(__EXEC_OBJECT_RESERVED | __EXEC_OBJECT_HAS_REF);
        }
 }
 
        }
 
        if (reloc->write_domain) {
-               target->exec_entry->flags |= EXEC_OBJECT_WRITE;
+               *target->exec_flags |= EXEC_OBJECT_WRITE;
 
                /*
                 * Sandybridge PPGTT errata: We need a global gtt mapping
         * do relocations we are already stalling, disable the user's opt
         * of our synchronisation.
         */
-       vma->exec_entry->flags &= ~EXEC_OBJECT_ASYNC;
+       *vma->exec_flags &= ~EXEC_OBJECT_ASYNC;
 
        /* and update the user's relocation entry */
        return relocate_entry(vma, reloc, eb, target);
 #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 = vma->exec_entry;
+       const struct drm_i915_gem_exec_object2 *entry = exec_entry(eb, vma);
        unsigned int remain;
 
        urelocs = u64_to_user_ptr(entry->relocs_ptr);
 static int
 eb_relocate_vma_slow(struct i915_execbuffer *eb, struct i915_vma *vma)
 {
-       const struct drm_i915_gem_exec_object2 *entry = vma->exec_entry;
+       const struct drm_i915_gem_exec_object2 *entry = exec_entry(eb, vma);
        struct drm_i915_gem_relocation_entry *relocs =
                u64_to_ptr(typeof(*relocs), entry->relocs_ptr);
        unsigned int i;
        if (err)
                goto err;
 
+       GEM_BUG_ON(!eb->batch);
+
        list_for_each_entry(vma, &eb->relocs, reloc_link) {
                if (!have_copy) {
                        pagefault_disable();
        int err;
 
        for (i = 0; i < count; i++) {
-               struct drm_i915_gem_exec_object2 *entry = &eb->exec[i];
-               struct i915_vma *vma = exec_to_vma(entry);
+               unsigned int flags = eb->flags[i];
+               struct i915_vma *vma = eb->vma[i];
                struct drm_i915_gem_object *obj = vma->obj;
 
-               if (entry->flags & EXEC_OBJECT_CAPTURE) {
+               if (flags & EXEC_OBJECT_CAPTURE) {
                        struct i915_gem_capture_list *capture;
 
                        capture = kmalloc(sizeof(*capture), GFP_KERNEL);
                                return -ENOMEM;
 
                        capture->next = eb->request->capture_list;
-                       capture->vma = vma;
+                       capture->vma = eb->vma[i];
                        eb->request->capture_list = capture;
                }
 
                 */
                if (unlikely(obj->cache_dirty & ~obj->cache_coherent)) {
                        if (i915_gem_clflush_object(obj, 0))
-                               entry->flags &= ~EXEC_OBJECT_ASYNC;
+                               flags &= ~EXEC_OBJECT_ASYNC;
                }
 
-               if (entry->flags & EXEC_OBJECT_ASYNC)
-                       goto skip_flushes;
+               if (flags & EXEC_OBJECT_ASYNC)
+                       continue;
 
                err = i915_gem_request_await_object
-                       (eb->request, obj, entry->flags & EXEC_OBJECT_WRITE);
+                       (eb->request, obj, flags & EXEC_OBJECT_WRITE);
                if (err)
                        return err;
-
-skip_flushes:
-               i915_vma_move_to_active(vma, eb->request, entry->flags);
-               __eb_unreserve_vma(vma, entry);
-               vma->exec_entry = NULL;
        }
 
        for (i = 0; i < count; i++) {
-               const struct drm_i915_gem_exec_object2 *entry = &eb->exec[i];
-               struct i915_vma *vma = exec_to_vma(entry);
+               unsigned int flags = eb->flags[i];
+               struct i915_vma *vma = eb->vma[i];
+
+               i915_vma_move_to_active(vma, eb->request, flags);
+               eb_export_fence(vma, eb->request, flags);
 
-               eb_export_fence(vma, eb->request, entry->flags);
-               if (unlikely(entry->flags & __EXEC_OBJECT_HAS_REF))
+               __eb_unreserve_vma(vma, flags);
+               vma->exec_flags = NULL;
+
+               if (unlikely(flags & __EXEC_OBJECT_HAS_REF))
                        i915_vma_put(vma);
        }
        eb->exec = NULL;
        if (IS_ERR(vma))
                goto out;
 
-       vma->exec_entry =
-               memset(&eb->exec[eb->buffer_count++],
-                      0, sizeof(*vma->exec_entry));
-       vma->exec_entry->flags = __EXEC_OBJECT_HAS_PIN | __EXEC_OBJECT_HAS_REF;
-       __exec_to_vma(vma->exec_entry) = (uintptr_t)i915_vma_get(vma);
+       eb->vma[eb->buffer_count] = i915_vma_get(vma);
+       eb->flags[eb->buffer_count] =
+               __EXEC_OBJECT_HAS_PIN | __EXEC_OBJECT_HAS_REF;
+       vma->exec_flags = &eb->flags[eb->buffer_count];
+       eb->buffer_count++;
 
 out:
        i915_gem_object_unpin_pages(shadow_batch_obj);
        eb.args = args;
        if (DBG_FORCE_RELOC || !(args->flags & I915_EXEC_NO_RELOC))
                args->flags |= __EXEC_HAS_RELOC;
+
        eb.exec = exec;
+       eb.vma = memset(exec + args->buffer_count + 1, 0,
+                       (args->buffer_count + 1) * sizeof(*eb.vma));
+       eb.flags = (unsigned int *)(eb.vma + args->buffer_count + 1);
+
        eb.invalid_flags = __EXEC_OBJECT_UNKNOWN_FLAGS;
        if (USES_FULL_PPGTT(eb.i915))
                eb.invalid_flags |= EXEC_OBJECT_NEEDS_GTT;
                goto err_vma;
        }
 
-       if (unlikely(eb.batch->exec_entry->flags & EXEC_OBJECT_WRITE)) {
+       if (unlikely(*eb.batch->exec_flags & EXEC_OBJECT_WRITE)) {
                DRM_DEBUG("Attempting to use self-modifying batch buffer\n");
                err = -EINVAL;
                goto err_vma;
 i915_gem_execbuffer(struct drm_device *dev, void *data,
                    struct drm_file *file)
 {
-       const size_t sz = sizeof(struct drm_i915_gem_exec_object2);
+       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;
 i915_gem_execbuffer2(struct drm_device *dev, void *data,
                     struct drm_file *file)
 {
-       const size_t sz = sizeof(struct drm_i915_gem_exec_object2);
+       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;
        struct drm_syncobj **fences = NULL;