vmwgfx_cotable.o vmwgfx_so.o vmwgfx_binding.o vmwgfx_msg.o \
            vmwgfx_simple_resource.o vmwgfx_va.o vmwgfx_blit.o \
            vmwgfx_validation.o vmwgfx_page_dirty.o vmwgfx_streamoutput.o \
-            vmwgfx_devcaps.o ttm_object.o ttm_memory.o
+           vmwgfx_devcaps.o ttm_object.o ttm_memory.o vmwgfx_system_manager.o
 
 vmwgfx-$(CONFIG_DRM_FBDEV_EMULATION) += vmwgfx_fb.o
 vmwgfx-$(CONFIG_TRANSPARENT_HUGEPAGE) += vmwgfx_thp.o
 
                                 "3D will be disabled.\n");
                        dev_priv->has_mob = false;
                }
+               if (vmw_sys_man_init(dev_priv) != 0) {
+                       drm_info(&dev_priv->drm,
+                                "No MOB page table memory available. "
+                                "3D will be disabled.\n");
+                       dev_priv->has_mob = false;
+               }
        }
 
        if (dev_priv->has_mob && (dev_priv->capabilities & SVGA_CAP_DX)) {
        vmw_overlay_close(dev_priv);
        vmw_kms_close(dev_priv);
 out_no_kms:
-       if (dev_priv->has_mob)
+       if (dev_priv->has_mob) {
                vmw_gmrid_man_fini(dev_priv, VMW_PL_MOB);
+               vmw_sys_man_fini(dev_priv);
+       }
        if (dev_priv->has_gmr)
                vmw_gmrid_man_fini(dev_priv, VMW_PL_GMR);
        vmw_devcaps_destroy(dev_priv);
                vmw_gmrid_man_fini(dev_priv, VMW_PL_GMR);
 
        vmw_release_device_early(dev_priv);
-       if (dev_priv->has_mob)
+       if (dev_priv->has_mob) {
                vmw_gmrid_man_fini(dev_priv, VMW_PL_MOB);
+               vmw_sys_man_fini(dev_priv);
+       }
        vmw_devcaps_destroy(dev_priv);
        vmw_vram_manager_fini(dev_priv);
        ttm_device_fini(&dev_priv->bdev);
 
                        VMWGFX_NUM_GB_SURFACE +\
                        VMWGFX_NUM_GB_SCREEN_TARGET)
 
-#define VMW_PL_GMR (TTM_PL_PRIV + 0)
-#define VMW_PL_MOB (TTM_PL_PRIV + 1)
+#define VMW_PL_GMR      (TTM_PL_PRIV + 0)
+#define VMW_PL_MOB      (TTM_PL_PRIV + 1)
+#define VMW_PL_SYSTEM   (TTM_PL_PRIV + 2)
 
 #define VMW_RES_CONTEXT ttm_driver_type0
 #define VMW_RES_SURFACE ttm_driver_type1
 extern struct ttm_placement vmw_vram_sys_placement;
 extern struct ttm_placement vmw_vram_gmr_placement;
 extern struct ttm_placement vmw_sys_placement;
-extern struct ttm_placement vmw_evictable_placement;
 extern struct ttm_placement vmw_srf_placement;
 extern struct ttm_placement vmw_mob_placement;
 extern struct ttm_placement vmw_nonfixed_placement;
 int vmw_gmrid_man_init(struct vmw_private *dev_priv, int type);
 void vmw_gmrid_man_fini(struct vmw_private *dev_priv, int type);
 
+/**
+ * System memory manager
+ */
+int vmw_sys_man_init(struct vmw_private *dev_priv);
+void vmw_sys_man_fini(struct vmw_private *dev_priv);
+
 /**
  * Prime - vmwgfx_prime.c
  */
 
