All of lore.kernel.org
 help / color / mirror / Atom feed
* [igt-dev] [PATCH i-g-t v4 0/3] Add GEM_MMAP_OFFSET support in IGT.
@ 2019-11-26 17:25 Zbigniew Kempczyński
  2019-11-26 17:25 ` [igt-dev] [PATCH i-g-t v4 1/3] include/drm-uapi/i915_drm: Add defs for mmap_offset Zbigniew Kempczyński
                   ` (9 more replies)
  0 siblings, 10 replies; 29+ messages in thread
From: Zbigniew Kempczyński @ 2019-11-26 17:25 UTC (permalink / raw)
  To: igt-dev

Enable GEM_MMAP_OFFSET uAPI.

Series comes from split 'LMEM enabling in IGT'.
Mmap_offset will land before memory region so add support for it.

v2: Change WC -> WB according to review
v3: Remove "local" from i915_drm.h and push dummy commit to it.
    (suggested by Petri).
    Add mmap-offset-close-race test (suggested by Chris).
v4: Additional checks + fixing leak in __gem_mmap__has_wc()

Cc: Lukasz Kalamarz <lukasz.kalamarz@intel.com>
Cc: Zbigniew Kempczyński <zbigniew.kempczynski@intel.com>
Cc: Chris Wilson <chris@chris-wilson.co.uk>
Cc: Vanshidhar Konda <vanshidhar.r.konda@intel.com>

Lukasz Kalamarz (2):
  lib/i915/gem_mman: add mmap_offset support
  tests/i915/gem_mmap_offset: Add new API test for gem_mmap_offset

Zbigniew Kempczyński (1):
  include/drm-uapi/i915_drm: Add defs for mmap_offset

 include/drm-uapi/i915_drm.h  |  27 ++++
 lib/i915/gem_mman.c          | 232 +++++++++++++++++++++++++++++------
 lib/i915/gem_mman.h          |  16 ++-
 tests/Makefile.sources       |   3 +
 tests/i915/gem_mmap_offset.c | 175 ++++++++++++++++++++++++++
 tests/meson.build            |   1 +
 6 files changed, 414 insertions(+), 40 deletions(-)
 create mode 100644 tests/i915/gem_mmap_offset.c

-- 
2.23.0

_______________________________________________
igt-dev mailing list
igt-dev@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/igt-dev

^ permalink raw reply	[flat|nested] 29+ messages in thread

* [igt-dev] [PATCH i-g-t v4 1/3] include/drm-uapi/i915_drm: Add defs for mmap_offset
  2019-11-26 17:25 [igt-dev] [PATCH i-g-t v4 0/3] Add GEM_MMAP_OFFSET support in IGT Zbigniew Kempczyński
@ 2019-11-26 17:25 ` Zbigniew Kempczyński
  2019-11-26 17:25 ` [igt-dev] [PATCH i-g-t v4 2/3] lib/i915/gem_mman: add mmap_offset support Zbigniew Kempczyński
                   ` (8 subsequent siblings)
  9 siblings, 0 replies; 29+ messages in thread
From: Zbigniew Kempczyński @ 2019-11-26 17:25 UTC (permalink / raw)
  To: igt-dev; +Cc: Petri Latvala

Pre-merge dummy commit of kernel uAPI i915_drm.h file.
Required to use GEM_MMAP_OFFSET ioctl().

Signed-off-by: Zbigniew Kempczyński <zbigniew.kempczynski@intel.com>
Suggested-by: Petri Latvala <petri.latvala@intel.com>
Cc: Chris Wilson <chris@chris-wilson.co.uk>
---
 include/drm-uapi/i915_drm.h | 27 +++++++++++++++++++++++++++
 1 file changed, 27 insertions(+)

diff --git a/include/drm-uapi/i915_drm.h b/include/drm-uapi/i915_drm.h
index ab899abb..8fb989f5 100644
--- a/include/drm-uapi/i915_drm.h
+++ b/include/drm-uapi/i915_drm.h
@@ -395,6 +395,7 @@ typedef struct _drm_i915_sarea {
 #define DRM_IOCTL_I915_GEM_PWRITE	DRM_IOW (DRM_COMMAND_BASE + DRM_I915_GEM_PWRITE, struct drm_i915_gem_pwrite)
 #define DRM_IOCTL_I915_GEM_MMAP		DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GEM_MMAP, struct drm_i915_gem_mmap)
 #define DRM_IOCTL_I915_GEM_MMAP_GTT	DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GEM_MMAP_GTT, struct drm_i915_gem_mmap_gtt)
+#define DRM_IOCTL_I915_GEM_MMAP_OFFSET	DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GEM_MMAP_GTT, struct drm_i915_gem_mmap_offset)
 #define DRM_IOCTL_I915_GEM_SET_DOMAIN	DRM_IOW (DRM_COMMAND_BASE + DRM_I915_GEM_SET_DOMAIN, struct drm_i915_gem_set_domain)
 #define DRM_IOCTL_I915_GEM_SW_FINISH	DRM_IOW (DRM_COMMAND_BASE + DRM_I915_GEM_SW_FINISH, struct drm_i915_gem_sw_finish)
 #define DRM_IOCTL_I915_GEM_SET_TILING	DRM_IOWR (DRM_COMMAND_BASE + DRM_I915_GEM_SET_TILING, struct drm_i915_gem_set_tiling)
@@ -793,6 +794,32 @@ struct drm_i915_gem_mmap_gtt {
 	__u64 offset;
 };
 
+struct drm_i915_gem_mmap_offset {
+	/** Handle for the object being mapped. */
+	__u32 handle;
+	__u32 pad;
+	/**
+	 * Fake offset to use for subsequent mmap call
+	 *
+	 * This is a fixed-size type for 32/64 compatibility.
+	 */
+	__u64 offset;
+
+	/**
+	 * Flags for extended behaviour.
+	 *
+	 * It is mandatory that either one of the MMAP_OFFSET flags
+	 * should be passed here.
+	 */
+	__u64 flags;
+#define I915_MMAP_OFFSET_GTT 0
+#define I915_MMAP_OFFSET_WC  1
+#define I915_MMAP_OFFSET_WB  2
+#define I915_MMAP_OFFSET_UC  3
+
+	__u64 extensions;
+};
+
 struct drm_i915_gem_set_domain {
 	/** Handle for the object */
 	__u32 handle;
-- 
2.23.0

_______________________________________________
igt-dev mailing list
igt-dev@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/igt-dev

^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [igt-dev] [PATCH i-g-t v4 2/3] lib/i915/gem_mman: add mmap_offset support
  2019-11-26 17:25 [igt-dev] [PATCH i-g-t v4 0/3] Add GEM_MMAP_OFFSET support in IGT Zbigniew Kempczyński
  2019-11-26 17:25 ` [igt-dev] [PATCH i-g-t v4 1/3] include/drm-uapi/i915_drm: Add defs for mmap_offset Zbigniew Kempczyński
@ 2019-11-26 17:25 ` Zbigniew Kempczyński
  2019-11-28 14:38   ` Chris Wilson
  2019-11-28 14:43   ` Chris Wilson
  2019-11-26 17:25 ` [igt-dev] [PATCH i-g-t v4 3/3] tests/i915/gem_mmap_offset: Add new API test for gem_mmap_offset Zbigniew Kempczyński
                   ` (7 subsequent siblings)
  9 siblings, 2 replies; 29+ messages in thread
From: Zbigniew Kempczyński @ 2019-11-26 17:25 UTC (permalink / raw)
  To: igt-dev

From: Lukasz Kalamarz <lukasz.kalamarz@intel.com>

With introduction of LMEM concept new IOCTL call were implemented
- gem_mmap_offset. This patch add support in IGT for it.

Signed-off-by: Lukasz Kalamarz <lukasz.kalamarz@intel.com>
Signed-off-by: Antonio Argenziano <antonio.argenziano@intel.com>
Signed-off-by: Zbigniew Kempczyński <zbigniew.kempczynski@intel.com>
Cc: Chris Wilson <chris@chris-wilson.co.uk>
Cc: Vanshidhar Konda <vanshidhar.r.konda@intel.com>
Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk>
---
 lib/i915/gem_mman.c | 232 ++++++++++++++++++++++++++++++++++++--------
 lib/i915/gem_mman.h |  16 ++-
 2 files changed, 208 insertions(+), 40 deletions(-)

diff --git a/lib/i915/gem_mman.c b/lib/i915/gem_mman.c
index 6256627b..3b54b6c8 100644
--- a/lib/i915/gem_mman.c
+++ b/lib/i915/gem_mman.c
@@ -40,6 +40,31 @@
 #define VG(x) do {} while (0)
 #endif
 
+static int gem_mmap_gtt_version(int fd)
+{
+	struct drm_i915_getparam gp;
+	int gtt_version = -1;
+
+	memset(&gp, 0, sizeof(gp));
+	gp.param = I915_PARAM_MMAP_GTT_VERSION;
+	gp.value = &gtt_version;
+	ioctl(fd, DRM_IOCTL_I915_GETPARAM, &gp);
+
+	return gtt_version;
+}
+
+static bool gem_has_mmap_offset(int fd)
+{
+	int gtt_version = gem_mmap_gtt_version(fd);
+
+	return gtt_version >= 4;
+}
+
+void gem_require_mmap_offset(int i915)
+{
+	igt_require(gem_has_mmap_offset(i915));
+}
+
 /**
  * __gem_mmap__gtt:
  * @fd: open i915 drm file descriptor
@@ -101,46 +126,66 @@ int gem_munmap(void *ptr, uint64_t size)
 	return ret;
 }
 
-bool gem_mmap__has_wc(int fd)
+bool __gem_mmap__has_wc(int fd)
 {
-	static int has_wc = -1;
-
-	if (has_wc == -1) {
-		struct drm_i915_getparam gp;
-		int mmap_version = -1;
-		int gtt_version = -1;
-
-		has_wc = 0;
-
-		memset(&gp, 0, sizeof(gp));
-		gp.param = I915_PARAM_MMAP_GTT_VERSION;
-		gp.value = &gtt_version;
-		ioctl(fd, DRM_IOCTL_I915_GETPARAM, &gp);
-
-		memset(&gp, 0, sizeof(gp));
-		gp.param = I915_PARAM_MMAP_VERSION;
-		gp.value = &mmap_version;
-		ioctl(fd, DRM_IOCTL_I915_GETPARAM, &gp);
-
-		/* Do we have the new mmap_ioctl with DOMAIN_WC? */
-		if (mmap_version >= 1 && gtt_version >= 2) {
-			struct drm_i915_gem_mmap arg;
-
-			/* Does this device support wc-mmaps ? */
-			memset(&arg, 0, sizeof(arg));
-			arg.handle = gem_create(fd, 4096);
-			arg.offset = 0;
-			arg.size = 4096;
-			arg.flags = I915_MMAP_WC;
-			has_wc = igt_ioctl(fd, DRM_IOCTL_I915_GEM_MMAP, &arg) == 0;
-			gem_close(fd, arg.handle);
-		}
-		errno = 0;
+	int has_wc = 0;
+
+	struct drm_i915_getparam gp;
+	int mmap_version = -1;
+
+	memset(&gp, 0, sizeof(gp));
+	gp.param = I915_PARAM_MMAP_VERSION;
+	gp.value = &mmap_version;
+	ioctl(fd, DRM_IOCTL_I915_GETPARAM, &gp);
+
+	/* Do we have the mmap_ioctl with DOMAIN_WC? */
+	if (mmap_version >= 1 && gem_mmap_gtt_version(fd) >= 2) {
+		struct drm_i915_gem_mmap arg;
+
+		/* Does this device support wc-mmaps ? */
+		memset(&arg, 0, sizeof(arg));
+		arg.handle = gem_create(fd, 4096);
+		arg.offset = 0;
+		arg.size = 4096;
+		arg.flags = I915_MMAP_WC;
+		has_wc = igt_ioctl(fd, DRM_IOCTL_I915_GEM_MMAP, &arg) == 0;
+		gem_close(fd, arg.handle);
+
+		if (has_wc && from_user_pointer(arg.addr_ptr))
+			munmap(from_user_pointer(arg.addr_ptr), arg.size);
 	}
+	errno = 0;
+
+	return has_wc > 0;
+}
+
+bool __gem_mmap_offset__has_wc(int fd)
+{
+	int has_wc = 0;
+	struct drm_i915_gem_mmap_offset arg;
+
+	if (!gem_has_mmap_offset(fd))
+		return false;
+
+	/* Does this device support wc-mmaps ? */
+	memset(&arg, 0, sizeof(arg));
+	arg.handle = gem_create(fd, 4096);
+	arg.offset = 0;
+	arg.flags = I915_MMAP_OFFSET_WC;
+	has_wc = igt_ioctl(fd, DRM_IOCTL_I915_GEM_MMAP_OFFSET,
+			   &arg) == 0;
+	gem_close(fd, arg.handle);
+
+	errno = 0;
 
 	return has_wc > 0;
 }
 
+bool gem_mmap__has_wc(int fd)
+{
+	return __gem_mmap_offset__has_wc(fd) || __gem_mmap__has_wc(fd);
+}
+
 /**
  * __gem_mmap:
  * @fd: open i915 drm file descriptor
@@ -157,11 +202,13 @@ bool gem_mmap__has_wc(int fd)
  *
  * Returns: A pointer to the created memory mapping, NULL on failure.
  */
-static void
-*__gem_mmap(int fd, uint32_t handle, uint64_t offset, uint64_t size, unsigned int prot, uint64_t flags)
+void *__gem_mmap(int fd, uint32_t handle, uint64_t offset, uint64_t size,
+		 unsigned int prot, uint64_t flags)
 {
 	struct drm_i915_gem_mmap arg;
 
+	igt_assert(offset == 0);
+
 	memset(&arg, 0, sizeof(arg));
 	arg.handle = handle;
 	arg.offset = offset;
@@ -177,6 +224,50 @@ static void
 	return from_user_pointer(arg.addr_ptr);
 }
 
+/**
+ * __gem_mmap_offset:
+ * @fd: open i915 drm file descriptor
+ * @handle: gem buffer object handle
+ * @offset: offset in the gem buffer of the mmap arena
+ * @size: size of the mmap arena
+ * @prot: memory protection bits as used by mmap()
+ * @flags: flags used to determine caching
+ *
+ * Mmap the gem buffer memory on offset returned in GEM_MMAP_OFFSET ioctl.
+ * Offset argument passed in function call must be 0. In the future
+ * when driver will allow slice mapping of buffer object this restriction
+ * will be removed.
+ *
+ * Returns: A pointer to the created memory mapping, NULL on failure.
+ */
+void *__gem_mmap_offset(int fd, uint32_t handle, uint64_t offset, uint64_t size,
+			unsigned int prot, uint64_t flags)
+{
+	struct drm_i915_gem_mmap_offset arg;
+	void *ptr;
+
+	if (!gem_has_mmap_offset(fd))
+		return NULL;
+
+	igt_assert(offset == 0);
+
+	memset(&arg, 0, sizeof(arg));
+	arg.handle = handle;
+	arg.flags = flags;
+
+	if (igt_ioctl(fd, DRM_IOCTL_I915_GEM_MMAP_OFFSET, &arg))
+		return NULL;
+
+	ptr = mmap64(0, size, prot, MAP_SHARED, fd, arg.offset + offset);
+
+	if (ptr == MAP_FAILED)
+		ptr = NULL;
+	else
+		errno = 0;
+
+	return ptr;
+}
+
 /**
  * __gem_mmap__wc:
  * @fd: open i915 drm file descriptor
@@ -194,7 +285,12 @@ static void
  */
 void *__gem_mmap__wc(int fd, uint32_t handle, uint64_t offset, uint64_t size, unsigned prot)
 {
-	return __gem_mmap(fd, handle, offset, size, prot, I915_MMAP_WC);
+	void *ptr = __gem_mmap_offset(fd, handle, offset, size, prot,
+				      I915_MMAP_OFFSET_WC);
+	if (!ptr)
+		ptr = __gem_mmap(fd, handle, offset, size, prot, I915_MMAP_WC);
+
+	return ptr;
 }
 
 /**
@@ -205,17 +301,71 @@ void *__gem_mmap__wc(int fd, uint32_t handle, uint64_t offset, uint64_t size, un
  * @size: size of the mmap arena
  * @prot: memory protection bits as used by mmap()
  *
- * Like __gem_mmap__wc() except we assert on failure.
+ * Try to __gem_mmap__wc(). Assert on failure.
  *
  * Returns: A pointer to the created memory mapping
  */
 void *gem_mmap__wc(int fd, uint32_t handle, uint64_t offset, uint64_t size, unsigned prot)
 {
 	void *ptr = __gem_mmap__wc(fd, handle, offset, size, prot);
+
 	igt_assert(ptr);
 	return ptr;
 }
 
+/**
+ * __gem_mmap__device_coherent:
+ * @fd: open i915 drm file descriptor
+ * @handle: gem buffer object handle
+ * @offset: offset in the gem buffer of the mmap arena
+ * @size: size of the mmap arena
+ * @prot: memory protection bits as used by mmap()
+ *
+ * Returns: A pointer to a block of linear device memory mapped into the
+ * process with WC semantics. When no WC is available try to mmap using GGTT.
+ */
+void *__gem_mmap__device_coherent(int fd, uint32_t handle, uint64_t offset,
+				  uint64_t size, unsigned prot)
+{
+	void *ptr = __gem_mmap_offset(fd, handle, offset, size, prot,
+				      I915_MMAP_OFFSET_WC);
+	if (!ptr)
+		ptr = __gem_mmap__wc(fd, handle, offset, size, prot);
+
+	if (!ptr)
+		ptr = __gem_mmap__gtt(fd, handle, size, prot);
+
+	return ptr;
+}
+
+/**
+ * gem_mmap__device_coherent:
+ * @fd: open i915 drm file descriptor
+ * @handle: gem buffer object handle
+ * @offset: offset in the gem buffer of the mmap arena
+ * @size: size of the mmap arena
+ * @prot: memory protection bits as used by mmap()
+ *
+ * Call __gem_mmap__device__coherent(), asserts on fail.
+ * Offset argument passed in function call must be 0. In the future
+ * when driver will allow slice mapping of buffer object this restriction
+ * will be removed.
+ *
+ * Returns: A pointer to the created memory mapping.
+ */
+void *gem_mmap__device_coherent(int fd, uint32_t handle, uint64_t offset,
+				uint64_t size, unsigned prot)
+{
+	void *ptr;
+
+	igt_assert(offset == 0);
+
+	ptr = gem_mmap__device_coherent(fd, handle, offset, size, prot);
+	igt_assert(ptr);
+
+	return ptr;
+}
+
 /**
  * __gem_mmap__cpu:
  * @fd: open i915 drm file descriptor
@@ -248,7 +398,11 @@ void *__gem_mmap__cpu(int fd, uint32_t handle, uint64_t offset, uint64_t size, u
  */
 void *gem_mmap__cpu(int fd, uint32_t handle, uint64_t offset, uint64_t size, unsigned prot)
 {
-	void *ptr = __gem_mmap__cpu(fd, handle, offset, size, prot);
+	void *ptr = __gem_mmap_offset(fd, handle, offset, size, prot,
+				      I915_MMAP_OFFSET_WB);
+	if (!ptr)
+		ptr = __gem_mmap__cpu(fd, handle, offset, size, prot);
+
 	igt_assert(ptr);
 	return ptr;
 }
diff --git a/lib/i915/gem_mman.h b/lib/i915/gem_mman.h
index 096ff592..ea304dbf 100644
--- a/lib/i915/gem_mman.h
+++ b/lib/i915/gem_mman.h
@@ -25,12 +25,20 @@
 #ifndef GEM_MMAN_H
 #define GEM_MMAN_H
 
+#include <stdint.h>
+
+void gem_require_mmap_offset(int i915);
+bool gem_mmap_has_gtt(int fd);
+
 void *gem_mmap__gtt(int fd, uint32_t handle, uint64_t size, unsigned prot);
 void *gem_mmap__cpu(int fd, uint32_t handle, uint64_t offset, uint64_t size, unsigned prot);
 
+bool __gem_mmap__has_wc(int fd);
+bool __gem_mmap_offset__has_wc(int fd);
 bool gem_mmap__has_wc(int fd);
 void *gem_mmap__wc(int fd, uint32_t handle, uint64_t offset, uint64_t size, unsigned prot);
-
+void *gem_mmap__device_coherent(int fd, uint32_t handle, uint64_t offset,
+				uint64_t size, unsigned prot);
 #ifndef I915_GEM_DOMAIN_WC
 #define I915_GEM_DOMAIN_WC 0x80
 #endif
@@ -38,9 +46,15 @@ void *gem_mmap__wc(int fd, uint32_t handle, uint64_t offset, uint64_t size, unsi
 bool gem_has_mappable_ggtt(int i915);
 void gem_require_mappable_ggtt(int i915);
 
+void *__gem_mmap(int fd, uint32_t handle, uint64_t offset, uint64_t size,
+		 unsigned int prot, uint64_t flags);
+void *__gem_mmap_offset(int fd, uint32_t handle, uint64_t offset, uint64_t size,
+			unsigned int prot, uint64_t flags);
 void *__gem_mmap__gtt(int fd, uint32_t handle, uint64_t size, unsigned prot);
 void *__gem_mmap__cpu(int fd, uint32_t handle, uint64_t offset, uint64_t size, unsigned prot);
 void *__gem_mmap__wc(int fd, uint32_t handle, uint64_t offset, uint64_t size, unsigned prot);
+void *__gem_mmap__device_coherent(int fd, uint32_t handle, uint64_t offset,
+				  uint64_t size, unsigned prot);
 
 int gem_munmap(void *ptr, uint64_t size);
 
-- 
2.23.0

_______________________________________________
igt-dev mailing list
igt-dev@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/igt-dev

^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [igt-dev] [PATCH i-g-t v4 3/3] tests/i915/gem_mmap_offset: Add new API test for gem_mmap_offset
  2019-11-26 17:25 [igt-dev] [PATCH i-g-t v4 0/3] Add GEM_MMAP_OFFSET support in IGT Zbigniew Kempczyński
  2019-11-26 17:25 ` [igt-dev] [PATCH i-g-t v4 1/3] include/drm-uapi/i915_drm: Add defs for mmap_offset Zbigniew Kempczyński
  2019-11-26 17:25 ` [igt-dev] [PATCH i-g-t v4 2/3] lib/i915/gem_mman: add mmap_offset support Zbigniew Kempczyński
@ 2019-11-26 17:25 ` Zbigniew Kempczyński
  2019-11-28 12:55     ` [Intel-gfx] " Chris Wilson
                     ` (2 more replies)
  2019-11-26 18:24 ` [igt-dev] ✓ Fi.CI.BAT: success for Add GEM_MMAP_OFFSET support in IGT. (rev4) Patchwork
                   ` (6 subsequent siblings)
  9 siblings, 3 replies; 29+ messages in thread
From: Zbigniew Kempczyński @ 2019-11-26 17:25 UTC (permalink / raw)
  To: igt-dev

From: Lukasz Kalamarz <lukasz.kalamarz@intel.com>

Few simple tests which tries to create / mmap buffer objects
using GEM_MMAP_OFFSET uAPI.

v2: change from WC -> WB (according to Chris review comment)
v3: add mmap-offset-close-race test

Signed-off-by: Lukasz Kalamarz <lukasz.kalamarz@intel.com>
Signed-off-by: Zbigniew Kempczyński <zbigniew.kempczynski@intel.com>
Cc: Chris Wilson <chris@chris-wilson.co.uk>
Cc: Vanshidhar Konda <vanshidhar.r.konda@intel.com>
---
 tests/Makefile.sources       |   3 +
 tests/i915/gem_mmap_offset.c | 175 +++++++++++++++++++++++++++++++++++
 tests/meson.build            |   1 +
 3 files changed, 179 insertions(+)
 create mode 100644 tests/i915/gem_mmap_offset.c

diff --git a/tests/Makefile.sources b/tests/Makefile.sources
index d86f9c26..af464aef 100644
--- a/tests/Makefile.sources
+++ b/tests/Makefile.sources
@@ -323,6 +323,9 @@ gem_mmap_SOURCES = i915/gem_mmap.c
 TESTS_progs += gem_mmap_gtt
 gem_mmap_gtt_SOURCES = i915/gem_mmap_gtt.c
 
+TESTS_progs += gem_mmap_offset
+gem_mmap_offset_SOURCES = i915/gem_mmap_offset.c
+
 TESTS_progs += gem_mmap_offset_exhaustion
 gem_mmap_offset_exhaustion_SOURCES = i915/gem_mmap_offset_exhaustion.c
 
