diff mbox series

drm/i915/selftests: Wrap vm_mmap() around GEM objects

Message ID 20191106011748.14419-1-chris@chris-wilson.co.uk (mailing list archive)
State New, archived
Headers show
Series drm/i915/selftests: Wrap vm_mmap() around GEM objects | expand

Commit Message

Chris Wilson Nov. 6, 2019, 1:17 a.m. UTC
Provide a utility function to create a vma corresponding to an mmap() of
our device.

Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Cc: Abdiel Janulgue <abdiel.janulgue@linux.intel.com>
---
 drivers/gpu/drm/drm_file.c                    |  2 +
 drivers/gpu/drm/i915/Makefile                 |  2 +
 .../drm/i915/gem/selftests/i915_gem_mman.c    | 33 +++++++++++
 drivers/gpu/drm/i915/selftests/igt_mmap.c     | 59 +++++++++++++++++++
 drivers/gpu/drm/i915/selftests/igt_mmap.h     | 12 ++++
 include/drm/drm_file.h                        |  3 +
 6 files changed, 111 insertions(+)
 create mode 100644 drivers/gpu/drm/i915/selftests/igt_mmap.c
 create mode 100644 drivers/gpu/drm/i915/selftests/igt_mmap.h
diff mbox series

Patch

diff --git a/drivers/gpu/drm/drm_file.c b/drivers/gpu/drm/drm_file.c
index ea34bc991858..33d9c6ec5636 100644
--- a/drivers/gpu/drm/drm_file.c
+++ b/drivers/gpu/drm/drm_file.c
@@ -168,6 +168,7 @@  struct drm_file *drm_file_alloc(struct drm_minor *minor)
 
 	return ERR_PTR(ret);
 }
+EXPORT_SYMBOL(drm_file_alloc);
 
 static void drm_events_release(struct drm_file *file_priv)
 {
@@ -258,6 +259,7 @@  void drm_file_free(struct drm_file *file)
 	put_pid(file->pid);
 	kfree(file);
 }
