static int i915_gem_object_wait_rendering(struct drm_gem_object *obj,
                                          bool interruptible);
 static int i915_gem_object_bind_to_gtt(struct drm_gem_object *obj,
-                                          unsigned alignment);
+                                      unsigned alignment, bool mappable);
 static void i915_gem_clear_fence_reg(struct drm_gem_object *obj);
 static int i915_gem_phys_pwrite(struct drm_device *dev, struct drm_gem_object *obj,
                                struct drm_i915_gem_pwrite *args,
        else if (obj_priv->tiling_mode == I915_TILING_NONE &&
                 obj_priv->gtt_space &&
                 obj->write_domain != I915_GEM_DOMAIN_CPU) {
-               ret = i915_gem_object_pin(obj, 0);
+               ret = i915_gem_object_pin(obj, 0, true);
                if (ret)
                        goto out;
 
        /* Now bind it into the GTT if needed */
        mutex_lock(&dev->struct_mutex);
        if (!obj_priv->gtt_space) {
-               ret = i915_gem_object_bind_to_gtt(obj, 0);
+               ret = i915_gem_object_bind_to_gtt(obj, 0, true);
                if (ret)
                        goto unlock;
 
         * initial fault faster and any subsequent flushing possible).
         */
        if (!obj_priv->agp_mem) {
-               ret = i915_gem_object_bind_to_gtt(obj, 0);
+               ret = i915_gem_object_bind_to_gtt(obj, 0, true);
                if (ret)
                        goto out;
        }
  * Finds free space in the GTT aperture and binds the object there.
  */
 static int
-i915_gem_object_bind_to_gtt(struct drm_gem_object *obj, unsigned alignment)
+i915_gem_object_bind_to_gtt(struct drm_gem_object *obj,
+                           unsigned alignment,
+                           bool mappable)
 {
        struct drm_device *dev = obj->dev;
        drm_i915_private_t *dev_priv = dev->dev_private;
        /* If the object is bigger than the entire aperture, reject it early
         * before evicting everything in a vain attempt to find space.
         */
-       if (obj->size > dev_priv->mm.gtt_total) {
+       if (obj->size >
+           (mappable ? dev_priv->mm.gtt_mappable_end : dev_priv->mm.gtt_total)) {
                DRM_ERROR("Attempting to bind an object larger than the aperture\n");
                return -E2BIG;
        }
 
  search_free:
-       free_space = drm_mm_search_free(&dev_priv->mm.gtt_space,
-                                       obj->size, alignment, 0);
-       if (free_space != NULL)
-               obj_priv->gtt_space = drm_mm_get_block(free_space, obj->size,
-                                                      alignment);
+       if (mappable)
+               free_space =
+                       drm_mm_search_free_in_range(&dev_priv->mm.gtt_space,
+                                                   obj->size, alignment, 0,
+                                                   dev_priv->mm.gtt_mappable_end,
+                                                   0);
+       else
+               free_space = drm_mm_search_free(&dev_priv->mm.gtt_space,
+                                               obj->size, alignment, 0);
+
+       if (free_space != NULL) {
+               if (mappable)
+                       obj_priv->gtt_space =
+                               drm_mm_get_block_range_generic(free_space,
+                                                              obj->size,
+                                                              alignment, 0,
+                                                              dev_priv->mm.gtt_mappable_end,
+                                                              0);
+               else
+                       obj_priv->gtt_space =
+                               drm_mm_get_block(free_space, obj->size,
+                                                alignment);
+       }
        if (obj_priv->gtt_space == NULL) {
                /* If the gtt is empty and we're still having trouble
                 * fitting our object in, we're out of memory.
                 */
-               ret = i915_gem_evict_something(dev, obj->size, alignment, true);
+               ret = i915_gem_evict_something(dev, obj->size, alignment,
+                                              mappable);
                if (ret)
                        return ret;
 
                if (ret == -ENOMEM) {
                        /* first try to clear up some space from the GTT */
                        ret = i915_gem_evict_something(dev, obj->size,
-                                                      alignment, true);
+                                                      alignment, mappable);
                        if (ret) {
                                /* now try to shrink everyone else */
                                if (gfpmask) {
                drm_mm_put_block(obj_priv->gtt_space);
                obj_priv->gtt_space = NULL;
 
-               ret = i915_gem_evict_something(dev, obj->size, alignment, true);
+               ret = i915_gem_evict_something(dev, obj->size, alignment,
+                                              mappable);
                if (ret)
                        return ret;
 
                                        break;
                        }
 
-                       ret = i915_gem_object_pin(&obj->base, entry->alignment);
+                       ret = i915_gem_object_pin(&obj->base,
+                                                 entry->alignment, true);
                        if (ret)
                                break;
 
 }
 
 int
-i915_gem_object_pin(struct drm_gem_object *obj, uint32_t alignment)
+i915_gem_object_pin(struct drm_gem_object *obj, uint32_t alignment,
+                   bool mappable)
 {
        struct drm_device *dev = obj->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
        }
 
        if (obj_priv->gtt_space == NULL) {
-               ret = i915_gem_object_bind_to_gtt(obj, alignment);
+               ret = i915_gem_object_bind_to_gtt(obj, alignment, mappable);
                if (ret)
                        return ret;
        }
        obj_priv->user_pin_count++;
        obj_priv->pin_filp = file_priv;
        if (obj_priv->user_pin_count == 1) {
-               ret = i915_gem_object_pin(obj, args->alignment);
+               ret = i915_gem_object_pin(obj, args->alignment, true);
                if (ret)
                        goto out;
        }
        obj_priv = to_intel_bo(obj);
        obj_priv->agp_type = AGP_USER_CACHED_MEMORY;
 
-       ret = i915_gem_object_pin(obj, 4096);
+       ret = i915_gem_object_pin(obj, 4096, true);
        if (ret)
                goto err_unref;