OSDN Git Service

drm/i915/selftests: Wrap vm_mmap() around GEM objects
authorChris Wilson <chris@chris-wilson.co.uk>
Thu, 7 Nov 2019 18:06:00 +0000 (18:06 +0000)
committerChris Wilson <chris@chris-wilson.co.uk>
Thu, 7 Nov 2019 21:22:58 +0000 (21:22 +0000)
Provide a utility function to create a vma corresponding to an mmap() of
our device. And use it to exercise the equivalent of userspace
performing a GTT mmap of our objects.

Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Cc: Abdiel Janulgue <abdiel.janulgue@linux.intel.com>
Reviewed-by: Abdiel Janulgue <abdiel.janulgue@linux.intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20191107180601.30815-4-chris@chris-wilson.co.uk
drivers/gpu/drm/i915/Makefile
drivers/gpu/drm/i915/gem/selftests/i915_gem_mman.c
drivers/gpu/drm/i915/selftests/igt_mmap.c [new file with mode: 0644]
drivers/gpu/drm/i915/selftests/igt_mmap.h [new file with mode: 0644]

index 90dcf09..e0fd10c 100644 (file)
@@ -259,6 +259,7 @@ i915-$(CONFIG_DRM_I915_SELFTEST) += \
        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
 
index 29b2077..e04d081 100644 (file)
@@ -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,111 @@ err_obj:
        goto out;
 }
 
+#define expand32(x) (((x) << 0) | ((x) << 8) | ((x) << 16) | ((x) << 24))
+static int igt_mmap_gtt(void *arg)
+{
+       struct drm_i915_private *i915 = arg;
+       struct drm_i915_gem_object *obj;
+       struct vm_area_struct *area;
+       unsigned long addr;
+       void *vaddr;
+       int err, i;
+
+       if (!i915_ggtt_has_aperture(&i915->ggtt))
+               return 0;
+
+       obj = i915_gem_object_create_internal(i915, PAGE_SIZE);
+       if (IS_ERR(obj))
+               return PTR_ERR(obj);
+
+       vaddr = i915_gem_object_pin_map(obj, I915_MAP_WB);
+       if (IS_ERR(vaddr)) {
+               err = PTR_ERR(vaddr);
+               goto out;
+       }
+       memset(vaddr, POISON_INUSE, PAGE_SIZE);
+       i915_gem_object_flush_map(obj);
+       i915_gem_object_unpin_map(obj);
+
+       err = create_mmap_offset(obj);
+       if (err)
+               goto out;
+
+       addr = igt_mmap_node(i915, &obj->base.vma_node,
+                            0, PROT_WRITE, MAP_SHARED);
+       if (IS_ERR_VALUE(addr)) {
+               err = addr;
+               goto out;
+       }
+
+       pr_debug("igt_mmap(obj:gtt) @ %lx\n", addr);
+
+       area = find_vma(current->mm, addr);
+       if (!area) {
+               pr_err("Did not create a vm_area_struct for the mmap\n");
+               err = -EINVAL;
+               goto out_unmap;
+       }
+
+       if (area->vm_private_data != obj) {
+               pr_err("vm_area_struct did not point back to our object!\n");
+               err = -EINVAL;
+               goto out_unmap;
+       }
+
+       for (i = 0; i < PAGE_SIZE / sizeof(u32); i++) {
+               u32 __user *ux = u64_to_user_ptr((u64)(addr + i * sizeof(*ux)));
+               u32 x;
+
+               if (get_user(x, ux)) {
+                       pr_err("Unable to read from GTT mmap, offset:%zd\n",
+                              i * sizeof(x));
+                       err = -EFAULT;
+                       break;
+               }
+
+               if (x != expand32(POISON_INUSE)) {
+                       pr_err("Read incorrect value from GTT mmap, offset:%zd, found:%x, expected:%x\n",
+                              i * sizeof(x), x, expand32(POISON_INUSE));
+                       err = -EINVAL;
+                       break;
+               }
+
+               x = expand32(POISON_FREE);
+               if (put_user(x, ux)) {
+                       pr_err("Unable to write to GTT mmap, offset:%zd\n",
+                              i * sizeof(x));
+                       err = -EFAULT;
+                       break;
+               }
+       }
+
+out_unmap:
+       vm_munmap(addr, PAGE_SIZE);
+
+       vaddr = i915_gem_object_pin_map(obj, I915_MAP_FORCE_WC);
+       if (IS_ERR(vaddr)) {
+               err = PTR_ERR(vaddr);
+               goto out;
+       }
+       if (err == 0 && memchr_inv(vaddr, POISON_FREE, PAGE_SIZE)) {
+               pr_err("Write via GGTT mmap did not land in backing store\n");
+               err = -EINVAL;
+       }
+       i915_gem_object_unpin_map(obj);
+
+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 (file)
index 0000000..583a4ff
--- /dev/null
@@ -0,0 +1,39 @@
+/*
+ * SPDX-License-Identifier: MIT
+ *
+ * Copyright © 2019 Intel Corporation
+ */
+
+#include <drm/drm_file.h>
+
+#include "i915_drv.h"
+#include "igt_mmap.h"
+
+unsigned long igt_mmap_node(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_drm_getfile(i915->drm.primary, O_RDWR);
+       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 (file)
index 0000000..6e716cb
--- /dev/null
@@ -0,0 +1,19 @@
+/*
+ * SPDX-License-Identifier: MIT
+ *
+ * Copyright © 2019 Intel Corporation
+ */
+
+#ifndef IGT_MMAP_H
+#define IGT_MMAP_H
+
+struct drm_i915_private;
+struct drm_vma_offset_node;
+
+unsigned long igt_mmap_node(struct drm_i915_private *i915,
+                           struct drm_vma_offset_node *node,
+                           unsigned long addr,
+                           unsigned long prot,
+                           unsigned long flags);
+
+#endif /* IGT_MMAP_H */