+EXPORT_SYMBOL(drm_file_free);
 
 static void drm_close_helper(struct file *filp)
 {
diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile
index 90dcf09f52cc..ea704be22cea 100644
--- a/drivers/gpu/drm/i915/Makefile
+++ b/drivers/gpu/drm/i915/Makefile
@@ -253,12 +253,14 @@  i915-y += i915_perf.o
 
 # Post-mortem debug and GPU hang state capture
 i915-$(CONFIG_DRM_I915_CAPTURE_ERROR) += i915_gpu_error.o
+
 i915-$(CONFIG_DRM_I915_SELFTEST) += \
 	gem/selftests/igt_gem_utils.o \
 	selftests/i915_random.o \
 	selftests/i915_selftest.o \
 	selftests/igt_flush_test.o \
 	selftests/igt_live_test.o \
+	selftests/igt_mmap.o \
 	selftests/igt_reset.o \
 	selftests/igt_spinner.o
 
diff --git a/drivers/gpu/drm/i915/gem/selftests/i915_gem_mman.c b/drivers/gpu/drm/i915/gem/selftests/i915_gem_mman.c
index 29b2077b73d2..2a62a945f04f 100644
--- a/drivers/gpu/drm/i915/gem/selftests/i915_gem_mman.c
+++ b/drivers/gpu/drm/i915/gem/selftests/i915_gem_mman.c
@@ -12,6 +12,7 @@ 
 #include "i915_selftest.h"
 #include "selftests/i915_random.h"
 #include "selftests/igt_flush_test.h"
+#include "selftests/igt_mmap.h"
 
 struct tile {
 	unsigned int width;
@@ -694,12 +695,44 @@  static int igt_mmap_offset_exhaustion(void *arg)
 	goto out;
 }
 
+static int igt_mmap_gtt(void *arg)
+{
+	struct drm_i915_private *i915 = arg;
+	struct drm_i915_gem_object *obj;
+	unsigned long addr;
+	int err;
+
+	obj = i915_gem_object_create_internal(i915, PAGE_SIZE);
+	if (IS_ERR(obj))
+		return PTR_ERR(obj);
+
+	err = create_mmap_offset(obj);
+	if (err) {
+		pr_err("Unable to insert object into reclaimed hole\n");
+		goto out;
+	}
+
+	addr = igt_mmap(i915, &obj->base.vma_node, 0, PROT_WRITE, MAP_SHARED);
+	if (IS_ERR_VALUE(addr)) {
+		err = addr;
+		goto out;
+	}
+
+	pr_info("igt_mmap(obj:gtt) @ %lx\n", addr);
+
+	vm_munmap(addr, PAGE_SIZE);
+out:
+	i915_gem_object_put(obj);
+	return err;
+}
+
 int i915_gem_mman_live_selftests(struct drm_i915_private *i915)
 {
 	static const struct i915_subtest tests[] = {
 		SUBTEST(igt_partial_tiling),
 		SUBTEST(igt_smoke_tiling),
 		SUBTEST(igt_mmap_offset_exhaustion),
+		SUBTEST(igt_mmap_gtt),
 	};
 
 	return i915_subtests(tests, i915);
diff --git a/drivers/gpu/drm/i915/selftests/igt_mmap.c b/drivers/gpu/drm/i915/selftests/igt_mmap.c
new file mode 100644
index 000000000000..c4b01096d330
--- /dev/null
+++ b/drivers/gpu/drm/i915/selftests/igt_mmap.c
@@ -0,0 +1,59 @@ 
+#include <linux/anon_inodes.h>
+#include <linux/file.h>
+#include <linux/mm.h>
+#include <linux/mount.h>
+
+#include <drm/drm_file.h>
+
+#include "i915_drv.h"
+#include "igt_mmap.h"
+
+static struct file *mock_file_open(struct drm_i915_private *i915)
+{
+	struct drm_file *priv;
+	struct file *file;
+
+	priv = drm_file_alloc(i915->drm.primary);
+	if (IS_ERR(priv))
+		return ERR_CAST(priv);
+
+	file = anon_inode_getfile("i915", i915->drm.driver->fops, priv, O_RDWR);
+	if (IS_ERR(file)) {
+		drm_file_free(priv);
+		return file;
+	}
+
+	drm_dev_get(&i915->drm);
+	priv->filp = file;
+
+	return file;
+}
+
+unsigned long igt_mmap(struct drm_i915_private *i915,
+		       struct drm_vma_offset_node *node,
+		       unsigned long addr,
+		       unsigned long prot,
+		       unsigned long flags)
+{
+	struct file *file;
+	int err;
+
+	/* Pretend to open("/dev/dri/card0") */
+	file = mock_file_open(i915);
+	if (IS_ERR(file))
+		return PTR_ERR(file);
+
+	err = drm_vma_node_allow(node, file->private_data);
+	if (err) {
+		addr = err;
+		goto out_file;
+	}
+
+	addr = vm_mmap(file, addr, drm_vma_node_size(node) << PAGE_SHIFT,
+		       prot, flags, drm_vma_node_offset_addr(node));
+
+	drm_vma_node_revoke(node, file->private_data);
+out_file:
+	fput(file);
+	return addr;
+}
diff --git a/drivers/gpu/drm/i915/selftests/igt_mmap.h b/drivers/gpu/drm/i915/selftests/igt_mmap.h
new file mode 100644
index 000000000000..9636e70e9595
--- /dev/null
+++ b/drivers/gpu/drm/i915/selftests/igt_mmap.h
@@ -0,0 +1,12 @@ 
+#ifndef IGT_MMAP_H
+#define IGT_MMAP_H
+
+struct drm_i915_private;
+
+unsigned long igt_mmap(struct drm_i915_private *i915,
+		       struct drm_vma_offset_node *node,
+		       unsigned long addr,
+		       unsigned long prot,
+		       unsigned long flags);
+
+#endif /* IGT_MMAP_H */
diff --git a/include/drm/drm_file.h b/include/drm/drm_file.h
index 67af60bb527a..6501d4101d0a 100644
--- a/include/drm/drm_file.h
+++ b/include/drm/drm_file.h
@@ -369,6 +369,9 @@  static inline bool drm_is_render_client(const struct drm_file *file_priv)
 	return file_priv->minor->type == DRM_MINOR_RENDER;
 }
 
+struct drm_file *drm_file_alloc(struct drm_minor *minor);
+void drm_file_free(struct drm_file *file);
+
 int drm_open(struct inode *inode, struct file *filp);
 ssize_t drm_read(struct file *filp, char __user *buffer,
 		 size_t count, loff_t *offset);