diff --git a/tests/i915/gem_mmap_offset.c b/tests/i915/gem_mmap_offset.c
new file mode 100644
index 00000000..d11f7f22
--- /dev/null
+++ b/tests/i915/gem_mmap_offset.c
@@ -0,0 +1,175 @@
+/*
+ * Copyright © 2019 Intel Corporation
+ *
+ * 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 (including the next
+ * paragraph) 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 "igt.h"
+#include <errno.h>
+#include <stdatomic.h>
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+#include "drm.h"
+
+IGT_TEST_DESCRIPTION("Basic MMAP_OFFSET IOCTL tests for mem regions\n");
+
+static int mmap_offset_ioctl(int fd, struct drm_i915_gem_mmap_offset *arg)
+{
+	int err = 0;
+
+	if (igt_ioctl(fd, DRM_IOCTL_I915_GEM_MMAP_OFFSET, arg))
+		err = -errno;
+
+	errno = 0;
+	return err;
+}
+
+static void mmap_offset_bad_object(int fd)
+{
+	uint32_t real_handle;
+	uint32_t handles[20];
+	int i = 0;
+
+	real_handle = gem_create(fd, 4096);
+
+	handles[i++] = 0xdeadbeef;
+	for (int bit = 0; bit < 16; bit++)
+		handles[i++] = real_handle | (1 << (bit + 16));
+	handles[i] = real_handle + 1;
+
+	for (; i >= 0; i--) {
+		struct drm_i915_gem_mmap_offset arg = {
+			.handle = handles[i],
+			.flags = I915_MMAP_OFFSET_WB,
+		};
+
+		igt_debug("Trying MMAP IOCTL with handle %x\n",
+			  handles[i]);
+		igt_assert_eq(mmap_offset_ioctl(fd, &arg),
+			      -ENOENT);
+	}
+
+	gem_close(fd, real_handle);
+}
+
+static void mmap_offset_basic(int fd)
+{
+	uint64_t flags;
+	uint32_t handle, obj_size;
+	uint8_t *expected, *buf, *addr;
+
+	obj_size = 4096;
+	handle = gem_create(fd, obj_size);
+	flags = I915_MMAP_OFFSET_WB;
+	addr = __gem_mmap_offset(fd, handle, 0, obj_size,
+				 PROT_READ | PROT_WRITE,
+				 flags);
+	igt_assert(addr);
+
+	igt_debug("Testing contents of newly created object.\n");
+	expected = calloc(obj_size, sizeof(*expected));
+	igt_assert_eq(memcmp(addr, expected, obj_size), 0);
+	free(expected);
+
+	igt_debug("Testing coherency of writes and mmap reads.\n");
+	buf = calloc(obj_size, sizeof(*buf));
+	memset(buf + 1024, 0x01, 1024);
+	gem_write(fd, handle, 0, buf, obj_size);
+
+	igt_debug("Testing that mapping stays after close\n");
+	gem_close(fd, handle);
+	igt_assert_eq(memcmp(buf, addr, obj_size), 0);
+	free(buf);
+
+	igt_debug("Testing unmapping\n");
+	munmap(addr, obj_size);
+}
+
+static void mmap_offset_close_race(int i915)
+{
+	const int ncpus = sysconf(_SC_NPROCESSORS_ONLN);
+	_Atomic uint32_t *handles;
+	size_t len = ALIGN((ncpus + 1) * sizeof(uint32_t), 4096);
+
+	handles = mmap64(0, len, PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0);
+	igt_assert(handles != MAP_FAILED);
+
+	igt_fork(child, ncpus + 1) {
+		do {
+			struct drm_i915_gem_mmap_offset mmap_arg = {};
+			const int i = 1 + random() % ncpus;
+			uint32_t old;
+
+			mmap_arg.handle = gem_create(i915, 4096);
+			mmap_arg.flags = I915_MMAP_OFFSET_WB;
+			old = atomic_exchange(&handles[i], mmap_arg.handle);
+			ioctl(i915, DRM_IOCTL_GEM_CLOSE, &old);
+
+			if (ioctl(i915,
+				  DRM_IOCTL_I915_GEM_MMAP_OFFSET,
+				  &mmap_arg) != -1) {
+				void *ptr;
+
+				ptr = mmap64(0, 4096,
+					     PROT_WRITE, MAP_SHARED, i915,
+					     mmap_arg.offset);
+				if (ptr != MAP_FAILED) {
+					*(volatile uint32_t *)ptr = 0;
+					munmap(ptr, 4096);
+				}
+			}
+
+		} while (!READ_ONCE(handles[0]));
+	}
+
+	sleep(20);
+	handles[0] = 1;
+	igt_waitchildren();
+
+	for (int i = 1; i <= ncpus; i++)
+		ioctl(i915, DRM_IOCTL_GEM_CLOSE, handles[i]);
+	munmap(handles, len);
+}
+
+igt_main
+{
+	int fd;
+
+	igt_fixture {
+		fd = drm_open_driver(DRIVER_INTEL);
+		gem_require_mmap_offset(fd);
+	}
+
+	igt_describe("Verify mapping to invalid gem objects won't be created");
+	igt_subtest_f("mmap-offset-bad-object")
+			mmap_offset_bad_object(fd);
+
+	igt_describe("Check buffer object mapping persists after gem_close");
+	igt_subtest_f("mmap-offset-basic")
+			mmap_offset_basic(fd);
+
+	igt_describe("Check race between close and mmap offset between threads");
+	igt_subtest_f("mmap-offset-close-race")
+			mmap_offset_close_race(fd);
+
+	igt_fixture {
+		close(fd);
+	}
+}
diff --git a/tests/meson.build b/tests/meson.build
index a909d271..ad55f697 100644
--- a/tests/meson.build
+++ b/tests/meson.build
@@ -174,6 +174,7 @@ i915_progs = [
 	'gem_media_vme',
 	'gem_mmap',
 	'gem_mmap_gtt',
+	'gem_mmap_offset',
 	'gem_mmap_offset_exhaustion',
 	'gem_mmap_wc',
 	'gem_partial_pwrite_pread',
-- 
2.23.0

_______________________________________________
igt-dev mailing list
igt-dev@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/igt-dev

^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [igt-dev] ✓ Fi.CI.BAT: success for Add GEM_MMAP_OFFSET support in IGT. (rev4)
  2019-11-26 17:25 [igt-dev] [PATCH i-g-t v4 0/3] Add GEM_MMAP_OFFSET support in IGT Zbigniew Kempczyński
                   ` (2 preceding siblings ...)
  2019-11-26 17:25 ` [igt-dev] [PATCH i-g-t v4 3/3] tests/i915/gem_mmap_offset: Add new API test for gem_mmap_offset Zbigniew Kempczyński
@ 2019-11-26 18:24 ` Patchwork
  2019-11-26 18:26   ` Chris Wilson
  2019-11-27  5:22 ` [igt-dev] ✗ Fi.CI.IGT: failure " Patchwork
                   ` (5 subsequent siblings)
  9 siblings, 1 reply; 29+ messages in thread
From: Patchwork @ 2019-11-26 18:24 UTC (permalink / raw)
  To: Zbigniew Kempczyński; +Cc: igt-dev

== Series Details ==

Series: Add GEM_MMAP_OFFSET support in IGT. (rev4)
URL   : https://patchwork.freedesktop.org/series/69973/
State : success

== Summary ==

CI Bug Log - changes from CI_DRM_7426 -> IGTPW_3761
====================================================

Summary
-------

  **SUCCESS**

  No regressions found.

  External URL: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_3761/index.html

Known issues
------------

  Here are the changes found in IGTPW_3761 that come from known issues:

### IGT changes ###

#### Issues hit ####

  * igt@i915_selftest@live_blt:
    - fi-hsw-peppy:       [PASS][1] -> [DMESG-FAIL][2] ([fdo#112147])
   [1]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_7426/fi-hsw-peppy/igt@i915_selftest@live_blt.html
   [2]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_3761/fi-hsw-peppy/igt@i915_selftest@live_blt.html

  * igt@kms_chamelium@dp-crc-fast:
    - fi-icl-u2:          [PASS][3] -> [FAIL][4] ([fdo#109635 ] / [fdo#110387])
   [3]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_7426/fi-icl-u2/igt@kms_chamelium@dp-crc-fast.html
   [4]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_3761/fi-icl-u2/igt@kms_chamelium@dp-crc-fast.html

  * igt@prime_self_import@basic-with_one_bo:
    - fi-icl-dsi:         [PASS][5] -> [DMESG-WARN][6] ([fdo#106107])
   [5]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_7426/fi-icl-dsi/igt@prime_self_import@basic-with_one_bo.html
   [6]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_3761/fi-icl-dsi/igt@prime_self_import@basic-with_one_bo.html

  
#### Warnings ####

  * igt@kms_cursor_legacy@basic-flip-after-cursor-legacy:
    - fi-kbl-x1275:       [DMESG-WARN][7] ([fdo#103558] / [fdo#105602] / [fdo#105763]) -> [DMESG-WARN][8] ([fdo#103558] / [fdo#105602]) +7 similar issues
   [7]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_7426/fi-kbl-x1275/igt@kms_cursor_legacy@basic-flip-after-cursor-legacy.html
   [8]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_3761/fi-kbl-x1275/igt@kms_cursor_legacy@basic-flip-after-cursor-legacy.html

  * igt@kms_flip@basic-flip-vs-modeset:
    - fi-kbl-x1275:       [DMESG-WARN][9] ([fdo#103558] / [fdo#105602]) -> [DMESG-WARN][10] ([fdo#103558] / [fdo#105602] / [fdo#105763]) +5 similar issues
   [9]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_7426/fi-kbl-x1275/igt@kms_flip@basic-flip-vs-modeset.html
   [10]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_3761/fi-kbl-x1275/igt@kms_flip@basic-flip-vs-modeset.html

  
  {name}: This element is suppressed. This means it is ignored when computing
          the status of the difference (SUCCESS, WARNING, or FAILURE).

  [fdo#103558]: https://bugs.freedesktop.org/show_bug.cgi?id=103558
  [fdo#105602]: https://bugs.freedesktop.org/show_bug.cgi?id=105602
  [fdo#105763]: https://bugs.freedesktop.org/show_bug.cgi?id=105763
  [fdo#106107]: https://bugs.freedesktop.org/show_bug.cgi?id=106107
  [fdo#109635 ]: https://bugs.freedesktop.org/show_bug.cgi?id=109635 
  [fdo#110387]: https://bugs.freedesktop.org/show_bug.cgi?id=110387
  [fdo#112147]: https://bugs.freedesktop.org/show_bug.cgi?id=112147
  [fdo#112261]: https://bugs.freedesktop.org/show_bug.cgi?id=112261


Participating hosts (49 -> 44)
------------------------------

  Additional (1): fi-whl-u 
  Missing    (6): fi-ilk-m540 fi-hsw-4200u fi-bsw-cyan fi-ctg-p8600 fi-byt-clapper fi-bdw-samus 


Build changes
-------------

  * CI: CI-20190529 -> None
  * IGT: IGT_5310 -> IGTPW_3761

  CI-20190529: 20190529
  CI_DRM_7426: b204d72d3485a148456e2077683974739b675b21 @ git://anongit.freedesktop.org/gfx-ci/linux
  IGTPW_3761: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_3761/index.html
  IGT_5310: d1ea62b3f759f10ff6860561ba82e5c4902511d3 @ git://anongit.freedesktop.org/xorg/app/intel-gpu-tools



== Testlist changes ==

+igt@gem_mmap_offset@mmap-offset-bad-object
+igt@gem_mmap_offset@mmap-offset-basic
+igt@gem_mmap_offset@mmap-offset-close-race

== Logs ==

For more details see: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_3761/index.html
_______________________________________________
igt-dev mailing list
igt-dev@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/igt-dev

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [igt-dev] ✓ Fi.CI.BAT: success for Add GEM_MMAP_OFFSET support in IGT. (rev4)
  2019-11-26 18:24 ` [igt-dev] ✓ Fi.CI.BAT: success for Add GEM_MMAP_OFFSET support in IGT. (rev4) Patchwork
@ 2019-11-26 18:26   ` Chris Wilson
  0 siblings, 0 replies; 29+ messages in thread
From: Chris Wilson @ 2019-11-26 18:26 UTC (permalink / raw)
  To: Zbigniew Kempczyński, Patchwork, igt-dev

Quoting Patchwork (2019-11-26 18:24:13)
> == Series Details ==
> 
> Series: Add GEM_MMAP_OFFSET support in IGT. (rev4)
> URL   : https://patchwork.freedesktop.org/series/69973/
> State : success
> 
> == Summary ==
> 
> CI Bug Log - changes from CI_DRM_7426 -> IGTPW_3761
> ====================================================
> 
> Summary
> -------
> 
>   **SUCCESS**
> 
>   No regressions found.
> 
>   External URL: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_3761/index.html

Of course it is behoven on us to reproduce the previous failures in a
testcase for posterity.
-Chris
_______________________________________________
igt-dev mailing list
igt-dev@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/igt-dev

^ permalink raw reply	[flat|nested] 29+ messages in thread

* [igt-dev] ✗ Fi.CI.IGT: failure for Add GEM_MMAP_OFFSET support in IGT. (rev4)
  2019-11-26 17:25 [igt-dev] [PATCH i-g-t v4 0/3] Add GEM_MMAP_OFFSET support in IGT Zbigniew Kempczyński
                   ` (3 preceding siblings ...)
  2019-11-26 18:24 ` [igt-dev] ✓ Fi.CI.BAT: success for Add GEM_MMAP_OFFSET support in IGT. (rev4) Patchwork
@ 2019-11-27  5:22 ` Patchwork
  2019-11-28 13:05 ` [igt-dev] ✗ GitLab.Pipeline: warning for Add GEM_MMAP_OFFSET support in IGT. (rev5) Patchwork
                   ` (4 subsequent siblings)
  9 siblings, 0 replies; 29+ messages in thread
From: Patchwork @ 2019-11-27  5:22 UTC (permalink / raw)
  To: Zbigniew Kempczyński; +Cc: igt-dev

== Series Details ==

Series: Add GEM_MMAP_OFFSET support in IGT. (rev4)
URL   : https://patchwork.freedesktop.org/series/69973/
State : failure

== Summary ==

CI Bug Log - changes from CI_DRM_7426_full -> IGTPW_3761_full
====================================================

Summary
-------

  **FAILURE**

  Serious unknown changes coming with IGTPW_3761_full absolutely need to be
  verified manually.
  
  If you think the reported changes have nothing to do with the changes
  introduced in IGTPW_3761_full, please notify your bug team to allow them
  to document this new failure mode, which will reduce false positives in CI.

  External URL: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_3761/index.html

Possible new issues
-------------------

  Here are the unknown changes that may have been introduced in IGTPW_3761_full:

### IGT changes ###

#### Possible regressions ####

  * igt@gem_ctx_persistence@rcs0-hostile-preempt:
    - shard-tglb:         NOTRUN -> [FAIL][1] +2 similar issues
   [1]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_3761/shard-tglb8/igt@gem_ctx_persistence@rcs0-hostile-preempt.html

  * igt@gem_ctx_persistence@vecs0-hostile-preempt:
    - shard-iclb:         NOTRUN -> [FAIL][2] +4 similar issues
   [2]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_3761/shard-iclb1/igt@gem_ctx_persistence@vecs0-hostile-preempt.html

  * {igt@gem_mmap_offset@mmap-offset-bad-object} (NEW):
    - shard-iclb:         NOTRUN -> [SKIP][3] +1 similar issue
   [3]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_3761/shard-iclb4/igt@gem_mmap_offset@mmap-offset-bad-object.html

  * {igt@gem_mmap_offset@mmap-offset-basic} (NEW):
    - shard-tglb:         NOTRUN -> [SKIP][4] +1 similar issue
   [4]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_3761/shard-tglb5/igt@gem_mmap_offset@mmap-offset-basic.html

  * igt@gem_tiled_wb:
    - shard-tglb:         [PASS][5] -> [FAIL][6]
   [5]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_7426/shard-tglb6/igt@gem_tiled_wb.html
   [6]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_3761/shard-tglb1/igt@gem_tiled_wb.html
    - shard-kbl:          [PASS][7] -> [FAIL][8] +1 similar issue
   [7]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_7426/shard-kbl4/igt@gem_tiled_wb.html
   [8]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_3761/shard-kbl3/igt@gem_tiled_wb.html
    - shard-hsw:          [PASS][9] -> [FAIL][10]
   [9]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_7426/shard-hsw7/igt@gem_tiled_wb.html
   [10]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_3761/shard-hsw5/igt@gem_tiled_wb.html

  * igt@gem_tiled_wc:
    - shard-glk:          [PASS][11] -> [FAIL][12] +1 similar issue
   [11]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_7426/shard-glk1/igt@gem_tiled_wc.html
   [12]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_3761/shard-glk1/igt@gem_tiled_wc.html
    - shard-apl:          [PASS][13] -> [FAIL][14] +1 similar issue
   [13]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_7426/shard-apl4/igt@gem_tiled_wc.html
   [14]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_3761/shard-apl1/igt@gem_tiled_wc.html
    - shard-hsw:          NOTRUN -> [FAIL][15]
   [15]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_3761/shard-hsw2/igt@gem_tiled_wc.html
    - shard-snb:          [PASS][16] -> [FAIL][17] +1 similar issue
   [16]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_7426/shard-snb5/igt@gem_tiled_wc.html
   [17]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_3761/shard-snb1/igt@gem_tiled_wc.html

  
New tests
---------

  New tests have been introduced between CI_DRM_7426_full and IGTPW_3761_full:

### New IGT tests (3) ###

  * igt@gem_mmap_offset@mmap-offset-bad-object:
    - Statuses : 5 skip(s)
    - Exec time: [0.0] s

  * igt@gem_mmap_offset@mmap-offset-basic:
    - Statuses : 7 skip(s)
    - Exec time: [0.0] s

  * igt@gem_mmap_offset@mmap-offset-close-race:
    - Statuses : 6 skip(s)
    - Exec time: [0.0] s

  

Known issues
------------

  Here are the changes found in IGTPW_3761_full that come from known issues:

### IGT changes ###

#### Issues hit ####

  * igt@gem_ctx_shared@q-smoketest-blt:
    - shard-tglb:         [PASS][18] -> [INCOMPLETE][19] ([fdo#111735])
   [18]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_7426/shard-tglb7/igt@gem_ctx_shared@q-smoketest-blt.html
   [19]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_3761/shard-tglb6/igt@gem_ctx_shared@q-smoketest-blt.html

  * igt@gem_exec_schedule@preempt-bsd:
    - shard-iclb:         [PASS][20] -> [SKIP][21] ([fdo#112146]) +1 similar issue
   [20]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_7426/shard-iclb8/igt@gem_exec_schedule@preempt-bsd.html
   [21]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_3761/shard-iclb1/igt@gem_exec_schedule@preempt-bsd.html

  * igt@gem_persistent_relocs@forked-interruptible-thrash-inactive:
    - shard-hsw:          [PASS][22] -> [FAIL][23] ([fdo#112037])
   [22]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_7426/shard-hsw8/igt@gem_persistent_relocs@forked-interruptible-thrash-inactive.html
   [23]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_3761/shard-hsw2/igt@gem_persistent_relocs@forked-interruptible-thrash-inactive.html

  * igt@gem_ppgtt@flink-and-close-vma-leak:
    - shard-glk:          [PASS][24] -> [FAIL][25] ([fdo#112392])
   [24]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_7426/shard-glk3/igt@gem_ppgtt@flink-and-close-vma-leak.html
   [25]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_3761/shard-glk5/igt@gem_ppgtt@flink-and-close-vma-leak.html

  * igt@gem_userptr_blits@sync-unmap-cycles:
    - shard-snb:          [PASS][26] -> [DMESG-WARN][27] ([fdo#111870]) +1 similar issue
   [26]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_7426/shard-snb2/igt@gem_userptr_blits@sync-unmap-cycles.html
   [27]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_3761/shard-snb4/igt@gem_userptr_blits@sync-unmap-cycles.html
    - shard-hsw:          [PASS][28] -> [DMESG-WARN][29] ([fdo#111870]) +1 similar issue
   [28]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_7426/shard-hsw5/igt@gem_userptr_blits@sync-unmap-cycles.html
   [29]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_3761/shard-hsw2/igt@gem_userptr_blits@sync-unmap-cycles.html

  * igt@gem_workarounds@suspend-resume-context:
    - shard-tglb:         [PASS][30] -> [INCOMPLETE][31] ([fdo#111832] / [fdo#111850])
   [30]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_7426/shard-tglb6/igt@gem_workarounds@suspend-resume-context.html
   [31]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_3761/shard-tglb3/igt@gem_workarounds@suspend-resume-context.html

  * igt@kms_cursor_crc@pipe-a-cursor-256x256-sliding:
    - shard-apl:          [PASS][32] -> [FAIL][33] ([fdo#103232])
   [32]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_7426/shard-apl6/igt@kms_cursor_crc@pipe-a-cursor-256x256-sliding.html
   [33]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_3761/shard-apl4/igt@kms_cursor_crc@pipe-a-cursor-256x256-sliding.html
    - shard-kbl:          [PASS][34] -> [FAIL][35] ([fdo#103232])
   [34]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_7426/shard-kbl7/igt@kms_cursor_crc@pipe-a-cursor-256x256-sliding.html
   [35]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_3761/shard-kbl1/igt@kms_cursor_crc@pipe-a-cursor-256x256-sliding.html

  * igt@kms_flip@flip-vs-suspend-interruptible:
    - shard-tglb:         [PASS][36] -> [INCOMPLETE][37] ([fdo#111832] / [fdo#111850] / [fdo#112031])
   [36]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_7426/shard-tglb6/igt@kms_flip@flip-vs-suspend-interruptible.html
   [37]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_3761/shard-tglb5/igt@kms_flip@flip-vs-suspend-interruptible.html

  * igt@kms_frontbuffer_tracking@fbc-2p-scndscrn-cur-indfb-draw-blt:
    - shard-glk:          [PASS][38] -> [FAIL][39] ([fdo#103167])
   [38]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_7426/shard-glk2/igt@kms_frontbuffer_tracking@fbc-2p-scndscrn-cur-indfb-draw-blt.html
   [39]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_3761/shard-glk2/igt@kms_frontbuffer_tracking@fbc-2p-scndscrn-cur-indfb-draw-blt.html

  * igt@kms_frontbuffer_tracking@fbc-rgb565-draw-mmap-cpu:
    - shard-tglb:         [PASS][40] -> [FAIL][41] ([fdo#103167]) +1 similar issue
   [40]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_7426/shard-tglb3/igt@kms_frontbuffer_tracking@fbc-rgb565-draw-mmap-cpu.html
   [41]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_3761/shard-tglb4/igt@kms_frontbuffer_tracking@fbc-rgb565-draw-mmap-cpu.html

  * igt@kms_frontbuffer_tracking@fbc-suspend:
    - shard-kbl:          [PASS][42] -> [DMESG-WARN][43] ([fdo#108566]) +5 similar issues
   [42]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_7426/shard-kbl3/igt@kms_frontbuffer_tracking@fbc-suspend.html
   [43]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_3761/shard-kbl7/igt@kms_frontbuffer_tracking@fbc-suspend.html

  * igt@kms_frontbuffer_tracking@fbcpsr-suspend:
    - shard-tglb:         [PASS][44] -> [INCOMPLETE][45] ([fdo#111832] / [fdo#111850] / [fdo#111884])
   [44]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_7426/shard-tglb6/igt@kms_frontbuffer_tracking@fbcpsr-suspend.html
   [45]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_3761/shard-tglb3/igt@kms_frontbuffer_tracking@fbcpsr-suspend.html

  * igt@kms_plane@pixel-format-pipe-a-planes-source-clamping:
    - shard-kbl:          [PASS][46] -> [INCOMPLETE][47] ([fdo#103665])
   [46]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_7426/shard-kbl2/igt@kms_plane@pixel-format-pipe-a-planes-source-clamping.html
   [47]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_3761/shard-kbl4/igt@kms_plane@pixel-format-pipe-a-planes-source-clamping.html

  * igt@kms_plane@plane-panning-bottom-right-suspend-pipe-a-planes:
    - shard-apl:          [PASS][48] -> [DMESG-WARN][49] ([fdo#108566]) +1 similar issue
   [48]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_7426/shard-apl7/igt@kms_plane@plane-panning-bottom-right-suspend-pipe-a-planes.html
   [49]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_3761/shard-apl6/igt@kms_plane@plane-panning-bottom-right-suspend-pipe-a-planes.html

  
#### Possible fixes ####

  * igt@drm_import_export@import-close-race-prime:
    - shard-hsw:          [INCOMPLETE][50] ([fdo#103540]) -> [PASS][51]
   [50]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_7426/shard-hsw2/igt@drm_import_export@import-close-race-prime.html
   [51]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_3761/shard-hsw8/igt@drm_import_export@import-close-race-prime.html

  * igt@gem_ctx_isolation@vcs1-s3:
    - shard-tglb:         [INCOMPLETE][52] ([fdo#111832]) -> [PASS][53]
   [52]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_7426/shard-tglb5/igt@gem_ctx_isolation@vcs1-s3.html
   [53]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_3761/shard-tglb6/igt@gem_ctx_isolation@vcs1-s3.html

  * igt@gem_ctx_persistence@smoketest:
    - shard-glk:          [TIMEOUT][54] -> [PASS][55]
   [54]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_7426/shard-glk7/igt@gem_ctx_persistence@smoketest.html
   [55]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_3761/shard-glk5/igt@gem_ctx_persistence@smoketest.html

  * igt@gem_ctx_switch@vcs1-heavy-queue:
    - shard-iclb:         [SKIP][56] ([fdo#112080]) -> [PASS][57] +1 similar issue
   [56]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_7426/shard-iclb8/igt@gem_ctx_switch@vcs1-heavy-queue.html
   [57]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_3761/shard-iclb4/igt@gem_ctx_switch@vcs1-heavy-queue.html

  * igt@gem_eio@in-flight-suspend:
    - shard-tglb:         [INCOMPLETE][58] ([fdo#111832] / [fdo#111850] / [fdo#112081]) -> [PASS][59]
   [58]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_7426/shard-tglb2/igt@gem_eio@in-flight-suspend.html
   [59]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_3761/shard-tglb1/igt@gem_eio@in-flight-suspend.html

  * igt@gem_exec_schedule@preempt-queue-bsd2:
    - shard-iclb:         [SKIP][60] ([fdo#109276]) -> [PASS][61] +4 similar issues
   [60]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_7426/shard-iclb3/igt@gem_exec_schedule@preempt-queue-bsd2.html
   [61]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_3761/shard-iclb4/igt@gem_exec_schedule@preempt-queue-bsd2.html

  * igt@gem_persistent_relocs@forked-interruptible-faulting-reloc-thrash-inactive:
    - shard-hsw:          [TIMEOUT][62] ([fdo#112068 ]) -> [PASS][63]
   [62]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_7426/shard-hsw2/igt@gem_persistent_relocs@forked-interruptible-faulting-reloc-thrash-inactive.html
   [63]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_3761/shard-hsw6/igt@gem_persistent_relocs@forked-interruptible-faulting-reloc-thrash-inactive.html

  * igt@gem_ppgtt@flink-and-close-vma-leak:
    - shard-kbl:          [FAIL][64] ([fdo#112392]) -> [PASS][65]
   [64]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_7426/shard-kbl4/igt@gem_ppgtt@flink-and-close-vma-leak.html
   [65]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_3761/shard-kbl3/igt@gem_ppgtt@flink-and-close-vma-leak.html

  * igt@gem_userptr_blits@map-fixed-invalidate-busy-gup:
    - shard-snb:          [DMESG-WARN][66] ([fdo#111870]) -> [PASS][67] +3 similar issues
   [66]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_7426/shard-snb4/igt@gem_userptr_blits@map-fixed-invalidate-busy-gup.html
   [67]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_3761/shard-snb4/igt@gem_userptr_blits@map-fixed-invalidate-busy-gup.html

  * igt@gem_userptr_blits@map-fixed-invalidate-overlap-busy:
    - shard-hsw:          [DMESG-WARN][68] ([fdo#111870]) -> [PASS][69] +3 similar issues
   [68]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_7426/shard-hsw4/igt@gem_userptr_blits@map-fixed-invalidate-overlap-busy.html
   [69]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_3761/shard-hsw2/igt@gem_userptr_blits@map-fixed-invalidate-overlap-busy.html

  * igt@kms_cursor_crc@pipe-c-cursor-128x128-onscreen:
    - shard-kbl:          [FAIL][70] ([fdo#103232]) -> [PASS][71] +1 similar issue
   [70]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_7426/shard-kbl1/igt@kms_cursor_crc@pipe-c-cursor-128x128-onscreen.html
   [71]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_3761/shard-kbl4/igt@kms_cursor_crc@pipe-c-cursor-128x128-onscreen.html
    - shard-apl:          [FAIL][72] ([fdo#103232]) -> [PASS][73] +1 similar issue
   [72]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_7426/shard-apl1/igt@kms_cursor_crc@pipe-c-cursor-128x128-onscreen.html
   [73]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_3761/shard-apl6/igt@kms_cursor_crc@pipe-c-cursor-128x128-onscreen.html
    - shard-glk:          [FAIL][74] ([fdo#103232]) -> [PASS][75]
   [74]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_7426/shard-glk4/igt@kms_cursor_crc@pipe-c-cursor-128x128-onscreen.html
   [75]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_3761/shard-glk5/igt@kms_cursor_crc@pipe-c-cursor-128x128-onscreen.html

  * igt@kms_cursor_legacy@cursor-vs-flip-varying-size:
    - shard-hsw:          [FAIL][76] ([fdo#103355]) -> [PASS][77]
   [76]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_7426/shard-hsw5/igt@kms_cursor_legacy@cursor-vs-flip-varying-size.html
   [77]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_3761/shard-hsw7/igt@kms_cursor_legacy@cursor-vs-flip-varying-size.html

  * igt@kms_flip@flip-vs-suspend-interruptible:
    - shard-apl:          [DMESG-WARN][78] ([fdo#108566]) -> [PASS][79] +1 similar issue
   [78]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_7426/shard-apl4/igt@kms_flip@flip-vs-suspend-interruptible.html
   [79]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_3761/shard-apl2/igt@kms_flip@flip-vs-suspend-interruptible.html

  * igt@kms_frontbuffer_tracking@fbc-1p-primscrn-cur-indfb-draw-pwrite:
    - shard-tglb:         [INCOMPLETE][80] ([fdo#111884]) -> [PASS][81]
   [80]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_7426/shard-tglb4/igt@kms_frontbuffer_tracking@fbc-1p-primscrn-cur-indfb-draw-pwrite.html
   [81]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_3761/shard-tglb6/igt@kms_frontbuffer_tracking@fbc-1p-primscrn-cur-indfb-draw-pwrite.html

  * igt@kms_frontbuffer_tracking@fbc-1p-primscrn-indfb-msflip-blt:
    - shard-tglb:         [FAIL][82] ([fdo#103167]) -> [PASS][83] +1 similar issue
   [82]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_7426/shard-tglb3/igt@kms_frontbuffer_tracking@fbc-1p-primscrn-indfb-msflip-blt.html
   [83]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_3761/shard-tglb6/igt@kms_frontbuffer_tracking@fbc-1p-primscrn-indfb-msflip-blt.html

  * igt@kms_frontbuffer_tracking@fbc-indfb-scaledprimary:
    - shard-kbl:          [INCOMPLETE][84] ([fdo#103665]) -> [PASS][85] +1 similar issue
   [84]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_7426/shard-kbl7/igt@kms_frontbuffer_tracking@fbc-indfb-scaledprimary.html
   [85]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_3761/shard-kbl1/igt@kms_frontbuffer_tracking@fbc-indfb-scaledprimary.html

  * igt@kms_frontbuffer_tracking@fbcpsr-1p-primscrn-pri-indfb-draw-pwrite:
    - shard-iclb:         [FAIL][86] ([fdo#103167]) -> [PASS][87] +1 similar issue
   [86]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_7426/shard-iclb8/igt@kms_frontbuffer_tracking@fbcpsr-1p-primscrn-pri-indfb-draw-pwrite.html
   [87]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_3761/shard-iclb1/igt@kms_frontbuffer_tracking@fbcpsr-1p-primscrn-pri-indfb-draw-pwrite.html

  * igt@kms_setmode@basic:
    - shard-kbl:          [FAIL][88] ([fdo#99912]) -> [PASS][89]
   [88]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_7426/shard-kbl2/igt@kms_setmode@basic.html
   [89]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_3761/shard-kbl7/igt@kms_setmode@basic.html

  * igt@kms_vblank@pipe-a-ts-continuation-suspend:
    - shard-kbl:          [DMESG-WARN][90] ([fdo#108566]) -> [PASS][91] +8 similar issues
   [90]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_7426/shard-kbl4/igt@kms_vblank@pipe-a-ts-continuation-suspend.html
   [91]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_3761/shard-kbl3/igt@kms_vblank@pipe-a-ts-continuation-suspend.html

  
#### Warnings ####

  * igt@kms_frontbuffer_tracking@fbc-1p-primscrn-spr-indfb-move:
    - shard-tglb:         [INCOMPLETE][92] ([fdo#111884]) -> [FAIL][93] ([fdo#103167])
   [92]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_7426/shard-tglb3/igt@kms_frontbuffer_tracking@fbc-1p-primscrn-spr-indfb-move.html
   [93]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_3761/shard-tglb1/igt@kms_frontbuffer_tracking@fbc-1p-primscrn-spr-indfb-move.html

  
  {name}: This element is suppressed. This means it is ignored when computing
          the status of the difference (SUCCESS, WARNING, or FAILURE).

  [fdo#103167]: https://bugs.freedesktop.org/show_bug.cgi?id=103167
  [fdo#103232]: https://bugs.freedesktop.org/show_bug.cgi?id=103232
  [fdo#103355]: https://bugs.freedesktop.org/show_bug.cgi?id=103355
  [fdo#103540]: https://bugs.freedesktop.org/show_bug.cgi?id=103540
  [fdo#103665]: https://bugs.freedesktop.org/show_bug.cgi?id=103665
  [fdo#108566]: https://bugs.freedesktop.org/show_bug.cgi?id=108566
  [fdo#109276]: https://bugs.freedesktop.org/show_bug.cgi?id=109276
  [fdo#111735]: https://bugs.freedesktop.org/show_bug.cgi?id=111735
  [fdo#111832]: https://bugs.freedesktop.org/show_bug.cgi?id=111832
  [fdo#111850]: https://bugs.freedesktop.org/show_bug.cgi?id=111850
  [fdo#111870]: https://bugs.freedesktop.org/show_bug.cgi?id=111870
  [fdo#111884]: https://bugs.freedesktop.org/show_bug.cgi?id=111884
  [fdo#112031]: https://bugs.freedesktop.org/show_bug.cgi?id=112031
  [fdo#112037]: https://bugs.freedesktop.org/show_bug.cgi?id=112037
  [fdo#112068 ]: https://bugs.freedesktop.org/show_bug.cgi?id=112068 
  [fdo#112080]: https://bugs.freedesktop.org/show_bug.cgi?id=112080
  [fdo#112081]: https://bugs.freedesktop.org/show_bug.cgi?id=112081
  [fdo#112146]: https://bugs.freedesktop.org/show_bug.cgi?id=112146
  [fdo#112271]: https://bugs.freedesktop.org/show_bug.cgi?id=112271
  [fdo#112392]: https://bugs.freedesktop.org/show_bug.cgi?id=112392
  [fdo#99912]: https://bugs.freedesktop.org/show_bug.cgi?id=

== Logs ==

For more details see: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_3761/index.html
_______________________________________________
igt-dev mailing list
igt-dev@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/igt-dev

^ permalink raw reply	[flat|nested] 29+ messages in thread

* [PATCH i-g-t] tests/i915/gem_mmap_offset: Add new API test for gem_mmap_offset
@ 2019-11-28 12:55     ` Chris Wilson
  0 siblings, 0 replies; 29+ messages in thread
From: Chris Wilson @ 2019-11-28 12:55 UTC (permalink / raw)
  To: intel-gfx; +Cc: igt-dev

From: Lukasz Kalamarz <lukasz.kalamarz@intel.com>

Few simple tests which tries to create / mmap buffer objects
using GEM_MMAP_OFFSET uAPI.

v2: change from WC -> WB (according to Chris review comment)
v3: add mmap-offset-close-race test

Signed-off-by: Lukasz Kalamarz <lukasz.kalamarz@intel.com>
Signed-off-by: Zbigniew Kempczyński <zbigniew.kempczynski@intel.com>
Cc: Chris Wilson <chris@chris-wilson.co.uk>
Cc: Vanshidhar Konda <vanshidhar.r.konda@intel.com>
---
Required (look to gem_mmap_(gtt,wc,cpu) for ideas):
 size - check we can handle objects beyond a reasonable limit (note the
kernel fails at beyond RAM)
 forked - interactions with pagefault + new mmap_offsets across
          threads/processes
 suspend - check speed is consistent before/after suspend
 coherency - combinatorial checker between all pointer types, prw and gpu
---
 tests/Makefile.sources       |   3 +
 tests/i915/gem_mmap_offset.c | 416 +++++++++++++++++++++++++++++++++++
 tests/meson.build            |   1 +
 3 files changed, 420 insertions(+)
 create mode 100644 tests/i915/gem_mmap_offset.c

diff --git a/tests/Makefile.sources b/tests/Makefile.sources
index a211851cf..ddbc69bc8 100644
--- a/tests/Makefile.sources
+++ b/tests/Makefile.sources
@@ -325,6 +325,9 @@ gem_mmap_SOURCES = i915/gem_mmap.c
 TESTS_progs += gem_mmap_gtt
 gem_mmap_gtt_SOURCES = i915/gem_mmap_gtt.c
 
+TESTS_progs += gem_mmap_offset
+gem_mmap_offset_SOURCES = i915/gem_mmap_offset.c
+
 TESTS_progs += gem_mmap_offset_exhaustion
 gem_mmap_offset_exhaustion_SOURCES = i915/gem_mmap_offset_exhaustion.c
 
diff --git a/tests/i915/gem_mmap_offset.c b/tests/i915/gem_mmap_offset.c
new file mode 100644
index 000000000..e75c3fd17
--- /dev/null
+++ b/tests/i915/gem_mmap_offset.c
@@ -0,0 +1,416 @@
+/*
+ * Copyright © 2019 Intel Corporation
+ *
+ * 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 (including the next
+ * paragraph) 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 <errno.h>
+#include <pthread.h>
+#include <stdatomic.h>
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+#include "drm.h"
+
+#include "igt.h"
+#include "igt_x86.h"
+
+IGT_TEST_DESCRIPTION("Basic MMAP_OFFSET IOCTL tests for mem regions\n");
+
+static const struct mmap_offset {
+	const char *name;
+	unsigned int type;
+	unsigned int domain;
+} mmap_offset_types[] = {
+	{ "gtt", I915_MMAP_OFFSET_GTT, I915_GEM_DOMAIN_GTT },
+	{ "wb", I915_MMAP_OFFSET_WB, I915_GEM_DOMAIN_CPU },
+	{ "wc", I915_MMAP_OFFSET_WC, I915_GEM_DOMAIN_WC },
+	{ "uc", I915_MMAP_OFFSET_UC, I915_GEM_DOMAIN_WC },
+	{},
+};
+
+#define for_each_mmap_offset_type(__t) \
+	for (const struct mmap_offset *__t = mmap_offset_types; \
+	     (__t)->name; \
+	     (__t)++)
+
+static int mmap_offset_ioctl(int i915, struct drm_i915_gem_mmap_offset *arg)
+{
+	int err = 0;
+
+	if (igt_ioctl(i915, DRM_IOCTL_I915_GEM_MMAP_OFFSET, arg)) {
+		err = -errno;
+		igt_assume(err);
+	}
+
+	errno = 0;
+	return err;
+}
+
+static void bad_object(int i915)
+{
+	uint32_t real_handle;
+	uint32_t handles[20];
+	int i = 0;
+
+	real_handle = gem_create(i915, 4096);
+
+	handles[i++] = 0xdeadbeef;
+	for (int bit = 0; bit < 16; bit++)
+		handles[i++] = real_handle | (1 << (bit + 16));
+	handles[i] = real_handle + 1;
+
+	for (; i >= 0; i--) {
+		struct drm_i915_gem_mmap_offset arg = {
+			.handle = handles[i],
+			.flags = I915_MMAP_OFFSET_WB,
+		};
+
+		igt_debug("Trying MMAP IOCTL with handle %x\n",
+			  handles[i]);
+		igt_assert_eq(mmap_offset_ioctl(i915, &arg),
+			      -ENOENT);
+	}
+
+	gem_close(i915, real_handle);
+}
+
+static void bad_flags(int i915)
+{
+	struct drm_i915_gem_mmap_offset arg = {
+		.handle = gem_create(i915, 4096),
+		.flags = -1ull,
+	};
+
+	igt_assert_eq(mmap_offset_ioctl(i915, &arg), -EINVAL);
+	gem_close(i915, arg.handle);
+}
+
+static void basic_uaf(int i915)
+{
+	const uint32_t obj_size = 4096;
+
+	for_each_mmap_offset_type(t) {
+		uint32_t handle = gem_create(i915, obj_size);
+		uint8_t *expected, *buf, *addr;
+
+		addr = __gem_mmap_offset(i915, handle, 0, obj_size,
+					 PROT_READ | PROT_WRITE,
+					 t->type);
+		if (!addr) {
+			gem_close(i915, handle);
+			continue;
+		}
+
+		expected = calloc(obj_size, sizeof(*expected));
+		gem_set_domain(i915, handle, t->domain, 0);
+		igt_assert_f(memcmp(addr, expected, obj_size) == 0,
+			     "mmap(%s) not clear on gem_create()\n",
+			     t->name);
+		free(expected);
+
+		buf = calloc(obj_size, sizeof(*buf));
+		memset(buf + 1024, 0x01, 1024);
+		gem_write(i915, handle, 0, buf, obj_size);
+		gem_set_domain(i915, handle, t->domain, 0);
+		igt_assert_f(memcmp(buf, addr, obj_size) == 0,
+			     "mmap(%s) not coherent with gem_write()\n",
+			     t->name);
+
+		gem_set_domain(i915, handle, t->domain, t->domain);
+		memset(addr + 2048, 0xff, 1024);
+		gem_read(i915, handle, 0, buf, obj_size);
+		gem_set_domain(i915, handle, t->domain, 0);
+		igt_assert_f(memcmp(buf, addr, obj_size) == 0,
+			     "mmap(%s) not coherent with gem_read()\n",
+			     t->name);
+
+		gem_close(i915, handle);
+		igt_assert_f(memcmp(buf, addr, obj_size) == 0,
+			     "mmap(%s) not resident after gem_close()\n",
+			     t->name);
+		free(buf);
+
+		igt_debug("Testing unmapping\n");
+		munmap(addr, obj_size);
+	}
+}
+
+static void isolation(int i915)
+{
+	for_each_mmap_offset_type(t) {
+		struct drm_i915_gem_mmap_offset mmap_arg = {
+			.flags = t->type
+		};
+		int A = gem_reopen_driver(i915);
+		int B = gem_reopen_driver(i915);
+		uint64_t offset_a, offset_b;
+		uint32_t a, b;
+		void *ptr;
+
+		a = gem_create(A, 4096);
+		b = gem_open(B, gem_flink(A, a));
+
+		mmap_arg.handle = a;
+		igt_assert_eq(mmap_offset_ioctl(i915, &mmap_arg), 0);
+		offset_a = mmap_arg.offset;
+
+		mmap_arg.handle = b;
+		igt_assert_eq(mmap_offset_ioctl(i915, &mmap_arg), 0);
+		offset_b = mmap_arg.offset;
+
+		igt_info("A[%s]: {fd:%d, handle:%d, offset:%"PRIx64"}\n",
+			 t->name, A, a, offset_a);
+		igt_info("B[%s]: {fd:%d, handle:%d, offset:%"PRIx64"}\n",
+			 t->name, B, b, offset_b);
+
+		close(B);
+
+		ptr = mmap64(0, 4096, PROT_READ, MAP_SHARED, A, offset_a);
+		igt_assert(ptr != MAP_FAILED);
+		munmap(ptr, 4096);
+
+		close(A);
+
+		ptr = mmap64(0, 4096, PROT_READ, MAP_SHARED, A, offset_a);
+		igt_assert(ptr == MAP_FAILED);
+	}
+}
+
+static void pf_nonblock(int i915)
+{
+	igt_spin_t *spin = igt_spin_new(i915);
+
+	for_each_mmap_offset_type(t) {
+		uint32_t *ptr;
+
+		ptr = __gem_mmap_offset(i915, spin->handle, 0, 4096,
+					PROT_READ | PROT_WRITE,
+					t->type);
+		if (!ptr)
+			continue;
+
+		igt_set_timeout(1, t->name);
+		/* no set-domain as we want to verify the pagefault is async */
+		ptr[256] = 0;
+		igt_reset_timeout();
+
+		munmap(ptr, 4096);
+	}
+
+	igt_spin_free(i915, spin);
+}
+
+static void close_race(int i915, int timeout)
+{
+	const int ncpus = sysconf(_SC_NPROCESSORS_ONLN);
+	_Atomic uint32_t *handles;
+	size_t len = ALIGN((ncpus + 1) * sizeof(uint32_t), 4096);
+
+	handles = mmap64(0, len, PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0);
+	igt_assert(handles != MAP_FAILED);
+
+	igt_fork(child, ncpus + 1) {
+		do {
+			struct drm_i915_gem_mmap_offset mmap_arg = {};
+			const int i = 1 + random() % ncpus;
+			uint32_t old;
+
+			mmap_arg.handle = gem_create(i915, 4096);
+			mmap_arg.flags = I915_MMAP_OFFSET_WB;
+			old = atomic_exchange(&handles[i], mmap_arg.handle);
+			ioctl(i915, DRM_IOCTL_GEM_CLOSE, &old);
+
+			if (ioctl(i915,
+				  DRM_IOCTL_I915_GEM_MMAP_OFFSET,
+				  &mmap_arg) != -1) {
+				void *ptr;
+
+				ptr = mmap64(0, 4096,
+					     PROT_WRITE, MAP_SHARED, i915,
+					     mmap_arg.offset);
+				if (ptr != MAP_FAILED) {
+					*(volatile uint32_t *)ptr = 0;
+					munmap(ptr, 4096);
+				}
+			}
+
+		} while (!READ_ONCE(handles[0]));
+	}
+
+	sleep(timeout);
+	handles[0] = 1;
+	igt_waitchildren();
+
+	for (int i = 1; i <= ncpus; i++)
+		ioctl(i915, DRM_IOCTL_GEM_CLOSE, handles[i]);
+	munmap(handles, len);
+}
+
+static uint64_t atomic_compare_swap_u64(_Atomic(uint64_t) *ptr,
+					uint64_t oldval, uint64_t newval)
+{
+	atomic_compare_exchange_strong(ptr, &oldval, newval);
+	return oldval;
+}
+
+static uint64_t get_npages(_Atomic(uint64_t) *global, uint64_t npages)
+{
+	uint64_t try, old, max;
+
+	max = *global;
+	do {
+		old = max;
+		try = 1 + npages % (max / 2);
+		max -= try;
+	} while ((max = atomic_compare_swap_u64(global, old, max)) != old);
+
+	return try;
+}
+
+struct thread_clear {
+	_Atomic(uint64_t) max;
+	int timeout;
+	int i915;
+};
+
+static int create_ioctl(int i915, struct drm_i915_gem_create *create)
+{
+	int err = 0;
+
+	if (igt_ioctl(i915, DRM_IOCTL_I915_GEM_CREATE, create)) {
+		err = -errno;
+		igt_assume(err != 0);
+	}
+
+	errno = 0;
+	return err;
+}
+
+static void *thread_clear(void *data)
+{
+	struct thread_clear *arg = data;
+	const struct mmap_offset *t;
+	unsigned long checked = 0;
+	int i915 = arg->i915;
+
+	t = mmap_offset_types;
+	igt_until_timeout(arg->timeout) {
+		struct drm_i915_gem_create create = {};
+		uint64_t npages;
+		void *ptr;
+
+		npages = random();
+		npages <<= 32;
+		npages |= random();
+		npages = get_npages(&arg->max, npages);
+		create.size = npages << 12;
+
+		create_ioctl(i915, &create);
+		ptr = __gem_mmap_offset(i915, create.handle, 0, create.size,
+					PROT_READ | PROT_WRITE,
+					t->type);
+		/* No set-domains as we are being as naughty as possible */
+		for (uint64_t page = 0; ptr && page < npages; page++) {
+			uint64_t x[8] = {
+				page * 4096 +
+					sizeof(x) * ((page % (4096 - sizeof(x)) / sizeof(x)))
+			};
+
+			if (page & 1)
+				igt_memcpy_from_wc(x, ptr + x[0], sizeof(x));
+			else
+				memcpy(x, ptr + x[0], sizeof(x));
+
+			for (int i = 0; i < ARRAY_SIZE(x); i++)
+				igt_assert_eq_u64(x[i], 0);
+		}
+		if (ptr)
+			munmap(ptr, create.size);
+		gem_close(i915, create.handle);
+		checked += npages;
+
+		atomic_fetch_add(&arg->max, npages);
+
+		if (!(++t)->name)
+			t = mmap_offset_types;
+	}
+
+	return (void *)(uintptr_t)checked;
+}
+
+static void always_clear(int i915, int timeout)
+{
+	struct thread_clear arg = {
+		.i915 = i915,
+		.timeout = timeout,
+		.max = intel_get_avail_ram_mb() << (20 - 12), /* in pages */
+	};
+	const int ncpus = sysconf(_SC_NPROCESSORS_ONLN);
+	unsigned long checked;
+	pthread_t thread[ncpus];
+	void *result;
+
+	for (int i = 0; i < ncpus; i++)
+		pthread_create(&thread[i], NULL, thread_clear, &arg);
+
+	checked = 0;
+	for (int i = 0; i < ncpus; i++) {
+		pthread_join(thread[i], &result);
+		checked += (uintptr_t)result;
+	}
+	igt_info("Checked %'lu page allocations\n", checked);
+}
+
+
+igt_main
+{
+	int i915;
+
+	igt_fixture {
+		i915 = drm_open_driver(DRIVER_INTEL);
+		gem_require_mmap_offset(i915);
+	}
+
+	igt_describe("Verify mapping to invalid gem objects won't be created");
+	igt_subtest_f("bad-object")
+		bad_object(i915);
+	igt_subtest_f("bad-flags")
+		bad_flags(i915);
+
+	igt_describe("Check buffer object mapping persists after gem_close");
+	igt_subtest_f("basic-uaf")
+		basic_uaf(i915);
+
+	igt_subtest_f("isolation")
+		isolation(i915);
+	igt_subtest_f("pf-nonblock")
+		pf_nonblock(i915);
+
+	igt_describe("Check race between close and mmap offset between threads");
+	igt_subtest_f("close-race")
+		close_race(i915, 20);
+
+	igt_subtest_f("clear")
+		always_clear(i915, 20);
+
+	igt_fixture {
+		close(i915);
+	}
+}
diff --git a/tests/meson.build b/tests/meson.build
index 18788d44b..05dea1f4e 100644
--- a/tests/meson.build
+++ b/tests/meson.build
@@ -174,6 +174,7 @@ i915_progs = [
 	'gem_media_vme',
 	'gem_mmap',
 	'gem_mmap_gtt',
+	'gem_mmap_offset',
 	'gem_mmap_offset_exhaustion',
 	'gem_mmap_wc',
 	'gem_partial_pwrite_pread',
-- 
2.24.0

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [Intel-gfx] [PATCH i-g-t] tests/i915/gem_mmap_offset: Add new API test for gem_mmap_offset
@ 2019-11-28 12:55     ` Chris Wilson
  0 siblings, 0 replies; 29+ messages in thread
From: Chris Wilson @ 2019-11-28 12:55 UTC (permalink / raw)
  To: intel-gfx; +Cc: igt-dev

From: Lukasz Kalamarz <lukasz.kalamarz@intel.com>

Few simple tests which tries to create / mmap buffer objects
using GEM_MMAP_OFFSET uAPI.

v2: change from WC -> WB (according to Chris review comment)
v3: add mmap-offset-close-race test

Signed-off-by: Lukasz Kalamarz <lukasz.kalamarz@intel.com>
Signed-off-by: Zbigniew Kempczyński <zbigniew.kempczynski@intel.com>
Cc: Chris Wilson <chris@chris-wilson.co.uk>
Cc: Vanshidhar Konda <vanshidhar.r.konda@intel.com>
---
Required (look to gem_mmap_(gtt,wc,cpu) for ideas):
 size - check we can handle objects beyond a reasonable limit (note the
kernel fails at beyond RAM)
 forked - interactions with pagefault + new mmap_offsets across
          threads/processes
 suspend - check speed is consistent before/after suspend
 coherency - combinatorial checker between all pointer types, prw and gpu
---
 tests/Makefile.sources       |   3 +
 tests/i915/gem_mmap_offset.c | 416 +++++++++++++++++++++++++++++++++++
 tests/meson.build            |   1 +
 3 files changed, 420 insertions(+)
 create mode 100644 tests/i915/gem_mmap_offset.c

diff --git a/tests/Makefile.sources b/tests/Makefile.sources
index a211851cf..ddbc69bc8 100644
--- a/tests/Makefile.sources
+++ b/tests/Makefile.sources
@@ -325,6 +325,9 @@ gem_mmap_SOURCES = i915/gem_mmap.c
 TESTS_progs += gem_mmap_gtt
 gem_mmap_gtt_SOURCES = i915/gem_mmap_gtt.c
 
+TESTS_progs += gem_mmap_offset
+gem_mmap_offset_SOURCES = i915/gem_mmap_offset.c
+
 TESTS_progs += gem_mmap_offset_exhaustion
 gem_mmap_offset_exhaustion_SOURCES = i915/gem_mmap_offset_exhaustion.c
 
diff --git a/tests/i915/gem_mmap_offset.c b/tests/i915/gem_mmap_offset.c
new file mode 100644
index 000000000..e75c3fd17
--- /dev/null
+++ b/tests/i915/gem_mmap_offset.c
@@ -0,0 +1,416 @@
+/*
+ * Copyright © 2019 Intel Corporation
+ *
+ * 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 (including the next
+ * paragraph) 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 <errno.h>
+#include <pthread.h>
+#include <stdatomic.h>
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+#include "drm.h"
+
+#include "igt.h"
+#include "igt_x86.h"
+
+IGT_TEST_DESCRIPTION("Basic MMAP_OFFSET IOCTL tests for mem regions\n");
+
+static const struct mmap_offset {
+	const char *name;
+	unsigned int type;
+	unsigned int domain;
+} mmap_offset_types[] = {
+	{ "gtt", I915_MMAP_OFFSET_GTT, I915_GEM_DOMAIN_GTT },
+	{ "wb", I915_MMAP_OFFSET_WB, I915_GEM_DOMAIN_CPU },
+	{ "wc", I915_MMAP_OFFSET_WC, I915_GEM_DOMAIN_WC },
+	{ "uc", I915_MMAP_OFFSET_UC, I915_GEM_DOMAIN_WC },
+	{},
+};
+
+#define for_each_mmap_offset_type(__t) \
+	for (const struct mmap_offset *__t = mmap_offset_types; \
+	     (__t)->name; \
+	     (__t)++)
+
+static int mmap_offset_ioctl(int i915, struct drm_i915_gem_mmap_offset *arg)
+{
+	int err = 0;
+
+	if (igt_ioctl(i915, DRM_IOCTL_I915_GEM_MMAP_OFFSET, arg)) {
+		err = -errno;
+		igt_assume(err);
+	}
+
+	errno = 0;
+	return err;
+}
+
+static void bad_object(int i915)
+{
+	uint32_t real_handle;
+	uint32_t handles[20];
+	int i = 0;
+
+	real_handle = gem_create(i915, 4096);
+
+	handles[i++] = 0xdeadbeef;
+	for (int bit = 0; bit < 16; bit++)
+		handles[i++] = real_handle | (1 << (bit + 16));
+	handles[i] = real_handle + 1;
+
+	for (; i >= 0; i--) {
+		struct drm_i915_gem_mmap_offset arg = {
+			.handle = handles[i],
+			.flags = I915_MMAP_OFFSET_WB,
+		};
+
+		igt_debug("Trying MMAP IOCTL with handle %x\n",
+			  handles[i]);
+		igt_assert_eq(mmap_offset_ioctl(i915, &arg),
+			      -ENOENT);
+	}
+
+	gem_close(i915, real_handle);
+}
+
+static void bad_flags(int i915)
+{
+	struct drm_i915_gem_mmap_offset arg = {
+		.handle = gem_create(i915, 4096),
+		.flags = -1ull,
+	};
+
+	igt_assert_eq(mmap_offset_ioctl(i915, &arg), -EINVAL);
+	gem_close(i915, arg.handle);
+}
+
+static void basic_uaf(int i915)
+{
+	const uint32_t obj_size = 4096;
+
+	for_each_mmap_offset_type(t) {
+		uint32_t handle = gem_create(i915, obj_size);
+		uint8_t *expected, *buf, *addr;
+
+		addr = __gem_mmap_offset(i915, handle, 0, obj_size,
+					 PROT_READ | PROT_WRITE,
+					 t->type);
+		if (!addr) {
+			gem_close(i915, handle);
+			continue;
+		}
+
+		expected = calloc(obj_size, sizeof(*expected));
+		gem_set_domain(i915, handle, t->domain, 0);
+		igt_assert_f(memcmp(addr, expected, obj_size) == 0,
+			     "mmap(%s) not clear on gem_create()\n",
+			     t->name);
+		free(expected);
+
+		buf = calloc(obj_size, sizeof(*buf));
+		memset(buf + 1024, 0x01, 1024);
+		gem_write(i915, handle, 0, buf, obj_size);
+		gem_set_domain(i915, handle, t->domain, 0);
+		igt_assert_f(memcmp(buf, addr, obj_size) == 0,
+			     "mmap(%s) not coherent with gem_write()\n",
+			     t->name);
+
+		gem_set_domain(i915, handle, t->domain, t->domain);
+		memset(addr + 2048, 0xff, 1024);
+		gem_read(i915, handle, 0, buf, obj_size);
+		gem_set_domain(i915, handle, t->domain, 0);
+		igt_assert_f(memcmp(buf, addr, obj_size) == 0,
+			     "mmap(%s) not coherent with gem_read()\n",
+			     t->name);
+
+		gem_close(i915, handle);
+		igt_assert_f(memcmp(buf, addr, obj_size) == 0,
+			     "mmap(%s) not resident after gem_close()\n",
+			     t->name);
+		free(buf);
+
+		igt_debug("Testing unmapping\n");
+		munmap(addr, obj_size);
+	}
+}
+
+static void isolation(int i915)
+{
+	for_each_mmap_offset_type(t) {
+		struct drm_i915_gem_mmap_offset mmap_arg = {
+			.flags = t->type
+		};
+		int A = gem_reopen_driver(i915);
+		int B = gem_reopen_driver(i915);
+		uint64_t offset_a, offset_b;
+		uint32_t a, b;
+		void *ptr;
+
+		a = gem_create(A, 4096);
+		b = gem_open(B, gem_flink(A, a));
+
+		mmap_arg.handle = a;
+		igt_assert_eq(mmap_offset_ioctl(i915, &mmap_arg), 0);
+		offset_a = mmap_arg.offset;
+
+		mmap_arg.handle = b;
+		igt_assert_eq(mmap_offset_ioctl(i915, &mmap_arg), 0);
+		offset_b = mmap_arg.offset;
+
+		igt_info("A[%s]: {fd:%d, handle:%d, offset:%"PRIx64"}\n",
+			 t->name, A, a, offset_a);
+		igt_info("B[%s]: {fd:%d, handle:%d, offset:%"PRIx64"}\n",
+			 t->name, B, b, offset_b);
+
+		close(B);
+
+		ptr = mmap64(0, 4096, PROT_READ, MAP_SHARED, A, offset_a);
+		igt_assert(ptr != MAP_FAILED);
+		munmap(ptr, 4096);
+
+		close(A);
+
+		ptr = mmap64(0, 4096, PROT_READ, MAP_SHARED, A, offset_a);
+		igt_assert(ptr == MAP_FAILED);
+	}
+}
+
+static void pf_nonblock(int i915)
+{
+	igt_spin_t *spin = igt_spin_new(i915);
+
+	for_each_mmap_offset_type(t) {
+		uint32_t *ptr;
+
+		ptr = __gem_mmap_offset(i915, spin->handle, 0, 4096,
+					PROT_READ | PROT_WRITE,
+					t->type);
+		if (!ptr)
+			continue;
+
+		igt_set_timeout(1, t->name);
+		/* no set-domain as we want to verify the pagefault is async */
+		ptr[256] = 0;
+		igt_reset_timeout();
+
+		munmap(ptr, 4096);
+	}
+
+	igt_spin_free(i915, spin);
+}
+
+static void close_race(int i915, int timeout)
+{
+	const int ncpus = sysconf(_SC_NPROCESSORS_ONLN);
+	_Atomic uint32_t *handles;
+	size_t len = ALIGN((ncpus + 1) * sizeof(uint32_t), 4096);
+
+	handles = mmap64(0, len, PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0);
+	igt_assert(handles != MAP_FAILED);
+
+	igt_fork(child, ncpus + 1) {
+		do {
+			struct drm_i915_gem_mmap_offset mmap_arg = {};
+			const int i = 1 + random() % ncpus;
+			uint32_t old;
+
+			mmap_arg.handle = gem_create(i915, 4096);
+			mmap_arg.flags = I915_MMAP_OFFSET_WB;
+			old = atomic_exchange(&handles[i], mmap_arg.handle);
+			ioctl(i915, DRM_IOCTL_GEM_CLOSE, &old);
+
+			if (ioctl(i915,
+				  DRM_IOCTL_I915_GEM_MMAP_OFFSET,
+				  &mmap_arg) != -1) {
+				void *ptr;
+
+				ptr = mmap64(0, 4096,
+					     PROT_WRITE, MAP_SHARED, i915,
+					     mmap_arg.offset);
+				if (ptr != MAP_FAILED) {
+					*(volatile uint32_t *)ptr = 0;
+					munmap(ptr, 4096);
+				}
+			}
+
+		} while (!READ_ONCE(handles[0]));
+	}
+
+	sleep(timeout);
+	handles[0] = 1;
+	igt_waitchildren();
+
+	for (int i = 1; i <= ncpus; i++)
+		ioctl(i915, DRM_IOCTL_GEM_CLOSE, handles[i]);
+	munmap(handles, len);
+}
+
+static uint64_t atomic_compare_swap_u64(_Atomic(uint64_t) *ptr,
+					uint64_t oldval, uint64_t newval)
+{
+	atomic_compare_exchange_strong(ptr, &oldval, newval);
+	return oldval;
+}
+
+static uint64_t get_npages(_Atomic(uint64_t) *global, uint64_t npages)
+{
+	uint64_t try, old, max;
+
+	max = *global;
+	do {
+		old = max;
+		try = 1 + npages % (max / 2);
+		max -= try;
+	} while ((max = atomic_compare_swap_u64(global, old, max)) != old);
+
+	return try;
+}
+
+struct thread_clear {
+	_Atomic(uint64_t) max;
+	int timeout;
+	int i915;
+};
+
+static int create_ioctl(int i915, struct drm_i915_gem_create *create)
+{
+	int err = 0;
+
+	if (igt_ioctl(i915, DRM_IOCTL_I915_GEM_CREATE, create)) {
+		err = -errno;
+		igt_assume(err != 0);
+	}
+
+	errno = 0;
+	return err;
+}
+
+static void *thread_clear(void *data)
+{
+	struct thread_clear *arg = data;
+	const struct mmap_offset *t;
+	unsigned long checked = 0;
+	int i915 = arg->i915;
+
+	t = mmap_offset_types;
+	igt_until_timeout(arg->timeout) {
+		struct drm_i915_gem_create create = {};
+		uint64_t npages;
+		void *ptr;
+
+		npages = random();
+		npages <<= 32;
+		npages |= random();
+		npages = get_npages(&arg->max, npages);
+		create.size = npages << 12;
+
+		create_ioctl(i915, &create);
+		ptr = __gem_mmap_offset(i915, create.handle, 0, create.size,
+					PROT_READ | PROT_WRITE,
+					t->type);
+		/* No set-domains as we are being as naughty as possible */
+		for (uint64_t page = 0; ptr && page < npages; page++) {
+			uint64_t x[8] = {
+				page * 4096 +
+					sizeof(x) * ((page % (4096 - sizeof(x)) / sizeof(x)))
+			};
+
+			if (page & 1)
+				igt_memcpy_from_wc(x, ptr + x[0], sizeof(x));
+			else
+				memcpy(x, ptr + x[0], sizeof(x));
+
+			for (int i = 0; i < ARRAY_SIZE(x); i++)
+				igt_assert_eq_u64(x[i], 0);
+		}
+		if (ptr)
+			munmap(ptr, create.size);
+		gem_close(i915, create.handle);
+		checked += npages;
+
+		atomic_fetch_add(&arg->max, npages);
+
+		if (!(++t)->name)
+			t = mmap_offset_types;
+	}
+
+	return (void *)(uintptr_t)checked;
+}
+
+static void always_clear(int i915, int timeout)
+{
+	struct thread_clear arg = {
+		.i915 = i915,
+		.timeout = timeout,
+		.max = intel_get_avail_ram_mb() << (20 - 12), /* in pages */
+	};
+	const int ncpus = sysconf(_SC_NPROCESSORS_ONLN);
+	unsigned long checked;
+	pthread_t thread[ncpus];
+	void *result;
+
+	for (int i = 0; i < ncpus; i++)
+		pthread_create(&thread[i], NULL, thread_clear, &arg);
+
+	checked = 0;
+	for (int i = 0; i < ncpus; i++) {
+		pthread_join(thread[i], &result);
+		checked += (uintptr_t)result;
+	}
+	igt_info("Checked %'lu page allocations\n", checked);
+}
+
+
+igt_main
+{
+	int i915;
+
+	igt_fixture {
+		i915 = drm_open_driver(DRIVER_INTEL);
+		gem_require_mmap_offset(i915);
+	}
+
+	igt_describe("Verify mapping to invalid gem objects won't be created");
+	igt_subtest_f("bad-object")
+		bad_object(i915);
+	igt_subtest_f("bad-flags")
+		bad_flags(i915);
+
+	igt_describe("Check buffer object mapping persists after gem_close");
+	igt_subtest_f("basic-uaf")
+		basic_uaf(i915);
+
+	igt_subtest_f("isolation")
+		isolation(i915);
+	igt_subtest_f("pf-nonblock")
+		pf_nonblock(i915);
+
+	igt_describe("Check race between close and mmap offset between threads");
+	igt_subtest_f("close-race")
+		close_race(i915, 20);
+
+	igt_subtest_f("clear")
+		always_clear(i915, 20);
+
+	igt_fixture {
+		close(i915);
+	}
+}
diff --git a/tests/meson.build b/tests/meson.build
index 18788d44b..05dea1f4e 100644
--- a/tests/meson.build
+++ b/tests/meson.build
@@ -174,6 +174,7 @@ i915_progs = [
 	'gem_media_vme',
 	'gem_mmap',
 	'gem_mmap_gtt',
+	'gem_mmap_offset',
 	'gem_mmap_offset_exhaustion',
 	'gem_mmap_wc',
 	'gem_partial_pwrite_pread',
-- 
2.24.0

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [igt-dev] [PATCH i-g-t] tests/i915/gem_mmap_offset: Add new API test for gem_mmap_offset
@ 2019-11-28 12:55     ` Chris Wilson
  0 siblings, 0 replies; 29+ messages in thread
From: Chris Wilson @ 2019-11-28 12:55 UTC (permalink / raw)
  To: intel-gfx; +Cc: igt-dev

From: Lukasz Kalamarz <lukasz.kalamarz@intel.com>

Few simple tests which tries to create / mmap buffer objects
using GEM_MMAP_OFFSET uAPI.

v2: change from WC -> WB (according to Chris review comment)
v3: add mmap-offset-close-race test

Signed-off-by: Lukasz Kalamarz <lukasz.kalamarz@intel.com>
Signed-off-by: Zbigniew Kempczyński <zbigniew.kempczynski@intel.com>
Cc: Chris Wilson <chris@chris-wilson.co.uk>
Cc: Vanshidhar Konda <vanshidhar.r.konda@intel.com>
---
Required (look to gem_mmap_(gtt,wc,cpu) for ideas):
 size - check we can handle objects beyond a reasonable limit (note the
kernel fails at beyond RAM)
 forked - interactions with pagefault + new mmap_offsets across
          threads/processes
 suspend - check speed is consistent before/after suspend
 coherency - combinatorial checker between all pointer types, prw and gpu
---
 tests/Makefile.sources       |   3 +
 tests/i915/gem_mmap_offset.c | 416 +++++++++++++++++++++++++++++++++++
 tests/meson.build            |   1 +
 3 files changed, 420 insertions(+)
 create mode 100644 tests/i915/gem_mmap_offset.c

diff --git a/tests/Makefile.sources b/tests/Makefile.sources
index a211851cf..ddbc69bc8 100644
--- a/tests/Makefile.sources
+++ b/tests/Makefile.sources
@@ -325,6 +325,9 @@ gem_mmap_SOURCES = i915/gem_mmap.c
 TESTS_progs += gem_mmap_gtt
 gem_mmap_gtt_SOURCES = i915/gem_mmap_gtt.c
 
+TESTS_progs += gem_mmap_offset
+gem_mmap_offset_SOURCES = i915/gem_mmap_offset.c
+
 TESTS_progs += gem_mmap_offset_exhaustion
 gem_mmap_offset_exhaustion_SOURCES = i915/gem_mmap_offset_exhaustion.c
 
diff --git a/tests/i915/gem_mmap_offset.c b/tests/i915/gem_mmap_offset.c
new file mode 100644
index 000000000..e75c3fd17
--- /dev/null
+++ b/tests/i915/gem_mmap_offset.c
@@ -0,0 +1,416 @@
+/*
+ * Copyright © 2019 Intel Corporation
+ *
+ * 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 (including the next
+ * paragraph) 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 <errno.h>
+#include <pthread.h>
+#include <stdatomic.h>
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+#include "drm.h"
+
+#include "igt.h"
+#include "igt_x86.h"
+
+IGT_TEST_DESCRIPTION("Basic MMAP_OFFSET IOCTL tests for mem regions\n");
+
+static const struct mmap_offset {
+	const char *name;
+	unsigned int type;
+	unsigned int domain;
+} mmap_offset_types[] = {
+	{ "gtt", I915_MMAP_OFFSET_GTT, I915_GEM_DOMAIN_GTT },
+	{ "wb", I915_MMAP_OFFSET_WB, I915_GEM_DOMAIN_CPU },
+	{ "wc", I915_MMAP_OFFSET_WC, I915_GEM_DOMAIN_WC },
+	{ "uc", I915_MMAP_OFFSET_UC, I915_GEM_DOMAIN_WC },
+	{},
+};
+
+#define for_each_mmap_offset_type(__t) \
+	for (const struct mmap_offset *__t = mmap_offset_types; \
+	     (__t)->name; \
+	     (__t)++)
+
+static int mmap_offset_ioctl(int i915, struct drm_i915_gem_mmap_offset *arg)
+{
+	int err = 0;
+
+	if (igt_ioctl(i915, DRM_IOCTL_I915_GEM_MMAP_OFFSET, arg)) {
+		err = -errno;
+		igt_assume(err);
+	}
+
+	errno = 0;
+	return err;
+}
+
+static void bad_object(int i915)
+{
+	uint32_t real_handle;
+	uint32_t handles[20];
+	int i = 0;
+
+	real_handle = gem_create(i915, 4096);
+
+	handles[i++] = 0xdeadbeef;
+	for (int bit = 0; bit < 16; bit++)
+		handles[i++] = real_handle | (1 << (bit + 16));
+	handles[i] = real_handle + 1;
+
+	for (; i >= 0; i--) {
+		struct drm_i915_gem_mmap_offset arg = {
+			.handle = handles[i],
+			.flags = I915_MMAP_OFFSET_WB,
+		};
+
+		igt_debug("Trying MMAP IOCTL with handle %x\n",
+			  handles[i]);
+		igt_assert_eq(mmap_offset_ioctl(i915, &arg),
+			      -ENOENT);
+	}
+
+	gem_close(i915, real_handle);
+}
+
+static void bad_flags(int i915)
+{
+	struct drm_i915_gem_mmap_offset arg = {
+		.handle = gem_create(i915, 4096),
+		.flags = -1ull,
+	};
+
+	igt_assert_eq(mmap_offset_ioctl(i915, &arg), -EINVAL);
+	gem_close(i915, arg.handle);
+}
+
+static void basic_uaf(int i915)
+{
+	const uint32_t obj_size = 4096;
+
+	for_each_mmap_offset_type(t) {
+		uint32_t handle = gem_create(i915, obj_size);
+		uint8_t *expected, *buf, *addr;
+
+		addr = __gem_mmap_offset(i915, handle, 0, obj_size,
+					 PROT_READ | PROT_WRITE,
+					 t->type);
+		if (!addr) {
+			gem_close(i915, handle);
+			continue;
+		}
+
+		expected = calloc(obj_size, sizeof(*expected));
+		gem_set_domain(i915, handle, t->domain, 0);
+		igt_assert_f(memcmp(addr, expected, obj_size) == 0,
+			     "mmap(%s) not clear on gem_create()\n",
+			     t->name);
+		free(expected);
+
+		buf = calloc(obj_size, sizeof(*buf));
+		memset(buf + 1024, 0x01, 1024);
+		gem_write(i915, handle, 0, buf, obj_size);
+		gem_set_domain(i915, handle, t->domain, 0);
+		igt_assert_f(memcmp(buf, addr, obj_size) == 0,
+			     "mmap(%s) not coherent with gem_write()\n",
+			     t->name);
+
+		gem_set_domain(i915, handle, t->domain, t->domain);
+		memset(addr + 2048, 0xff, 1024);
+		gem_read(i915, handle, 0, buf, obj_size);
+		gem_set_domain(i915, handle, t->domain, 0);
+		igt_assert_f(memcmp(buf, addr, obj_size) == 0,
+			     "mmap(%s) not coherent with gem_read()\n",
+			     t->name);
+
+		gem_close(i915, handle);
+		igt_assert_f(memcmp(buf, addr, obj_size) == 0,
+			     "mmap(%s) not resident after gem_close()\n",
+			     t->name);
+		free(buf);
+
+		igt_debug("Testing unmapping\n");
+		munmap(addr, obj_size);
+	}
+}
+
+static void isolation(int i915)
+{
+	for_each_mmap_offset_type(t) {
+		struct drm_i915_gem_mmap_offset mmap_arg = {
+			.flags = t->type
+		};
+		int A = gem_reopen_driver(i915);
+		int B = gem_reopen_driver(i915);
+		uint64_t offset_a, offset_b;
+		uint32_t a, b;
+		void *ptr;
+
+		a = gem_create(A, 4096);
+		b = gem_open(B, gem_flink(A, a));
+
+		mmap_arg.handle = a;
+		igt_assert_eq(mmap_offset_ioctl(i915, &mmap_arg), 0);
+		offset_a = mmap_arg.offset;
+
+		mmap_arg.handle = b;
+		igt_assert_eq(mmap_offset_ioctl(i915, &mmap_arg), 0);
+		offset_b = mmap_arg.offset;
+
+		igt_info("A[%s]: {fd:%d, handle:%d, offset:%"PRIx64"}\n",
+			 t->name, A, a, offset_a);
+		igt_info("B[%s]: {fd:%d, handle:%d, offset:%"PRIx64"}\n",
+			 t->name, B, b, offset_b);
+
+		close(B);
+
+		ptr = mmap64(0, 4096, PROT_READ, MAP_SHARED, A, offset_a);
+		igt_assert(ptr != MAP_FAILED);
+		munmap(ptr, 4096);
+
+		close(A);
+
+		ptr = mmap64(0, 4096, PROT_READ, MAP_SHARED, A, offset_a);
+		igt_assert(ptr == MAP_FAILED);
+	}
+}
+
+static void pf_nonblock(int i915)
+{
+	igt_spin_t *spin = igt_spin_new(i915);
+
+	for_each_mmap_offset_type(t) {
+		uint32_t *ptr;
+
+		ptr = __gem_mmap_offset(i915, spin->handle, 0, 4096,
+					PROT_READ | PROT_WRITE,
+					t->type);
+		if (!ptr)
+			continue;
+
+		igt_set_timeout(1, t->name);
+		/* no set-domain as we want to verify the pagefault is async */
+		ptr[256] = 0;
+		igt_reset_timeout();
+
+		munmap(ptr, 4096);
+	}
+
+	igt_spin_free(i915, spin);
+}
+
+static void close_race(int i915, int timeout)
+{
+	const int ncpus = sysconf(_SC_NPROCESSORS_ONLN);
+	_Atomic uint32_t *handles;
+	size_t len = ALIGN((ncpus + 1) * sizeof(uint32_t), 4096);
+
+	handles = mmap64(0, len, PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0);
+	igt_assert(handles != MAP_FAILED);
+
+	igt_fork(child, ncpus + 1) {
+		do {
+			struct drm_i915_gem_mmap_offset mmap_arg = {};
+			const int i = 1 + random() % ncpus;
+			uint32_t old;
+
+			mmap_arg.handle = gem_create(i915, 4096);
+			mmap_arg.flags = I915_MMAP_OFFSET_WB;
+			old = atomic_exchange(&handles[i], mmap_arg.handle);
+			ioctl(i915, DRM_IOCTL_GEM_CLOSE, &old);
+
+			if (ioctl(i915,
+				  DRM_IOCTL_I915_GEM_MMAP_OFFSET,
+				  &mmap_arg) != -1) {
+				void *ptr;
+
+				ptr = mmap64(0, 4096,
+					     PROT_WRITE, MAP_SHARED, i915,
+					     mmap_arg.offset);
+				if (ptr != MAP_FAILED) {
+					*(volatile uint32_t *)ptr = 0;
+					munmap(ptr, 4096);
+				}
+			}
+
+		} while (!READ_ONCE(handles[0]));
+	}
+
+	sleep(timeout);
+	handles[0] = 1;
+	igt_waitchildren();
+
+	for (int i = 1; i <= ncpus; i++)
+		ioctl(i915, DRM_IOCTL_GEM_CLOSE, handles[i]);
+	munmap(handles, len);
+}
+
+static uint64_t atomic_compare_swap_u64(_Atomic(uint64_t) *ptr,
+					uint64_t oldval, uint64_t newval)
+{
+	atomic_compare_exchange_strong(ptr, &oldval, newval);
+	return oldval;
+}
+
+static uint64_t get_npages(_Atomic(uint64_t) *global, uint64_t npages)
+{
+	uint64_t try, old, max;
+
+	max = *global;
+	do {
+		old = max;
+		try = 1 + npages % (max / 2);
+		max -= try;
+	} while ((max = atomic_compare_swap_u64(global, old, max)) != old);
+
+	return try;
+}
+
+struct thread_clear {
+	_Atomic(uint64_t) max;
+	int timeout;
+	int i915;
+};
+
+static int create_ioctl(int i915, struct drm_i915_gem_create *create)
+{
+	int err = 0;
+
+	if (igt_ioctl(i915, DRM_IOCTL_I915_GEM_CREATE, create)) {
+		err = -errno;
+		igt_assume(err != 0);
+	}
+
+	errno = 0;
+	return err;
+}
+
+static void *thread_clear(void *data)
+{
+	struct thread_clear *arg = data;
+	const struct mmap_offset *t;
+	unsigned long checked = 0;
+	int i915 = arg->i915;
+
+	t = mmap_offset_types;
+	igt_until_timeout(arg->timeout) {
+		struct drm_i915_gem_create create = {};
+		uint64_t npages;
+		void *ptr;
+
+		npages = random();
+		npages <<= 32;
+		npages |= random();
+		npages = get_npages(&arg->max, npages);
+		create.size = npages << 12;
+
+		create_ioctl(i915, &create);
+		ptr = __gem_mmap_offset(i915, create.handle, 0, create.size,
+					PROT_READ | PROT_WRITE,
+					t->type);
+		/* No set-domains as we are being as naughty as possible */
+		for (uint64_t page = 0; ptr && page < npages; page++) {
+			uint64_t x[8] = {
+				page * 4096 +
+					sizeof(x) * ((page % (4096 - sizeof(x)) / sizeof(x)))
+			};
+
+			if (page & 1)
+				igt_memcpy_from_wc(x, ptr + x[0], sizeof(x));
+			else
+				memcpy(x, ptr + x[0], sizeof(x));
+
+			for (int i = 0; i < ARRAY_SIZE(x); i++)
+				igt_assert_eq_u64(x[i], 0);
+		}
+		if (ptr)
+			munmap(ptr, create.size);
+		gem_close(i915, create.handle);
+		checked += npages;
+
+		atomic_fetch_add(&arg->max, npages);
+
+		if (!(++t)->name)
+			t = mmap_offset_types;
+	}
+
+	return (void *)(uintptr_t)checked;
+}
+
+static void always_clear(int i915, int timeout)
+{
+	struct thread_clear arg = {
+		.i915 = i915,
+		.timeout = timeout,
+		.max = intel_get_avail_ram_mb() << (20 - 12), /* in pages */
+	};
+	const int ncpus = sysconf(_SC_NPROCESSORS_ONLN);
+	unsigned long checked;
+	pthread_t thread[ncpus];
+	void *result;
+
+	for (int i = 0; i < ncpus; i++)
+		pthread_create(&thread[i], NULL, thread_clear, &arg);
+
+	checked = 0;
+	for (int i = 0; i < ncpus; i++) {
+		pthread_join(thread[i], &result);
+		checked += (uintptr_t)result;
+	}
+	igt_info("Checked %'lu page allocations\n", checked);
+}
+
+
+igt_main
+{
+	int i915;
+
+	igt_fixture {
+		i915 = drm_open_driver(DRIVER_INTEL);
+		gem_require_mmap_offset(i915);
+	}
+
+	igt_describe("Verify mapping to invalid gem objects won't be created");
+	igt_subtest_f("bad-object")
+		bad_object(i915);
+	igt_subtest_f("bad-flags")
+		bad_flags(i915);
+
+	igt_describe("Check buffer object mapping persists after gem_close");
+	igt_subtest_f("basic-uaf")
+		basic_uaf(i915);
+
+	igt_subtest_f("isolation")
+		isolation(i915);
+	igt_subtest_f("pf-nonblock")
+		pf_nonblock(i915);
+
+	igt_describe("Check race between close and mmap offset between threads");
+	igt_subtest_f("close-race")
+		close_race(i915, 20);
+
+	igt_subtest_f("clear")
+		always_clear(i915, 20);
+
+	igt_fixture {
+		close(i915);
+	}
+}
diff --git a/tests/meson.build b/tests/meson.build
index 18788d44b..05dea1f4e 100644
--- a/tests/meson.build
+++ b/tests/meson.build
@@ -174,6 +174,7 @@ i915_progs = [
 	'gem_media_vme',
 	'gem_mmap',
 	'gem_mmap_gtt',
+	'gem_mmap_offset',
 	'gem_mmap_offset_exhaustion',
 	'gem_mmap_wc',
 	'gem_partial_pwrite_pread',
-- 
2.24.0

_______________________________________________
igt-dev mailing list
igt-dev@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/igt-dev

^ permalink raw reply related	[flat|nested] 29+ messages in thread

* Re: [PATCH i-g-t] tests/i915/gem_mmap_offset: Add new API test for gem_mmap_offset
@ 2019-11-28 12:59       ` Chris Wilson
  0 siblings, 0 replies; 29+ messages in thread
From: Chris Wilson @ 2019-11-28 12:59 UTC (permalink / raw)
  To: intel-gfx; +Cc: igt-dev

Quoting Chris Wilson (2019-11-28 12:55:02)
> +static void isolation(int i915)
> +{
> +       for_each_mmap_offset_type(t) {
> +               struct drm_i915_gem_mmap_offset mmap_arg = {
> +                       .flags = t->type
> +               };
> +               int A = gem_reopen_driver(i915);
> +               int B = gem_reopen_driver(i915);
> +               uint64_t offset_a, offset_b;
> +               uint32_t a, b;
> +               void *ptr;
> +
> +               a = gem_create(A, 4096);
> +               b = gem_open(B, gem_flink(A, a));
> +
> +               mmap_arg.handle = a;
> +               igt_assert_eq(mmap_offset_ioctl(i915, &mmap_arg), 0);

First ioctl should skip if type is not supported.

> +               offset_a = mmap_arg.offset;
> +
> +               mmap_arg.handle = b;
> +               igt_assert_eq(mmap_offset_ioctl(i915, &mmap_arg), 0);

Then second must succeed.
-Chris
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [Intel-gfx] [PATCH i-g-t] tests/i915/gem_mmap_offset: Add new API test for gem_mmap_offset
@ 2019-11-28 12:59       ` Chris Wilson
  0 siblings, 0 replies; 29+ messages in thread
From: Chris Wilson @ 2019-11-28 12:59 UTC (permalink / raw)
  To: intel-gfx; +Cc: igt-dev

Quoting Chris Wilson (2019-11-28 12:55:02)
> +static void isolation(int i915)
> +{
> +       for_each_mmap_offset_type(t) {
> +               struct drm_i915_gem_mmap_offset mmap_arg = {
> +                       .flags = t->type
> +               };
> +               int A = gem_reopen_driver(i915);
> +               int B = gem_reopen_driver(i915);
> +               uint64_t offset_a, offset_b;
> +               uint32_t a, b;
> +               void *ptr;
> +
> +               a = gem_create(A, 4096);
> +               b = gem_open(B, gem_flink(A, a));
> +
> +               mmap_arg.handle = a;
> +               igt_assert_eq(mmap_offset_ioctl(i915, &mmap_arg), 0);

First ioctl should skip if type is not supported.

> +               offset_a = mmap_arg.offset;
> +
> +               mmap_arg.handle = b;
> +               igt_assert_eq(mmap_offset_ioctl(i915, &mmap_arg), 0);

Then second must succeed.
-Chris
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [igt-dev] [PATCH i-g-t] tests/i915/gem_mmap_offset: Add new API test for gem_mmap_offset
@ 2019-11-28 12:59       ` Chris Wilson
  0 siblings, 0 replies; 29+ messages in thread
From: Chris Wilson @ 2019-11-28 12:59 UTC (permalink / raw)
  To: intel-gfx; +Cc: igt-dev

Quoting Chris Wilson (2019-11-28 12:55:02)
> +static void isolation(int i915)
> +{
> +       for_each_mmap_offset_type(t) {
> +               struct drm_i915_gem_mmap_offset mmap_arg = {
> +                       .flags = t->type
> +               };
> +               int A = gem_reopen_driver(i915);
> +               int B = gem_reopen_driver(i915);
> +               uint64_t offset_a, offset_b;
> +               uint32_t a, b;
> +               void *ptr;
> +
> +               a = gem_create(A, 4096);
> +               b = gem_open(B, gem_flink(A, a));
> +
> +               mmap_arg.handle = a;
> +               igt_assert_eq(mmap_offset_ioctl(i915, &mmap_arg), 0);

First ioctl should skip if type is not supported.

> +               offset_a = mmap_arg.offset;
> +
> +               mmap_arg.handle = b;
> +               igt_assert_eq(mmap_offset_ioctl(i915, &mmap_arg), 0);

Then second must succeed.
-Chris
_______________________________________________
igt-dev mailing list
igt-dev@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/igt-dev

^ permalink raw reply	[flat|nested] 29+ messages in thread

* [PATCH i-g-t] tests/i915/gem_mmap_offset: Add new API test for gem_mmap_offset
@ 2019-11-28 13:05     ` Chris Wilson
  0 siblings, 0 replies; 29+ messages in thread
From: Chris Wilson @ 2019-11-28 13:05 UTC (permalink / raw)
  To: intel-gfx; +Cc: igt-dev

From: Lukasz Kalamarz <lukasz.kalamarz@intel.com>

Few simple tests which tries to create / mmap buffer objects
using GEM_MMAP_OFFSET uAPI.

v2: change from WC -> WB (according to Chris review comment)
v3: add mmap-offset-close-race test

Signed-off-by: Lukasz Kalamarz <lukasz.kalamarz@intel.com>
Signed-off-by: Zbigniew Kempczyński <zbigniew.kempczynski@intel.com>
Cc: Chris Wilson <chris@chris-wilson.co.uk>
Cc: Vanshidhar Konda <vanshidhar.r.konda@intel.com>
---
Required (look to gem_mmap_(gtt,wc,cpu) for ideas):
 size - check we can handle objects beyond a reasonable limit (note the
kernel fails at beyond RAM)
 forked - interactions with pagefault + new mmap_offsets across
          threads/processes
 suspend - check speed is consistent before/after suspend
 coherency - combinatorial checker between all pointer types, prw and gpu
---
 tests/Makefile.sources       |   3 +
 tests/i915/gem_mmap_offset.c | 420 +++++++++++++++++++++++++++++++++++
 tests/meson.build            |   1 +
 3 files changed, 424 insertions(+)
 create mode 100644 tests/i915/gem_mmap_offset.c

diff --git a/tests/Makefile.sources b/tests/Makefile.sources
index a211851cf..ddbc69bc8 100644
--- a/tests/Makefile.sources
+++ b/tests/Makefile.sources
@@ -325,6 +325,9 @@ gem_mmap_SOURCES = i915/gem_mmap.c
 TESTS_progs += gem_mmap_gtt
 gem_mmap_gtt_SOURCES = i915/gem_mmap_gtt.c
 
+TESTS_progs += gem_mmap_offset
+gem_mmap_offset_SOURCES = i915/gem_mmap_offset.c
+
 TESTS_progs += gem_mmap_offset_exhaustion
 gem_mmap_offset_exhaustion_SOURCES = i915/gem_mmap_offset_exhaustion.c
 
diff --git a/tests/i915/gem_mmap_offset.c b/tests/i915/gem_mmap_offset.c
new file mode 100644
index 000000000..f0ffc3cd9
--- /dev/null
+++ b/tests/i915/gem_mmap_offset.c
@@ -0,0 +1,420 @@
+/*
+ * Copyright © 2019 Intel Corporation
+ *
+ * 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 (including the next
+ * paragraph) 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 <errno.h>
+#include <pthread.h>
+#include <stdatomic.h>
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+#include "drm.h"
+
+#include "igt.h"
+#include "igt_x86.h"
+
+IGT_TEST_DESCRIPTION("Basic MMAP_OFFSET IOCTL tests for mem regions\n");
+
+static const struct mmap_offset {
+	const char *name;
+	unsigned int type;
+	unsigned int domain;
+} mmap_offset_types[] = {
+	{ "gtt", I915_MMAP_OFFSET_GTT, I915_GEM_DOMAIN_GTT },
+	{ "wb", I915_MMAP_OFFSET_WB, I915_GEM_DOMAIN_CPU },
+	{ "wc", I915_MMAP_OFFSET_WC, I915_GEM_DOMAIN_WC },
+	{ "uc", I915_MMAP_OFFSET_UC, I915_GEM_DOMAIN_WC },
+	{},
+};
+
+#define for_each_mmap_offset_type(__t) \
+	for (const struct mmap_offset *__t = mmap_offset_types; \
+	     (__t)->name; \
+	     (__t)++)
+
+static int mmap_offset_ioctl(int i915, struct drm_i915_gem_mmap_offset *arg)
+{
+	int err = 0;
+
+	if (igt_ioctl(i915, DRM_IOCTL_I915_GEM_MMAP_OFFSET, arg)) {
+		err = -errno;
+		igt_assume(err);
+	}
+
+	errno = 0;
+	return err;
+}
+
+static void bad_object(int i915)
+{
+	uint32_t real_handle;
+	uint32_t handles[20];
+	int i = 0;
+
+	real_handle = gem_create(i915, 4096);
+
+	handles[i++] = 0xdeadbeef;
+	for (int bit = 0; bit < 16; bit++)
+		handles[i++] = real_handle | (1 << (bit + 16));
+	handles[i] = real_handle + 1;
+
+	for (; i >= 0; i--) {
+		struct drm_i915_gem_mmap_offset arg = {
+			.handle = handles[i],
+			.flags = I915_MMAP_OFFSET_WB,
+		};
+
+		igt_debug("Trying MMAP IOCTL with handle %x\n",
+			  handles[i]);
+		igt_assert_eq(mmap_offset_ioctl(i915, &arg),
+			      -ENOENT);
+	}
+
+	gem_close(i915, real_handle);
+}
+
+static void bad_flags(int i915)
+{
+	struct drm_i915_gem_mmap_offset arg = {
+		.handle = gem_create(i915, 4096),
+		.flags = -1ull,
+	};
+
+	igt_assert_eq(mmap_offset_ioctl(i915, &arg), -EINVAL);
+	gem_close(i915, arg.handle);
+}
+
+static void basic_uaf(int i915)
+{
+	const uint32_t obj_size = 4096;
+
+	for_each_mmap_offset_type(t) {
+		uint32_t handle = gem_create(i915, obj_size);
+		uint8_t *expected, *buf, *addr;
+
+		addr = __gem_mmap_offset(i915, handle, 0, obj_size,
+					 PROT_READ | PROT_WRITE,
+					 t->type);
+		if (!addr) {
+			gem_close(i915, handle);
+			continue;
+		}
+
+		expected = calloc(obj_size, sizeof(*expected));
+		gem_set_domain(i915, handle, t->domain, 0);
+		igt_assert_f(memcmp(addr, expected, obj_size) == 0,
+			     "mmap(%s) not clear on gem_create()\n",
+			     t->name);
+		free(expected);
+
+		buf = calloc(obj_size, sizeof(*buf));
+		memset(buf + 1024, 0x01, 1024);
+		gem_write(i915, handle, 0, buf, obj_size);
+		gem_set_domain(i915, handle, t->domain, 0);
+		igt_assert_f(memcmp(buf, addr, obj_size) == 0,
+			     "mmap(%s) not coherent with gem_write()\n",
+			     t->name);
+
+		gem_set_domain(i915, handle, t->domain, t->domain);
+		memset(addr + 2048, 0xff, 1024);
+		gem_read(i915, handle, 0, buf, obj_size);
+		gem_set_domain(i915, handle, t->domain, 0);
+		igt_assert_f(memcmp(buf, addr, obj_size) == 0,
+			     "mmap(%s) not coherent with gem_read()\n",
+			     t->name);
+
+		gem_close(i915, handle);
+		igt_assert_f(memcmp(buf, addr, obj_size) == 0,
+			     "mmap(%s) not resident after gem_close()\n",
+			     t->name);
+		free(buf);
+
+		igt_debug("Testing unmapping\n");
+		munmap(addr, obj_size);
+	}
+}
+
+static void isolation(int i915)
+{
+	for_each_mmap_offset_type(t) {
+		struct drm_i915_gem_mmap_offset mmap_arg = {
+			.flags = t->type
+		};
+		int A = gem_reopen_driver(i915);
+		int B = gem_reopen_driver(i915);
+		uint64_t offset_a, offset_b;
+		uint32_t a, b;
+		void *ptr;
+
+		a = gem_create(A, 4096);
+		b = gem_open(B, gem_flink(A, a));
+
+		mmap_arg.handle = a;
+		if (mmap_offset_ioctl(i915, &mmap_arg)) {
+			close(A);
+			close(B);
+			continue;
+		}
+		offset_a = mmap_arg.offset;
+
+		mmap_arg.handle = b;
+		igt_assert_eq(mmap_offset_ioctl(i915, &mmap_arg), 0);
+		offset_b = mmap_arg.offset;
+
+		igt_info("A[%s]: {fd:%d, handle:%d, offset:%"PRIx64"}\n",
+			 t->name, A, a, offset_a);
+		igt_info("B[%s]: {fd:%d, handle:%d, offset:%"PRIx64"}\n",
+			 t->name, B, b, offset_b);
+
+		close(B);
+
+		ptr = mmap64(0, 4096, PROT_READ, MAP_SHARED, A, offset_a);
+		igt_assert(ptr != MAP_FAILED);
+		munmap(ptr, 4096);
+
+		close(A);
+
+		ptr = mmap64(0, 4096, PROT_READ, MAP_SHARED, A, offset_a);
+		igt_assert(ptr == MAP_FAILED);
+	}
+}
+
+static void pf_nonblock(int i915)
+{
+	igt_spin_t *spin = igt_spin_new(i915);
+
+	for_each_mmap_offset_type(t) {
+		uint32_t *ptr;
+
+		ptr = __gem_mmap_offset(i915, spin->handle, 0, 4096,
+					PROT_READ | PROT_WRITE,
+					t->type);
+		if (!ptr)
+			continue;
+
+		igt_set_timeout(1, t->name);
+		/* no set-domain as we want to verify the pagefault is async */
+		ptr[256] = 0;
+		igt_reset_timeout();
+
+		munmap(ptr, 4096);
+	}
+
+	igt_spin_free(i915, spin);
+}
+
+static void close_race(int i915, int timeout)
+{
+	const int ncpus = sysconf(_SC_NPROCESSORS_ONLN);
+	_Atomic uint32_t *handles;
+	size_t len = ALIGN((ncpus + 1) * sizeof(uint32_t), 4096);
+
+	handles = mmap64(0, len, PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0);
+	igt_assert(handles != MAP_FAILED);
+
+	igt_fork(child, ncpus + 1) {
+		do {
+			struct drm_i915_gem_mmap_offset mmap_arg = {};
+			const int i = 1 + random() % ncpus;
+			uint32_t old;
+
+			mmap_arg.handle = gem_create(i915, 4096);
+			mmap_arg.flags = I915_MMAP_OFFSET_WB;
+			old = atomic_exchange(&handles[i], mmap_arg.handle);
+			ioctl(i915, DRM_IOCTL_GEM_CLOSE, &old);
+
+			if (ioctl(i915,
+				  DRM_IOCTL_I915_GEM_MMAP_OFFSET,
+				  &mmap_arg) != -1) {
+				void *ptr;
+
+				ptr = mmap64(0, 4096,
+					     PROT_WRITE, MAP_SHARED, i915,
+					     mmap_arg.offset);
+				if (ptr != MAP_FAILED) {
+					*(volatile uint32_t *)ptr = 0;
+					munmap(ptr, 4096);
+				}
+			}
+
+		} while (!READ_ONCE(handles[0]));
+	}
+
+	sleep(timeout);
+	handles[0] = 1;
+	igt_waitchildren();
+
+	for (int i = 1; i <= ncpus; i++)
+		ioctl(i915, DRM_IOCTL_GEM_CLOSE, handles[i]);
+	munmap(handles, len);
+}
+
+static uint64_t atomic_compare_swap_u64(_Atomic(uint64_t) *ptr,
+					uint64_t oldval, uint64_t newval)
+{
+	atomic_compare_exchange_strong(ptr, &oldval, newval);
+	return oldval;
+}
+
+static uint64_t get_npages(_Atomic(uint64_t) *global, uint64_t npages)
+{
+	uint64_t try, old, max;
+
+	max = *global;
+	do {
+		old = max;
+		try = 1 + npages % (max / 2);
+		max -= try;
+	} while ((max = atomic_compare_swap_u64(global, old, max)) != old);
+
+	return try;
+}
+
+struct thread_clear {
+	_Atomic(uint64_t) max;
+	int timeout;
+	int i915;
+};
+
+static int create_ioctl(int i915, struct drm_i915_gem_create *create)
+{
+	int err = 0;
+
+	if (igt_ioctl(i915, DRM_IOCTL_I915_GEM_CREATE, create)) {
+		err = -errno;
+		igt_assume(err != 0);
+	}
+
+	errno = 0;
+	return err;
+}
+
+static void *thread_clear(void *data)
+{
+	struct thread_clear *arg = data;
+	const struct mmap_offset *t;
+	unsigned long checked = 0;
+	int i915 = arg->i915;
+
+	t = mmap_offset_types;
+	igt_until_timeout(arg->timeout) {
+		struct drm_i915_gem_create create = {};
+		uint64_t npages;
+		void *ptr;
+
+		npages = random();
+		npages <<= 32;
+		npages |= random();
+		npages = get_npages(&arg->max, npages);
+		create.size = npages << 12;
+
+		create_ioctl(i915, &create);
+		ptr = __gem_mmap_offset(i915, create.handle, 0, create.size,
+					PROT_READ | PROT_WRITE,
+					t->type);
+		/* No set-domains as we are being as naughty as possible */
+		for (uint64_t page = 0; ptr && page < npages; page++) {
+			uint64_t x[8] = {
+				page * 4096 +
+					sizeof(x) * ((page % (4096 - sizeof(x)) / sizeof(x)))
+			};
+
+			if (page & 1)
+				igt_memcpy_from_wc(x, ptr + x[0], sizeof(x));
+			else
+				memcpy(x, ptr + x[0], sizeof(x));
+
+			for (int i = 0; i < ARRAY_SIZE(x); i++)
+				igt_assert_eq_u64(x[i], 0);
+		}
+		if (ptr)
+			munmap(ptr, create.size);
+		gem_close(i915, create.handle);
+		checked += npages;
+
+		atomic_fetch_add(&arg->max, npages);
+
+		if (!(++t)->name)
+			t = mmap_offset_types;
+	}
+
+	return (void *)(uintptr_t)checked;
+}
+
+static void always_clear(int i915, int timeout)
+{
+	struct thread_clear arg = {
+		.i915 = i915,
+		.timeout = timeout,
+		.max = intel_get_avail_ram_mb() << (20 - 12), /* in pages */
+	};
+	const int ncpus = sysconf(_SC_NPROCESSORS_ONLN);
+	unsigned long checked;
+	pthread_t thread[ncpus];
+	void *result;
+
+	for (int i = 0; i < ncpus; i++)
+		pthread_create(&thread[i], NULL, thread_clear, &arg);
+
+	checked = 0;
+	for (int i = 0; i < ncpus; i++) {
+		pthread_join(thread[i], &result);
+		checked += (uintptr_t)result;
+	}
+	igt_info("Checked %'lu page allocations\n", checked);
+}
+
+
+igt_main
+{
+	int i915;
+
+	igt_fixture {
+		i915 = drm_open_driver(DRIVER_INTEL);
+		gem_require_mmap_offset(i915);
+	}
+
+	igt_describe("Verify mapping to invalid gem objects won't be created");
+	igt_subtest_f("bad-object")
+		bad_object(i915);
+	igt_subtest_f("bad-flags")
+		bad_flags(i915);
+
+	igt_describe("Check buffer object mapping persists after gem_close");
+	igt_subtest_f("basic-uaf")
+		basic_uaf(i915);
+
+	igt_subtest_f("isolation")
+		isolation(i915);
+	igt_subtest_f("pf-nonblock")
+		pf_nonblock(i915);
+
+	igt_describe("Check race between close and mmap offset between threads");
+	igt_subtest_f("close-race")
+		close_race(i915, 20);
+
+	igt_subtest_f("clear")
+		always_clear(i915, 20);
+
+	igt_fixture {
+		close(i915);
+	}
+}
diff --git a/tests/meson.build b/tests/meson.build
index 18788d44b..05dea1f4e 100644
--- a/tests/meson.build
+++ b/tests/meson.build
@@ -174,6 +174,7 @@ i915_progs = [
 	'gem_media_vme',
 	'gem_mmap',
 	'gem_mmap_gtt',
+	'gem_mmap_offset',
 	'gem_mmap_offset_exhaustion',
 	'gem_mmap_wc',
 	'gem_partial_pwrite_pread',
-- 
2.24.0

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [Intel-gfx] [PATCH i-g-t] tests/i915/gem_mmap_offset: Add new API test for gem_mmap_offset
@ 2019-11-28 13:05     ` Chris Wilson
  0 siblings, 0 replies; 29+ messages in thread
From: Chris Wilson @ 2019-11-28 13:05 UTC (permalink / raw)
  To: intel-gfx; +Cc: igt-dev

From: Lukasz Kalamarz <lukasz.kalamarz@intel.com>

Few simple tests which tries to create / mmap buffer objects
using GEM_MMAP_OFFSET uAPI.

v2: change from WC -> WB (according to Chris review comment)
v3: add mmap-offset-close-race test

Signed-off-by: Lukasz Kalamarz <lukasz.kalamarz@intel.com>
Signed-off-by: Zbigniew Kempczyński <zbigniew.kempczynski@intel.com>
Cc: Chris Wilson <chris@chris-wilson.co.uk>
Cc: Vanshidhar Konda <vanshidhar.r.konda@intel.com>
---
Required (look to gem_mmap_(gtt,wc,cpu) for ideas):
 size - check we can handle objects beyond a reasonable limit (note the
kernel fails at beyond RAM)
 forked - interactions with pagefault + new mmap_offsets across
          threads/processes
 suspend - check speed is consistent before/after suspend
 coherency - combinatorial checker between all pointer types, prw and gpu
---
 tests/Makefile.sources       |   3 +
 tests/i915/gem_mmap_offset.c | 420 +++++++++++++++++++++++++++++++++++
 tests/meson.build            |   1 +
 3 files changed, 424 insertions(+)
 create mode 100644 tests/i915/gem_mmap_offset.c

diff --git a/tests/Makefile.sources b/tests/Makefile.sources
index a211851cf..ddbc69bc8 100644
--- a/tests/Makefile.sources
+++ b/tests/Makefile.sources
@@ -325,6 +325,9 @@ gem_mmap_SOURCES = i915/gem_mmap.c
 TESTS_progs += gem_mmap_gtt
 gem_mmap_gtt_SOURCES = i915/gem_mmap_gtt.c
 
+TESTS_progs += gem_mmap_offset
+gem_mmap_offset_SOURCES = i915/gem_mmap_offset.c
+
 TESTS_progs += gem_mmap_offset_exhaustion
 gem_mmap_offset_exhaustion_SOURCES = i915/gem_mmap_offset_exhaustion.c
 
diff --git a/tests/i915/gem_mmap_offset.c b/tests/i915/gem_mmap_offset.c
new file mode 100644
index 000000000..f0ffc3cd9
--- /dev/null
+++ b/tests/i915/gem_mmap_offset.c
@@ -0,0 +1,420 @@
+/*
+ * Copyright © 2019 Intel Corporation
+ *
+ * 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 (including the next
+ * paragraph) 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 <errno.h>
+#include <pthread.h>
+#include <stdatomic.h>
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+#include "drm.h"
+
+#include "igt.h"
+#include "igt_x86.h"
+
+IGT_TEST_DESCRIPTION("Basic MMAP_OFFSET IOCTL tests for mem regions\n");
+
+static const struct mmap_offset {
+	const char *name;
+	unsigned int type;
+	unsigned int domain;
+} mmap_offset_types[] = {
+	{ "gtt", I915_MMAP_OFFSET_GTT, I915_GEM_DOMAIN_GTT },
+	{ "wb", I915_MMAP_OFFSET_WB, I915_GEM_DOMAIN_CPU },
+	{ "wc", I915_MMAP_OFFSET_WC, I915_GEM_DOMAIN_WC },
+	{ "uc", I915_MMAP_OFFSET_UC, I915_GEM_DOMAIN_WC },
+	{},
+};
+
+#define for_each_mmap_offset_type(__t) \
+	for (const struct mmap_offset *__t = mmap_offset_types; \
+	     (__t)->name; \
+	     (__t)++)
+
+static int mmap_offset_ioctl(int i915, struct drm_i915_gem_mmap_offset *arg)
+{
+	int err = 0;
+
+	if (igt_ioctl(i915, DRM_IOCTL_I915_GEM_MMAP_OFFSET, arg)) {
+		err = -errno;
+		igt_assume(err);
+	}
+
+	errno = 0;
+	return err;
+}
+
+static void bad_object(int i915)
+{
+	uint32_t real_handle;
+	uint32_t handles[20];
+	int i = 0;
+
+	real_handle = gem_create(i915, 4096);
+
+	handles[i++] = 0xdeadbeef;
+	for (int bit = 0; bit < 16; bit++)
+		handles[i++] = real_handle | (1 << (bit + 16));
+	handles[i] = real_handle + 1;
+
+	for (; i >= 0; i--) {
+		struct drm_i915_gem_mmap_offset arg = {
+			.handle = handles[i],
+			.flags = I915_MMAP_OFFSET_WB,
+		};
+
+		igt_debug("Trying MMAP IOCTL with handle %x\n",
+			  handles[i]);
+		igt_assert_eq(mmap_offset_ioctl(i915, &arg),
+			      -ENOENT);
+	}
+
+	gem_close(i915, real_handle);
+}
+
+static void bad_flags(int i915)
+{
+	struct drm_i915_gem_mmap_offset arg = {
+		.handle = gem_create(i915, 4096),
+		.flags = -1ull,
+	};
+
+	igt_assert_eq(mmap_offset_ioctl(i915, &arg), -EINVAL);
+	gem_close(i915, arg.handle);
+}
+
+static void basic_uaf(int i915)
+{
+	const uint32_t obj_size = 4096;
+
+	for_each_mmap_offset_type(t) {
+		uint32_t handle = gem_create(i915, obj_size);
+		uint8_t *expected, *buf, *addr;
+
+		addr = __gem_mmap_offset(i915, handle, 0, obj_size,
+					 PROT_READ | PROT_WRITE,
+					 t->type);
+		if (!addr) {
+			gem_close(i915, handle);
+			continue;
+		}
+
+		expected = calloc(obj_size, sizeof(*expected));
+		gem_set_domain(i915, handle, t->domain, 0);
+		igt_assert_f(memcmp(addr, expected, obj_size) == 0,
+			     "mmap(%s) not clear on gem_create()\n",
+			     t->name);
+		free(expected);
+
+		buf = calloc(obj_size, sizeof(*buf));
+		memset(buf + 1024, 0x01, 1024);
+		gem_write(i915, handle, 0, buf, obj_size);
+		gem_set_domain(i915, handle, t->domain, 0);
+		igt_assert_f(memcmp(buf, addr, obj_size) == 0,
+			     "mmap(%s) not coherent with gem_write()\n",
+			     t->name);
+
+		gem_set_domain(i915, handle, t->domain, t->domain);
+		memset(addr + 2048, 0xff, 1024);
+		gem_read(i915, handle, 0, buf, obj_size);
+		gem_set_domain(i915, handle, t->domain, 0);
+		igt_assert_f(memcmp(buf, addr, obj_size) == 0,
+			     "mmap(%s) not coherent with gem_read()\n",
+			     t->name);
+
+		gem_close(i915, handle);
+		igt_assert_f(memcmp(buf, addr, obj_size) == 0,
+			     "mmap(%s) not resident after gem_close()\n",
+			     t->name);
+		free(buf);
+
+		igt_debug("Testing unmapping\n");
+		munmap(addr, obj_size);
+	}
+}
+
+static void isolation(int i915)
+{
+	for_each_mmap_offset_type(t) {
+		struct drm_i915_gem_mmap_offset mmap_arg = {
+			.flags = t->type
+		};
+		int A = gem_reopen_driver(i915);
+		int B = gem_reopen_driver(i915);
+		uint64_t offset_a, offset_b;
+		uint32_t a, b;
+		void *ptr;
+
+		a = gem_create(A, 4096);
+		b = gem_open(B, gem_flink(A, a));
+
+		mmap_arg.handle = a;
+		if (mmap_offset_ioctl(i915, &mmap_arg)) {
+			close(A);
+			close(B);
+			continue;
+		}
+		offset_a = mmap_arg.offset;
+
+		mmap_arg.handle = b;
+		igt_assert_eq(mmap_offset_ioctl(i915, &mmap_arg), 0);
+		offset_b = mmap_arg.offset;
+
+		igt_info("A[%s]: {fd:%d, handle:%d, offset:%"PRIx64"}\n",
+			 t->name, A, a, offset_a);
+		igt_info("B[%s]: {fd:%d, handle:%d, offset:%"PRIx64"}\n",
+			 t->name, B, b, offset_b);
+
+		close(B);
+
+		ptr = mmap64(0, 4096, PROT_READ, MAP_SHARED, A, offset_a);
+		igt_assert(ptr != MAP_FAILED);
+		munmap(ptr, 4096);
+
+		close(A);
+
+		ptr = mmap64(0, 4096, PROT_READ, MAP_SHARED, A, offset_a);
+		igt_assert(ptr == MAP_FAILED);
+	}
+}
+
+static void pf_nonblock(int i915)
+{
+	igt_spin_t *spin = igt_spin_new(i915);
+
+	for_each_mmap_offset_type(t) {
+		uint32_t *ptr;
+
+		ptr = __gem_mmap_offset(i915, spin->handle, 0, 4096,
+					PROT_READ | PROT_WRITE,
+					t->type);
+		if (!ptr)
+			continue;
+
+		igt_set_timeout(1, t->name);
+		/* no set-domain as we want to verify the pagefault is async */
+		ptr[256] = 0;
+		igt_reset_timeout();
+
+		munmap(ptr, 4096);
+	}
+
+	igt_spin_free(i915, spin);
+}
+
+static void close_race(int i915, int timeout)
+{
+	const int ncpus = sysconf(_SC_NPROCESSORS_ONLN);
+	_Atomic uint32_t *handles;
+	size_t len = ALIGN((ncpus + 1) * sizeof(uint32_t), 4096);
+
+	handles = mmap64(0, len, PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0);
+	igt_assert(handles != MAP_FAILED);
+
+	igt_fork(child, ncpus + 1) {
+		do {
+			struct drm_i915_gem_mmap_offset mmap_arg = {};
+			const int i = 1 + random() % ncpus;
+			uint32_t old;
+
+			mmap_arg.handle = gem_create(i915, 4096);
+			mmap_arg.flags = I915_MMAP_OFFSET_WB;
+			old = atomic_exchange(&handles[i], mmap_arg.handle);
+			ioctl(i915, DRM_IOCTL_GEM_CLOSE, &old);
+
+			if (ioctl(i915,
+				  DRM_IOCTL_I915_GEM_MMAP_OFFSET,
+				  &mmap_arg) != -1) {
+				void *ptr;
+
+				ptr = mmap64(0, 4096,
+					     PROT_WRITE, MAP_SHARED, i915,
+					     mmap_arg.offset);
+				if (ptr != MAP_FAILED) {
+					*(volatile uint32_t *)ptr = 0;
+					munmap(ptr, 4096);
+				}
+			}
+
+		} while (!READ_ONCE(handles[0]));
+	}
+
+	sleep(timeout);
+	handles[0] = 1;
+	igt_waitchildren();
+
+	for (int i = 1; i <= ncpus; i++)
+		ioctl(i915, DRM_IOCTL_GEM_CLOSE, handles[i]);
+	munmap(handles, len);
+}
+
+static uint64_t atomic_compare_swap_u64(_Atomic(uint64_t) *ptr,
+					uint64_t oldval, uint64_t newval)
+{
+	atomic_compare_exchange_strong(ptr, &oldval, newval);
+	return oldval;
+}
+
+static uint64_t get_npages(_Atomic(uint64_t) *global, uint64_t npages)
+{
+	uint64_t try, old, max;
+
+	max = *global;
+	do {
+		old = max;
+		try = 1 + npages % (max / 2);
+		max -= try;
+	} while ((max = atomic_compare_swap_u64(global, old, max)) != old);
+
+	return try;
+}
+
+struct thread_clear {
+	_Atomic(uint64_t) max;
+	int timeout;
+	int i915;
+};
+
+static int create_ioctl(int i915, struct drm_i915_gem_create *create)
+{
+	int err = 0;
+
+	if (igt_ioctl(i915, DRM_IOCTL_I915_GEM_CREATE, create)) {
+		err = -errno;
+		igt_assume(err != 0);
+	}
+
+	errno = 0;
+	return err;
+}
+
+static void *thread_clear(void *data)
+{
+	struct thread_clear *arg = data;
+	const struct mmap_offset *t;
+	unsigned long checked = 0;
+	int i915 = arg->i915;
+
+	t = mmap_offset_types;
+	igt_until_timeout(arg->timeout) {
+		struct drm_i915_gem_create create = {};
+		uint64_t npages;
+		void *ptr;
+
+		npages = random();
+		npages <<= 32;
+		npages |= random();
+		npages = get_npages(&arg->max, npages);
+		create.size = npages << 12;
+
+		create_ioctl(i915, &create);
+		ptr = __gem_mmap_offset(i915, create.handle, 0, create.size,
+					PROT_READ | PROT_WRITE,
+					t->type);
+		/* No set-domains as we are being as naughty as possible */
+		for (uint64_t page = 0; ptr && page < npages; page++) {
+			uint64_t x[8] = {
+				page * 4096 +
+					sizeof(x) * ((page % (4096 - sizeof(x)) / sizeof(x)))
+			};
+
+			if (page & 1)
+				igt_memcpy_from_wc(x, ptr + x[0], sizeof(x));
+			else
+				memcpy(x, ptr + x[0], sizeof(x));
+
+			for (int i = 0; i < ARRAY_SIZE(x); i++)
+				igt_assert_eq_u64(x[i], 0);
+		}
+		if (ptr)
+			munmap(ptr, create.size);
+		gem_close(i915, create.handle);
+		checked += npages;
+
+		atomic_fetch_add(&arg->max, npages);
+
+		if (!(++t)->name)
+			t = mmap_offset_types;
+	}
+
+	return (void *)(uintptr_t)checked;
+}
+
+static void always_clear(int i915, int timeout)
+{
+	struct thread_clear arg = {
+		.i915 = i915,
+		.timeout = timeout,
+		.max = intel_get_avail_ram_mb() << (20 - 12), /* in pages */
+	};
+	const int ncpus = sysconf(_SC_NPROCESSORS_ONLN);
+	unsigned long checked;
+	pthread_t thread[ncpus];
+	void *result;
+
+	for (int i = 0; i < ncpus; i++)
+		pthread_create(&thread[i], NULL, thread_clear, &arg);
+
+	checked = 0;
+	for (int i = 0; i < ncpus; i++) {
+		pthread_join(thread[i], &result);
+		checked += (uintptr_t)result;
+	}
+	igt_info("Checked %'lu page allocations\n", checked);
+}
+
+
+igt_main
+{
+	int i915;
+
+	igt_fixture {
+		i915 = drm_open_driver(DRIVER_INTEL);
+		gem_require_mmap_offset(i915);
+	}
+
+	igt_describe("Verify mapping to invalid gem objects won't be created");
+	igt_subtest_f("bad-object")
+		bad_object(i915);
+	igt_subtest_f("bad-flags")
+		bad_flags(i915);
+
+	igt_describe("Check buffer object mapping persists after gem_close");
+	igt_subtest_f("basic-uaf")
+		basic_uaf(i915);
+
+	igt_subtest_f("isolation")
+		isolation(i915);
+	igt_subtest_f("pf-nonblock")
+		pf_nonblock(i915);
+
+	igt_describe("Check race between close and mmap offset between threads");
+	igt_subtest_f("close-race")
+		close_race(i915, 20);
+
+	igt_subtest_f("clear")
+		always_clear(i915, 20);
+
+	igt_fixture {
+		close(i915);
+	}
+}
diff --git a/tests/meson.build b/tests/meson.build
index 18788d44b..05dea1f4e 100644
--- a/tests/meson.build
+++ b/tests/meson.build
@@ -174,6 +174,7 @@ i915_progs = [
 	'gem_media_vme',
 	'gem_mmap',
 	'gem_mmap_gtt',
+	'gem_mmap_offset',
 	'gem_mmap_offset_exhaustion',
 	'gem_mmap_wc',
 	'gem_partial_pwrite_pread',
-- 
2.24.0

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [igt-dev] [PATCH i-g-t] tests/i915/gem_mmap_offset: Add new API test for gem_mmap_offset
@ 2019-11-28 13:05     ` Chris Wilson
  0 siblings, 0 replies; 29+ messages in thread
From: Chris Wilson @ 2019-11-28 13:05 UTC (permalink / raw)
  To: intel-gfx; +Cc: igt-dev

From: Lukasz Kalamarz <lukasz.kalamarz@intel.com>

Few simple tests which tries to create / mmap buffer objects
using GEM_MMAP_OFFSET uAPI.

v2: change from WC -> WB (according to Chris review comment)
v3: add mmap-offset-close-race test

Signed-off-by: Lukasz Kalamarz <lukasz.kalamarz@intel.com>
Signed-off-by: Zbigniew Kempczyński <zbigniew.kempczynski@intel.com>
Cc: Chris Wilson <chris@chris-wilson.co.uk>
Cc: Vanshidhar Konda <vanshidhar.r.konda@intel.com>
---
Required (look to gem_mmap_(gtt,wc,cpu) for ideas):
 size - check we can handle objects beyond a reasonable limit (note the
kernel fails at beyond RAM)
 forked - interactions with pagefault + new mmap_offsets across
          threads/processes
 suspend - check speed is consistent before/after suspend
 coherency - combinatorial checker between all pointer types, prw and gpu
---
 tests/Makefile.sources       |   3 +
 tests/i915/gem_mmap_offset.c | 420 +++++++++++++++++++++++++++++++++++
 tests/meson.build            |   1 +
 3 files changed, 424 insertions(+)
 create mode 100644 tests/i915/gem_mmap_offset.c

diff --git a/tests/Makefile.sources b/tests/Makefile.sources
index a211851cf..ddbc69bc8 100644
--- a/tests/Makefile.sources
+++ b/tests/Makefile.sources
@@ -325,6 +325,9 @@ gem_mmap_SOURCES = i915/gem_mmap.c
 TESTS_progs += gem_mmap_gtt
 gem_mmap_gtt_SOURCES = i915/gem_mmap_gtt.c
 
+TESTS_progs += gem_mmap_offset
+gem_mmap_offset_SOURCES = i915/gem_mmap_offset.c
+
 TESTS_progs += gem_mmap_offset_exhaustion
 gem_mmap_offset_exhaustion_SOURCES = i915/gem_mmap_offset_exhaustion.c
 
diff --git a/tests/i915/gem_mmap_offset.c b/tests/i915/gem_mmap_offset.c
new file mode 100644
index 000000000..f0ffc3cd9
--- /dev/null
+++ b/tests/i915/gem_mmap_offset.c
@@ -0,0 +1,420 @@
+/*
+ * Copyright © 2019 Intel Corporation
+ *
+ * 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 (including the next
+ * paragraph) 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 <errno.h>
+#include <pthread.h>
+#include <stdatomic.h>
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+#include "drm.h"
+
+#include "igt.h"
+#include "igt_x86.h"
+
+IGT_TEST_DESCRIPTION("Basic MMAP_OFFSET IOCTL tests for mem regions\n");
+
+static const struct mmap_offset {
+	const char *name;
+	unsigned int type;
+	unsigned int domain;
+} mmap_offset_types[] = {
+	{ "gtt", I915_MMAP_OFFSET_GTT, I915_GEM_DOMAIN_GTT },
+	{ "wb", I915_MMAP_OFFSET_WB, I915_GEM_DOMAIN_CPU },
+	{ "wc", I915_MMAP_OFFSET_WC, I915_GEM_DOMAIN_WC },
+	{ "uc", I915_MMAP_OFFSET_UC, I915_GEM_DOMAIN_WC },
+	{},
+};
+
+#define for_each_mmap_offset_type(__t) \
+	for (const struct mmap_offset *__t = mmap_offset_types; \
+	     (__t)->name; \
+	     (__t)++)
+
+static int mmap_offset_ioctl(int i915, struct drm_i915_gem_mmap_offset *arg)
+{
+	int err = 0;
+
+	if (igt_ioctl(i915, DRM_IOCTL_I915_GEM_MMAP_OFFSET, arg)) {
+		err = -errno;
+		igt_assume(err);
+	}
+
+	errno = 0;
+	return err;
+}
+
+static void bad_object(int i915)
+{
+	uint32_t real_handle;
+	uint32_t handles[20];
+	int i = 0;
+
+	real_handle = gem_create(i915, 4096);
+
+	handles[i++] = 0xdeadbeef;
+	for (int bit = 0; bit < 16; bit++)
+		handles[i++] = real_handle | (1 << (bit + 16));
+	handles[i] = real_handle + 1;
+
+	for (; i >= 0; i--) {
+		struct drm_i915_gem_mmap_offset arg = {
+			.handle = handles[i],
+			.flags = I915_MMAP_OFFSET_WB,
+		};
+
+		igt_debug("Trying MMAP IOCTL with handle %x\n",
+			  handles[i]);
+		igt_assert_eq(mmap_offset_ioctl(i915, &arg),
+			      -ENOENT);
+	}
+
+	gem_close(i915, real_handle);
+}
+
+static void bad_flags(int i915)
+{
+	struct drm_i915_gem_mmap_offset arg = {
+		.handle = gem_create(i915, 4096),
+		.flags = -1ull,
+	};
+
+	igt_assert_eq(mmap_offset_ioctl(i915, &arg), -EINVAL);
+	gem_close(i915, arg.handle);
+}
+
+static void basic_uaf(int i915)
+{
+	const uint32_t obj_size = 4096;
+
+	for_each_mmap_offset_type(t) {
+		uint32_t handle = gem_create(i915, obj_size);
+		uint8_t *expected, *buf, *addr;
+
+		addr = __gem_mmap_offset(i915, handle, 0, obj_size,
+					 PROT_READ | PROT_WRITE,
+					 t->type);
+		if (!addr) {
+			gem_close(i915, handle);
+			continue;
+		}
+
+		expected = calloc(obj_size, sizeof(*expected));
+		gem_set_domain(i915, handle, t->domain, 0);
+		igt_assert_f(memcmp(addr, expected, obj_size) == 0,
+			     "mmap(%s) not clear on gem_create()\n",
+			     t->name);
+		free(expected);
+
+		buf = calloc(obj_size, sizeof(*buf));
+		memset(buf + 1024, 0x01, 1024);
+		gem_write(i915, handle, 0, buf, obj_size);
+		gem_set_domain(i915, handle, t->domain, 0);
+		igt_assert_f(memcmp(buf, addr, obj_size) == 0,
+			     "mmap(%s) not coherent with gem_write()\n",
+			     t->name);
+
+		gem_set_domain(i915, handle, t->domain, t->domain);
+		memset(addr + 2048, 0xff, 1024);
+		gem_read(i915, handle, 0, buf, obj_size);
+		gem_set_domain(i915, handle, t->domain, 0);
+		igt_assert_f(memcmp(buf, addr, obj_size) == 0,
+			     "mmap(%s) not coherent with gem_read()\n",
+			     t->name);
+
+		gem_close(i915, handle);
+		igt_assert_f(memcmp(buf, addr, obj_size) == 0,
+			     "mmap(%s) not resident after gem_close()\n",
+			     t->name);
+		free(buf);
+
+		igt_debug("Testing unmapping\n");
+		munmap(addr, obj_size);
+	}
+}
+
+static void isolation(int i915)
+{
+	for_each_mmap_offset_type(t) {
+		struct drm_i915_gem_mmap_offset mmap_arg = {
+			.flags = t->type
+		};
+		int A = gem_reopen_driver(i915);
+		int B = gem_reopen_driver(i915);
+		uint64_t offset_a, offset_b;
+		uint32_t a, b;
+		void *ptr;
+
+		a = gem_create(A, 4096);
+		b = gem_open(B, gem_flink(A, a));
+
+		mmap_arg.handle = a;
+		if (mmap_offset_ioctl(i915, &mmap_arg)) {
+			close(A);
+			close(B);
+			continue;
+		}
+		offset_a = mmap_arg.offset;
+
+		mmap_arg.handle = b;
+		igt_assert_eq(mmap_offset_ioctl(i915, &mmap_arg), 0);
+		offset_b = mmap_arg.offset;
+
+		igt_info("A[%s]: {fd:%d, handle:%d, offset:%"PRIx64"}\n",
+			 t->name, A, a, offset_a);
+		igt_info("B[%s]: {fd:%d, handle:%d, offset:%"PRIx64"}\n",
+			 t->name, B, b, offset_b);
+
+		close(B);
+
+		ptr = mmap64(0, 4096, PROT_READ, MAP_SHARED, A, offset_a);
+		igt_assert(ptr != MAP_FAILED);
+		munmap(ptr, 4096);
+
+		close(A);
+
+		ptr = mmap64(0, 4096, PROT_READ, MAP_SHARED, A, offset_a);
+		igt_assert(ptr == MAP_FAILED);
+	}
+}
+
+static void pf_nonblock(int i915)
+{
+	igt_spin_t *spin = igt_spin_new(i915);
+
+	for_each_mmap_offset_type(t) {
+		uint32_t *ptr;
+
+		ptr = __gem_mmap_offset(i915, spin->handle, 0, 4096,
+					PROT_READ | PROT_WRITE,
+					t->type);
+		if (!ptr)
+			continue;
+
+		igt_set_timeout(1, t->name);
+		/* no set-domain as we want to verify the pagefault is async */
+		ptr[256] = 0;
+		igt_reset_timeout();
+
+		munmap(ptr, 4096);
+	}
+
+	igt_spin_free(i915, spin);
+}
+
+static void close_race(int i915, int timeout)
+{
+	const int ncpus = sysconf(_SC_NPROCESSORS_ONLN);
+	_Atomic uint32_t *handles;
+	size_t len = ALIGN((ncpus + 1) * sizeof(uint32_t), 4096);
+
+	handles = mmap64(0, len, PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0);
+	igt_assert(handles != MAP_FAILED);
+
+	igt_fork(child, ncpus + 1) {
+		do {
+			struct drm_i915_gem_mmap_offset mmap_arg = {};
+			const int i = 1 + random() % ncpus;
+			uint32_t old;
+
+			mmap_arg.handle = gem_create(i915, 4096);
+			mmap_arg.flags = I915_MMAP_OFFSET_WB;
+			old = atomic_exchange(&handles[i], mmap_arg.handle);
+			ioctl(i915, DRM_IOCTL_GEM_CLOSE, &old);
+
+			if (ioctl(i915,
+				  DRM_IOCTL_I915_GEM_MMAP_OFFSET,
+				  &mmap_arg) != -1) {
+				void *ptr;
+
+				ptr = mmap64(0, 4096,
+					     PROT_WRITE, MAP_SHARED, i915,
+					     mmap_arg.offset);
+				if (ptr != MAP_FAILED) {
+					*(volatile uint32_t *)ptr = 0;
+					munmap(ptr, 4096);
+				}
+			}
+
+		} while (!READ_ONCE(handles[0]));
+	}
+
+	sleep(timeout);
+	handles[0] = 1;
+	igt_waitchildren();
+
+	for (int i = 1; i <= ncpus; i++)
+		ioctl(i915, DRM_IOCTL_GEM_CLOSE, handles[i]);
+	munmap(handles, len);
+}
+
+static uint64_t atomic_compare_swap_u64(_Atomic(uint64_t) *ptr,
+					uint64_t oldval, uint64_t newval)
+{
+	atomic_compare_exchange_strong(ptr, &oldval, newval);
+	return oldval;
+}
+
+static uint64_t get_npages(_Atomic(uint64_t) *global, uint64_t npages)
+{
+	uint64_t try, old, max;
+
+	max = *global;
+	do {
+		old = max;
+		try = 1 + npages % (max / 2);
+		max -= try;
+	} while ((max = atomic_compare_swap_u64(global, old, max)) != old);
+
+	return try;
+}
+
+struct thread_clear {
+	_Atomic(uint64_t) max;
+	int timeout;
+	int i915;
+};
+
+static int create_ioctl(int i915, struct drm_i915_gem_create *create)
+{
+	int err = 0;
+
+	if (igt_ioctl(i915, DRM_IOCTL_I915_GEM_CREATE, create)) {
+		err = -errno;
+		igt_assume(err != 0);
+	}
+
+	errno = 0;
+	return err;
+}
+
+static void *thread_clear(void *data)
+{
+	struct thread_clear *arg = data;
+	const struct mmap_offset *t;
+	unsigned long checked = 0;
+	int i915 = arg->i915;
+
+	t = mmap_offset_types;
+	igt_until_timeout(arg->timeout) {
+		struct drm_i915_gem_create create = {};
+		uint64_t npages;
+		void *ptr;
+
+		npages = random();
+		npages <<= 32;
+		npages |= random();
+		npages = get_npages(&arg->max, npages);
+		create.size = npages << 12;
+
+		create_ioctl(i915, &create);
+		ptr = __gem_mmap_offset(i915, create.handle, 0, create.size,
+					PROT_READ | PROT_WRITE,
+					t->type);
+		/* No set-domains as we are being as naughty as possible */
+		for (uint64_t page = 0; ptr && page < npages; page++) {
+			uint64_t x[8] = {
+				page * 4096 +
+					sizeof(x) * ((page % (4096 - sizeof(x)) / sizeof(x)))
+			};
+
+			if (page & 1)
+				igt_memcpy_from_wc(x, ptr + x[0], sizeof(x));
+			else
+				memcpy(x, ptr + x[0], sizeof(x));
+
+			for (int i = 0; i < ARRAY_SIZE(x); i++)
+				igt_assert_eq_u64(x[i], 0);
+		}
+		if (ptr)
+			munmap(ptr, create.size);
+		gem_close(i915, create.handle);
+		checked += npages;
+
+		atomic_fetch_add(&arg->max, npages);
+
+		if (!(++t)->name)
+			t = mmap_offset_types;
+	}
+
+	return (void *)(uintptr_t)checked;
+}
+
+static void always_clear(int i915, int timeout)
+{
+	struct thread_clear arg = {
+		.i915 = i915,
+		.timeout = timeout,
+		.max = intel_get_avail_ram_mb() << (20 - 12), /* in pages */
+	};
+	const int ncpus = sysconf(_SC_NPROCESSORS_ONLN);
+	unsigned long checked;
+	pthread_t thread[ncpus];
+	void *result;
+
+	for (int i = 0; i < ncpus; i++)
+		pthread_create(&thread[i], NULL, thread_clear, &arg);
+
+	checked = 0;
+	for (int i = 0; i < ncpus; i++) {
+		pthread_join(thread[i], &result);
+		checked += (uintptr_t)result;
+	}
+	igt_info("Checked %'lu page allocations\n", checked);
+}
+
+
+igt_main
+{
+	int i915;
+
+	igt_fixture {
+		i915 = drm_open_driver(DRIVER_INTEL);
+		gem_require_mmap_offset(i915);
+	}
+
+	igt_describe("Verify mapping to invalid gem objects won't be created");
+	igt_subtest_f("bad-object")
+		bad_object(i915);
+	igt_subtest_f("bad-flags")
+		bad_flags(i915);
+
+	igt_describe("Check buffer object mapping persists after gem_close");
+	igt_subtest_f("basic-uaf")
+		basic_uaf(i915);
+
+	igt_subtest_f("isolation")
+		isolation(i915);
+	igt_subtest_f("pf-nonblock")
+		pf_nonblock(i915);
+
+	igt_describe("Check race between close and mmap offset between threads");
+	igt_subtest_f("close-race")
+		close_race(i915, 20);
+
+	igt_subtest_f("clear")
+		always_clear(i915, 20);
+
+	igt_fixture {
+		close(i915);
+	}
+}
diff --git a/tests/meson.build b/tests/meson.build
index 18788d44b..05dea1f4e 100644
--- a/tests/meson.build
+++ b/tests/meson.build
@@ -174,6 +174,7 @@ i915_progs = [
 	'gem_media_vme',
 	'gem_mmap',
 	'gem_mmap_gtt',
+	'gem_mmap_offset',
 	'gem_mmap_offset_exhaustion',
 	'gem_mmap_wc',
 	'gem_partial_pwrite_pread',
-- 
2.24.0

_______________________________________________
igt-dev mailing list
igt-dev@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/igt-dev

^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [igt-dev] ✗ GitLab.Pipeline: warning for Add GEM_MMAP_OFFSET support in IGT. (rev5)
  2019-11-26 17:25 [igt-dev] [PATCH i-g-t v4 0/3] Add GEM_MMAP_OFFSET support in IGT Zbigniew Kempczyński
                   ` (4 preceding siblings ...)
  2019-11-27  5:22 ` [igt-dev] ✗ Fi.CI.IGT: failure " Patchwork
@ 2019-11-28 13:05 ` Patchwork
  2019-11-28 13:20 ` [igt-dev] ✓ Fi.CI.BAT: success " Patchwork
                   ` (3 subsequent siblings)
  9 siblings, 0 replies; 29+ messages in thread
From: Patchwork @ 2019-11-28 13:05 UTC (permalink / raw)
  To: Chris Wilson; +Cc: igt-dev

== Series Details ==

Series: Add GEM_MMAP_OFFSET support in IGT. (rev5)
URL   : https://patchwork.freedesktop.org/series/69973/
State : warning

== Summary ==

Did not get list of undocumented tests for this run, something is wrong!

Other than that, pipeline status: FAILED.

see https://gitlab.freedesktop.org/gfx-ci/igt-ci-tags/pipelines/83695 for the overview.

build:tests-debian-meson-mips has failed (https://gitlab.freedesktop.org/gfx-ci/igt-ci-tags/-/jobs/1033878):
  FAILED: tests/gem_mmap_offset 
  /usr/bin/mips-linux-gnu-gcc  -o tests/gem_mmap_offset 'tests/59830eb@@gem_mmap_offset@exe/i915_gem_mmap_offset.c.o' -Wl,--no-undefined -Wl,--as-needed -Wl,--start-group lib/libigt.so.0 /usr/lib/mips-linux-gnu/libcairo.so /usr/lib/mips-linux-gnu/libglib-2.0.so /usr/lib/mips-linux-gnu/libdrm.so /usr/lib/mips-linux-gnu/libdw.so /usr/lib/mips-linux-gnu/libelf.so /usr/lib/mips-linux-gnu/libkmod.so /usr/lib/mips-linux-gnu/libprocps.so /lib/mips-linux-gnu/libudev.so -lm /usr/lib/mips-linux-gnu/libpciaccess.so /usr/lib/mips-linux-gnu/libpixman-1.so -lrt -lz /usr/lib/mips-linux-gnu/libunwind.so /usr/lib/mips-linux-gnu/libgsl.so /usr/lib/mips-linux-gnu/libgslcblas.so -lm /usr/lib/mips-linux-gnu/libasound.so /usr/lib/mips-linux-gnu/libdrm_nouveau.so -Wl,--end-group -pthread '-Wl,-rpath,$ORIGIN/../lib' -Wl,-rpath-link,/builds/gfx-ci/igt-ci-tags/build/lib  
  tests/59830eb@@gem_mmap_offset@exe/i915_gem_mmap_offset.c.o: In function `get_npages':
  /builds/gfx-ci/igt-ci-tags/build/../tests/i915/gem_mmap_offset.c:277: undefined reference to `__atomic_load_8'
  /builds/gfx-ci/igt-ci-tags/build/../tests/i915/gem_mmap_offset.c:277: undefined reference to `__atomic_load_8'
  tests/59830eb@@gem_mmap_offset@exe/i915_gem_mmap_offset.c.o: In function `atomic_compare_swap_u64':
  /builds/gfx-ci/igt-ci-tags/build/../tests/i915/gem_mmap_offset.c:269: undefined reference to `__atomic_compare_exchange_8'
  /builds/gfx-ci/igt-ci-tags/build/../tests/i915/gem_mmap_offset.c:269: undefined reference to `__atomic_compare_exchange_8'
  tests/59830eb@@gem_mmap_offset@exe/i915_gem_mmap_offset.c.o: In function `thread_clear':
  /builds/gfx-ci/igt-ci-tags/build/../tests/i915/gem_mmap_offset.c:349: undefined reference to `__atomic_fetch_add_8'
  /builds/gfx-ci/igt-ci-tags/build/../tests/i915/gem_mmap_offset.c:349: undefined reference to `__atomic_fetch_add_8'
  collect2: error: ld returned 1 exit status
  ninja: build stopped: subcommand failed.
  section_end:1574946023:build_script
  ^[[0Ksection_start:1574946023:after_script
  ^[[0Ksection_end:1574946025:after_script
  ^[[0Ksection_start:1574946025:upload_artifacts_on_failure
  ^[[0Ksection_end:1574946026:upload_artifacts_on_failure
  ^[[0K^[[31;1mERROR: Job failed: exit code 1
  ^[[0;m

== Logs ==

For more details see: https://gitlab.freedesktop.org/gfx-ci/igt-ci-tags/pipelines/83695
_______________________________________________
igt-dev mailing list
igt-dev@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/igt-dev

^ permalink raw reply	[flat|nested] 29+ messages in thread

* [PATCH i-g-t] tests/i915/gem_mmap_offset: Add new API test for gem_mmap_offset
@ 2019-11-28 13:10     ` Chris Wilson
  0 siblings, 0 replies; 29+ messages in thread
From: Chris Wilson @ 2019-11-28 13:10 UTC (permalink / raw)
  To: intel-gfx; +Cc: igt-dev

From: Lukasz Kalamarz <lukasz.kalamarz@intel.com>

Few simple tests which tries to create / mmap buffer objects
using GEM_MMAP_OFFSET uAPI.

v2: change from WC -> WB (according to Chris review comment)
v3: add mmap-offset-close-race test

Signed-off-by: Lukasz Kalamarz <lukasz.kalamarz@intel.com>
Signed-off-by: Zbigniew Kempczyński <zbigniew.kempczynski@intel.com>
Cc: Chris Wilson <chris@chris-wilson.co.uk>
Cc: Vanshidhar Konda <vanshidhar.r.konda@intel.com>
---
Required (look to gem_mmap_(gtt,wc,cpu) for ideas):
 size - check we can handle objects beyond a reasonable limit (note the
kernel fails at beyond RAM)
 forked - interactions with pagefault + new mmap_offsets across
          threads/processes
 suspend - check speed is consistent before/after suspend
 coherency - combinatorial checker between all pointer types, prw and gpu
---
 tests/Makefile.sources       |   3 +
 tests/i915/gem_mmap_offset.c | 426 +++++++++++++++++++++++++++++++++++
 tests/meson.build            |   1 +
 3 files changed, 430 insertions(+)
 create mode 100644 tests/i915/gem_mmap_offset.c

diff --git a/tests/Makefile.sources b/tests/Makefile.sources
index a211851cf..ddbc69bc8 100644
--- a/tests/Makefile.sources
+++ b/tests/Makefile.sources
@@ -325,6 +325,9 @@ gem_mmap_SOURCES = i915/gem_mmap.c
 TESTS_progs += gem_mmap_gtt
 gem_mmap_gtt_SOURCES = i915/gem_mmap_gtt.c
 
+TESTS_progs += gem_mmap_offset
+gem_mmap_offset_SOURCES = i915/gem_mmap_offset.c
+
 TESTS_progs += gem_mmap_offset_exhaustion
 gem_mmap_offset_exhaustion_SOURCES = i915/gem_mmap_offset_exhaustion.c
 
diff --git a/tests/i915/gem_mmap_offset.c b/tests/i915/gem_mmap_offset.c
new file mode 100644
index 000000000..e02f0fb60
--- /dev/null
+++ b/tests/i915/gem_mmap_offset.c
@@ -0,0 +1,426 @@
+/*
+ * Copyright © 2019 Intel Corporation
+ *
+ * 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 (including the next
+ * paragraph) 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 <errno.h>
+#include <pthread.h>
+#include <stdatomic.h>
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+#include "drm.h"
+
+#include "igt.h"
+#include "igt_x86.h"
+
+IGT_TEST_DESCRIPTION("Basic MMAP_OFFSET IOCTL tests for mem regions\n");
+
+static const struct mmap_offset {
+	const char *name;
+	unsigned int type;
+	unsigned int domain;
+} mmap_offset_types[] = {
+	{ "gtt", I915_MMAP_OFFSET_GTT, I915_GEM_DOMAIN_GTT },
+	{ "wb", I915_MMAP_OFFSET_WB, I915_GEM_DOMAIN_CPU },
+	{ "wc", I915_MMAP_OFFSET_WC, I915_GEM_DOMAIN_WC },
+	{ "uc", I915_MMAP_OFFSET_UC, I915_GEM_DOMAIN_WC },
+	{},
+};
+
+#define for_each_mmap_offset_type(__t) \
+	for (const struct mmap_offset *__t = mmap_offset_types; \
+	     (__t)->name; \
+	     (__t)++)
+
+static int mmap_offset_ioctl(int i915, struct drm_i915_gem_mmap_offset *arg)
+{
+	int err = 0;
+
+	if (igt_ioctl(i915, DRM_IOCTL_I915_GEM_MMAP_OFFSET, arg)) {
+		err = -errno;
+		igt_assume(err);
+	}
+
+	errno = 0;
+	return err;
+}
+
+static void bad_object(int i915)
+{
+	uint32_t real_handle;
+	uint32_t handles[20];
+	int i = 0;
+
+	real_handle = gem_create(i915, 4096);
+
+	handles[i++] = 0xdeadbeef;
+	for (int bit = 0; bit < 16; bit++)
+		handles[i++] = real_handle | (1 << (bit + 16));
+	handles[i] = real_handle + 1;
+
+	for (; i >= 0; i--) {
+		struct drm_i915_gem_mmap_offset arg = {
+			.handle = handles[i],
+			.flags = I915_MMAP_OFFSET_WB,
+		};
+
+		igt_debug("Trying MMAP IOCTL with handle %x\n",
+			  handles[i]);
+		igt_assert_eq(mmap_offset_ioctl(i915, &arg),
+			      -ENOENT);
+	}
+
+	gem_close(i915, real_handle);
+}
+
+static void bad_flags(int i915)
+{
+	struct drm_i915_gem_mmap_offset arg = {
+		.handle = gem_create(i915, 4096),
+		.flags = -1ull,
+	};
+
+	igt_assert_eq(mmap_offset_ioctl(i915, &arg), -EINVAL);
+	gem_close(i915, arg.handle);
+}
+
+static void basic_uaf(int i915)
+{
+	const uint32_t obj_size = 4096;
+
+	for_each_mmap_offset_type(t) {
+		uint32_t handle = gem_create(i915, obj_size);
+		uint8_t *expected, *buf, *addr;
+
+		addr = __gem_mmap_offset(i915, handle, 0, obj_size,
+					 PROT_READ | PROT_WRITE,
+					 t->type);
+		if (!addr) {
+			gem_close(i915, handle);
+			continue;
+		}
+
+		expected = calloc(obj_size, sizeof(*expected));
+		gem_set_domain(i915, handle, t->domain, 0);
+		igt_assert_f(memcmp(addr, expected, obj_size) == 0,
+			     "mmap(%s) not clear on gem_create()\n",
+			     t->name);
+		free(expected);
+
+		buf = calloc(obj_size, sizeof(*buf));
+		memset(buf + 1024, 0x01, 1024);
+		gem_write(i915, handle, 0, buf, obj_size);
+		gem_set_domain(i915, handle, t->domain, 0);
+		igt_assert_f(memcmp(buf, addr, obj_size) == 0,
+			     "mmap(%s) not coherent with gem_write()\n",
+			     t->name);
+
+		gem_set_domain(i915, handle, t->domain, t->domain);
+		memset(addr + 2048, 0xff, 1024);
+		gem_read(i915, handle, 0, buf, obj_size);
+		gem_set_domain(i915, handle, t->domain, 0);
+		igt_assert_f(memcmp(buf, addr, obj_size) == 0,
+			     "mmap(%s) not coherent with gem_read()\n",
+			     t->name);
+
+		gem_close(i915, handle);
+		igt_assert_f(memcmp(buf, addr, obj_size) == 0,
+			     "mmap(%s) not resident after gem_close()\n",
+			     t->name);
+		free(buf);
+
+		igt_debug("Testing unmapping\n");
+		munmap(addr, obj_size);
+	}
+}
+
+static void isolation(int i915)
+{
+	for_each_mmap_offset_type(t) {
+		struct drm_i915_gem_mmap_offset mmap_arg = {
+			.flags = t->type
+		};
+		int A = gem_reopen_driver(i915);
+		int B = gem_reopen_driver(i915);
+		uint64_t offset_a, offset_b;
+		uint32_t a, b;
+		void *ptr;
+
+		a = gem_create(A, 4096);
+		b = gem_open(B, gem_flink(A, a));
+
+		mmap_arg.handle = a;
+		if (mmap_offset_ioctl(i915, &mmap_arg)) {
+			close(A);
+			close(B);
+			continue;
+		}
+		offset_a = mmap_arg.offset;
+
+		mmap_arg.handle = b;
+		igt_assert_eq(mmap_offset_ioctl(i915, &mmap_arg), 0);
+		offset_b = mmap_arg.offset;
+
+		igt_info("A[%s]: {fd:%d, handle:%d, offset:%"PRIx64"}\n",
+			 t->name, A, a, offset_a);
+		igt_info("B[%s]: {fd:%d, handle:%d, offset:%"PRIx64"}\n",
+			 t->name, B, b, offset_b);
+
+		ptr = mmap64(0, 4096, PROT_READ, MAP_SHARED, B, offset_a);
+		igt_assert(ptr == MAP_FAILED);
+
+		ptr = mmap64(0, 4096, PROT_READ, MAP_SHARED, A, offset_b);
+		igt_assert(ptr == MAP_FAILED);
+
+		close(B);
+
+		ptr = mmap64(0, 4096, PROT_READ, MAP_SHARED, A, offset_a);
+		igt_assert(ptr != MAP_FAILED);
+		munmap(ptr, 4096);
+
+		close(A);
+
+		ptr = mmap64(0, 4096, PROT_READ, MAP_SHARED, A, offset_a);
+		igt_assert(ptr == MAP_FAILED);
+	}
+}
+
+static void pf_nonblock(int i915)
+{
+	igt_spin_t *spin = igt_spin_new(i915);
+
+	for_each_mmap_offset_type(t) {
+		uint32_t *ptr;
+
+		ptr = __gem_mmap_offset(i915, spin->handle, 0, 4096,
+					PROT_READ | PROT_WRITE,
+					t->type);
+		if (!ptr)
+			continue;
+
+		igt_set_timeout(1, t->name);
+		/* no set-domain as we want to verify the pagefault is async */
+		ptr[256] = 0;
+		igt_reset_timeout();
+
+		munmap(ptr, 4096);
+	}
+
+	igt_spin_free(i915, spin);
+}
+
+static void close_race(int i915, int timeout)
+{
+	const int ncpus = sysconf(_SC_NPROCESSORS_ONLN);
+	_Atomic uint32_t *handles;
+	size_t len = ALIGN((ncpus + 1) * sizeof(uint32_t), 4096);
+
+	handles = mmap64(0, len, PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0);
+	igt_assert(handles != MAP_FAILED);
+
+	igt_fork(child, ncpus + 1) {
+		do {
+			struct drm_i915_gem_mmap_offset mmap_arg = {};
+			const int i = 1 + random() % ncpus;
+			uint32_t old;
+
+			mmap_arg.handle = gem_create(i915, 4096);
+			mmap_arg.flags = I915_MMAP_OFFSET_WB;
+			old = atomic_exchange(&handles[i], mmap_arg.handle);
+			ioctl(i915, DRM_IOCTL_GEM_CLOSE, &old);
+
+			if (ioctl(i915,
+				  DRM_IOCTL_I915_GEM_MMAP_OFFSET,
+				  &mmap_arg) != -1) {
+				void *ptr;
+
+				ptr = mmap64(0, 4096,
+					     PROT_WRITE, MAP_SHARED, i915,
+					     mmap_arg.offset);
+				if (ptr != MAP_FAILED) {
+					*(volatile uint32_t *)ptr = 0;
+					munmap(ptr, 4096);
+				}
+			}
+
+		} while (!READ_ONCE(handles[0]));
+	}
+
+	sleep(timeout);
+	handles[0] = 1;
+	igt_waitchildren();
+
+	for (int i = 1; i <= ncpus; i++)
+		ioctl(i915, DRM_IOCTL_GEM_CLOSE, handles[i]);
+	munmap(handles, len);
+}
+
+static uint64_t atomic_compare_swap_u64(_Atomic(uint64_t) *ptr,
+					uint64_t oldval, uint64_t newval)
+{
+	atomic_compare_exchange_strong(ptr, &oldval, newval);
+	return oldval;
+}
+
+static uint64_t get_npages(_Atomic(uint64_t) *global, uint64_t npages)
+{
+	uint64_t try, old, max;
+
+	max = *global;
+	do {
+		old = max;
+		try = 1 + npages % (max / 2);
+		max -= try;
+	} while ((max = atomic_compare_swap_u64(global, old, max)) != old);
+
+	return try;
+}
+
+struct thread_clear {
+	_Atomic(uint64_t) max;
+	int timeout;
+	int i915;
+};
+
+static int create_ioctl(int i915, struct drm_i915_gem_create *create)
+{
+	int err = 0;
+
+	if (igt_ioctl(i915, DRM_IOCTL_I915_GEM_CREATE, create)) {
+		err = -errno;
+		igt_assume(err != 0);
+	}
+
+	errno = 0;
+	return err;
+}
+
+static void *thread_clear(void *data)
+{
+	struct thread_clear *arg = data;
+	const struct mmap_offset *t;
+	unsigned long checked = 0;
+	int i915 = arg->i915;
+
+	t = mmap_offset_types;
+	igt_until_timeout(arg->timeout) {
+		struct drm_i915_gem_create create = {};
+		uint64_t npages;
+		void *ptr;
+
+		npages = random();
+		npages <<= 32;
+		npages |= random();
+		npages = get_npages(&arg->max, npages);
+		create.size = npages << 12;
+
+		create_ioctl(i915, &create);
+		ptr = __gem_mmap_offset(i915, create.handle, 0, create.size,
+					PROT_READ | PROT_WRITE,
+					t->type);
+		/* No set-domains as we are being as naughty as possible */
+		for (uint64_t page = 0; ptr && page < npages; page++) {
+			uint64_t x[8] = {
+				page * 4096 +
+					sizeof(x) * ((page % (4096 - sizeof(x)) / sizeof(x)))
+			};
+
+			if (page & 1)
+				igt_memcpy_from_wc(x, ptr + x[0], sizeof(x));
+			else
+				memcpy(x, ptr + x[0], sizeof(x));
+
+			for (int i = 0; i < ARRAY_SIZE(x); i++)
+				igt_assert_eq_u64(x[i], 0);
+		}
+		if (ptr)
+			munmap(ptr, create.size);
+		gem_close(i915, create.handle);
+		checked += npages;
+
+		atomic_fetch_add(&arg->max, npages);
+
+		if (!(++t)->name)
+			t = mmap_offset_types;
+	}
+
+	return (void *)(uintptr_t)checked;
+}
+
+static void always_clear(int i915, int timeout)
+{
+	struct thread_clear arg = {
+		.i915 = i915,
+		.timeout = timeout,
+		.max = intel_get_avail_ram_mb() << (20 - 12), /* in pages */
+	};
+	const int ncpus = sysconf(_SC_NPROCESSORS_ONLN);
+	unsigned long checked;
+	pthread_t thread[ncpus];
+	void *result;
+
+	for (int i = 0; i < ncpus; i++)
+		pthread_create(&thread[i], NULL, thread_clear, &arg);
+
+	checked = 0;
+	for (int i = 0; i < ncpus; i++) {
+		pthread_join(thread[i], &result);
+		checked += (uintptr_t)result;
+	}
+	igt_info("Checked %'lu page allocations\n", checked);
+}
+
+
+igt_main
+{
+	int i915;
+
+	igt_fixture {
+		i915 = drm_open_driver(DRIVER_INTEL);
+		gem_require_mmap_offset(i915);
+	}
+
+	igt_describe("Verify mapping to invalid gem objects won't be created");
+	igt_subtest_f("bad-object")
+		bad_object(i915);
+	igt_subtest_f("bad-flags")
+		bad_flags(i915);
+
+	igt_describe("Check buffer object mapping persists after gem_close");
+	igt_subtest_f("basic-uaf")
+		basic_uaf(i915);
+
+	igt_subtest_f("isolation")
+		isolation(i915);
+	igt_subtest_f("pf-nonblock")
+		pf_nonblock(i915);
+
+	igt_describe("Check race between close and mmap offset between threads");
+	igt_subtest_f("close-race")
+		close_race(i915, 20);
+
+	igt_subtest_f("clear")
+		always_clear(i915, 20);
+
+	igt_fixture {
+		close(i915);
+	}
+}
diff --git a/tests/meson.build b/tests/meson.build
index 18788d44b..05dea1f4e 100644
--- a/tests/meson.build
+++ b/tests/meson.build
@@ -174,6 +174,7 @@ i915_progs = [
 	'gem_media_vme',
 	'gem_mmap',
 	'gem_mmap_gtt',
+	'gem_mmap_offset',
 	'gem_mmap_offset_exhaustion',
 	'gem_mmap_wc',
 	'gem_partial_pwrite_pread',
-- 
2.24.0

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [Intel-gfx] [PATCH i-g-t] tests/i915/gem_mmap_offset: Add new API test for gem_mmap_offset
@ 2019-11-28 13:10     ` Chris Wilson
  0 siblings, 0 replies; 29+ messages in thread
From: Chris Wilson @ 2019-11-28 13:10 UTC (permalink / raw)
  To: intel-gfx; +Cc: igt-dev

From: Lukasz Kalamarz <lukasz.kalamarz@intel.com>

Few simple tests which tries to create / mmap buffer objects
using GEM_MMAP_OFFSET uAPI.

v2: change from WC -> WB (according to Chris review comment)
v3: add mmap-offset-close-race test

Signed-off-by: Lukasz Kalamarz <lukasz.kalamarz@intel.com>
Signed-off-by: Zbigniew Kempczyński <zbigniew.kempczynski@intel.com>
Cc: Chris Wilson <chris@chris-wilson.co.uk>
Cc: Vanshidhar Konda <vanshidhar.r.konda@intel.com>
---
Required (look to gem_mmap_(gtt,wc,cpu) for ideas):
 size - check we can handle objects beyond a reasonable limit (note the
kernel fails at beyond RAM)
 forked - interactions with pagefault + new mmap_offsets across
          threads/processes
 suspend - check speed is consistent before/after suspend
 coherency - combinatorial checker between all pointer types, prw and gpu
---
 tests/Makefile.sources       |   3 +
 tests/i915/gem_mmap_offset.c | 426 +++++++++++++++++++++++++++++++++++
 tests/meson.build            |   1 +
 3 files changed, 430 insertions(+)
 create mode 100644 tests/i915/gem_mmap_offset.c

diff --git a/tests/Makefile.sources b/tests/Makefile.sources
index a211851cf..ddbc69bc8 100644
--- a/tests/Makefile.sources
+++ b/tests/Makefile.sources
@@ -325,6 +325,9 @@ gem_mmap_SOURCES = i915/gem_mmap.c
 TESTS_progs += gem_mmap_gtt
 gem_mmap_gtt_SOURCES = i915/gem_mmap_gtt.c
 
+TESTS_progs += gem_mmap_offset
+gem_mmap_offset_SOURCES = i915/gem_mmap_offset.c
+
 TESTS_progs += gem_mmap_offset_exhaustion
 gem_mmap_offset_exhaustion_SOURCES = i915/gem_mmap_offset_exhaustion.c
 
diff --git a/tests/i915/gem_mmap_offset.c b/tests/i915/gem_mmap_offset.c
new file mode 100644
index 000000000..e02f0fb60
--- /dev/null
+++ b/tests/i915/gem_mmap_offset.c
@@ -0,0 +1,426 @@
+/*
+ * Copyright © 2019 Intel Corporation
+ *
+ * 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 (including the next
+ * paragraph) 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 <errno.h>
+#include <pthread.h>
+#include <stdatomic.h>
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+#include "drm.h"
+
+#include "igt.h"
+#include "igt_x86.h"
+
+IGT_TEST_DESCRIPTION("Basic MMAP_OFFSET IOCTL tests for mem regions\n");
+
+static const struct mmap_offset {
+	const char *name;
+	unsigned int type;
+	unsigned int domain;
+} mmap_offset_types[] = {
+	{ "gtt", I915_MMAP_OFFSET_GTT, I915_GEM_DOMAIN_GTT },
+	{ "wb", I915_MMAP_OFFSET_WB, I915_GEM_DOMAIN_CPU },
+	{ "wc", I915_MMAP_OFFSET_WC, I915_GEM_DOMAIN_WC },
+	{ "uc", I915_MMAP_OFFSET_UC, I915_GEM_DOMAIN_WC },
+	{},
+};
+
+#define for_each_mmap_offset_type(__t) \
+	for (const struct mmap_offset *__t = mmap_offset_types; \
+	     (__t)->name; \
+	     (__t)++)
+
+static int mmap_offset_ioctl(int i915, struct drm_i915_gem_mmap_offset *arg)
+{
+	int err = 0;
+
+	if (igt_ioctl(i915, DRM_IOCTL_I915_GEM_MMAP_OFFSET, arg)) {
+		err = -errno;
+		igt_assume(err);
+	}
+
+	errno = 0;
+	return err;
+}
+
+static void bad_object(int i915)
+{
+	uint32_t real_handle;
+	uint32_t handles[20];
+	int i = 0;
+
+	real_handle = gem_create(i915, 4096);
+
+	handles[i++] = 0xdeadbeef;
+	for (int bit = 0; bit < 16; bit++)
+		handles[i++] = real_handle | (1 << (bit + 16));
+	handles[i] = real_handle + 1;
+
+	for (; i >= 0; i--) {
+		struct drm_i915_gem_mmap_offset arg = {
+			.handle = handles[i],
+			.flags = I915_MMAP_OFFSET_WB,
+		};
+
+		igt_debug("Trying MMAP IOCTL with handle %x\n",
+			  handles[i]);
+		igt_assert_eq(mmap_offset_ioctl(i915, &arg),
+			      -ENOENT);
+	}
+
+	gem_close(i915, real_handle);
+}
+
+static void bad_flags(int i915)
+{
+	struct drm_i915_gem_mmap_offset arg = {
+		.handle = gem_create(i915, 4096),
+		.flags = -1ull,
+	};
+
+	igt_assert_eq(mmap_offset_ioctl(i915, &arg), -EINVAL);
+	gem_close(i915, arg.handle);
+}
+
+static void basic_uaf(int i915)
+{
+	const uint32_t obj_size = 4096;
+
+	for_each_mmap_offset_type(t) {
+		uint32_t handle = gem_create(i915, obj_size);
+		uint8_t *expected, *buf, *addr;
+
+		addr = __gem_mmap_offset(i915, handle, 0, obj_size,
+					 PROT_READ | PROT_WRITE,
+					 t->type);
+		if (!addr) {
+			gem_close(i915, handle);
+			continue;
+		}
+
+		expected = calloc(obj_size, sizeof(*expected));
+		gem_set_domain(i915, handle, t->domain, 0);
+		igt_assert_f(memcmp(addr, expected, obj_size) == 0,
+			     "mmap(%s) not clear on gem_create()\n",
+			     t->name);
+		free(expected);
+
+		buf = calloc(obj_size, sizeof(*buf));
+		memset(buf + 1024, 0x01, 1024);
+		gem_write(i915, handle, 0, buf, obj_size);
+		gem_set_domain(i915, handle, t->domain, 0);
+		igt_assert_f(memcmp(buf, addr, obj_size) == 0,
+			     "mmap(%s) not coherent with gem_write()\n",
+			     t->name);
+
+		gem_set_domain(i915, handle, t->domain, t->domain);
+		memset(addr + 2048, 0xff, 1024);
+		gem_read(i915, handle, 0, buf, obj_size);
+		gem_set_domain(i915, handle, t->domain, 0);
+		igt_assert_f(memcmp(buf, addr, obj_size) == 0,
+			     "mmap(%s) not coherent with gem_read()\n",
+			     t->name);
+
+		gem_close(i915, handle);
+		igt_assert_f(memcmp(buf, addr, obj_size) == 0,
+			     "mmap(%s) not resident after gem_close()\n",
+			     t->name);
+		free(buf);
+
+		igt_debug("Testing unmapping\n");
+		munmap(addr, obj_size);
+	}
+}
+
+static void isolation(int i915)
+{
+	for_each_mmap_offset_type(t) {
+		struct drm_i915_gem_mmap_offset mmap_arg = {
+			.flags = t->type
+		};
+		int A = gem_reopen_driver(i915);
+		int B = gem_reopen_driver(i915);
+		uint64_t offset_a, offset_b;
+		uint32_t a, b;
+		void *ptr;
+
+		a = gem_create(A, 4096);
+		b = gem_open(B, gem_flink(A, a));
+
+		mmap_arg.handle = a;
+		if (mmap_offset_ioctl(i915, &mmap_arg)) {
+			close(A);
+			close(B);
+			continue;
+		}
+		offset_a = mmap_arg.offset;
+
+		mmap_arg.handle = b;
+		igt_assert_eq(mmap_offset_ioctl(i915, &mmap_arg), 0);
+		offset_b = mmap_arg.offset;
+
+		igt_info("A[%s]: {fd:%d, handle:%d, offset:%"PRIx64"}\n",
+			 t->name, A, a, offset_a);
+		igt_info("B[%s]: {fd:%d, handle:%d, offset:%"PRIx64"}\n",
+			 t->name, B, b, offset_b);
+
+		ptr = mmap64(0, 4096, PROT_READ, MAP_SHARED, B, offset_a);
+		igt_assert(ptr == MAP_FAILED);
+
+		ptr = mmap64(0, 4096, PROT_READ, MAP_SHARED, A, offset_b);
+		igt_assert(ptr == MAP_FAILED);
+
+		close(B);
+
+		ptr = mmap64(0, 4096, PROT_READ, MAP_SHARED, A, offset_a);
+		igt_assert(ptr != MAP_FAILED);
+		munmap(ptr, 4096);
+
+		close(A);
+
+		ptr = mmap64(0, 4096, PROT_READ, MAP_SHARED, A, offset_a);
+		igt_assert(ptr == MAP_FAILED);
+	}
+}
+
+static void pf_nonblock(int i915)
+{
+	igt_spin_t *spin = igt_spin_new(i915);
+
+	for_each_mmap_offset_type(t) {
+		uint32_t *ptr;
+
+		ptr = __gem_mmap_offset(i915, spin->handle, 0, 4096,
+					PROT_READ | PROT_WRITE,
+					t->type);
+		if (!ptr)
+			continue;
+
+		igt_set_timeout(1, t->name);
+		/* no set-domain as we want to verify the pagefault is async */
+		ptr[256] = 0;
+		igt_reset_timeout();
+
+		munmap(ptr, 4096);
+	}
+
+	igt_spin_free(i915, spin);
+}
+
+static void close_race(int i915, int timeout)
+{
+	const int ncpus = sysconf(_SC_NPROCESSORS_ONLN);
+	_Atomic uint32_t *handles;
+	size_t len = ALIGN((ncpus + 1) * sizeof(uint32_t), 4096);
+
+	handles = mmap64(0, len, PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0);
+	igt_assert(handles != MAP_FAILED);
+
+	igt_fork(child, ncpus + 1) {
+		do {
+			struct drm_i915_gem_mmap_offset mmap_arg = {};
+			const int i = 1 + random() % ncpus;
+			uint32_t old;
+
+			mmap_arg.handle = gem_create(i915, 4096);
+			mmap_arg.flags = I915_MMAP_OFFSET_WB;
+			old = atomic_exchange(&handles[i], mmap_arg.handle);
+			ioctl(i915, DRM_IOCTL_GEM_CLOSE, &old);
+
+			if (ioctl(i915,
+				  DRM_IOCTL_I915_GEM_MMAP_OFFSET,
+				  &mmap_arg) != -1) {
+				void *ptr;
+
+				ptr = mmap64(0, 4096,
+					     PROT_WRITE, MAP_SHARED, i915,
+					     mmap_arg.offset);
+				if (ptr != MAP_FAILED) {
+					*(volatile uint32_t *)ptr = 0;
+					munmap(ptr, 4096);
+				}
+			}
+
+		} while (!READ_ONCE(handles[0]));
+	}
+
+	sleep(timeout);
+	handles[0] = 1;
+	igt_waitchildren();
+
+	for (int i = 1; i <= ncpus; i++)
+		ioctl(i915, DRM_IOCTL_GEM_CLOSE, handles[i]);
+	munmap(handles, len);
+}
+
+static uint64_t atomic_compare_swap_u64(_Atomic(uint64_t) *ptr,
+					uint64_t oldval, uint64_t newval)
+{
+	atomic_compare_exchange_strong(ptr, &oldval, newval);
+	return oldval;
+}
+
+static uint64_t get_npages(_Atomic(uint64_t) *global, uint64_t npages)
+{
+	uint64_t try, old, max;
+
+	max = *global;
+	do {
+		old = max;
+		try = 1 + npages % (max / 2);
+		max -= try;
+	} while ((max = atomic_compare_swap_u64(global, old, max)) != old);
+
+	return try;
+}
+
+struct thread_clear {
+	_Atomic(uint64_t) max;
+	int timeout;
+	int i915;
+};
+
+static int create_ioctl(int i915, struct drm_i915_gem_create *create)
+{
+	int err = 0;
+
+	if (igt_ioctl(i915, DRM_IOCTL_I915_GEM_CREATE, create)) {
+		err = -errno;
+		igt_assume(err != 0);
+	}
+
+	errno = 0;
+	return err;
+}
+
+static void *thread_clear(void *data)
+{
+	struct thread_clear *arg = data;
+	const struct mmap_offset *t;
+	unsigned long checked = 0;
+	int i915 = arg->i915;
+
+	t = mmap_offset_types;
+	igt_until_timeout(arg->timeout) {
+		struct drm_i915_gem_create create = {};
+		uint64_t npages;
+		void *ptr;
+
+		npages = random();
+		npages <<= 32;
+		npages |= random();
+		npages = get_npages(&arg->max, npages);
+		create.size = npages << 12;
+
+		create_ioctl(i915, &create);
+		ptr = __gem_mmap_offset(i915, create.handle, 0, create.size,
+					PROT_READ | PROT_WRITE,
+					t->type);
+		/* No set-domains as we are being as naughty as possible */
+		for (uint64_t page = 0; ptr && page < npages; page++) {
+			uint64_t x[8] = {
+				page * 4096 +
+					sizeof(x) * ((page % (4096 - sizeof(x)) / sizeof(x)))
+			};
+
+			if (page & 1)
+				igt_memcpy_from_wc(x, ptr + x[0], sizeof(x));
+			else
+				memcpy(x, ptr + x[0], sizeof(x));
+
+			for (int i = 0; i < ARRAY_SIZE(x); i++)
+				igt_assert_eq_u64(x[i], 0);
+		}
+		if (ptr)
+			munmap(ptr, create.size);
+		gem_close(i915, create.handle);
+		checked += npages;
+
+		atomic_fetch_add(&arg->max, npages);
+
+		if (!(++t)->name)
+			t = mmap_offset_types;
+	}
+
+	return (void *)(uintptr_t)checked;
+}
+
+static void always_clear(int i915, int timeout)
+{
+	struct thread_clear arg = {
+		.i915 = i915,
+		.timeout = timeout,
+		.max = intel_get_avail_ram_mb() << (20 - 12), /* in pages */
+	};
+	const int ncpus = sysconf(_SC_NPROCESSORS_ONLN);
+	unsigned long checked;
+	pthread_t thread[ncpus];
+	void *result;
+
+	for (int i = 0; i < ncpus; i++)
+		pthread_create(&thread[i], NULL, thread_clear, &arg);
+
+	checked = 0;
+	for (int i = 0; i < ncpus; i++) {
+		pthread_join(thread[i], &result);
+		checked += (uintptr_t)result;
+	}
+	igt_info("Checked %'lu page allocations\n", checked);
+}
+
+
+igt_main
+{
+	int i915;
+
+	igt_fixture {
+		i915 = drm_open_driver(DRIVER_INTEL);
+		gem_require_mmap_offset(i915);
+	}
+
+	igt_describe("Verify mapping to invalid gem objects won't be created");
+	igt_subtest_f("bad-object")
+		bad_object(i915);
+	igt_subtest_f("bad-flags")
+		bad_flags(i915);
+
+	igt_describe("Check buffer object mapping persists after gem_close");
+	igt_subtest_f("basic-uaf")
+		basic_uaf(i915);
+
+	igt_subtest_f("isolation")
+		isolation(i915);
+	igt_subtest_f("pf-nonblock")
+		pf_nonblock(i915);
+
+	igt_describe("Check race between close and mmap offset between threads");
+	igt_subtest_f("close-race")
+		close_race(i915, 20);
+
+	igt_subtest_f("clear")
+		always_clear(i915, 20);
+
+	igt_fixture {
+		close(i915);
+	}
+}
diff --git a/tests/meson.build b/tests/meson.build
index 18788d44b..05dea1f4e 100644
--- a/tests/meson.build
+++ b/tests/meson.build
@@ -174,6 +174,7 @@ i915_progs = [
 	'gem_media_vme',
 	'gem_mmap',
 	'gem_mmap_gtt',
+	'gem_mmap_offset',
 	'gem_mmap_offset_exhaustion',
 	'gem_mmap_wc',
 	'gem_partial_pwrite_pread',
-- 
2.24.0

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [igt-dev] [PATCH i-g-t] tests/i915/gem_mmap_offset: Add new API test for gem_mmap_offset
@ 2019-11-28 13:10     ` Chris Wilson
  0 siblings, 0 replies; 29+ messages in thread
From: Chris Wilson @ 2019-11-28 13:10 UTC (permalink / raw)
  To: intel-gfx; +Cc: igt-dev

From: Lukasz Kalamarz <lukasz.kalamarz@intel.com>

Few simple tests which tries to create / mmap buffer objects
using GEM_MMAP_OFFSET uAPI.

v2: change from WC -> WB (according to Chris review comment)
v3: add mmap-offset-close-race test

Signed-off-by: Lukasz Kalamarz <lukasz.kalamarz@intel.com>
Signed-off-by: Zbigniew Kempczyński <zbigniew.kempczynski@intel.com>
Cc: Chris Wilson <chris@chris-wilson.co.uk>
Cc: Vanshidhar Konda <vanshidhar.r.konda@intel.com>
---
Required (look to gem_mmap_(gtt,wc,cpu) for ideas):
 size - check we can handle objects beyond a reasonable limit (note the
kernel fails at beyond RAM)
 forked - interactions with pagefault + new mmap_offsets across
          threads/processes
 suspend - check speed is consistent before/after suspend
 coherency - combinatorial checker between all pointer types, prw and gpu
---
 tests/Makefile.sources       |   3 +
 tests/i915/gem_mmap_offset.c | 426 +++++++++++++++++++++++++++++++++++
 tests/meson.build            |   1 +
 3 files changed, 430 insertions(+)
 create mode 100644 tests/i915/gem_mmap_offset.c

diff --git a/tests/Makefile.sources b/tests/Makefile.sources
index a211851cf..ddbc69bc8 100644
--- a/tests/Makefile.sources
+++ b/tests/Makefile.sources
@@ -325,6 +325,9 @@ gem_mmap_SOURCES = i915/gem_mmap.c
 TESTS_progs += gem_mmap_gtt
 gem_mmap_gtt_SOURCES = i915/gem_mmap_gtt.c
 
+TESTS_progs += gem_mmap_offset
+gem_mmap_offset_SOURCES = i915/gem_mmap_offset.c
+
 TESTS_progs += gem_mmap_offset_exhaustion
 gem_mmap_offset_exhaustion_SOURCES = i915/gem_mmap_offset_exhaustion.c
 
diff --git a/tests/i915/gem_mmap_offset.c b/tests/i915/gem_mmap_offset.c
new file mode 100644
index 000000000..e02f0fb60
--- /dev/null
+++ b/tests/i915/gem_mmap_offset.c
@@ -0,0 +1,426 @@
+/*
+ * Copyright © 2019 Intel Corporation
+ *
+ * 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 (including the next
+ * paragraph) 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 <errno.h>
+#include <pthread.h>
+#include <stdatomic.h>
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+#include "drm.h"
+
+#include "igt.h"
+#include "igt_x86.h"
+
+IGT_TEST_DESCRIPTION("Basic MMAP_OFFSET IOCTL tests for mem regions\n");
+
+static const struct mmap_offset {
+	const char *name;
+	unsigned int type;
+	unsigned int domain;
+} mmap_offset_types[] = {
+	{ "gtt", I915_MMAP_OFFSET_GTT, I915_GEM_DOMAIN_GTT },
+	{ "wb", I915_MMAP_OFFSET_WB, I915_GEM_DOMAIN_CPU },
+	{ "wc", I915_MMAP_OFFSET_WC, I915_GEM_DOMAIN_WC },
+	{ "uc", I915_MMAP_OFFSET_UC, I915_GEM_DOMAIN_WC },
+	{},
+};
+
+#define for_each_mmap_offset_type(__t) \
+	for (const struct mmap_offset *__t = mmap_offset_types; \
+	     (__t)->name; \
+	     (__t)++)
+
+static int mmap_offset_ioctl(int i915, struct drm_i915_gem_mmap_offset *arg)
+{
+	int err = 0;
+
+	if (igt_ioctl(i915, DRM_IOCTL_I915_GEM_MMAP_OFFSET, arg)) {
+		err = -errno;
+		igt_assume(err);
+	}
+
+	errno = 0;
+	return err;
+}
+
+static void bad_object(int i915)
+{
+	uint32_t real_handle;
+	uint32_t handles[20];
+	int i = 0;
+
+	real_handle = gem_create(i915, 4096);
+
+	handles[i++] = 0xdeadbeef;
+	for (int bit = 0; bit < 16; bit++)
+		handles[i++] = real_handle | (1 << (bit + 16));
+	handles[i] = real_handle + 1;
+
+	for (; i >= 0; i--) {
+		struct drm_i915_gem_mmap_offset arg = {
+			.handle = handles[i],
+			.flags = I915_MMAP_OFFSET_WB,
+		};
+
+		igt_debug("Trying MMAP IOCTL with handle %x\n",
+			  handles[i]);
+		igt_assert_eq(mmap_offset_ioctl(i915, &arg),
+			      -ENOENT);
+	}
+
+	gem_close(i915, real_handle);
+}
+
+static void bad_flags(int i915)
+{
+	struct drm_i915_gem_mmap_offset arg = {
+		.handle = gem_create(i915, 4096),
+		.flags = -1ull,
+	};
+
+	igt_assert_eq(mmap_offset_ioctl(i915, &arg), -EINVAL);
+	gem_close(i915, arg.handle);
+}
+
+static void basic_uaf(int i915)
+{
+	const uint32_t obj_size = 4096;
+
+	for_each_mmap_offset_type(t) {
+		uint32_t handle = gem_create(i915, obj_size);
+		uint8_t *expected, *buf, *addr;
+
+		addr = __gem_mmap_offset(i915, handle, 0, obj_size,
+					 PROT_READ | PROT_WRITE,
+					 t->type);
+		if (!addr) {
+			gem_close(i915, handle);
+			continue;
+		}
+
+		expected = calloc(obj_size, sizeof(*expected));
+		gem_set_domain(i915, handle, t->domain, 0);
+		igt_assert_f(memcmp(addr, expected, obj_size) == 0,
+			     "mmap(%s) not clear on gem_create()\n",
+			     t->name);
+		free(expected);
+
+		buf = calloc(obj_size, sizeof(*buf));
+		memset(buf + 1024, 0x01, 1024);
+		gem_write(i915, handle, 0, buf, obj_size);
+		gem_set_domain(i915, handle, t->domain, 0);
+		igt_assert_f(memcmp(buf, addr, obj_size) == 0,
+			     "mmap(%s) not coherent with gem_write()\n",
+			     t->name);
+
+		gem_set_domain(i915, handle, t->domain, t->domain);
+		memset(addr + 2048, 0xff, 1024);
+		gem_read(i915, handle, 0, buf, obj_size);
+		gem_set_domain(i915, handle, t->domain, 0);
+		igt_assert_f(memcmp(buf, addr, obj_size) == 0,
+			     "mmap(%s) not coherent with gem_read()\n",
+			     t->name);
+
+		gem_close(i915, handle);
+		igt_assert_f(memcmp(buf, addr, obj_size) == 0,
+			     "mmap(%s) not resident after gem_close()\n",
+			     t->name);
+		free(buf);
+
+		igt_debug("Testing unmapping\n");
+		munmap(addr, obj_size);
+	}
+}
+
+static void isolation(int i915)
+{
+	for_each_mmap_offset_type(t) {
+		struct drm_i915_gem_mmap_offset mmap_arg = {
+			.flags = t->type
+		};
+		int A = gem_reopen_driver(i915);
+		int B = gem_reopen_driver(i915);
+		uint64_t offset_a, offset_b;
+		uint32_t a, b;
+		void *ptr;
+
+		a = gem_create(A, 4096);
+		b = gem_open(B, gem_flink(A, a));
+
+		mmap_arg.handle = a;
+		if (mmap_offset_ioctl(i915, &mmap_arg)) {
+			close(A);
+			close(B);
+			continue;
+		}
+		offset_a = mmap_arg.offset;
+
+		mmap_arg.handle = b;
+		igt_assert_eq(mmap_offset_ioctl(i915, &mmap_arg), 0);
+		offset_b = mmap_arg.offset;
+
+		igt_info("A[%s]: {fd:%d, handle:%d, offset:%"PRIx64"}\n",
+			 t->name, A, a, offset_a);
+		igt_info("B[%s]: {fd:%d, handle:%d, offset:%"PRIx64"}\n",
+			 t->name, B, b, offset_b);
+
+		ptr = mmap64(0, 4096, PROT_READ, MAP_SHARED, B, offset_a);
+		igt_assert(ptr == MAP_FAILED);
+
+		ptr = mmap64(0, 4096, PROT_READ, MAP_SHARED, A, offset_b);
+		igt_assert(ptr == MAP_FAILED);
+
+		close(B);
+
+		ptr = mmap64(0, 4096, PROT_READ, MAP_SHARED, A, offset_a);
+		igt_assert(ptr != MAP_FAILED);
+		munmap(ptr, 4096);
+
+		close(A);
+
+		ptr = mmap64(0, 4096, PROT_READ, MAP_SHARED, A, offset_a);
+		igt_assert(ptr == MAP_FAILED);
+	}
+}
+
+static void pf_nonblock(int i915)
+{
+	igt_spin_t *spin = igt_spin_new(i915);
+
+	for_each_mmap_offset_type(t) {
+		uint32_t *ptr;
+
+		ptr = __gem_mmap_offset(i915, spin->handle, 0, 4096,
+					PROT_READ | PROT_WRITE,
+					t->type);
+		if (!ptr)
+			continue;
+
+		igt_set_timeout(1, t->name);
+		/* no set-domain as we want to verify the pagefault is async */
+		ptr[256] = 0;
+		igt_reset_timeout();
+
+		munmap(ptr, 4096);
+	}
+
+	igt_spin_free(i915, spin);
+}
+
+static void close_race(int i915, int timeout)
+{
+	const int ncpus = sysconf(_SC_NPROCESSORS_ONLN);
+	_Atomic uint32_t *handles;
+	size_t len = ALIGN((ncpus + 1) * sizeof(uint32_t), 4096);
+
+	handles = mmap64(0, len, PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0);
+	igt_assert(handles != MAP_FAILED);
+
+	igt_fork(child, ncpus + 1) {
+		do {
+			struct drm_i915_gem_mmap_offset mmap_arg = {};
+			const int i = 1 + random() % ncpus;
+			uint32_t old;
+
+			mmap_arg.handle = gem_create(i915, 4096);
+			mmap_arg.flags = I915_MMAP_OFFSET_WB;
+			old = atomic_exchange(&handles[i], mmap_arg.handle);
+			ioctl(i915, DRM_IOCTL_GEM_CLOSE, &old);
+
+			if (ioctl(i915,
+				  DRM_IOCTL_I915_GEM_MMAP_OFFSET,
+				  &mmap_arg) != -1) {
+				void *ptr;
+
+				ptr = mmap64(0, 4096,
+					     PROT_WRITE, MAP_SHARED, i915,
+					     mmap_arg.offset);
+				if (ptr != MAP_FAILED) {
+					*(volatile uint32_t *)ptr = 0;
+					munmap(ptr, 4096);
+				}
+			}
+
+		} while (!READ_ONCE(handles[0]));
+	}
+
+	sleep(timeout);
+	handles[0] = 1;
+	igt_waitchildren();
+
+	for (int i = 1; i <= ncpus; i++)
+		ioctl(i915, DRM_IOCTL_GEM_CLOSE, handles[i]);
+	munmap(handles, len);
+}
+
+static uint64_t atomic_compare_swap_u64(_Atomic(uint64_t) *ptr,
+					uint64_t oldval, uint64_t newval)
+{
+	atomic_compare_exchange_strong(ptr, &oldval, newval);
+	return oldval;
+}
+
+static uint64_t get_npages(_Atomic(uint64_t) *global, uint64_t npages)
+{
+	uint64_t try, old, max;
+
+	max = *global;
+	do {
+		old = max;
+		try = 1 + npages % (max / 2);
+		max -= try;
+	} while ((max = atomic_compare_swap_u64(global, old, max)) != old);
+
+	return try;
+}
+
+struct thread_clear {
+	_Atomic(uint64_t) max;
+	int timeout;
+	int i915;
+};
+
+static int create_ioctl(int i915, struct drm_i915_gem_create *create)
+{
+	int err = 0;
+
+	if (igt_ioctl(i915, DRM_IOCTL_I915_GEM_CREATE, create)) {
+		err = -errno;
+		igt_assume(err != 0);
+	}
+
+	errno = 0;
+	return err;
+}
+
+static void *thread_clear(void *data)
+{
+	struct thread_clear *arg = data;
+	const struct mmap_offset *t;
+	unsigned long checked = 0;
+	int i915 = arg->i915;
+
+	t = mmap_offset_types;
+	igt_until_timeout(arg->timeout) {
+		struct drm_i915_gem_create create = {};
+		uint64_t npages;
+		void *ptr;
+
+		npages = random();
+		npages <<= 32;
+		npages |= random();
+		npages = get_npages(&arg->max, npages);
+		create.size = npages << 12;
+
+		create_ioctl(i915, &create);
+		ptr = __gem_mmap_offset(i915, create.handle, 0, create.size,
+					PROT_READ | PROT_WRITE,
+					t->type);
+		/* No set-domains as we are being as naughty as possible */
+		for (uint64_t page = 0; ptr && page < npages; page++) {
+			uint64_t x[8] = {
+				page * 4096 +
+					sizeof(x) * ((page % (4096 - sizeof(x)) / sizeof(x)))
+			};
+
+			if (page & 1)
+				igt_memcpy_from_wc(x, ptr + x[0], sizeof(x));
+			else
+				memcpy(x, ptr + x[0], sizeof(x));
+
+			for (int i = 0; i < ARRAY_SIZE(x); i++)
+				igt_assert_eq_u64(x[i], 0);
+		}
+		if (ptr)
+			munmap(ptr, create.size);
+		gem_close(i915, create.handle);
+		checked += npages;
+
+		atomic_fetch_add(&arg->max, npages);
+
+		if (!(++t)->name)
+			t = mmap_offset_types;
+	}
+
+	return (void *)(uintptr_t)checked;
+}
+
+static void always_clear(int i915, int timeout)
+{
+	struct thread_clear arg = {
+		.i915 = i915,
+		.timeout = timeout,
+		.max = intel_get_avail_ram_mb() << (20 - 12), /* in pages */
+	};
+	const int ncpus = sysconf(_SC_NPROCESSORS_ONLN);
+	unsigned long checked;
+	pthread_t thread[ncpus];
+	void *result;
+
+	for (int i = 0; i < ncpus; i++)
+		pthread_create(&thread[i], NULL, thread_clear, &arg);
+
+	checked = 0;
+	for (int i = 0; i < ncpus; i++) {
+		pthread_join(thread[i], &result);
+		checked += (uintptr_t)result;
+	}
+	igt_info("Checked %'lu page allocations\n", checked);
+}
+
+
+igt_main
+{
+	int i915;
+
+	igt_fixture {
+		i915 = drm_open_driver(DRIVER_INTEL);
+		gem_require_mmap_offset(i915);
+	}
+
+	igt_describe("Verify mapping to invalid gem objects won't be created");
+	igt_subtest_f("bad-object")
+		bad_object(i915);
+	igt_subtest_f("bad-flags")
+		bad_flags(i915);
+
+	igt_describe("Check buffer object mapping persists after gem_close");
+	igt_subtest_f("basic-uaf")
+		basic_uaf(i915);
+
+	igt_subtest_f("isolation")
+		isolation(i915);
+	igt_subtest_f("pf-nonblock")
+		pf_nonblock(i915);
+
+	igt_describe("Check race between close and mmap offset between threads");
+	igt_subtest_f("close-race")
+		close_race(i915, 20);
+
+	igt_subtest_f("clear")
+		always_clear(i915, 20);
+
+	igt_fixture {
+		close(i915);
+	}
+}
diff --git a/tests/meson.build b/tests/meson.build
index 18788d44b..05dea1f4e 100644
--- a/tests/meson.build
+++ b/tests/meson.build
@@ -174,6 +174,7 @@ i915_progs = [
 	'gem_media_vme',
 	'gem_mmap',
 	'gem_mmap_gtt',
+	'gem_mmap_offset',
 	'gem_mmap_offset_exhaustion',
 	'gem_mmap_wc',
 	'gem_partial_pwrite_pread',
-- 
2.24.0

_______________________________________________
igt-dev mailing list
igt-dev@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/igt-dev

^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [igt-dev] ✓ Fi.CI.BAT: success for Add GEM_MMAP_OFFSET support in IGT. (rev5)
  2019-11-26 17:25 [igt-dev] [PATCH i-g-t v4 0/3] Add GEM_MMAP_OFFSET support in IGT Zbigniew Kempczyński
                   ` (5 preceding siblings ...)
  2019-11-28 13:05 ` [igt-dev] ✗ GitLab.Pipeline: warning for Add GEM_MMAP_OFFSET support in IGT. (rev5) Patchwork
@ 2019-11-28 13:20 ` Patchwork
  2019-11-28 13:43 ` [igt-dev] ✓ Fi.CI.BAT: success for Add GEM_MMAP_OFFSET support in IGT. (rev7) Patchwork
                   ` (2 subsequent siblings)
  9 siblings, 0 replies; 29+ messages in thread
From: Patchwork @ 2019-11-28 13:20 UTC (permalink / raw)
  To: Chris Wilson; +Cc: igt-dev

== Series Details ==

Series: Add GEM_MMAP_OFFSET support in IGT. (rev5)
URL   : https://patchwork.freedesktop.org/series/69973/
State : success

== Summary ==

CI Bug Log - changes from CI_DRM_7438 -> IGTPW_3778
====================================================

Summary
-------

  **SUCCESS**

  No regressions found.

  External URL: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_3778/index.html

Known issues
------------

  Here are the changes found in IGTPW_3778 that come from known issues:

### IGT changes ###

#### Possible fixes ####

  * igt@gem_ctx_create@basic-files:
    - {fi-tgl-u}:         [INCOMPLETE][1] ([fdo#111735]) -> [PASS][2]
   [1]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_7438/fi-tgl-u/igt@gem_ctx_create@basic-files.html
   [2]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_3778/fi-tgl-u/igt@gem_ctx_create@basic-files.html

  * igt@i915_pm_rpm@module-reload:
    - fi-skl-6770hq:      [FAIL][3] ([fdo#108511]) -> [PASS][4]
   [3]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_7438/fi-skl-6770hq/igt@i915_pm_rpm@module-reload.html
   [4]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_3778/fi-skl-6770hq/igt@i915_pm_rpm@module-reload.html

  
#### Warnings ####

  * igt@kms_busy@basic-flip-pipe-b:
    - fi-kbl-x1275:       [DMESG-WARN][5] ([fdo#103558] / [fdo#105602] / [fdo#105763]) -> [DMESG-WARN][6] ([fdo#103558] / [fdo#105602]) +6 similar issues
   [5]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_7438/fi-kbl-x1275/igt@kms_busy@basic-flip-pipe-b.html
   [6]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_3778/fi-kbl-x1275/igt@kms_busy@basic-flip-pipe-b.html

  * igt@kms_flip@basic-flip-vs-dpms:
    - fi-icl-dsi:         [INCOMPLETE][7] ([fdo#107713]) -> [DMESG-WARN][8] ([fdo#107724])
   [7]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_7438/fi-icl-dsi/igt@kms_flip@basic-flip-vs-dpms.html
   [8]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_3778/fi-icl-dsi/igt@kms_flip@basic-flip-vs-dpms.html

  * igt@kms_pipe_crc_basic@suspend-read-crc-pipe-a:
    - fi-kbl-x1275:       [DMESG-WARN][9] ([fdo#103558] / [fdo#105602]) -> [DMESG-WARN][10] ([fdo#103558] / [fdo#105602] / [fdo#105763]) +9 similar issues
   [9]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_7438/fi-kbl-x1275/igt@kms_pipe_crc_basic@suspend-read-crc-pipe-a.html
   [10]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_3778/fi-kbl-x1275/igt@kms_pipe_crc_basic@suspend-read-crc-pipe-a.html

  
  {name}: This element is suppressed. This means it is ignored when computing
          the status of the difference (SUCCESS, WARNING, or FAILURE).

  [fdo#103558]: https://bugs.freedesktop.org/show_bug.cgi?id=103558
  [fdo#105602]: https://bugs.freedesktop.org/show_bug.cgi?id=105602
  [fdo#105763]: https://bugs.freedesktop.org/show_bug.cgi?id=105763
  [fdo#107713]: https://bugs.freedesktop.org/show_bug.cgi?id=107713
  [fdo#107724]: https://bugs.freedesktop.org/show_bug.cgi?id=107724
  [fdo#108511]: https://bugs.freedesktop.org/show_bug.cgi?id=108511
  [fdo#109964]: https://bugs.freedesktop.org/show_bug.cgi?id=109964
  [fdo#111735]: https://bugs.freedesktop.org/show_bug.cgi?id=111735
  [fdo#112260]: https://bugs.freedesktop.org/show_bug.cgi?id=112260
  [fdo#112298]: https://bugs.freedesktop.org/show_bug.cgi?id=112298


Participating hosts (51 -> 45)
------------------------------

  Missing    (6): fi-ilk-m540 fi-hsw-4200u fi-bsw-cyan fi-ctg-p8600 fi-byt-clapper fi-bdw-samus 


Build changes
-------------

  * CI: CI-20190529 -> None
  * IGT: IGT_5313 -> IGTPW_3778

  CI-20190529: 20190529
  CI_DRM_7438: 8a2661592e79e48bcba9c24565b2b16edafbcbaa @ git://anongit.freedesktop.org/gfx-ci/linux
  IGTPW_3778: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_3778/index.html
  IGT_5313: 92caadb4e551ba05aa6e6e567ef69da96ca7e328 @ git://anongit.freedesktop.org/xorg/app/intel-gpu-tools



== Testlist changes ==

+igt@gem_mmap_offset@bad-flags
+igt@gem_mmap_offset@bad-object
+igt@gem_mmap_offset@basic-uaf
+igt@gem_mmap_offset@clear
+igt@gem_mmap_offset@close-race
+igt@gem_mmap_offset@isolation
+igt@gem_mmap_offset@pf-nonblock

== Logs ==

For more details see: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_3778/index.html
_______________________________________________
igt-dev mailing list
igt-dev@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/igt-dev

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [igt-dev] [PATCH i-g-t] tests/i915/gem_mmap_offset: Add new API test for gem_mmap_offset
@ 2019-11-28 13:38       ` Petri Latvala
  0 siblings, 0 replies; 29+ messages in thread
From: Petri Latvala @ 2019-11-28 13:38 UTC (permalink / raw)
  To: Chris Wilson; +Cc: igt-dev, intel-gfx

On Thu, Nov 28, 2019 at 12:55:02PM +0000, Chris Wilson wrote:
> From: Lukasz Kalamarz <lukasz.kalamarz@intel.com>
> 
> Few simple tests which tries to create / mmap buffer objects
> using GEM_MMAP_OFFSET uAPI.
> 
> v2: change from WC -> WB (according to Chris review comment)
> v3: add mmap-offset-close-race test
> 
> Signed-off-by: Lukasz Kalamarz <lukasz.kalamarz@intel.com>
> Signed-off-by: Zbigniew Kempczyński <zbigniew.kempczynski@intel.com>
> Cc: Chris Wilson <chris@chris-wilson.co.uk>
> Cc: Vanshidhar Konda <vanshidhar.r.konda@intel.com>
> ---
> Required (look to gem_mmap_(gtt,wc,cpu) for ideas):
>  size - check we can handle objects beyond a reasonable limit (note the
> kernel fails at beyond RAM)
>  forked - interactions with pagefault + new mmap_offsets across
>           threads/processes
>  suspend - check speed is consistent before/after suspend
>  coherency - combinatorial checker between all pointer types, prw and gpu
> ---
>  tests/Makefile.sources       |   3 +
>  tests/i915/gem_mmap_offset.c | 416 +++++++++++++++++++++++++++++++++++
>  tests/meson.build            |   1 +
>  3 files changed, 420 insertions(+)
>  create mode 100644 tests/i915/gem_mmap_offset.c
> 
> diff --git a/tests/Makefile.sources b/tests/Makefile.sources
> index a211851cf..ddbc69bc8 100644
> --- a/tests/Makefile.sources
> +++ b/tests/Makefile.sources
> @@ -325,6 +325,9 @@ gem_mmap_SOURCES = i915/gem_mmap.c
>  TESTS_progs += gem_mmap_gtt
>  gem_mmap_gtt_SOURCES = i915/gem_mmap_gtt.c
>  
> +TESTS_progs += gem_mmap_offset
> +gem_mmap_offset_SOURCES = i915/gem_mmap_offset.c
> +
>  TESTS_progs += gem_mmap_offset_exhaustion
>  gem_mmap_offset_exhaustion_SOURCES = i915/gem_mmap_offset_exhaustion.c
>  
> diff --git a/tests/i915/gem_mmap_offset.c b/tests/i915/gem_mmap_offset.c
> new file mode 100644
> index 000000000..e75c3fd17
> --- /dev/null
> +++ b/tests/i915/gem_mmap_offset.c
> @@ -0,0 +1,416 @@
> +/*
> + * Copyright © 2019 Intel Corporation
> + *
> + * 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 (including the next
> + * paragraph) 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 <errno.h>
> +#include <pthread.h>
> +#include <stdatomic.h>
> +#include <sys/stat.h>
> +#include <sys/ioctl.h>
> +#include "drm.h"
> +
> +#include "igt.h"
> +#include "igt_x86.h"
> +
> +IGT_TEST_DESCRIPTION("Basic MMAP_OFFSET IOCTL tests for mem regions\n");
> +
> +static const struct mmap_offset {
> +	const char *name;
> +	unsigned int type;
> +	unsigned int domain;
> +} mmap_offset_types[] = {
> +	{ "gtt", I915_MMAP_OFFSET_GTT, I915_GEM_DOMAIN_GTT },
> +	{ "wb", I915_MMAP_OFFSET_WB, I915_GEM_DOMAIN_CPU },
> +	{ "wc", I915_MMAP_OFFSET_WC, I915_GEM_DOMAIN_WC },
> +	{ "uc", I915_MMAP_OFFSET_UC, I915_GEM_DOMAIN_WC },
> +	{},
> +};
> +
> +#define for_each_mmap_offset_type(__t) \
> +	for (const struct mmap_offset *__t = mmap_offset_types; \
> +	     (__t)->name; \
> +	     (__t)++)
> +
> +static int mmap_offset_ioctl(int i915, struct drm_i915_gem_mmap_offset *arg)
> +{
> +	int err = 0;
> +
> +	if (igt_ioctl(i915, DRM_IOCTL_I915_GEM_MMAP_OFFSET, arg)) {
> +		err = -errno;
> +		igt_assume(err);
> +	}
> +
> +	errno = 0;
> +	return err;
> +}
> +
> +static void bad_object(int i915)
> +{
> +	uint32_t real_handle;
> +	uint32_t handles[20];
> +	int i = 0;
> +
> +	real_handle = gem_create(i915, 4096);
> +
> +	handles[i++] = 0xdeadbeef;
> +	for (int bit = 0; bit < 16; bit++)
> +		handles[i++] = real_handle | (1 << (bit + 16));
> +	handles[i] = real_handle + 1;
> +
> +	for (; i >= 0; i--) {
> +		struct drm_i915_gem_mmap_offset arg = {
> +			.handle = handles[i],
> +			.flags = I915_MMAP_OFFSET_WB,
> +		};
> +
> +		igt_debug("Trying MMAP IOCTL with handle %x\n",
> +			  handles[i]);
> +		igt_assert_eq(mmap_offset_ioctl(i915, &arg),
> +			      -ENOENT);
> +	}
> +
> +	gem_close(i915, real_handle);
> +}
> +
> +static void bad_flags(int i915)
> +{
> +	struct drm_i915_gem_mmap_offset arg = {
> +		.handle = gem_create(i915, 4096),
> +		.flags = -1ull,
> +	};
> +
> +	igt_assert_eq(mmap_offset_ioctl(i915, &arg), -EINVAL);
> +	gem_close(i915, arg.handle);
> +}
> +
> +static void basic_uaf(int i915)
> +{
> +	const uint32_t obj_size = 4096;
> +
> +	for_each_mmap_offset_type(t) {
> +		uint32_t handle = gem_create(i915, obj_size);
> +		uint8_t *expected, *buf, *addr;
> +
> +		addr = __gem_mmap_offset(i915, handle, 0, obj_size,
> +					 PROT_READ | PROT_WRITE,
> +					 t->type);
> +		if (!addr) {
> +			gem_close(i915, handle);
> +			continue;
> +		}
> +
> +		expected = calloc(obj_size, sizeof(*expected));
> +		gem_set_domain(i915, handle, t->domain, 0);
> +		igt_assert_f(memcmp(addr, expected, obj_size) == 0,
> +			     "mmap(%s) not clear on gem_create()\n",
> +			     t->name);
> +		free(expected);
> +
> +		buf = calloc(obj_size, sizeof(*buf));
> +		memset(buf + 1024, 0x01, 1024);
> +		gem_write(i915, handle, 0, buf, obj_size);
> +		gem_set_domain(i915, handle, t->domain, 0);
> +		igt_assert_f(memcmp(buf, addr, obj_size) == 0,
> +			     "mmap(%s) not coherent with gem_write()\n",
> +			     t->name);
> +
> +		gem_set_domain(i915, handle, t->domain, t->domain);
> +		memset(addr + 2048, 0xff, 1024);
> +		gem_read(i915, handle, 0, buf, obj_size);
> +		gem_set_domain(i915, handle, t->domain, 0);
> +		igt_assert_f(memcmp(buf, addr, obj_size) == 0,
> +			     "mmap(%s) not coherent with gem_read()\n",
> +			     t->name);
> +
> +		gem_close(i915, handle);
> +		igt_assert_f(memcmp(buf, addr, obj_size) == 0,
> +			     "mmap(%s) not resident after gem_close()\n",
> +			     t->name);
> +		free(buf);
> +
> +		igt_debug("Testing unmapping\n");
> +		munmap(addr, obj_size);
> +	}
> +}
> +
> +static void isolation(int i915)
> +{
> +	for_each_mmap_offset_type(t) {
> +		struct drm_i915_gem_mmap_offset mmap_arg = {
> +			.flags = t->type
> +		};
> +		int A = gem_reopen_driver(i915);
> +		int B = gem_reopen_driver(i915);
> +		uint64_t offset_a, offset_b;
> +		uint32_t a, b;
> +		void *ptr;
> +
> +		a = gem_create(A, 4096);
> +		b = gem_open(B, gem_flink(A, a));
> +
> +		mmap_arg.handle = a;
> +		igt_assert_eq(mmap_offset_ioctl(i915, &mmap_arg), 0);
> +		offset_a = mmap_arg.offset;
> +
> +		mmap_arg.handle = b;
> +		igt_assert_eq(mmap_offset_ioctl(i915, &mmap_arg), 0);
> +		offset_b = mmap_arg.offset;
> +
> +		igt_info("A[%s]: {fd:%d, handle:%d, offset:%"PRIx64"}\n",
> +			 t->name, A, a, offset_a);
> +		igt_info("B[%s]: {fd:%d, handle:%d, offset:%"PRIx64"}\n",
> +			 t->name, B, b, offset_b);
> +
> +		close(B);
> +
> +		ptr = mmap64(0, 4096, PROT_READ, MAP_SHARED, A, offset_a);
> +		igt_assert(ptr != MAP_FAILED);
> +		munmap(ptr, 4096);
> +
> +		close(A);
> +
> +		ptr = mmap64(0, 4096, PROT_READ, MAP_SHARED, A, offset_a);
> +		igt_assert(ptr == MAP_FAILED);
> +	}
> +}
> +
> +static void pf_nonblock(int i915)
> +{
> +	igt_spin_t *spin = igt_spin_new(i915);
> +
> +	for_each_mmap_offset_type(t) {
> +		uint32_t *ptr;
> +
> +		ptr = __gem_mmap_offset(i915, spin->handle, 0, 4096,
> +					PROT_READ | PROT_WRITE,
> +					t->type);
> +		if (!ptr)
> +			continue;
> +
> +		igt_set_timeout(1, t->name);
> +		/* no set-domain as we want to verify the pagefault is async */
> +		ptr[256] = 0;
> +		igt_reset_timeout();
> +
> +		munmap(ptr, 4096);
> +	}
> +
> +	igt_spin_free(i915, spin);
> +}
> +
> +static void close_race(int i915, int timeout)
> +{
> +	const int ncpus = sysconf(_SC_NPROCESSORS_ONLN);
> +	_Atomic uint32_t *handles;
> +	size_t len = ALIGN((ncpus + 1) * sizeof(uint32_t), 4096);
> +
> +	handles = mmap64(0, len, PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0);
> +	igt_assert(handles != MAP_FAILED);
> +
> +	igt_fork(child, ncpus + 1) {
> +		do {
> +			struct drm_i915_gem_mmap_offset mmap_arg = {};
> +			const int i = 1 + random() % ncpus;
> +			uint32_t old;
> +
> +			mmap_arg.handle = gem_create(i915, 4096);
> +			mmap_arg.flags = I915_MMAP_OFFSET_WB;
> +			old = atomic_exchange(&handles[i], mmap_arg.handle);

This will require adding libatomic to this executable's dependencies
with meson. Look to handling of gem_create.c for an example.


-- 
Petri Latvala




> +			ioctl(i915, DRM_IOCTL_GEM_CLOSE, &old);
> +
> +			if (ioctl(i915,
> +				  DRM_IOCTL_I915_GEM_MMAP_OFFSET,
> +				  &mmap_arg) != -1) {
> +				void *ptr;
> +
> +				ptr = mmap64(0, 4096,
> +					     PROT_WRITE, MAP_SHARED, i915,
> +					     mmap_arg.offset);
> +				if (ptr != MAP_FAILED) {
> +					*(volatile uint32_t *)ptr = 0;
> +					munmap(ptr, 4096);
> +				}
> +			}
> +
> +		} while (!READ_ONCE(handles[0]));
> +	}
> +
> +	sleep(timeout);
> +	handles[0] = 1;
> +	igt_waitchildren();
> +
> +	for (int i = 1; i <= ncpus; i++)
> +		ioctl(i915, DRM_IOCTL_GEM_CLOSE, handles[i]);
> +	munmap(handles, len);
> +}
> +
> +static uint64_t atomic_compare_swap_u64(_Atomic(uint64_t) *ptr,
> +					uint64_t oldval, uint64_t newval)
> +{
> +	atomic_compare_exchange_strong(ptr, &oldval, newval);
> +	return oldval;
> +}
> +
> +static uint64_t get_npages(_Atomic(uint64_t) *global, uint64_t npages)
> +{
> +	uint64_t try, old, max;
> +
> +	max = *global;
> +	do {
> +		old = max;
> +		try = 1 + npages % (max / 2);
> +		max -= try;
> +	} while ((max = atomic_compare_swap_u64(global, old, max)) != old);
> +
> +	return try;
> +}
> +
> +struct thread_clear {
> +	_Atomic(uint64_t) max;
> +	int timeout;
> +	int i915;
> +};
> +
> +static int create_ioctl(int i915, struct drm_i915_gem_create *create)
> +{
> +	int err = 0;
> +
> +	if (igt_ioctl(i915, DRM_IOCTL_I915_GEM_CREATE, create)) {
> +		err = -errno;
> +		igt_assume(err != 0);
> +	}
> +
> +	errno = 0;
> +	return err;
> +}
> +
> +static void *thread_clear(void *data)
> +{
> +	struct thread_clear *arg = data;
> +	const struct mmap_offset *t;
> +	unsigned long checked = 0;
> +	int i915 = arg->i915;
> +
> +	t = mmap_offset_types;
> +	igt_until_timeout(arg->timeout) {
> +		struct drm_i915_gem_create create = {};
> +		uint64_t npages;
> +		void *ptr;
> +
> +		npages = random();
> +		npages <<= 32;
> +		npages |= random();
> +		npages = get_npages(&arg->max, npages);
> +		create.size = npages << 12;
> +
> +		create_ioctl(i915, &create);
> +		ptr = __gem_mmap_offset(i915, create.handle, 0, create.size,
> +					PROT_READ | PROT_WRITE,
> +					t->type);
> +		/* No set-domains as we are being as naughty as possible */
> +		for (uint64_t page = 0; ptr && page < npages; page++) {
> +			uint64_t x[8] = {
> +				page * 4096 +
> +					sizeof(x) * ((page % (4096 - sizeof(x)) / sizeof(x)))
> +			};
> +
> +			if (page & 1)
> +				igt_memcpy_from_wc(x, ptr + x[0], sizeof(x));
> +			else
> +				memcpy(x, ptr + x[0], sizeof(x));
> +
> +			for (int i = 0; i < ARRAY_SIZE(x); i++)
> +				igt_assert_eq_u64(x[i], 0);
> +		}
> +		if (ptr)
> +			munmap(ptr, create.size);
> +		gem_close(i915, create.handle);
> +		checked += npages;
> +
> +		atomic_fetch_add(&arg->max, npages);
> +
> +		if (!(++t)->name)
> +			t = mmap_offset_types;
> +	}
> +
> +	return (void *)(uintptr_t)checked;
> +}
> +
> +static void always_clear(int i915, int timeout)
> +{
> +	struct thread_clear arg = {
> +		.i915 = i915,
> +		.timeout = timeout,
> +		.max = intel_get_avail_ram_mb() << (20 - 12), /* in pages */
> +	};
> +	const int ncpus = sysconf(_SC_NPROCESSORS_ONLN);
> +	unsigned long checked;
> +	pthread_t thread[ncpus];
> +	void *result;
> +
> +	for (int i = 0; i < ncpus; i++)
> +		pthread_create(&thread[i], NULL, thread_clear, &arg);
> +
> +	checked = 0;
> +	for (int i = 0; i < ncpus; i++) {
> +		pthread_join(thread[i], &result);
> +		checked += (uintptr_t)result;
> +	}
> +	igt_info("Checked %'lu page allocations\n", checked);
> +}
> +
> +
> +igt_main
> +{
> +	int i915;
> +
> +	igt_fixture {
> +		i915 = drm_open_driver(DRIVER_INTEL);
> +		gem_require_mmap_offset(i915);
> +	}
> +
> +	igt_describe("Verify mapping to invalid gem objects won't be created");
> +	igt_subtest_f("bad-object")
> +		bad_object(i915);
> +	igt_subtest_f("bad-flags")
> +		bad_flags(i915);
> +
> +	igt_describe("Check buffer object mapping persists after gem_close");
> +	igt_subtest_f("basic-uaf")
> +		basic_uaf(i915);
> +
> +	igt_subtest_f("isolation")
> +		isolation(i915);
> +	igt_subtest_f("pf-nonblock")
> +		pf_nonblock(i915);
> +
> +	igt_describe("Check race between close and mmap offset between threads");
> +	igt_subtest_f("close-race")
> +		close_race(i915, 20);
> +
> +	igt_subtest_f("clear")
> +		always_clear(i915, 20);
> +
> +	igt_fixture {
> +		close(i915);
> +	}
> +}
> diff --git a/tests/meson.build b/tests/meson.build
> index 18788d44b..05dea1f4e 100644
> --- a/tests/meson.build
> +++ b/tests/meson.build
> @@ -174,6 +174,7 @@ i915_progs = [
>  	'gem_media_vme',
>  	'gem_mmap',
>  	'gem_mmap_gtt',
> +	'gem_mmap_offset',
>  	'gem_mmap_offset_exhaustion',
>  	'gem_mmap_wc',
>  	'gem_partial_pwrite_pread',
> -- 
> 2.24.0
> 
> _______________________________________________
> igt-dev mailing list
> igt-dev@lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/igt-dev
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [Intel-gfx] [igt-dev] [PATCH i-g-t] tests/i915/gem_mmap_offset: Add new API test for gem_mmap_offset
@ 2019-11-28 13:38       ` Petri Latvala
  0 siblings, 0 replies; 29+ messages in thread
From: Petri Latvala @ 2019-11-28 13:38 UTC (permalink / raw)
  To: Chris Wilson; +Cc: igt-dev, intel-gfx

On Thu, Nov 28, 2019 at 12:55:02PM +0000, Chris Wilson wrote:
> From: Lukasz Kalamarz <lukasz.kalamarz@intel.com>
> 
> Few simple tests which tries to create / mmap buffer objects
> using GEM_MMAP_OFFSET uAPI.
> 
> v2: change from WC -> WB (according to Chris review comment)
> v3: add mmap-offset-close-race test
> 
> Signed-off-by: Lukasz Kalamarz <lukasz.kalamarz@intel.com>
> Signed-off-by: Zbigniew Kempczyński <zbigniew.kempczynski@intel.com>
> Cc: Chris Wilson <chris@chris-wilson.co.uk>
> Cc: Vanshidhar Konda <vanshidhar.r.konda@intel.com>
> ---
> Required (look to gem_mmap_(gtt,wc,cpu) for ideas):
>  size - check we can handle objects beyond a reasonable limit (note the
> kernel fails at beyond RAM)
>  forked - interactions with pagefault + new mmap_offsets across
>           threads/processes
>  suspend - check speed is consistent before/after suspend
>  coherency - combinatorial checker between all pointer types, prw and gpu
> ---
>  tests/Makefile.sources       |   3 +
>  tests/i915/gem_mmap_offset.c | 416 +++++++++++++++++++++++++++++++++++
>  tests/meson.build            |   1 +
>  3 files changed, 420 insertions(+)
>  create mode 100644 tests/i915/gem_mmap_offset.c
> 
> diff --git a/tests/Makefile.sources b/tests/Makefile.sources
> index a211851cf..ddbc69bc8 100644
> --- a/tests/Makefile.sources
> +++ b/tests/Makefile.sources
> @@ -325,6 +325,9 @@ gem_mmap_SOURCES = i915/gem_mmap.c
>  TESTS_progs += gem_mmap_gtt
>  gem_mmap_gtt_SOURCES = i915/gem_mmap_gtt.c
>  
> +TESTS_progs += gem_mmap_offset
> +gem_mmap_offset_SOURCES = i915/gem_mmap_offset.c
> +
>  TESTS_progs += gem_mmap_offset_exhaustion
>  gem_mmap_offset_exhaustion_SOURCES = i915/gem_mmap_offset_exhaustion.c
>  
> diff --git a/tests/i915/gem_mmap_offset.c b/tests/i915/gem_mmap_offset.c
> new file mode 100644
> index 000000000..e75c3fd17
> --- /dev/null
> +++ b/tests/i915/gem_mmap_offset.c
> @@ -0,0 +1,416 @@
> +/*
> + * Copyright © 2019 Intel Corporation
> + *
> + * 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 (including the next
> + * paragraph) 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 <errno.h>
> +#include <pthread.h>
> +#include <stdatomic.h>
> +#include <sys/stat.h>
> +#include <sys/ioctl.h>
> +#include "drm.h"
> +
> +#include "igt.h"
> +#include "igt_x86.h"
> +
> +IGT_TEST_DESCRIPTION("Basic MMAP_OFFSET IOCTL tests for mem regions\n");
> +
> +static const struct mmap_offset {
> +	const char *name;
> +	unsigned int type;
> +	unsigned int domain;
> +} mmap_offset_types[] = {
> +	{ "gtt", I915_MMAP_OFFSET_GTT, I915_GEM_DOMAIN_GTT },
> +	{ "wb", I915_MMAP_OFFSET_WB, I915_GEM_DOMAIN_CPU },
> +	{ "wc", I915_MMAP_OFFSET_WC, I915_GEM_DOMAIN_WC },
> +	{ "uc", I915_MMAP_OFFSET_UC, I915_GEM_DOMAIN_WC },
> +	{},
> +};
> +
> +#define for_each_mmap_offset_type(__t) \
> +	for (const struct mmap_offset *__t = mmap_offset_types; \
> +	     (__t)->name; \
> +	     (__t)++)
> +
> +static int mmap_offset_ioctl(int i915, struct drm_i915_gem_mmap_offset *arg)
> +{
> +	int err = 0;
> +
> +	if (igt_ioctl(i915, DRM_IOCTL_I915_GEM_MMAP_OFFSET, arg)) {
> +		err = -errno;
> +		igt_assume(err);
> +	}
> +
> +	errno = 0;
> +	return err;
> +}
> +
> +static void bad_object(int i915)
> +{
> +	uint32_t real_handle;
> +	uint32_t handles[20];
> +	int i = 0;
> +
> +	real_handle = gem_create(i915, 4096);
> +
> +	handles[i++] = 0xdeadbeef;
> +	for (int bit = 0; bit < 16; bit++)
> +		handles[i++] = real_handle | (1 << (bit + 16));
> +	handles[i] = real_handle + 1;
> +
> +	for (; i >= 0; i--) {
> +		struct drm_i915_gem_mmap_offset arg = {
> +			.handle = handles[i],
> +			.flags = I915_MMAP_OFFSET_WB,
> +		};
> +
> +		igt_debug("Trying MMAP IOCTL with handle %x\n",
> +			  handles[i]);
> +		igt_assert_eq(mmap_offset_ioctl(i915, &arg),
> +			      -ENOENT);
> +	}
> +
> +	gem_close(i915, real_handle);
> +}
> +
> +static void bad_flags(int i915)
> +{
> +	struct drm_i915_gem_mmap_offset arg = {
> +		.handle = gem_create(i915, 4096),
> +		.flags = -1ull,
> +	};
> +
> +	igt_assert_eq(mmap_offset_ioctl(i915, &arg), -EINVAL);
> +	gem_close(i915, arg.handle);
> +}
> +
> +static void basic_uaf(int i915)
> +{
> +	const uint32_t obj_size = 4096;
> +
> +	for_each_mmap_offset_type(t) {
> +		uint32_t handle = gem_create(i915, obj_size);
> +		uint8_t *expected, *buf, *addr;
> +
> +		addr = __gem_mmap_offset(i915, handle, 0, obj_size,
> +					 PROT_READ | PROT_WRITE,
> +					 t->type);
> +		if (!addr) {
> +			gem_close(i915, handle);
> +			continue;
> +		}
> +
> +		expected = calloc(obj_size, sizeof(*expected));
> +		gem_set_domain(i915, handle, t->domain, 0);
> +		igt_assert_f(memcmp(addr, expected, obj_size) == 0,
> +			     "mmap(%s) not clear on gem_create()\n",
> +			     t->name);
> +		free(expected);
> +
> +		buf = calloc(obj_size, sizeof(*buf));
> +		memset(buf + 1024, 0x01, 1024);
> +		gem_write(i915, handle, 0, buf, obj_size);
> +		gem_set_domain(i915, handle, t->domain, 0);
> +		igt_assert_f(memcmp(buf, addr, obj_size) == 0,
> +			     "mmap(%s) not coherent with gem_write()\n",
> +			     t->name);
> +
> +		gem_set_domain(i915, handle, t->domain, t->domain);
> +		memset(addr + 2048, 0xff, 1024);
> +		gem_read(i915, handle, 0, buf, obj_size);
> +		gem_set_domain(i915, handle, t->domain, 0);
> +		igt_assert_f(memcmp(buf, addr, obj_size) == 0,
> +			     "mmap(%s) not coherent with gem_read()\n",
> +			     t->name);
> +
> +		gem_close(i915, handle);
> +		igt_assert_f(memcmp(buf, addr, obj_size) == 0,
> +			     "mmap(%s) not resident after gem_close()\n",
> +			     t->name);
> +		free(buf);
> +
> +		igt_debug("Testing unmapping\n");
> +		munmap(addr, obj_size);
> +	}
> +}
> +
> +static void isolation(int i915)
> +{
> +	for_each_mmap_offset_type(t) {
> +		struct drm_i915_gem_mmap_offset mmap_arg = {
> +			.flags = t->type
> +		};
> +		int A = gem_reopen_driver(i915);
> +		int B = gem_reopen_driver(i915);
> +		uint64_t offset_a, offset_b;
> +		uint32_t a, b;
> +		void *ptr;
> +
> +		a = gem_create(A, 4096);
> +		b = gem_open(B, gem_flink(A, a));
> +
> +		mmap_arg.handle = a;
> +		igt_assert_eq(mmap_offset_ioctl(i915, &mmap_arg), 0);
> +		offset_a = mmap_arg.offset;
> +
> +		mmap_arg.handle = b;
> +		igt_assert_eq(mmap_offset_ioctl(i915, &mmap_arg), 0);
> +		offset_b = mmap_arg.offset;
> +
> +		igt_info("A[%s]: {fd:%d, handle:%d, offset:%"PRIx64"}\n",
> +			 t->name, A, a, offset_a);
> +		igt_info("B[%s]: {fd:%d, handle:%d, offset:%"PRIx64"}\n",
> +			 t->name, B, b, offset_b);
> +
> +		close(B);
> +
> +		ptr = mmap64(0, 4096, PROT_READ, MAP_SHARED, A, offset_a);
> +		igt_assert(ptr != MAP_FAILED);
> +		munmap(ptr, 4096);
> +
> +		close(A);
> +
> +		ptr = mmap64(0, 4096, PROT_READ, MAP_SHARED, A, offset_a);
> +		igt_assert(ptr == MAP_FAILED);
> +	}
> +}
> +
> +static void pf_nonblock(int i915)
> +{
> +	igt_spin_t *spin = igt_spin_new(i915);
> +
> +	for_each_mmap_offset_type(t) {
> +		uint32_t *ptr;
> +
> +		ptr = __gem_mmap_offset(i915, spin->handle, 0, 4096,
> +					PROT_READ | PROT_WRITE,
> +					t->type);
> +		if (!ptr)
> +			continue;
> +
> +		igt_set_timeout(1, t->name);
> +		/* no set-domain as we want to verify the pagefault is async */
> +		ptr[256] = 0;
> +		igt_reset_timeout();
> +
> +		munmap(ptr, 4096);
> +	}
> +
> +	igt_spin_free(i915, spin);
> +}
> +
> +static void close_race(int i915, int timeout)
> +{
> +	const int ncpus = sysconf(_SC_NPROCESSORS_ONLN);
> +	_Atomic uint32_t *handles;
> +	size_t len = ALIGN((ncpus + 1) * sizeof(uint32_t), 4096);
> +
> +	handles = mmap64(0, len, PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0);
> +	igt_assert(handles != MAP_FAILED);
> +
> +	igt_fork(child, ncpus + 1) {
> +		do {
> +			struct drm_i915_gem_mmap_offset mmap_arg = {};
> +			const int i = 1 + random() % ncpus;
> +			uint32_t old;
> +
> +			mmap_arg.handle = gem_create(i915, 4096);
> +			mmap_arg.flags = I915_MMAP_OFFSET_WB;
> +			old = atomic_exchange(&handles[i], mmap_arg.handle);

This will require adding libatomic to this executable's dependencies
with meson. Look to handling of gem_create.c for an example.


-- 
Petri Latvala




> +			ioctl(i915, DRM_IOCTL_GEM_CLOSE, &old);
> +
> +			if (ioctl(i915,
> +				  DRM_IOCTL_I915_GEM_MMAP_OFFSET,
> +				  &mmap_arg) != -1) {
> +				void *ptr;
> +
> +				ptr = mmap64(0, 4096,
> +					     PROT_WRITE, MAP_SHARED, i915,
> +					     mmap_arg.offset);
> +				if (ptr != MAP_FAILED) {
> +					*(volatile uint32_t *)ptr = 0;
> +					munmap(ptr, 4096);
> +				}
> +			}
> +
> +		} while (!READ_ONCE(handles[0]));
> +	}
> +
> +	sleep(timeout);
> +	handles[0] = 1;
> +	igt_waitchildren();
> +
> +	for (int i = 1; i <= ncpus; i++)
> +		ioctl(i915, DRM_IOCTL_GEM_CLOSE, handles[i]);
> +	munmap(handles, len);
> +}
> +
> +static uint64_t atomic_compare_swap_u64(_Atomic(uint64_t) *ptr,
> +					uint64_t oldval, uint64_t newval)
> +{
> +	atomic_compare_exchange_strong(ptr, &oldval, newval);
> +	return oldval;
> +}
> +
> +static uint64_t get_npages(_Atomic(uint64_t) *global, uint64_t npages)
> +{
> +	uint64_t try, old, max;
> +
> +	max = *global;
> +	do {
> +		old = max;
> +		try = 1 + npages % (max / 2);
> +		max -= try;
> +	} while ((max = atomic_compare_swap_u64(global, old, max)) != old);
> +
> +	return try;
> +}
> +
> +struct thread_clear {
> +	_Atomic(uint64_t) max;
> +	int timeout;
> +	int i915;
> +};
> +
> +static int create_ioctl(int i915, struct drm_i915_gem_create *create)
> +{
> +	int err = 0;
> +
> +	if (igt_ioctl(i915, DRM_IOCTL_I915_GEM_CREATE, create)) {
> +		err = -errno;
> +		igt_assume(err != 0);
> +	}
> +
> +	errno = 0;
> +	return err;
> +}
> +
> +static void *thread_clear(void *data)
> +{
> +	struct thread_clear *arg = data;
> +	const struct mmap_offset *t;
> +	unsigned long checked = 0;
> +	int i915 = arg->i915;
> +
> +	t = mmap_offset_types;
> +	igt_until_timeout(arg->timeout) {
> +		struct drm_i915_gem_create create = {};
> +		uint64_t npages;
> +		void *ptr;
> +
> +		npages = random();
> +		npages <<= 32;
> +		npages |= random();
> +		npages = get_npages(&arg->max, npages);
> +		create.size = npages << 12;
> +
> +		create_ioctl(i915, &create);
> +		ptr = __gem_mmap_offset(i915, create.handle, 0, create.size,
> +					PROT_READ | PROT_WRITE,
> +					t->type);
> +		/* No set-domains as we are being as naughty as possible */
> +		for (uint64_t page = 0; ptr && page < npages; page++) {
> +			uint64_t x[8] = {
> +				page * 4096 +
> +					sizeof(x) * ((page % (4096 - sizeof(x)) / sizeof(x)))
> +			};
> +
> +			if (page & 1)
> +				igt_memcpy_from_wc(x, ptr + x[0], sizeof(x));
> +			else
> +				memcpy(x, ptr + x[0], sizeof(x));
> +
> +			for (int i = 0; i < ARRAY_SIZE(x); i++)
> +				igt_assert_eq_u64(x[i], 0);
> +		}
> +		if (ptr)
> +			munmap(ptr, create.size);
> +		gem_close(i915, create.handle);
> +		checked += npages;
> +
> +		atomic_fetch_add(&arg->max, npages);
> +
> +		if (!(++t)->name)
> +			t = mmap_offset_types;
> +	}
> +
> +	return (void *)(uintptr_t)checked;
> +}
> +
> +static void always_clear(int i915, int timeout)
> +{
> +	struct thread_clear arg = {
> +		.i915 = i915,
> +		.timeout = timeout,
> +		.max = intel_get_avail_ram_mb() << (20 - 12), /* in pages */
> +	};
> +	const int ncpus = sysconf(_SC_NPROCESSORS_ONLN);
> +	unsigned long checked;
> +	pthread_t thread[ncpus];
> +	void *result;
> +
> +	for (int i = 0; i < ncpus; i++)
> +		pthread_create(&thread[i], NULL, thread_clear, &arg);
> +
> +	checked = 0;
> +	for (int i = 0; i < ncpus; i++) {
> +		pthread_join(thread[i], &result);
> +		checked += (uintptr_t)result;
> +	}
> +	igt_info("Checked %'lu page allocations\n", checked);
> +}
> +
> +
> +igt_main
> +{
> +	int i915;
> +
> +	igt_fixture {
> +		i915 = drm_open_driver(DRIVER_INTEL);
> +		gem_require_mmap_offset(i915);
> +	}
> +
> +	igt_describe("Verify mapping to invalid gem objects won't be created");
> +	igt_subtest_f("bad-object")
> +		bad_object(i915);
> +	igt_subtest_f("bad-flags")
> +		bad_flags(i915);
> +
> +	igt_describe("Check buffer object mapping persists after gem_close");
> +	igt_subtest_f("basic-uaf")
> +		basic_uaf(i915);
> +
> +	igt_subtest_f("isolation")
> +		isolation(i915);
> +	igt_subtest_f("pf-nonblock")
> +		pf_nonblock(i915);
> +
> +	igt_describe("Check race between close and mmap offset between threads");
> +	igt_subtest_f("close-race")
> +		close_race(i915, 20);
> +
> +	igt_subtest_f("clear")
> +		always_clear(i915, 20);
> +
> +	igt_fixture {
> +		close(i915);
> +	}
> +}
> diff --git a/tests/meson.build b/tests/meson.build
> index 18788d44b..05dea1f4e 100644
> --- a/tests/meson.build
> +++ b/tests/meson.build
> @@ -174,6 +174,7 @@ i915_progs = [
>  	'gem_media_vme',
>  	'gem_mmap',
>  	'gem_mmap_gtt',
> +	'gem_mmap_offset',
>  	'gem_mmap_offset_exhaustion',
>  	'gem_mmap_wc',
>  	'gem_partial_pwrite_pread',
> -- 
> 2.24.0
> 
> _______________________________________________
> igt-dev mailing list
> igt-dev@lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/igt-dev
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [igt-dev] [PATCH i-g-t] tests/i915/gem_mmap_offset: Add new API test for gem_mmap_offset
@ 2019-11-28 13:38       ` Petri Latvala
  0 siblings, 0 replies; 29+ messages in thread
From: Petri Latvala @ 2019-11-28 13:38 UTC (permalink / raw)
  To: Chris Wilson; +Cc: igt-dev, intel-gfx

On Thu, Nov 28, 2019 at 12:55:02PM +0000, Chris Wilson wrote:
> From: Lukasz Kalamarz <lukasz.kalamarz@intel.com>
> 
> Few simple tests which tries to create / mmap buffer objects
> using GEM_MMAP_OFFSET uAPI.
> 
> v2: change from WC -> WB (according to Chris review comment)
> v3: add mmap-offset-close-race test
> 
> Signed-off-by: Lukasz Kalamarz <lukasz.kalamarz@intel.com>
> Signed-off-by: Zbigniew Kempczyński <zbigniew.kempczynski@intel.com>
> Cc: Chris Wilson <chris@chris-wilson.co.uk>
> Cc: Vanshidhar Konda <vanshidhar.r.konda@intel.com>
> ---
> Required (look to gem_mmap_(gtt,wc,cpu) for ideas):
>  size - check we can handle objects beyond a reasonable limit (note the
> kernel fails at beyond RAM)
>  forked - interactions with pagefault + new mmap_offsets across
>           threads/processes
>  suspend - check speed is consistent before/after suspend
>  coherency - combinatorial checker between all pointer types, prw and gpu
> ---
>  tests/Makefile.sources       |   3 +
>  tests/i915/gem_mmap_offset.c | 416 +++++++++++++++++++++++++++++++++++
>  tests/meson.build            |   1 +
>  3 files changed, 420 insertions(+)
>  create mode 100644 tests/i915/gem_mmap_offset.c
> 
> diff --git a/tests/Makefile.sources b/tests/Makefile.sources
> index a211851cf..ddbc69bc8 100644
> --- a/tests/Makefile.sources
> +++ b/tests/Makefile.sources
> @@ -325,6 +325,9 @@ gem_mmap_SOURCES = i915/gem_mmap.c
>  TESTS_progs += gem_mmap_gtt
>  gem_mmap_gtt_SOURCES = i915/gem_mmap_gtt.c
>  
> +TESTS_progs += gem_mmap_offset
> +gem_mmap_offset_SOURCES = i915/gem_mmap_offset.c
> +
>  TESTS_progs += gem_mmap_offset_exhaustion
>  gem_mmap_offset_exhaustion_SOURCES = i915/gem_mmap_offset_exhaustion.c
>  
> diff --git a/tests/i915/gem_mmap_offset.c b/tests/i915/gem_mmap_offset.c
> new file mode 100644
> index 000000000..e75c3fd17
> --- /dev/null
> +++ b/tests/i915/gem_mmap_offset.c
> @@ -0,0 +1,416 @@
> +/*
> + * Copyright © 2019 Intel Corporation
> + *
> + * 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 (including the next
> + * paragraph) 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 <errno.h>
> +#include <pthread.h>
> +#include <stdatomic.h>
> +#include <sys/stat.h>
> +#include <sys/ioctl.h>
> +#include "drm.h"
> +
> +#include "igt.h"
> +#include "igt_x86.h"
> +
> +IGT_TEST_DESCRIPTION("Basic MMAP_OFFSET IOCTL tests for mem regions\n");
> +
> +static const struct mmap_offset {
> +	const char *name;
> +	unsigned int type;
> +	unsigned int domain;
> +} mmap_offset_types[] = {
> +	{ "gtt", I915_MMAP_OFFSET_GTT, I915_GEM_DOMAIN_GTT },
> +	{ "wb", I915_MMAP_OFFSET_WB, I915_GEM_DOMAIN_CPU },
> +	{ "wc", I915_MMAP_OFFSET_WC, I915_GEM_DOMAIN_WC },
> +	{ "uc", I915_MMAP_OFFSET_UC, I915_GEM_DOMAIN_WC },
> +	{},
> +};
> +
> +#define for_each_mmap_offset_type(__t) \
> +	for (const struct mmap_offset *__t = mmap_offset_types; \
> +	     (__t)->name; \
> +	     (__t)++)
> +
> +static int mmap_offset_ioctl(int i915, struct drm_i915_gem_mmap_offset *arg)
> +{
> +	int err = 0;
> +
> +	if (igt_ioctl(i915, DRM_IOCTL_I915_GEM_MMAP_OFFSET, arg)) {
> +		err = -errno;
> +		igt_assume(err);
> +	}
> +
> +	errno = 0;
> +	return err;
> +}
> +
> +static void bad_object(int i915)
> +{
> +	uint32_t real_handle;
> +	uint32_t handles[20];
> +	int i = 0;
> +
> +	real_handle = gem_create(i915, 4096);
> +
> +	handles[i++] = 0xdeadbeef;
> +	for (int bit = 0; bit < 16; bit++)
> +		handles[i++] = real_handle | (1 << (bit + 16));
> +	handles[i] = real_handle + 1;
> +
> +	for (; i >= 0; i--) {
> +		struct drm_i915_gem_mmap_offset arg = {
> +			.handle = handles[i],
> +			.flags = I915_MMAP_OFFSET_WB,
> +		};
> +
> +		igt_debug("Trying MMAP IOCTL with handle %x\n",
> +			  handles[i]);
> +		igt_assert_eq(mmap_offset_ioctl(i915, &arg),
> +			      -ENOENT);
> +	}
> +
> +	gem_close(i915, real_handle);
> +}
> +
> +static void bad_flags(int i915)
> +{
> +	struct drm_i915_gem_mmap_offset arg = {
> +		.handle = gem_create(i915, 4096),
> +		.flags = -1ull,
> +	};
> +
> +	igt_assert_eq(mmap_offset_ioctl(i915, &arg), -EINVAL);
> +	gem_close(i915, arg.handle);
> +}
> +
> +static void basic_uaf(int i915)
> +{
> +	const uint32_t obj_size = 4096;
> +
> +	for_each_mmap_offset_type(t) {
> +		uint32_t handle = gem_create(i915, obj_size);
> +		uint8_t *expected, *buf, *addr;
> +
> +		addr = __gem_mmap_offset(i915, handle, 0, obj_size,
> +					 PROT_READ | PROT_WRITE,
> +					 t->type);
> +		if (!addr) {
> +			gem_close(i915, handle);
> +			continue;
> +		}
> +
> +		expected = calloc(obj_size, sizeof(*expected));
> +		gem_set_domain(i915, handle, t->domain, 0);
> +		igt_assert_f(memcmp(addr, expected, obj_size) == 0,
> +			     "mmap(%s) not clear on gem_create()\n",
> +			     t->name);
> +		free(expected);
> +
> +		buf = calloc(obj_size, sizeof(*buf));
> +		memset(buf + 1024, 0x01, 1024);
> +		gem_write(i915, handle, 0, buf, obj_size);
> +		gem_set_domain(i915, handle, t->domain, 0);
> +		igt_assert_f(memcmp(buf, addr, obj_size) == 0,
> +			     "mmap(%s) not coherent with gem_write()\n",
> +			     t->name);
> +
> +		gem_set_domain(i915, handle, t->domain, t->domain);
> +		memset(addr + 2048, 0xff, 1024);
> +		gem_read(i915, handle, 0, buf, obj_size);
> +		gem_set_domain(i915, handle, t->domain, 0);
> +		igt_assert_f(memcmp(buf, addr, obj_size) == 0,
> +			     "mmap(%s) not coherent with gem_read()\n",
> +			     t->name);
> +
> +		gem_close(i915, handle);
> +		igt_assert_f(memcmp(buf, addr, obj_size) == 0,
> +			     "mmap(%s) not resident after gem_close()\n",
> +			     t->name);
> +		free(buf);
> +
> +		igt_debug("Testing unmapping\n");
> +		munmap(addr, obj_size);
> +	}
> +}
> +
> +static void isolation(int i915)
> +{
> +	for_each_mmap_offset_type(t) {
> +		struct drm_i915_gem_mmap_offset mmap_arg = {
> +			.flags = t->type
> +		};
> +		int A = gem_reopen_driver(i915);
> +		int B = gem_reopen_driver(i915);
> +		uint64_t offset_a, offset_b;
> +		uint32_t a, b;
> +		void *ptr;
> +
> +		a = gem_create(A, 4096);
> +		b = gem_open(B, gem_flink(A, a));
> +
> +		mmap_arg.handle = a;
> +		igt_assert_eq(mmap_offset_ioctl(i915, &mmap_arg), 0);
> +		offset_a = mmap_arg.offset;
> +
> +		mmap_arg.handle = b;
> +		igt_assert_eq(mmap_offset_ioctl(i915, &mmap_arg), 0);
> +		offset_b = mmap_arg.offset;
> +
> +		igt_info("A[%s]: {fd:%d, handle:%d, offset:%"PRIx64"}\n",
> +			 t->name, A, a, offset_a);
> +		igt_info("B[%s]: {fd:%d, handle:%d, offset:%"PRIx64"}\n",
> +			 t->name, B, b, offset_b);
> +
> +		close(B);
> +
> +		ptr = mmap64(0, 4096, PROT_READ, MAP_SHARED, A, offset_a);
> +		igt_assert(ptr != MAP_FAILED);
> +		munmap(ptr, 4096);
> +
> +		close(A);
> +
> +		ptr = mmap64(0, 4096, PROT_READ, MAP_SHARED, A, offset_a);
> +		igt_assert(ptr == MAP_FAILED);
> +	}
> +}
> +
> +static void pf_nonblock(int i915)
> +{
> +	igt_spin_t *spin = igt_spin_new(i915);
> +
> +	for_each_mmap_offset_type(t) {
> +		uint32_t *ptr;
> +
> +		ptr = __gem_mmap_offset(i915, spin->handle, 0, 4096,
> +					PROT_READ | PROT_WRITE,
> +					t->type);
> +		if (!ptr)
> +			continue;
> +
> +		igt_set_timeout(1, t->name);
> +		/* no set-domain as we want to verify the pagefault is async */
> +		ptr[256] = 0;
> +		igt_reset_timeout();
> +
> +		munmap(ptr, 4096);
> +	}
> +
> +	igt_spin_free(i915, spin);
> +}
> +
> +static void close_race(int i915, int timeout)
> +{
> +	const int ncpus = sysconf(_SC_NPROCESSORS_ONLN);
> +	_Atomic uint32_t *handles;
> +	size_t len = ALIGN((ncpus + 1) * sizeof(uint32_t), 4096);
> +
> +	handles = mmap64(0, len, PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0);
> +	igt_assert(handles != MAP_FAILED);
> +
> +	igt_fork(child, ncpus + 1) {
> +		do {
> +			struct drm_i915_gem_mmap_offset mmap_arg = {};
> +			const int i = 1 + random() % ncpus;
> +			uint32_t old;
> +
> +			mmap_arg.handle = gem_create(i915, 4096);
> +			mmap_arg.flags = I915_MMAP_OFFSET_WB;
> +			old = atomic_exchange(&handles[i], mmap_arg.handle);

This will require adding libatomic to this executable's dependencies
with meson. Look to handling of gem_create.c for an example.


-- 
Petri Latvala




> +			ioctl(i915, DRM_IOCTL_GEM_CLOSE, &old);
> +
> +			if (ioctl(i915,
> +				  DRM_IOCTL_I915_GEM_MMAP_OFFSET,
> +				  &mmap_arg) != -1) {
> +				void *ptr;
> +
> +				ptr = mmap64(0, 4096,
> +					     PROT_WRITE, MAP_SHARED, i915,
> +					     mmap_arg.offset);
> +				if (ptr != MAP_FAILED) {
> +					*(volatile uint32_t *)ptr = 0;
> +					munmap(ptr, 4096);
> +				}
> +			}
> +
> +		} while (!READ_ONCE(handles[0]));
> +	}
> +
> +	sleep(timeout);
> +	handles[0] = 1;
> +	igt_waitchildren();
> +
> +	for (int i = 1; i <= ncpus; i++)
> +		ioctl(i915, DRM_IOCTL_GEM_CLOSE, handles[i]);
> +	munmap(handles, len);
> +}
> +
> +static uint64_t atomic_compare_swap_u64(_Atomic(uint64_t) *ptr,
> +					uint64_t oldval, uint64_t newval)
> +{
> +	atomic_compare_exchange_strong(ptr, &oldval, newval);
> +	return oldval;
> +}
> +
> +static uint64_t get_npages(_Atomic(uint64_t) *global, uint64_t npages)
> +{
> +	uint64_t try, old, max;
> +
> +	max = *global;
> +	do {
> +		old = max;
> +		try = 1 + npages % (max / 2);
> +		max -= try;
> +	} while ((max = atomic_compare_swap_u64(global, old, max)) != old);
> +
> +	return try;
> +}
> +
> +struct thread_clear {
> +	_Atomic(uint64_t) max;
> +	int timeout;
> +	int i915;
> +};
> +
> +static int create_ioctl(int i915, struct drm_i915_gem_create *create)
> +{
> +	int err = 0;
> +
> +	if (igt_ioctl(i915, DRM_IOCTL_I915_GEM_CREATE, create)) {
> +		err = -errno;
> +		igt_assume(err != 0);
> +	}
> +
> +	errno = 0;
> +	return err;
> +}
> +
> +static void *thread_clear(void *data)
> +{
> +	struct thread_clear *arg = data;
> +	const struct mmap_offset *t;
> +	unsigned long checked = 0;
> +	int i915 = arg->i915;
> +
> +	t = mmap_offset_types;
> +	igt_until_timeout(arg->timeout) {
> +		struct drm_i915_gem_create create = {};
> +		uint64_t npages;
> +		void *ptr;
> +
> +		npages = random();
> +		npages <<= 32;
> +		npages |= random();
> +		npages = get_npages(&arg->max, npages);
> +		create.size = npages << 12;
> +
> +		create_ioctl(i915, &create);
> +		ptr = __gem_mmap_offset(i915, create.handle, 0, create.size,
> +					PROT_READ | PROT_WRITE,
> +					t->type);
> +		/* No set-domains as we are being as naughty as possible */
> +		for (uint64_t page = 0; ptr && page < npages; page++) {
> +			uint64_t x[8] = {
> +				page * 4096 +
> +					sizeof(x) * ((page % (4096 - sizeof(x)) / sizeof(x)))
> +			};
> +
> +			if (page & 1)
> +				igt_memcpy_from_wc(x, ptr + x[0], sizeof(x));
> +			else
> +				memcpy(x, ptr + x[0], sizeof(x));
> +
> +			for (int i = 0; i < ARRAY_SIZE(x); i++)
> +				igt_assert_eq_u64(x[i], 0);
> +		}
> +		if (ptr)
> +			munmap(ptr, create.size);
> +		gem_close(i915, create.handle);
> +		checked += npages;
> +
> +		atomic_fetch_add(&arg->max, npages);
> +
> +		if (!(++t)->name)
> +			t = mmap_offset_types;
> +	}
> +
> +	return (void *)(uintptr_t)checked;
> +}
> +
> +static void always_clear(int i915, int timeout)
> +{
> +	struct thread_clear arg = {
> +		.i915 = i915,
> +		.timeout = timeout,
> +		.max = intel_get_avail_ram_mb() << (20 - 12), /* in pages */
> +	};
> +	const int ncpus = sysconf(_SC_NPROCESSORS_ONLN);
> +	unsigned long checked;
> +	pthread_t thread[ncpus];
> +	void *result;
> +
> +	for (int i = 0; i < ncpus; i++)
> +		pthread_create(&thread[i], NULL, thread_clear, &arg);
> +
> +	checked = 0;
> +	for (int i = 0; i < ncpus; i++) {
> +		pthread_join(thread[i], &result);
> +		checked += (uintptr_t)result;
> +	}
> +	igt_info("Checked %'lu page allocations\n", checked);
> +}
> +
> +
> +igt_main
> +{
> +	int i915;
> +
> +	igt_fixture {
> +		i915 = drm_open_driver(DRIVER_INTEL);
> +		gem_require_mmap_offset(i915);
> +	}
> +
> +	igt_describe("Verify mapping to invalid gem objects won't be created");
> +	igt_subtest_f("bad-object")
> +		bad_object(i915);
> +	igt_subtest_f("bad-flags")
> +		bad_flags(i915);
> +
> +	igt_describe("Check buffer object mapping persists after gem_close");
> +	igt_subtest_f("basic-uaf")
> +		basic_uaf(i915);
> +
> +	igt_subtest_f("isolation")
> +		isolation(i915);
> +	igt_subtest_f("pf-nonblock")
> +		pf_nonblock(i915);
> +
> +	igt_describe("Check race between close and mmap offset between threads");
> +	igt_subtest_f("close-race")
> +		close_race(i915, 20);
> +
> +	igt_subtest_f("clear")
> +		always_clear(i915, 20);
> +
> +	igt_fixture {
> +		close(i915);
> +	}
> +}
> diff --git a/tests/meson.build b/tests/meson.build
> index 18788d44b..05dea1f4e 100644
> --- a/tests/meson.build
> +++ b/tests/meson.build
> @@ -174,6 +174,7 @@ i915_progs = [
>  	'gem_media_vme',
>  	'gem_mmap',
>  	'gem_mmap_gtt',
> +	'gem_mmap_offset',
>  	'gem_mmap_offset_exhaustion',
>  	'gem_mmap_wc',
>  	'gem_partial_pwrite_pread',
> -- 
> 2.24.0
> 
> _______________________________________________
> igt-dev mailing list
> igt-dev@lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/igt-dev
_______________________________________________
igt-dev mailing list
igt-dev@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/igt-dev

^ permalink raw reply	[flat|nested] 29+ messages in thread

* [igt-dev] ✓ Fi.CI.BAT: success for Add GEM_MMAP_OFFSET support in IGT. (rev7)
  2019-11-26 17:25 [igt-dev] [PATCH i-g-t v4 0/3] Add GEM_MMAP_OFFSET support in IGT Zbigniew Kempczyński
                   ` (6 preceding siblings ...)
  2019-11-28 13:20 ` [igt-dev] ✓ Fi.CI.BAT: success " Patchwork
@ 2019-11-28 13:43 ` Patchwork
  2019-11-29 19:26 ` [igt-dev] ✗ Fi.CI.IGT: failure for Add GEM_MMAP_OFFSET support in IGT. (rev5) Patchwork
  2019-11-29 19:35 ` [igt-dev] ✗ Fi.CI.IGT: failure for Add GEM_MMAP_OFFSET support in IGT. (rev7) Patchwork
  9 siblings, 0 replies; 29+ messages in thread
From: Patchwork @ 2019-11-28 13:43 UTC (permalink / raw)
  To: Chris Wilson; +Cc: igt-dev

== Series Details ==

Series: Add GEM_MMAP_OFFSET support in IGT. (rev7)
URL   : https://patchwork.freedesktop.org/series/69973/
State : success

== Summary ==

CI Bug Log - changes from CI_DRM_7438 -> IGTPW_3779
====================================================

Summary
-------

  **SUCCESS**

  No regressions found.

  External URL: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_3779/index.html

Known issues
------------

  Here are the changes found in IGTPW_3779 that come from known issues:

### IGT changes ###

#### Possible fixes ####

  * igt@gem_ctx_create@basic-files:
    - {fi-tgl-u}:         [INCOMPLETE][1] ([fdo#111735]) -> [PASS][2]
   [1]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_7438/fi-tgl-u/igt@gem_ctx_create@basic-files.html
   [2]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_3779/fi-tgl-u/igt@gem_ctx_create@basic-files.html

  * igt@i915_pm_rpm@module-reload:
    - fi-skl-6770hq:      [FAIL][3] ([fdo#108511]) -> [PASS][4]
   [3]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_7438/fi-skl-6770hq/igt@i915_pm_rpm@module-reload.html
   [4]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_3779/fi-skl-6770hq/igt@i915_pm_rpm@module-reload.html

  
#### Warnings ####

  * igt@kms_busy@basic-flip-pipe-b:
    - fi-kbl-x1275:       [DMESG-WARN][5] ([fdo#103558] / [fdo#105602] / [fdo#105763]) -> [DMESG-WARN][6] ([fdo#103558] / [fdo#105602]) +3 similar issues
   [5]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_7438/fi-kbl-x1275/igt@kms_busy@basic-flip-pipe-b.html
   [6]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_3779/fi-kbl-x1275/igt@kms_busy@basic-flip-pipe-b.html

  * igt@kms_cursor_legacy@basic-busy-flip-before-cursor-legacy:
    - fi-kbl-x1275:       [DMESG-WARN][7] ([fdo#103558] / [fdo#105602]) -> [DMESG-WARN][8] ([fdo#103558] / [fdo#105602] / [fdo#105763]) +6 similar issues
   [7]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_7438/fi-kbl-x1275/igt@kms_cursor_legacy@basic-busy-flip-before-cursor-legacy.html
   [8]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_3779/fi-kbl-x1275/igt@kms_cursor_legacy@basic-busy-flip-before-cursor-legacy.html

  * igt@kms_flip@basic-flip-vs-dpms:
    - fi-icl-dsi:         [INCOMPLETE][9] ([fdo#107713]) -> [DMESG-WARN][10] ([fdo#107724])
   [9]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_7438/fi-icl-dsi/igt@kms_flip@basic-flip-vs-dpms.html
   [10]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_3779/fi-icl-dsi/igt@kms_flip@basic-flip-vs-dpms.html

  
  {name}: This element is suppressed. This means it is ignored when computing
          the status of the difference (SUCCESS, WARNING, or FAILURE).

  [fdo#103558]: https://bugs.freedesktop.org/show_bug.cgi?id=103558
  [fdo#105602]: https://bugs.freedesktop.org/show_bug.cgi?id=105602
  [fdo#105763]: https://bugs.freedesktop.org/show_bug.cgi?id=105763
  [fdo#107713]: https://bugs.freedesktop.org/show_bug.cgi?id=107713
  [fdo#107724]: https://bugs.freedesktop.org/show_bug.cgi?id=107724
  [fdo#108511]: https://bugs.freedesktop.org/show_bug.cgi?id=108511
  [fdo#111735]: https://bugs.freedesktop.org/show_bug.cgi?id=111735


Participating hosts (51 -> 45)
------------------------------

  Missing    (6): fi-ilk-m540 fi-hsw-4200u fi-bsw-cyan fi-ctg-p8600 fi-byt-clapper fi-bdw-samus 


Build changes
-------------

  * CI: CI-20190529 -> None
  * IGT: IGT_5313 -> IGTPW_3779

  CI-20190529: 20190529
  CI_DRM_7438: 8a2661592e79e48bcba9c24565b2b16edafbcbaa @ git://anongit.freedesktop.org/gfx-ci/linux
  IGTPW_3779: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_3779/index.html
  IGT_5313: 92caadb4e551ba05aa6e6e567ef69da96ca7e328 @ git://anongit.freedesktop.org/xorg/app/intel-gpu-tools



== Testlist changes ==

+igt@gem_mmap_offset@bad-flags
+igt@gem_mmap_offset@bad-object
+igt@gem_mmap_offset@basic-uaf
+igt@gem_mmap_offset@clear
+igt@gem_mmap_offset@close-race
+igt@gem_mmap_offset@isolation
+igt@gem_mmap_offset@pf-nonblock

== Logs ==

For more details see: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_3779/index.html
_______________________________________________
igt-dev mailing list
igt-dev@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/igt-dev

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [igt-dev] [PATCH i-g-t v4 2/3] lib/i915/gem_mman: add mmap_offset support
  2019-11-26 17:25 ` [igt-dev] [PATCH i-g-t v4 2/3] lib/i915/gem_mman: add mmap_offset support Zbigniew Kempczyński
@ 2019-11-28 14:38   ` Chris Wilson
  2019-11-28 14:43   ` Chris Wilson
  1 sibling, 0 replies; 29+ messages in thread
From: Chris Wilson @ 2019-11-28 14:38 UTC (permalink / raw)
  To: Zbigniew Kempczyński, igt-dev

Quoting Zbigniew Kempczyński (2019-11-26 17:25:55)
>  /**
>   * __gem_mmap__wc:
>   * @fd: open i915 drm file descriptor
> @@ -194,7 +285,12 @@ static void
>   */
>  void *__gem_mmap__wc(int fd, uint32_t handle, uint64_t offset, uint64_t size, unsigned prot)
>  {
> -       return __gem_mmap(fd, handle, offset, size, prot, I915_MMAP_WC);
> +       void *ptr = __gem_mmap_offset(fd, handle, offset, size, prot,
> +                                     I915_MMAP_OFFSET_WC);
> +       if (!ptr)
> +               ptr = __gem_mmap(fd, handle, offset, size, prot, I915_MMAP_WC);

This subverts the tests/i915/gem_mmap_wc.c so we lose coverage of the
legacy API.

Yikes.
-Chris
_______________________________________________
igt-dev mailing list
igt-dev@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/igt-dev

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [igt-dev] [PATCH i-g-t v4 2/3] lib/i915/gem_mman: add mmap_offset support
  2019-11-26 17:25 ` [igt-dev] [PATCH i-g-t v4 2/3] lib/i915/gem_mman: add mmap_offset support Zbigniew Kempczyński
  2019-11-28 14:38   ` Chris Wilson
@ 2019-11-28 14:43   ` Chris Wilson
  1 sibling, 0 replies; 29+ messages in thread
From: Chris Wilson @ 2019-11-28 14:43 UTC (permalink / raw)
  To: Zbigniew Kempczyński, igt-dev

Quoting Zbigniew Kempczyński (2019-11-26 17:25:55)
> +void *gem_mmap__device_coherent(int fd, uint32_t handle, uint64_t offset,
> +                               uint64_t size, unsigned prot)
> +{
> +       void *ptr;
> +
> +       igt_assert(offset == 0);
> +
> +       ptr = gem_mmap__device_coherent(fd, handle, offset, size, prot);

You meant __gem_mmap__device_coherent()
> +       igt_assert(ptr);
> +
> +       return ptr;
> +}
_______________________________________________
igt-dev mailing list
igt-dev@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/igt-dev

^ permalink raw reply	[flat|nested] 29+ messages in thread

* [igt-dev] ✗ Fi.CI.IGT: failure for Add GEM_MMAP_OFFSET support in IGT. (rev5)
  2019-11-26 17:25 [igt-dev] [PATCH i-g-t v4 0/3] Add GEM_MMAP_OFFSET support in IGT Zbigniew Kempczyński
                   ` (7 preceding siblings ...)
  2019-11-28 13:43 ` [igt-dev] ✓ Fi.CI.BAT: success for Add GEM_MMAP_OFFSET support in IGT. (rev7) Patchwork
@ 2019-11-29 19:26 ` Patchwork
  2019-11-29 19:35 ` [igt-dev] ✗ Fi.CI.IGT: failure for Add GEM_MMAP_OFFSET support in IGT. (rev7) Patchwork
  9 siblings, 0 replies; 29+ messages in thread
From: Patchwork @ 2019-11-29 19:26 UTC (permalink / raw)
  To: Chris Wilson; +Cc: igt-dev

== Series Details ==

Series: Add GEM_MMAP_OFFSET support in IGT. (rev5)
URL   : https://patchwork.freedesktop.org/series/69973/
State : failure

== Summary ==

CI Bug Log - changes from CI_DRM_7438_full -> IGTPW_3778_full
====================================================

Summary
-------

  **FAILURE**

  Serious unknown changes coming with IGTPW_3778_full absolutely need to be
  verified manually.
  
  If you think the reported changes have nothing to do with the changes
  introduced in IGTPW_3778_full, please notify your bug team to allow them
  to document this new failure mode, which will reduce false positives in CI.

  External URL: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_3778/index.html

Possible new issues
-------------------

  Here are the unknown changes that may have been introduced in IGTPW_3778_full:

### IGT changes ###

#### Possible regressions ####

  * igt@gem_tiled_wb:
    - shard-hsw:          [PASS][1] -> [FAIL][2] +1 similar issue
   [1]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_7438/shard-hsw2/igt@gem_tiled_wb.html
   [2]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_3778/shard-hsw1/igt@gem_tiled_wb.html

  * igt@gem_tiled_wc:
    - shard-glk:          [PASS][3] -> [FAIL][4] +1 similar issue
   [3]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_7438/shard-glk8/igt@gem_tiled_wc.html
   [4]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_3778/shard-glk3/igt@gem_tiled_wc.html
    - shard-apl:          [PASS][5] -> [FAIL][6] +1 similar issue
   [5]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_7438/shard-apl1/igt@gem_tiled_wc.html
   [6]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_3778/shard-apl1/igt@gem_tiled_wc.html
    - shard-snb:          [PASS][7] -> [FAIL][8] +1 similar issue
   [7]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_7438/shard-snb6/igt@gem_tiled_wc.html
   [8]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_3778/shard-snb2/igt@gem_tiled_wc.html

  
New tests
---------

  New tests have been introduced between CI_DRM_7438_full and IGTPW_3778_full:

### New IGT tests (7) ###

  * igt@gem_mmap_offset@bad-flags:
    - Statuses : 4 skip(s)
    - Exec time: [0.0] s

  * igt@gem_mmap_offset@bad-object:
    - Statuses : 4 skip(s)
    - Exec time: [0.0] s

  * igt@gem_mmap_offset@basic-uaf:
    - Statuses : 4 skip(s)
    - Exec time: [0.0] s

  * igt@gem_mmap_offset@clear:
    - Statuses : 4 skip(s)
    - Exec time: [0.0] s

  * igt@gem_mmap_offset@close-race:
    - Statuses : 4 skip(s)
    - Exec time: [0.0] s

  * igt@gem_mmap_offset@isolation:
    - Statuses : 4 skip(s)
    - Exec time: [0.0] s

  * igt@gem_mmap_offset@pf-nonblock:
    - Statuses : 4 skip(s)
    - Exec time: [0.0] s

  

Known issues
------------

  Here are the changes found in IGTPW_3778_full that come from known issues:

### IGT changes ###

#### Issues hit ####

  * igt@gem_ctx_isolation@bcs0-s3:
    - shard-apl:          [PASS][9] -> [DMESG-WARN][10] ([fdo#108566]) +2 similar issues
   [9]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_7438/shard-apl3/igt@gem_ctx_isolation@bcs0-s3.html
   [10]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_3778/shard-apl6/igt@gem_ctx_isolation@bcs0-s3.html

  * igt@kms_setmode@basic:
    - shard-apl:          [PASS][11] -> [FAIL][12] ([fdo#99912])
   [11]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_7438/shard-apl7/igt@kms_setmode@basic.html
   [12]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_3778/shard-apl8/igt@kms_setmode@basic.html

  
#### Possible fixes ####

  * igt@gem_ctx_persistence@rcs0-mixed-process:
    - shard-apl:          [FAIL][13] -> [PASS][14]
   [13]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_7438/shard-apl7/igt@gem_ctx_persistence@rcs0-mixed-process.html
   [14]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_3778/shard-apl2/igt@gem_ctx_persistence@rcs0-mixed-process.html

  * igt@gem_eio@unwedge-stress:
    - shard-snb:          [FAIL][15] ([fdo#109661]) -> [PASS][16]
   [15]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_7438/shard-snb7/igt@gem_eio@unwedge-stress.html
   [16]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_3778/shard-snb2/igt@gem_eio@unwedge-stress.html

  * igt@gem_userptr_blits@map-fixed-invalidate-busy-gup:
    - shard-hsw:          [DMESG-WARN][17] ([fdo#111870]) -> [PASS][18] +1 similar issue
   [17]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_7438/shard-hsw2/igt@gem_userptr_blits@map-fixed-invalidate-busy-gup.html
   [18]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_3778/shard-hsw7/igt@gem_userptr_blits@map-fixed-invalidate-busy-gup.html
    - shard-snb:          [DMESG-WARN][19] ([fdo#111870]) -> [PASS][20]
   [19]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_7438/shard-snb6/igt@gem_userptr_blits@map-fixed-invalidate-busy-gup.html
   [20]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_3778/shard-snb5/igt@gem_userptr_blits@map-fixed-invalidate-busy-gup.html

  * igt@gem_userptr_blits@map-fixed-invalidate-overlap-busy:
    - shard-snb:          [DMESG-WARN][21] ([fdo#110789] / [fdo#111870]) -> [PASS][22]
   [21]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_7438/shard-snb1/igt@gem_userptr_blits@map-fixed-invalidate-overlap-busy.html
   [22]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_3778/shard-snb7/igt@gem_userptr_blits@map-fixed-invalidate-overlap-busy.html

  * igt@i915_suspend@sysfs-reader:
    - shard-apl:          [DMESG-WARN][23] ([fdo#108566]) -> [PASS][24] +1 similar issue
   [23]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_7438/shard-apl1/igt@i915_suspend@sysfs-reader.html
   [24]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_3778/shard-apl7/igt@i915_suspend@sysfs-reader.html

  * igt@kms_cursor_crc@pipe-b-cursor-128x42-random:
    - shard-apl:          [FAIL][25] ([fdo#103232]) -> [PASS][26]
   [25]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_7438/shard-apl6/igt@kms_cursor_crc@pipe-b-cursor-128x42-random.html
   [26]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_3778/shard-apl2/igt@kms_cursor_crc@pipe-b-cursor-128x42-random.html

  * igt@kms_flip@flip-vs-suspend:
    - shard-hsw:          [INCOMPLETE][27] ([fdo#103540]) -> [PASS][28]
   [27]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_7438/shard-hsw7/igt@kms_flip@flip-vs-suspend.html
   [28]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_3778/shard-hsw8/igt@kms_flip@flip-vs-suspend.html

  
#### Warnings ####

  * igt@gem_eio@kms:
    - shard-snb:          [INCOMPLETE][29] ([fdo#105411]) -> [DMESG-WARN][30] ([fdo#111780] / [fdo#111781])
   [29]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_7438/shard-snb1/igt@gem_eio@kms.html
   [30]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_3778/shard-snb4/igt@gem_eio@kms.html

  
  [fdo#103232]: https://bugs.freedesktop.org/show_bug.cgi?id=103232
  [fdo#103540]: https://bugs.freedesktop.org/show_bug.cgi?id=103540
  [fdo#105411]: https://bugs.freedesktop.org/show_bug.cgi?id=105411
  [fdo#108566]: https://bugs.freedesktop.org/show_bug.cgi?id=108566
  [fdo#109661]: https://bugs.freedesktop.org/show_bug.cgi?id=109661
  [fdo#110789]: https://bugs.freedesktop.org/show_bug.cgi?id=110789
  [fdo#111780]: https://bugs.freedesktop.org/show_bug.cgi?id=111780
  [fdo#111781]: https://bugs.freedesktop.org/show_bug.cgi?id=111781
  [fdo#111870]: https://bugs.freedesktop.org/show_bug.cgi?id=111870
  [fdo#99912]: https://bugs.freedesktop.org/show_bug.cgi?id=99912


Participating hosts (11 -> 8)
------------------------------

  Missing    (3): pig-skl-6260u pig-glk-j5005 pig-hsw-4770r 


Build changes
-------------

  * CI: CI-20190529 -> None
  * IGT: IGT_5313 -> IGTPW_3778
  * Piglit: piglit_4509 -> None

  CI-20190529: 20190529
  CI_DRM_7438: 8a2661592e79e48bcba9c24565b2b16edafbcbaa @ git://anongit.freedesktop.org/gfx-ci/linux
  IGTPW_3778: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_3778/index.html
  IGT_5313: 92caadb4e551ba05aa6e6e567ef69da96ca7e328 @ git://anongit.freedesktop.org/xorg/app/intel-gpu-tools
  piglit_4509: fdc5a4ca11124ab8413c7988896eec4c97336694 @ git://anongit.freedesktop.org/piglit

== Logs ==

For more details see: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_3778/index.html
_______________________________________________
igt-dev mailing list
igt-dev@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/igt-dev

^ permalink raw reply	[flat|nested] 29+ messages in thread

* [igt-dev] ✗ Fi.CI.IGT: failure for Add GEM_MMAP_OFFSET support in IGT. (rev7)
  2019-11-26 17:25 [igt-dev] [PATCH i-g-t v4 0/3] Add GEM_MMAP_OFFSET support in IGT Zbigniew Kempczyński
                   ` (8 preceding siblings ...)
  2019-11-29 19:26 ` [igt-dev] ✗ Fi.CI.IGT: failure for Add GEM_MMAP_OFFSET support in IGT. (rev5) Patchwork
@ 2019-11-29 19:35 ` Patchwork
  9 siblings, 0 replies; 29+ messages in thread
From: Patchwork @ 2019-11-29 19:35 UTC (permalink / raw)
  To: Chris Wilson; +Cc: igt-dev

== Series Details ==

Series: Add GEM_MMAP_OFFSET support in IGT. (rev7)
URL   : https://patchwork.freedesktop.org/series/69973/
State : failure

== Summary ==

CI Bug Log - changes from CI_DRM_7438_full -> IGTPW_3779_full
====================================================

Summary
-------

  **FAILURE**

  Serious unknown changes coming with IGTPW_3779_full absolutely need to be
  verified manually.
  
  If you think the reported changes have nothing to do with the changes
  introduced in IGTPW_3779_full, please notify your bug team to allow them
  to document this new failure mode, which will reduce false positives in CI.

  External URL: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_3779/index.html

Possible new issues
-------------------

  Here are the unknown changes that may have been introduced in IGTPW_3779_full:

### IGT changes ###

#### Possible regressions ####

  * igt@gem_tiled_wb:
    - shard-hsw:          [PASS][1] -> [FAIL][2] +1 similar issue
   [1]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_7438/shard-hsw2/igt@gem_tiled_wb.html
   [2]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_3779/shard-hsw8/igt@gem_tiled_wb.html

  * igt@gem_tiled_wc:
    - shard-glk:          [PASS][3] -> [FAIL][4] +1 similar issue
   [3]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_7438/shard-glk8/igt@gem_tiled_wc.html
   [4]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_3779/shard-glk1/igt@gem_tiled_wc.html
    - shard-apl:          [PASS][5] -> [FAIL][6] +1 similar issue
   [5]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_7438/shard-apl1/igt@gem_tiled_wc.html
   [6]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_3779/shard-apl4/igt@gem_tiled_wc.html
    - shard-snb:          [PASS][7] -> [FAIL][8] +1 similar issue
   [7]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_7438/shard-snb6/igt@gem_tiled_wc.html
   [8]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_3779/shard-snb1/igt@gem_tiled_wc.html

  
New tests
---------

  New tests have been introduced between CI_DRM_7438_full and IGTPW_3779_full:

### New IGT tests (7) ###

  * igt@gem_mmap_offset@bad-flags:
    - Statuses : 3 skip(s)
    - Exec time: [0.0] s

  * igt@gem_mmap_offset@bad-object:
    - Statuses : 4 skip(s)
    - Exec time: [0.0] s

  * igt@gem_mmap_offset@basic-uaf:
    - Statuses : 4 skip(s)
    - Exec time: [0.0] s

  * igt@gem_mmap_offset@clear:
    - Statuses : 4 skip(s)
    - Exec time: [0.0] s

  * igt@gem_mmap_offset@close-race:
    - Statuses : 4 skip(s)
    - Exec time: [0.0] s

  * igt@gem_mmap_offset@isolation:
    - Statuses : 4 skip(s)
    - Exec time: [0.0] s

  * igt@gem_mmap_offset@pf-nonblock:
    - Statuses : 4 skip(s)
    - Exec time: [0.0] s

  

Known issues
------------

  Here are the changes found in IGTPW_3779_full that come from known issues:

### IGT changes ###

#### Issues hit ####

  * igt@gem_ctx_isolation@bcs0-s3:
    - shard-apl:          [PASS][9] -> [DMESG-WARN][10] ([fdo#108566]) +4 similar issues
   [9]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_7438/shard-apl3/igt@gem_ctx_isolation@bcs0-s3.html
   [10]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_3779/shard-apl4/igt@gem_ctx_isolation@bcs0-s3.html

  * igt@gem_userptr_blits@dmabuf-sync:
    - shard-snb:          [PASS][11] -> [DMESG-WARN][12] ([fdo#111870])
   [11]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_7438/shard-snb5/igt@gem_userptr_blits@dmabuf-sync.html
   [12]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_3779/shard-snb6/igt@gem_userptr_blits@dmabuf-sync.html

  * igt@i915_selftest@live_perf:
    - shard-hsw:          [PASS][13] -> [INCOMPLETE][14] ([fdo#103540])
   [13]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_7438/shard-hsw2/igt@i915_selftest@live_perf.html
   [14]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_3779/shard-hsw2/igt@i915_selftest@live_perf.html

  * igt@kms_cursor_crc@pipe-b-cursor-256x85-random:
    - shard-apl:          [PASS][15] -> [FAIL][16] ([fdo#103232])
   [15]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_7438/shard-apl1/igt@kms_cursor_crc@pipe-b-cursor-256x85-random.html
   [16]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_3779/shard-apl1/igt@kms_cursor_crc@pipe-b-cursor-256x85-random.html

  * igt@kms_setmode@basic:
    - shard-apl:          [PASS][17] -> [FAIL][18] ([fdo#99912])
   [17]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_7438/shard-apl7/igt@kms_setmode@basic.html
   [18]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_3779/shard-apl1/igt@kms_setmode@basic.html

  
#### Possible fixes ####

  * igt@gem_ctx_persistence@rcs0-mixed-process:
    - shard-apl:          [FAIL][19] -> [PASS][20]
   [19]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_7438/shard-apl7/igt@gem_ctx_persistence@rcs0-mixed-process.html
   [20]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_3779/shard-apl8/igt@gem_ctx_persistence@rcs0-mixed-process.html

  * igt@gem_userptr_blits@map-fixed-invalidate-overlap-busy:
    - shard-snb:          [DMESG-WARN][21] ([fdo#110789] / [fdo#111870]) -> [PASS][22]
   [21]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_7438/shard-snb1/igt@gem_userptr_blits@map-fixed-invalidate-overlap-busy.html
   [22]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_3779/shard-snb1/igt@gem_userptr_blits@map-fixed-invalidate-overlap-busy.html

  * igt@gem_userptr_blits@sync-unmap-cycles:
    - shard-snb:          [DMESG-WARN][23] ([fdo#111870]) -> [PASS][24] +1 similar issue
   [23]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_7438/shard-snb4/igt@gem_userptr_blits@sync-unmap-cycles.html
   [24]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_3779/shard-snb1/igt@gem_userptr_blits@sync-unmap-cycles.html
    - shard-hsw:          [DMESG-WARN][25] ([fdo#111870]) -> [PASS][26] +3 similar issues
   [25]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_7438/shard-hsw4/igt@gem_userptr_blits@sync-unmap-cycles.html
   [26]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_3779/shard-hsw8/igt@gem_userptr_blits@sync-unmap-cycles.html

  * igt@i915_suspend@sysfs-reader:
    - shard-apl:          [DMESG-WARN][27] ([fdo#108566]) -> [PASS][28] +1 similar issue
   [27]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_7438/shard-apl1/igt@i915_suspend@sysfs-reader.html
   [28]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_3779/shard-apl7/igt@i915_suspend@sysfs-reader.html

  * igt@kms_cursor_crc@pipe-b-cursor-128x42-random:
    - shard-apl:          [FAIL][29] ([fdo#103232]) -> [PASS][30]
   [29]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_7438/shard-apl6/igt@kms_cursor_crc@pipe-b-cursor-128x42-random.html
   [30]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_3779/shard-apl3/igt@kms_cursor_crc@pipe-b-cursor-128x42-random.html

  * igt@kms_flip@flip-vs-suspend:
    - shard-hsw:          [INCOMPLETE][31] ([fdo#103540]) -> [PASS][32]
   [31]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_7438/shard-hsw7/igt@kms_flip@flip-vs-suspend.html
   [32]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_3779/shard-hsw7/igt@kms_flip@flip-vs-suspend.html

  
  [fdo#103232]: https://bugs.freedesktop.org/show_bug.cgi?id=103232
  [fdo#103540]: https://bugs.freedesktop.org/show_bug.cgi?id=103540
  [fdo#108566]: https://bugs.freedesktop.org/show_bug.cgi?id=108566
  [fdo#110789]: https://bugs.freedesktop.org/show_bug.cgi?id=110789
  [fdo#111870]: https://bugs.freedesktop.org/show_bug.cgi?id=111870
  [fdo#99912]: https://bugs.freedesktop.org/show_bug.cgi?id=99912


Participating hosts (11 -> 8)
------------------------------

  Missing    (3): pig-skl-6260u pig-glk-j5005 pig-hsw-4770r 


Build changes
-------------

  * CI: CI-20190529 -> None
  * IGT: IGT_5313 -> IGTPW_3779
  * Piglit: piglit_4509 -> None

  CI-20190529: 20190529
  CI_DRM_7438: 8a2661592e79e48bcba9c24565b2b16edafbcbaa @ git://anongit.freedesktop.org/gfx-ci/linux
  IGTPW_3779: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_3779/index.html
  IGT_5313: 92caadb4e551ba05aa6e6e567ef69da96ca7e328 @ git://anongit.freedesktop.org/xorg/app/intel-gpu-tools
  piglit_4509: fdc5a4ca11124ab8413c7988896eec4c97336694 @ git://anongit.freedesktop.org/piglit

== Logs ==

For more details see: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_3779/index.html
_______________________________________________
igt-dev mailing list
igt-dev@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/igt-dev

^ permalink raw reply	[flat|nested] 29+ messages in thread

end of thread, other threads:[~2019-11-29 19:35 UTC | newest]

Thread overview: 29+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-11-26 17:25 [igt-dev] [PATCH i-g-t v4 0/3] Add GEM_MMAP_OFFSET support in IGT Zbigniew Kempczyński
2019-11-26 17:25 ` [igt-dev] [PATCH i-g-t v4 1/3] include/drm-uapi/i915_drm: Add defs for mmap_offset Zbigniew Kempczyński
2019-11-26 17:25 ` [igt-dev] [PATCH i-g-t v4 2/3] lib/i915/gem_mman: add mmap_offset support Zbigniew Kempczyński
2019-11-28 14:38   ` Chris Wilson
2019-11-28 14:43   ` Chris Wilson
2019-11-26 17:25 ` [igt-dev] [PATCH i-g-t v4 3/3] tests/i915/gem_mmap_offset: Add new API test for gem_mmap_offset Zbigniew Kempczyński
2019-11-28 12:55   ` [PATCH i-g-t] " Chris Wilson
2019-11-28 12:55     ` [igt-dev] " Chris Wilson
2019-11-28 12:55     ` [Intel-gfx] " Chris Wilson
2019-11-28 12:59     ` Chris Wilson
2019-11-28 12:59       ` [igt-dev] " Chris Wilson
2019-11-28 12:59       ` [Intel-gfx] " Chris Wilson
2019-11-28 13:38     ` [igt-dev] " Petri Latvala
2019-11-28 13:38       ` Petri Latvala
2019-11-28 13:38       ` [Intel-gfx] " Petri Latvala
2019-11-28 13:05   ` Chris Wilson
2019-11-28 13:05     ` [igt-dev] " Chris Wilson
2019-11-28 13:05     ` [Intel-gfx] " Chris Wilson
2019-11-28 13:10   ` Chris Wilson
2019-11-28 13:10     ` [igt-dev] " Chris Wilson
2019-11-28 13:10     ` [Intel-gfx] " Chris Wilson
2019-11-26 18:24 ` [igt-dev] ✓ Fi.CI.BAT: success for Add GEM_MMAP_OFFSET support in IGT. (rev4) Patchwork
2019-11-26 18:26   ` Chris Wilson
2019-11-27  5:22 ` [igt-dev] ✗ Fi.CI.IGT: failure " Patchwork
2019-11-28 13:05 ` [igt-dev] ✗ GitLab.Pipeline: warning for Add GEM_MMAP_OFFSET support in IGT. (rev5) Patchwork
2019-11-28 13:20 ` [igt-dev] ✓ Fi.CI.BAT: success " Patchwork
2019-11-28 13:43 ` [igt-dev] ✓ Fi.CI.BAT: success for Add GEM_MMAP_OFFSET support in IGT. (rev7) Patchwork
2019-11-29 19:26 ` [igt-dev] ✗ Fi.CI.IGT: failure for Add GEM_MMAP_OFFSET support in IGT. (rev5) Patchwork
2019-11-29 19:35 ` [igt-dev] ✗ Fi.CI.IGT: failure for Add GEM_MMAP_OFFSET support in IGT. (rev7) Patchwork

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.