struct drm_buddy mm;
        struct list_head reserved;
        struct mutex lock;
+       unsigned long visible_size;
+       unsigned long visible_avail;
+       unsigned long visible_reserved;
        u64 default_page_size;
 };
 
        n_pages = size >> ilog2(mm->chunk_size);
 
        mutex_lock(&bman->lock);
+       if (lpfn <= bman->visible_size && n_pages > bman->visible_avail) {
+               mutex_unlock(&bman->lock);
+               err = -ENOSPC;
+               goto err_free_res;
+       }
+
        err = drm_buddy_alloc_blocks(mm, (u64)place->fpfn << PAGE_SHIFT,
                                     (u64)lpfn << PAGE_SHIFT,
                                     (u64)n_pages << PAGE_SHIFT,
                mutex_unlock(&bman->lock);
        }
 
+       if (lpfn <= bman->visible_size) {
+               bman_res->used_visible_size = bman_res->base.num_pages;
+       } else {
+               struct drm_buddy_block *block;
+
+               list_for_each_entry(block, &bman_res->blocks, link) {
+                       unsigned long start =
+                               drm_buddy_block_offset(block) >> PAGE_SHIFT;
+
+                       if (start < bman->visible_size) {
+                               unsigned long end = start +
+                                       (drm_buddy_block_size(mm, block) >> PAGE_SHIFT);
+
+                               bman_res->used_visible_size +=
+                                       min(end, bman->visible_size) - start;
+                       }
+               }
+       }
+
+       if (bman_res->used_visible_size) {
+               mutex_lock(&bman->lock);
+               bman->visible_avail -= bman_res->used_visible_size;
+               mutex_unlock(&bman->lock);
+       }
+
        *res = &bman_res->base;
        return 0;
 
 
        mutex_lock(&bman->lock);
        drm_buddy_free_list(&bman->mm, &bman_res->blocks);
+       bman->visible_avail += bman_res->used_visible_size;
        mutex_unlock(&bman->lock);
 
        ttm_resource_fini(man, res);
        mutex_lock(&bman->lock);
        drm_printf(printer, "default_page_size: %lluKiB\n",
                   bman->default_page_size >> 10);
+       drm_printf(printer, "visible_avail: %lluMiB\n",
+                  (u64)bman->visible_avail << PAGE_SHIFT >> 20);
+       drm_printf(printer, "visible_size: %lluMiB\n",
+                  (u64)bman->visible_size << PAGE_SHIFT >> 20);
+       drm_printf(printer, "visible_reserved: %lluMiB\n",
+                  (u64)bman->visible_reserved << PAGE_SHIFT >> 20);
 
        drm_buddy_print(&bman->mm, printer);
 
  * @type: Memory type we want to manage
  * @use_tt: Set use_tt for the manager
  * @size: The size in bytes to manage
+ * @visible_size: The CPU visible size in bytes to manage
  * @default_page_size: The default minimum page size in bytes for allocations,
  * this must be at least as large as @chunk_size, and can be overridden by
  * setting the BO page_alignment, to be larger or smaller as needed.
  */
 int i915_ttm_buddy_man_init(struct ttm_device *bdev,
                            unsigned int type, bool use_tt,
-                           u64 size, u64 default_page_size,
+                           u64 size, u64 visible_size, u64 default_page_size,
                            u64 chunk_size)
 {
        struct ttm_resource_manager *man;
        INIT_LIST_HEAD(&bman->reserved);
        GEM_BUG_ON(default_page_size < chunk_size);
        bman->default_page_size = default_page_size;
+       bman->visible_size = visible_size >> PAGE_SHIFT;
+       bman->visible_avail = bman->visible_size;
 
        man = &bman->manager;
        man->use_tt = use_tt;
        mutex_lock(&bman->lock);
        drm_buddy_free_list(mm, &bman->reserved);
        drm_buddy_fini(mm);
+       bman->visible_avail += bman->visible_reserved;
+       WARN_ON_ONCE(bman->visible_avail != bman->visible_size);
        mutex_unlock(&bman->lock);
 
        ttm_resource_manager_cleanup(man);
 {
        struct i915_ttm_buddy_manager *bman = to_buddy_manager(man);
        struct drm_buddy *mm = &bman->mm;
+       unsigned long fpfn = start >> PAGE_SHIFT;
        unsigned long flags = 0;
        int ret;
 
                                     size, mm->chunk_size,
                                     &bman->reserved,
                                     flags);
+
+       if (fpfn < bman->visible_size) {
+               unsigned long lpfn = fpfn + (size >> PAGE_SHIFT);
+               unsigned long visible = min(lpfn, bman->visible_size) - fpfn;
+
+               bman->visible_reserved += visible;
+               bman->visible_avail -= visible;
+       }
        mutex_unlock(&bman->lock);
 
        return ret;
 }
 
+/**
+ * i915_ttm_buddy_man_visible_size - Return the size of the CPU visible portion
+ * in pages.
+ * @man: The buddy allocator ttm manager
+ */
+u64 i915_ttm_buddy_man_visible_size(struct ttm_resource_manager *man)
+{
+       struct i915_ttm_buddy_manager *bman = to_buddy_manager(man);
+
+       return bman->visible_size;
+}
 
  * @base: struct ttm_resource base class we extend
  * @blocks: the list of struct i915_buddy_block for this resource/allocation
  * @flags: DRM_BUDDY_*_ALLOCATION flags
+ * @used_visible_size: How much of this resource, if any, uses the CPU visible
+ * portion, in pages.
  * @mm: the struct i915_buddy_mm for this resource
  *
  * Extends the struct ttm_resource to manage an address space allocation with
        struct ttm_resource base;
        struct list_head blocks;
        unsigned long flags;
+       unsigned long used_visible_size;
        struct drm_buddy *mm;
 };
 
 
 int i915_ttm_buddy_man_init(struct ttm_device *bdev,
                            unsigned type, bool use_tt,
-                           u64 size, u64 default_page_size, u64 chunk_size);
+                           u64 size, u64 visible_size,
+                           u64 default_page_size, u64 chunk_size);
 int i915_ttm_buddy_man_fini(struct ttm_device *bdev,
                            unsigned int type);
 
 int i915_ttm_buddy_man_reserve(struct ttm_resource_manager *man,
                               u64 start, u64 size);
 
+u64 i915_ttm_buddy_man_visible_size(struct ttm_resource_manager *man);
+
 #endif