Re: [Intel-gfx] [PATCH] drm/i915/selftests: Wrap vm_mmap() around GEM objects
On 06/11/2019 10.26, Chris Wilson wrote: > 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 > Cc: Abdiel Janulgue Reviewed-by: Abdiel Janulgue ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
[Intel-gfx] [PATCH] drm/i915/selftests: Wrap vm_mmap() around GEM objects
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 Cc: Abdiel Janulgue --- drivers/gpu/drm/drm_file.c| 2 + drivers/gpu/drm/i915/Makefile | 2 + .../drm/i915/gem/selftests/i915_gem_mman.c| 98 +++ drivers/gpu/drm/i915/selftests/igt_mmap.c | 65 drivers/gpu/drm/i915/selftests/igt_mmap.h | 19 include/drm/drm_file.h| 3 + 6 files changed, 189 insertions(+) create mode 100644 drivers/gpu/drm/i915/selftests/igt_mmap.c create mode 100644 drivers/gpu/drm/i915/selftests/igt_mmap.h 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..af2e44b65791 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,109 @@ static int igt_mmap_offset_exhaustion(void *arg) 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; + + 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) { + pr_err("Unable to insert object into reclaimed hole\n"); + goto out; + } + + addr = igt_mmap(i915, >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); + + 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", +
[Intel-gfx] [PATCH] drm/i915/selftests: Wrap vm_mmap() around GEM objects
Provide a utility function to create a vma corresponding to an mmap() of our device. Signed-off-by: Chris Wilson Cc: Abdiel Janulgue --- 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 --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, >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 ..c4b01096d330 --- /dev/null +++ b/drivers/gpu/drm/i915/selftests/igt_mmap.c @@ -0,0 +1,59 @@ +#include +#include +#include +#include + +#include + +#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(>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) { +