From: Ashutosh Dixit <ashutosh.dixit@intel.com>
To: igt-dev@lists.freedesktop.org
Subject: [igt-dev] [PATCH i-g-t] lib/ioctl_wrappers: Keep IGT working without pread/pwrite ioctls
Date: Wed, 16 Sep 2020 13:11:47 -0700 [thread overview]
Message-ID: <20200916201147.7618-1-ashutosh.dixit@intel.com> (raw)
The general direction at this time is to phase out pread/write ioctls
and not support them in future products. This means IGT must handle
the absence of these ioctls. This patch does this by modifying
gem_read() and gem_write() to do the read/write using the pread/pwrite
ioctls first but when these ioctls are unavailable fall back to doing
the read/write using a combination of mmap and memcpy.
Callers who must absolutely use the pread/pwrite ioctls (such as tests
which test these ioctls or must otherwise only use the pread/pwrite
ioctls) must use gem_require_pread_pwrite() to skip when these ioctls
are not available.
v1: Removed __gem_pread, gem_pread, __gem_pwrite and gem_pwrite
introduced previously since they are not necessary,
gem_require_pread_pwrite is sufficient
v2: Fix CI failures in gem_advise and gen9_exec_parse by introducing
gem_require_pread_pwrite
v3: Skip mmap for 0 length read/write's
v4: Remove redundant igt_assert's
Signed-off-by: Ashutosh Dixit <ashutosh.dixit@intel.com>
---
lib/ioctl_wrappers.c | 135 +++++++++++++++++++-
lib/ioctl_wrappers.h | 3 +
tests/i915/gem_madvise.c | 2 +
tests/i915/gem_partial_pwrite_pread.c | 1 +
tests/i915/gem_pread.c | 1 +
tests/i915/gem_pread_after_blit.c | 1 +
tests/i915/gem_pwrite.c | 1 +
tests/i915/gem_pwrite_snooped.c | 1 +
tests/i915/gem_readwrite.c | 1 +
tests/i915/gem_set_tiling_vs_pwrite.c | 1 +
tests/i915/gem_tiled_partial_pwrite_pread.c | 1 +
tests/i915/gem_tiled_pread_basic.c | 1 +
tests/i915/gem_tiled_pread_pwrite.c | 1 +
tests/i915/gem_userptr_blits.c | 2 +
tests/i915/gen9_exec_parse.c | 4 +-
15 files changed, 149 insertions(+), 7 deletions(-)
diff --git a/lib/ioctl_wrappers.c b/lib/ioctl_wrappers.c
index 3781286d8e..1e80e30bd5 100644
--- a/lib/ioctl_wrappers.c
+++ b/lib/ioctl_wrappers.c
@@ -55,6 +55,7 @@
#include "igt_debugfs.h"
#include "igt_sysfs.h"
#include "config.h"
+#include "i915/gem_mman.h"
#ifdef HAVE_VALGRIND
#include <valgrind/valgrind.h>
@@ -323,6 +324,70 @@ void gem_close(int fd, uint32_t handle)
do_ioctl(fd, DRM_IOCTL_GEM_CLOSE, &close_bo);
}
+static bool is_cache_coherent(int fd, uint32_t handle)
+{
+ return gem_get_caching(fd, handle) != I915_CACHING_NONE;
+}
+
+static void mmap_write(int fd, uint32_t handle, uint64_t offset,
+ const void *buf, uint64_t length)
+{
+ void *map = NULL;
+
+ if (!length)
+ return;
+
+ if (is_cache_coherent(fd, handle)) {
+ /* offset arg for mmap functions must be 0 */
+ map = __gem_mmap__cpu_coherent(fd, handle, 0, offset + length,
+ PROT_READ | PROT_WRITE);
+ if (map)
+ gem_set_domain(fd, handle,
+ I915_GEM_DOMAIN_CPU, I915_GEM_DOMAIN_CPU);
+ }
+
+ if (!map) {
+ map = __gem_mmap_offset__wc(fd, handle, 0, offset + length,
+ PROT_READ | PROT_WRITE);
+ if (!map)
+ map = gem_mmap__wc(fd, handle, 0, offset + length,
+ PROT_READ | PROT_WRITE);
+ gem_set_domain(fd, handle,
+ I915_GEM_DOMAIN_WC, I915_GEM_DOMAIN_WC);
+ }
+
+ memcpy(map + offset, buf, length);
+ munmap(map, offset + length);
+}
+
+static void mmap_read(int fd, uint32_t handle, uint64_t offset, void *buf, uint64_t length)
+{
+ void *map = NULL;
+
+ if (!length)
+ return;
+
+ if (gem_has_llc(fd) || is_cache_coherent(fd, handle)) {
+ /* offset arg for mmap functions must be 0 */
+ map = __gem_mmap__cpu_coherent(fd, handle, 0,
+ offset + length, PROT_READ);
+ if (map)
+ gem_set_domain(fd, handle, I915_GEM_DOMAIN_CPU, 0);
+ }
+
+ if (!map) {
+ map = __gem_mmap_offset__wc(fd, handle, 0, offset + length,
+ PROT_READ);
+ if (!map)
+ map = gem_mmap__wc(fd, handle, 0, offset + length,
+ PROT_READ);
+ gem_set_domain(fd, handle, I915_GEM_DOMAIN_WC, 0);
+ }
+
+ memcpy(buf, map + offset, length);
+ munmap(map, offset + length);
+}
+
int __gem_write(int fd, uint32_t handle, uint64_t offset, const void *buf, uint64_t length)
{
struct drm_i915_gem_pwrite gem_pwrite;
@@ -348,12 +413,18 @@ int __gem_write(int fd, uint32_t handle, uint64_t offset, const void *buf, uint6
* @buf: pointer to the data to write into the buffer
* @length: size of the subrange
*
- * This wraps the PWRITE ioctl, which is to upload a linear data to a subrange
- * of a gem buffer object.
+ * Method to write to a gem object. Uses the PWRITE ioctl when it is
+ * available, else it uses mmap + memcpy to upload linear data to a
+ * subrange of a gem buffer object.
*/
void gem_write(int fd, uint32_t handle, uint64_t offset, const void *buf, uint64_t length)
{
- igt_assert_eq(__gem_write(fd, handle, offset, buf, length), 0);
+ int ret = __gem_write(fd, handle, offset, buf, length);
+
+ igt_assert(ret == 0 || ret == EOPNOTSUPP);
+
+ if (ret == EOPNOTSUPP)
+ mmap_write(fd, handle, offset, buf, length);
}
int __gem_read(int fd, uint32_t handle, uint64_t offset, void *buf, uint64_t length)
@@ -380,12 +451,64 @@ int __gem_read(int fd, uint32_t handle, uint64_t offset, void *buf, uint64_t len
* @buf: pointer to the data to read into
* @length: size of the subrange
*
- * This wraps the PREAD ioctl, which is to download a linear data to a subrange
- * of a gem buffer object.
+ * Method to read from a gem object. Uses the PREAD ioctl when it is
+ * available, else it uses mmap + memcpy to download linear data from a
+ * subrange of a gem buffer object.
*/
void gem_read(int fd, uint32_t handle, uint64_t offset, void *buf, uint64_t length)
{
- igt_assert_eq(__gem_read(fd, handle, offset, buf, length), 0);
+ int ret = __gem_read(fd, handle, offset, buf, length);
+
+ igt_assert(ret == 0 || ret == EOPNOTSUPP);
+
+ if (ret == EOPNOTSUPP)
+ mmap_read(fd, handle, offset, buf, length);
+}
+
+/**
+ * gem_has_pwrite
+ * @fd: open i915 drm file descriptor
+ *
+ * Feature test macro to query whether pwrite ioctl is supported
+ */
+bool gem_has_pwrite(int fd)
+{
+ uint32_t handle = gem_create(fd, 4096);
+ int buf, ret;
+
+ ret = __gem_write(fd, handle, 0, &buf, sizeof(buf));
+ gem_close(fd, handle);
+
+ return ret != EOPNOTSUPP;
+}
+
+/**
+ * gem_has_pread
+ * @fd: open i915 drm file descriptor
+ *
+ * Feature test macro to query whether pread ioctl is supported
+ */
+bool gem_has_pread(int fd)
+{
+ uint32_t handle = gem_create(fd, 4096);
+ int buf, ret;
+
+ ret = __gem_read(fd, handle, 0, &buf, sizeof(buf));
+ gem_close(fd, handle);
+
+ return ret != EOPNOTSUPP;
+}
+
+/**
+ * gem_require_pread_pwrite
+ * @fd: open i915 drm file descriptor
+ *
+ * Feature test macro to query whether pread/pwrite ioctls are supported
+ * and skip if they are not
+ */
+void gem_require_pread_pwrite(int fd)
+{
+ igt_require(gem_has_pread(fd) && gem_has_pwrite(fd));
}
int __gem_set_domain(int fd, uint32_t handle, uint32_t read, uint32_t write)
diff --git a/lib/ioctl_wrappers.h b/lib/ioctl_wrappers.h
index 870ac8b7bc..6ba551a71b 100644
--- a/lib/ioctl_wrappers.h
+++ b/lib/ioctl_wrappers.h
@@ -71,6 +71,9 @@ int __gem_write(int fd, uint32_t handle, uint64_t offset, const void *buf, uint6
void gem_write(int fd, uint32_t handle, uint64_t offset, const void *buf, uint64_t length);
int __gem_read(int fd, uint32_t handle, uint64_t offset, void *buf, uint64_t length);
void gem_read(int fd, uint32_t handle, uint64_t offset, void *buf, uint64_t length);
+bool gem_has_pwrite(int fd);
+bool gem_has_pread(int fd);
+void gem_require_pread_pwrite(int fd);
int __gem_set_domain(int fd, uint32_t handle, uint32_t read, uint32_t write);
void gem_set_domain(int fd, uint32_t handle, uint32_t read, uint32_t write);
int gem_wait(int fd, uint32_t handle, int64_t *timeout_ns);
diff --git a/tests/i915/gem_madvise.c b/tests/i915/gem_madvise.c
index 54c9befff2..92e1c5192d 100644
--- a/tests/i915/gem_madvise.c
+++ b/tests/i915/gem_madvise.c
@@ -154,6 +154,7 @@ dontneed_before_pwrite(void)
uint32_t bbe = MI_BATCH_BUFFER_END;
uint32_t handle;
+ gem_require_pread_pwrite(fd);
handle = gem_create(fd, OBJECT_SIZE);
gem_madvise(fd, handle, I915_MADV_DONTNEED);
@@ -170,6 +171,7 @@ dontneed_before_exec(void)
struct drm_i915_gem_exec_object2 exec;
uint32_t buf[] = { MI_BATCH_BUFFER_END, 0 };
+ gem_require_pread_pwrite(fd);
memset(&execbuf, 0, sizeof(execbuf));
memset(&exec, 0, sizeof(exec));
diff --git a/tests/i915/gem_partial_pwrite_pread.c b/tests/i915/gem_partial_pwrite_pread.c
index b102847212..fd7b19f31b 100644
--- a/tests/i915/gem_partial_pwrite_pread.c
+++ b/tests/i915/gem_partial_pwrite_pread.c
@@ -281,6 +281,7 @@ igt_main
data.drm_fd = drm_open_driver(DRIVER_INTEL);
igt_require_gem(data.drm_fd);
gem_require_blitter(data.drm_fd);
+ gem_require_pread_pwrite(data.drm_fd);
data.devid = intel_get_drm_devid(data.drm_fd);
data.bops = buf_ops_create(data.drm_fd);
diff --git a/tests/i915/gem_pread.c b/tests/i915/gem_pread.c
index 6d12b8e9f8..db1eacedc2 100644
--- a/tests/i915/gem_pread.c
+++ b/tests/i915/gem_pread.c
@@ -149,6 +149,7 @@ igt_main_args("s:", NULL, help_str, opt_handler, NULL)
igt_fixture {
fd = drm_open_driver(DRIVER_INTEL);
+ gem_require_pread_pwrite(fd);
dst = gem_create(fd, object_size);
src = malloc(object_size);
diff --git a/tests/i915/gem_pread_after_blit.c b/tests/i915/gem_pread_after_blit.c
index 81454c9303..5c99d0887c 100644
--- a/tests/i915/gem_pread_after_blit.c
+++ b/tests/i915/gem_pread_after_blit.c
@@ -212,6 +212,7 @@ igt_main
igt_fixture {
fd = drm_open_driver(DRIVER_INTEL);
igt_require_gem(fd);
+ gem_require_pread_pwrite(fd);
bufmgr = drm_intel_bufmgr_gem_init(fd, 4096);
drm_intel_bufmgr_gem_enable_reuse(bufmgr);
diff --git a/tests/i915/gem_pwrite.c b/tests/i915/gem_pwrite.c
index e491263fd3..eea51f9780 100644
--- a/tests/i915/gem_pwrite.c
+++ b/tests/i915/gem_pwrite.c
@@ -317,6 +317,7 @@ igt_main_args("s:", NULL, help_str, opt_handler, NULL)
igt_fixture {
fd = drm_open_driver(DRIVER_INTEL);
+ gem_require_pread_pwrite(fd);
dst = gem_create(fd, object_size);
src = malloc(object_size);
diff --git a/tests/i915/gem_pwrite_snooped.c b/tests/i915/gem_pwrite_snooped.c
index 4a33952414..a2eca6afc5 100644
--- a/tests/i915/gem_pwrite_snooped.c
+++ b/tests/i915/gem_pwrite_snooped.c
@@ -132,6 +132,7 @@ igt_simple_main
fd = drm_open_driver(DRIVER_INTEL);
igt_require_gem(fd);
gem_require_blitter(fd);
+ gem_require_pread_pwrite(fd);
devid = intel_get_drm_devid(fd);
bufmgr = drm_intel_bufmgr_gem_init(fd, 4096);
diff --git a/tests/i915/gem_readwrite.c b/tests/i915/gem_readwrite.c
index 6b2977c1c4..ca31741c60 100644
--- a/tests/i915/gem_readwrite.c
+++ b/tests/i915/gem_readwrite.c
@@ -83,6 +83,7 @@ igt_main
igt_fixture {
fd = drm_open_driver(DRIVER_INTEL);
+ gem_require_pread_pwrite(fd);
handle = gem_create(fd, OBJECT_SIZE);
}
diff --git a/tests/i915/gem_set_tiling_vs_pwrite.c b/tests/i915/gem_set_tiling_vs_pwrite.c
index 302ea24b6d..8f38c9b9b7 100644
--- a/tests/i915/gem_set_tiling_vs_pwrite.c
+++ b/tests/i915/gem_set_tiling_vs_pwrite.c
@@ -55,6 +55,7 @@ igt_simple_main
fd = drm_open_driver(DRIVER_INTEL);
igt_require(gem_available_fences(fd) > 0);
+ gem_require_pread_pwrite(fd);
for (int i = 0; i < OBJECT_SIZE/4; i++)
data[i] = i;
diff --git a/tests/i915/gem_tiled_partial_pwrite_pread.c b/tests/i915/gem_tiled_partial_pwrite_pread.c
index 7de5358b20..0c4545990c 100644
--- a/tests/i915/gem_tiled_partial_pwrite_pread.c
+++ b/tests/i915/gem_tiled_partial_pwrite_pread.c
@@ -270,6 +270,7 @@ igt_main
igt_require_gem(fd);
gem_require_mappable_ggtt(fd);
gem_require_blitter(fd);
+ gem_require_pread_pwrite(fd);
bufmgr = drm_intel_bufmgr_gem_init(fd, 4096);
//drm_intel_bufmgr_gem_enable_reuse(bufmgr);
diff --git a/tests/i915/gem_tiled_pread_basic.c b/tests/i915/gem_tiled_pread_basic.c
index 7cb644104f..f8f73c03a2 100644
--- a/tests/i915/gem_tiled_pread_basic.c
+++ b/tests/i915/gem_tiled_pread_basic.c
@@ -127,6 +127,7 @@ igt_simple_main
igt_require(gem_available_fences(fd) > 0);
handle = create_bo(fd);
igt_require(gem_get_tiling(fd, handle, &tiling, &swizzle));
+ gem_require_pread_pwrite(fd);
devid = intel_get_drm_devid(fd);
diff --git a/tests/i915/gem_tiled_pread_pwrite.c b/tests/i915/gem_tiled_pread_pwrite.c
index f58048faa1..28490840fd 100644
--- a/tests/i915/gem_tiled_pread_pwrite.c
+++ b/tests/i915/gem_tiled_pread_pwrite.c
@@ -114,6 +114,7 @@ igt_simple_main
fd = drm_open_driver(DRIVER_INTEL);
igt_require(gem_available_fences(fd) > 0);
+ gem_require_pread_pwrite(fd);
count = gem_available_fences(fd) + 1;
intel_require_memory(2 * count, sizeof(linear), CHECK_RAM);
diff --git a/tests/i915/gem_userptr_blits.c b/tests/i915/gem_userptr_blits.c
index 268423dcd1..0ccfdbd9cc 100644
--- a/tests/i915/gem_userptr_blits.c
+++ b/tests/i915/gem_userptr_blits.c
@@ -890,6 +890,7 @@ static int test_forbidden_ops(int fd)
uint32_t handle;
void *ptr;
+ gem_require_pread_pwrite(fd);
igt_assert(posix_memalign(&ptr, PAGE_SIZE, PAGE_SIZE) == 0);
gem_userptr(fd, ptr, PAGE_SIZE, 0, userptr_flags, &handle);
@@ -1416,6 +1417,7 @@ static void test_readonly_pwrite(int i915)
*/
igt_require(igt_setup_clflush());
+ gem_require_pread_pwrite(i915);
sz = 16 << 12;
pages = mmap(NULL, sz, PROT_WRITE, MAP_ANON | MAP_PRIVATE, -1, 0);
diff --git a/tests/i915/gen9_exec_parse.c b/tests/i915/gen9_exec_parse.c
index 8cd82f5688..eddc0f871f 100644
--- a/tests/i915/gen9_exec_parse.c
+++ b/tests/i915/gen9_exec_parse.c
@@ -1029,8 +1029,10 @@ igt_main
-EINVAL);
}
- igt_subtest("batch-invalid-length")
+ igt_subtest("batch-invalid-length") {
+ gem_require_pread_pwrite(i915);
test_invalid_length(i915, handle);
+ }
igt_subtest("basic-rejected")
test_rejected(i915, handle, false);
--
2.26.2.593.gb994622632
_______________________________________________
igt-dev mailing list
igt-dev@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/igt-dev
next reply other threads:[~2020-09-16 20:11 UTC|newest]
Thread overview: 18+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-09-16 20:11 Ashutosh Dixit [this message]
2020-09-16 20:52 ` [igt-dev] ✓ Fi.CI.BAT: success for lib/ioctl_wrappers: Keep IGT working without pread/pwrite ioctls (rev4) Patchwork
2020-09-17 0:35 ` [igt-dev] ✗ Fi.CI.IGT: failure " Patchwork
2020-09-18 0:25 ` [igt-dev] ✓ Fi.CI.BAT: success for lib/ioctl_wrappers: Keep IGT working without pread/pwrite ioctls (rev5) Patchwork
2020-09-18 2:13 ` [igt-dev] ✓ Fi.CI.IGT: " Patchwork
-- strict thread matches above, loose matches on Subject: below --
2021-03-15 22:53 [igt-dev] [PATCH i-g-t] lib/ioctl_wrappers: Keep IGT working without pread/pwrite ioctls Ashutosh Dixit
2021-01-21 8:37 Ashutosh Dixit
2021-03-15 16:51 ` Tvrtko Ursulin
2021-03-15 23:19 ` Dixit, Ashutosh
2021-03-16 9:16 ` Tvrtko Ursulin
2021-03-16 18:46 ` Dixit, Ashutosh
2020-09-30 3:40 Ashutosh Dixit
2020-10-02 9:36 ` Chris Wilson
2020-10-02 19:34 ` Dixit, Ashutosh
2020-09-06 23:43 Ashutosh Dixit
2020-09-09 7:03 ` Zbigniew Kempczyński
2020-09-06 17:49 Ashutosh Dixit
2020-09-04 20:25 Ashutosh Dixit
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20200916201147.7618-1-ashutosh.dixit@intel.com \
--to=ashutosh.dixit@intel.com \
--cc=igt-dev@lists.freedesktop.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
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.