struct ttm_place *places, u32 bo_flags, u32 mem_type, u32 *c)
 {
        struct xe_tile *tile = mem_type_to_tile(xe, mem_type);
+       struct ttm_place place = { .mem_type = mem_type };
+       u64 io_size = tile->mem.vram.io_size;
 
        XE_BUG_ON(!tile->mem.vram.usable_size);
 
-       places[*c] = (struct ttm_place) {
-               .mem_type = mem_type,
-               /*
-                * For eviction / restore on suspend / resume objects
-                * pinned in VRAM must be contiguous
-                */
-               .flags = bo_flags & (XE_BO_CREATE_PINNED_BIT |
-                                    XE_BO_CREATE_GGTT_BIT) ?
-                       TTM_PL_FLAG_CONTIGUOUS : 0,
-       };
+       /*
+        * For eviction / restore on suspend / resume objects
+        * pinned in VRAM must be contiguous
+        */
+       if (bo_flags & (XE_BO_CREATE_PINNED_BIT |
+                       XE_BO_CREATE_GGTT_BIT))
+               place.flags |= TTM_PL_FLAG_CONTIGUOUS;
+
+       if (io_size < tile->mem.vram.usable_size) {
+               if (bo_flags & XE_BO_NEEDS_CPU_ACCESS) {
+                       place.fpfn = 0;
+                       place.lpfn = io_size >> PAGE_SHIFT;
+               } else {
+                       place.flags |= TTM_PL_FLAG_TOPDOWN;
+               }
+       }
+       places[*c] = place;
        *c += 1;
 
        if (bo->props.preferred_mem_type == XE_BO_PROPS_INVALID)
                                 struct ttm_resource *mem)
 {
        struct xe_device *xe = ttm_to_xe_device(bdev);
-       struct xe_tile *tile;
 
        switch (mem->mem_type) {
        case XE_PL_SYSTEM:
        case XE_PL_TT:
                return 0;
        case XE_PL_VRAM0:
-       case XE_PL_VRAM1:
-               tile = mem_type_to_tile(xe, mem->mem_type);
+       case XE_PL_VRAM1: {
+               struct xe_tile *tile = mem_type_to_tile(xe, mem->mem_type);
+               struct xe_ttm_vram_mgr_resource *vres =
+                       to_xe_ttm_vram_mgr_resource(mem);
+
+               if (vres->used_visible_size < mem->size)
+                       return -EINVAL;
+
                mem->bus.offset = mem->start << PAGE_SHIFT;
 
                if (tile->mem.vram.mapping &&
                mem->bus.caching = ttm_write_combined;
 #endif
                return 0;
-       case XE_PL_STOLEN:
+       } case XE_PL_STOLEN:
                return xe_ttm_stolen_io_mem_reserve(xe, mem);
        default:
                return -EINVAL;
            xe_ttm_stolen_cpu_access_needs_ggtt(xe))
                flags |= XE_BO_CREATE_GGTT_BIT;
 
-       bo = xe_bo_create_locked_range(xe, tile, vm, size, start, end, type, flags);
+       bo = xe_bo_create_locked_range(xe, tile, vm, size, start, end, type,
+                                      flags | XE_BO_NEEDS_CPU_ACCESS);
        if (IS_ERR(bo))
                return bo;
 
 
        xe_bo_assert_held(bo);
 
+       if (!(bo->flags & XE_BO_NEEDS_CPU_ACCESS))
+               return -EINVAL;
+
        if (!iosys_map_is_null(&bo->vmap))
                return 0;