--- /dev/null
+/* SPDX-License-Identifier: GPL-2.0 OR MIT */
+/*
+ * Copyright 2021 VMware, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+#include "vmwgfx_drv.h"
+
+#include <drm/ttm/ttm_bo_driver.h>
+#include <drm/ttm/ttm_device.h>
+#include <drm/ttm/ttm_placement.h>
+#include <drm/ttm/ttm_resource.h>
+#include <linux/slab.h>
+
+
+static int vmw_sys_man_alloc(struct ttm_resource_manager *man,
+                            struct ttm_buffer_object *bo,
+                            const struct ttm_place *place,
+                            struct ttm_resource **res)
+{
+       *res = kzalloc(sizeof(**res), GFP_KERNEL);
+       if (!*res)
+               return -ENOMEM;
+
+       ttm_resource_init(bo, place, *res);
+       return 0;
+}
+
+static void vmw_sys_man_free(struct ttm_resource_manager *man,
+                            struct ttm_resource *res)
+{
+       kfree(res);
+}
+
+static const struct ttm_resource_manager_func vmw_sys_manager_func = {
+       .alloc = vmw_sys_man_alloc,
+       .free = vmw_sys_man_free,
+};
+
+int vmw_sys_man_init(struct vmw_private *dev_priv)
+{
+       struct ttm_device *bdev = &dev_priv->bdev;
+       struct ttm_resource_manager *man =
+                       kzalloc(sizeof(*man), GFP_KERNEL);
+
+       if (!man)
+               return -ENOMEM;
+
+       man->use_tt = true;
+       man->func = &vmw_sys_manager_func;
+
+       ttm_resource_manager_init(man, 0);
+       ttm_set_driver_manager(bdev, VMW_PL_SYSTEM, man);
+       ttm_resource_manager_set_used(man, true);
+       return 0;
+}
+
+void vmw_sys_man_fini(struct vmw_private *dev_priv)
+{
+       struct ttm_resource_manager *man = ttm_manager_type(&dev_priv->bdev,
+                                                           VMW_PL_SYSTEM);
+
+       ttm_resource_manager_evict_all(&dev_priv->bdev, man);
+
+       ttm_resource_manager_set_used(man, false);
+       ttm_resource_manager_cleanup(man);
+
+       ttm_set_driver_manager(&dev_priv->bdev, VMW_PL_SYSTEM, NULL);
+       kfree(man);
+}
 
        }
 };
 
+static const struct ttm_place vmw_sys_placement_flags = {
+       .fpfn = 0,
+       .lpfn = 0,
+       .mem_type = VMW_PL_SYSTEM,
+       .flags = 0
+};
+
 struct ttm_placement vmw_vram_gmr_placement = {
        .num_placement = 2,
        .placement = vram_gmr_placement_flags,
        .busy_placement = &sys_placement_flags
 };
 
-static const struct ttm_place evictable_placement_flags[] = {
-       {
-               .fpfn = 0,
-               .lpfn = 0,
-               .mem_type = TTM_PL_SYSTEM,
-               .flags = 0
-       }, {
-               .fpfn = 0,
-               .lpfn = 0,
-               .mem_type = TTM_PL_VRAM,
-               .flags = 0
-       }, {
-               .fpfn = 0,
-               .lpfn = 0,
-               .mem_type = VMW_PL_GMR,
-               .flags = 0
-       }, {
-               .fpfn = 0,
-               .lpfn = 0,
-               .mem_type = VMW_PL_MOB,
-               .flags = 0
-       }
+struct ttm_placement vmw_pt_sys_placement = {
+       .num_placement = 1,
+       .placement = &vmw_sys_placement_flags,
+       .num_busy_placement = 1,
+       .busy_placement = &vmw_sys_placement_flags
 };
 
 static const struct ttm_place nonfixed_placement_flags[] = {
        }
 };
 
-struct ttm_placement vmw_evictable_placement = {
-       .num_placement = 4,
-       .placement = evictable_placement_flags,
-       .num_busy_placement = 1,
-       .busy_placement = &sys_placement_flags
-};
-
 struct ttm_placement vmw_srf_placement = {
        .num_placement = 1,
        .num_busy_placement = 2,
                                    &vmw_be->vsgt, ttm->num_pages,
                                    vmw_be->gmr_id);
                break;
+       case VMW_PL_SYSTEM:
+               /* Nothing to be done for a system bind */
+               break;
        default:
                BUG();
        }
        case VMW_PL_MOB:
                vmw_mob_unbind(vmw_be->dev_priv, vmw_be->mob);
                break;
+       case VMW_PL_SYSTEM:
+               break;
        default:
                BUG();
        }
 
        switch (mem->mem_type) {
        case TTM_PL_SYSTEM:
+       case VMW_PL_SYSTEM:
        case VMW_PL_GMR:
        case VMW_PL_MOB:
                return 0;
        (void) ttm_bo_wait(bo, false, false);
 }
 
+static bool vmw_memtype_is_system(uint32_t mem_type)
+{
+       return mem_type == TTM_PL_SYSTEM || mem_type == VMW_PL_SYSTEM;
+}
+
 static int vmw_move(struct ttm_buffer_object *bo,
                    bool evict,
                    struct ttm_operation_ctx *ctx,
        struct ttm_resource_manager *new_man = ttm_manager_type(bo->bdev, new_mem->mem_type);
        int ret;
 
-       if (new_man->use_tt && new_mem->mem_type != TTM_PL_SYSTEM) {
+       if (new_man->use_tt && !vmw_memtype_is_system(new_mem->mem_type)) {
                ret = vmw_ttm_bind(bo->bdev, bo->ttm, new_mem);
                if (ret)
                        return ret;
        vmw_move_notify(bo, bo->resource, new_mem);
 
        if (old_man->use_tt && new_man->use_tt) {
-               if (bo->resource->mem_type == TTM_PL_SYSTEM) {
+               if (vmw_memtype_is_system(bo->resource->mem_type)) {
                        ttm_bo_move_null(bo, new_mem);
                        return 0;
                }
        int ret;
 
        ret = vmw_bo_create_kernel(dev_priv, bo_size,
-                                  &vmw_sys_placement,
+                                  &vmw_pt_sys_placement,
                                   &bo);
        if (unlikely(ret != 0))
                return ret;