goto err_unpin;
                }
+
+               GEM_BUG_ON(vma->node.start < start);
+               GEM_BUG_ON(vma->node.start + vma->node.size > end);
        }
        GEM_BUG_ON(!i915_gem_valid_gtt_space(vma, obj->cache_level));
 
                         u64 alignment,
                         u64 flags)
 {
-       struct i915_address_space *vm = &to_i915(obj->base.dev)->ggtt.base;
+       struct drm_i915_private *dev_priv = to_i915(obj->base.dev);
+       struct i915_address_space *vm = &dev_priv->ggtt.base;
        struct i915_vma *vma;
        int ret;
 
                    (i915_vma_is_pinned(vma) || i915_vma_is_active(vma)))
                        return ERR_PTR(-ENOSPC);
 
+               if (flags & PIN_MAPPABLE) {
+                       u32 fence_size;
+
+                       fence_size = i915_gem_get_ggtt_size(dev_priv, vma->size,
+                                                           i915_gem_object_get_tiling(obj));
+                       /* If the required space is larger than the available
+                        * aperture, we will not able to find a slot for the
+                        * object and unbinding the object now will be in
+                        * vain. Worse, doing so may cause us to ping-pong
+                        * the object in and out of the Global GTT and
+                        * waste a lot of cycles under the mutex.
+                        */
+                       if (fence_size > dev_priv->ggtt.mappable_end)
+                               return ERR_PTR(-E2BIG);
+
+                       /* If NONBLOCK is set the caller is optimistically
+                        * trying to cache the full object within the mappable
+                        * aperture, and *must* have a fallback in place for
+                        * situations where we cannot bind the object. We
+                        * can be a little more lax here and use the fallback
+                        * more often to avoid costly migrations of ourselves
+                        * and other objects within the aperture.
+                        *
+                        * Half-the-aperture is used as a simple heuristic.
+                        * More interesting would to do search for a free
+                        * block prior to making the commitment to unbind.
+                        * That caters for the self-harm case, and with a
+                        * little more heuristics (e.g. NOFAULT, NOEVICT)
+                        * we could try to minimise harm to others.
+                        */
+                       if (flags & PIN_NONBLOCK &&
+                           fence_size > dev_priv->ggtt.mappable_end / 2)
+                               return ERR_PTR(-ENOSPC);
+               }
+
                WARN(i915_vma_is_pinned(vma),
                     "bo is already pinned in ggtt with incorrect alignment:"
                     " offset=%08x, req.alignment=%llx,"