gem/i915_gem_internal.o \
        gem/i915_gem_object.o \
        gem/i915_gem_object_blt.o \
+       gem/i915_gem_lmem.o \
        gem/i915_gem_mman.o \
        gem/i915_gem_pages.o \
        gem/i915_gem_phys.o \
          i915_scheduler.o \
          i915_trace_points.o \
          i915_vma.o \
+         intel_region_lmem.o \
          intel_wopcm.o
 
 # general-purpose microcontroller (GuC) support
 
--- /dev/null
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright © 2019 Intel Corporation
+ */
+
+#include "intel_memory_region.h"
+#include "gem/i915_gem_region.h"
+#include "gem/i915_gem_lmem.h"
+#include "i915_drv.h"
+
+const struct drm_i915_gem_object_ops i915_gem_lmem_obj_ops = {
+       .get_pages = i915_gem_object_get_pages_buddy,
+       .put_pages = i915_gem_object_put_pages_buddy,
+       .release = i915_gem_object_release_memory_region,
+};
+
+bool i915_gem_object_is_lmem(struct drm_i915_gem_object *obj)
+{
+       return obj->ops == &i915_gem_lmem_obj_ops;
+}
+
+struct drm_i915_gem_object *
+i915_gem_object_create_lmem(struct drm_i915_private *i915,
+                           resource_size_t size,
+                           unsigned int flags)
+{
+       return i915_gem_object_create_region(i915->mm.regions[INTEL_REGION_LMEM],
+                                            size, flags);
+}
+
+struct drm_i915_gem_object *
+__i915_gem_lmem_object_create(struct intel_memory_region *mem,
+                             resource_size_t size,
+                             unsigned int flags)
+{
+       static struct lock_class_key lock_class;
+       struct drm_i915_private *i915 = mem->i915;
+       struct drm_i915_gem_object *obj;
+
+       if (size > BIT(mem->mm.max_order) * mem->mm.chunk_size)
+               return ERR_PTR(-E2BIG);
+
+       obj = i915_gem_object_alloc();
+       if (!obj)
+               return ERR_PTR(-ENOMEM);
+
+       drm_gem_private_object_init(&i915->drm, &obj->base, size);
+       i915_gem_object_init(obj, &i915_gem_lmem_obj_ops, &lock_class);
+
+       obj->read_domains = I915_GEM_DOMAIN_WC | I915_GEM_DOMAIN_GTT;
+
+       i915_gem_object_set_cache_coherency(obj, I915_CACHE_NONE);
+
+       i915_gem_object_init_memory_region(obj, mem, flags);
+
+       return obj;
+}
 
--- /dev/null
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright © 2019 Intel Corporation
+ */
+
+#ifndef __I915_GEM_LMEM_H
+#define __I915_GEM_LMEM_H
+
+#include <linux/types.h>
+
+struct drm_i915_private;
+struct drm_i915_gem_object;
+struct intel_memory_region;
+
+extern const struct drm_i915_gem_object_ops i915_gem_lmem_obj_ops;
+
+bool i915_gem_object_is_lmem(struct drm_i915_gem_object *obj);
+
+struct drm_i915_gem_object *
+i915_gem_object_create_lmem(struct drm_i915_private *i915,
+                           resource_size_t size,
+                           unsigned int flags);
+
+struct drm_i915_gem_object *
+__i915_gem_lmem_object_create(struct intel_memory_region *mem,
+                             resource_size_t size,
+                             unsigned int flags);
+
+#endif /* !__I915_GEM_LMEM_H */
 
 #include "i915_vma.h"
 #include "i915_irq.h"
 
+#include "intel_region_lmem.h"
+
 #include "intel_gvt.h"
 
 /* General customization:
 #define HAS_IPC(dev_priv)               (INTEL_INFO(dev_priv)->display.has_ipc)
 
 #define HAS_REGION(i915, i) (INTEL_INFO(i915)->memory_regions & (i))
+#define HAS_LMEM(i915) HAS_REGION(i915, REGION_LMEM)
 
 #define HAS_GT_UC(dev_priv)    (INTEL_INFO(dev_priv)->has_gt_uc)
 
 
--- /dev/null
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright © 2019 Intel Corporation
+ */
+
+#include "i915_drv.h"
+#include "intel_memory_region.h"
+#include "gem/i915_gem_lmem.h"
+#include "gem/i915_gem_region.h"
+#include "intel_region_lmem.h"
+
+const struct intel_memory_region_ops intel_region_lmem_ops = {
+       .init = intel_memory_region_init_buddy,
+       .release = intel_memory_region_release_buddy,
+       .create_object = __i915_gem_lmem_object_create,
+};
 
--- /dev/null
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright © 2019 Intel Corporation
+ */
+
+#ifndef __INTEL_REGION_LMEM_H
+#define __INTEL_REGION_LMEM_H
+
+extern const struct intel_memory_region_ops intel_region_lmem_ops;
+
+#endif /* !__INTEL_REGION_LMEM_H */
 
 selftest(blt, i915_gem_object_blt_live_selftests)
 selftest(client, i915_gem_client_blt_live_selftests)
 selftest(reset, intel_reset_live_selftests)
+selftest(memory_region, intel_memory_region_live_selftests)
 selftest(hangcheck, intel_hangcheck_live_selftests)
 selftest(execlists, intel_execlists_live_selftests)
 selftest(guc, intel_guc_live_selftest)
 
 #include "mock_gem_device.h"
 #include "mock_region.h"
 
+#include "gem/i915_gem_lmem.h"
 #include "gem/i915_gem_region.h"
 #include "gem/selftests/mock_context.h"
+#include "gt/intel_gt.h"
 #include "selftests/i915_random.h"
 
 static void close_objects(struct intel_memory_region *mem,
        return err;
 }
 
+static int igt_lmem_create(void *arg)
+{
+       struct drm_i915_private *i915 = arg;
+       struct drm_i915_gem_object *obj;
+       int err = 0;
+
+       obj = i915_gem_object_create_lmem(i915, PAGE_SIZE, 0);
+       if (IS_ERR(obj))
+               return PTR_ERR(obj);
+
+       err = i915_gem_object_pin_pages(obj);
+       if (err)
+               goto out_put;
+
+       i915_gem_object_unpin_pages(obj);
+out_put:
+       i915_gem_object_put(obj);
+
+       return err;
+}
+
 int intel_memory_region_mock_selftests(void)
 {
        static const struct i915_subtest tests[] = {
        drm_dev_put(&i915->drm);
        return err;
 }
+
+int intel_memory_region_live_selftests(struct drm_i915_private *i915)
+{
+       static const struct i915_subtest tests[] = {
+               SUBTEST(igt_lmem_create),
+       };
+
+       if (!HAS_LMEM(i915)) {
+               pr_info("device lacks LMEM support, skipping\n");
+               return 0;
+       }
+
+       if (intel_gt_is_wedged(&i915->gt))
+               return 0;
+
+       return i915_live_subtests(tests, i915);
+}