[i-g-t,2/4] tests/gem_pread: test reads from a bo not backed by struct page
diff mbox

Message ID 1507847444-3593-3-git-send-email-daniele.ceraolospurio@intel.com
State New
Headers show

Commit Message

Daniele Ceraolo Spurio Oct. 12, 2017, 10:30 p.m. UTC
Using an imported vgem bo we can test reads from an object not backed
by struct page. These reads use different paths in the kernel.

While at it, extract some common code in an helper function and fix the
src vs dst naming (they are the other way around).

Suggested-by: Chris Wilson <chris@chris-wilson.co.uk>
Signed-off-by: Daniele Ceraolo Spurio <daniele.ceraolospurio@intel.com>
Cc: Chris Wilson <chris@chris-wilson.co.uk>
---
 tests/gem_pread.c | 160 +++++++++++++++++++++++++++++++++++++-----------------
 1 file changed, 111 insertions(+), 49 deletions(-)

Comments

Chris Wilson Oct. 19, 2017, 8 a.m. UTC | #1
Quoting Daniele Ceraolo Spurio (2017-10-12 23:30:42)
> Using an imported vgem bo we can test reads from an object not backed
> by struct page. These reads use different paths in the kernel.
> 
> While at it, extract some common code in an helper function and fix the
> src vs dst naming (they are the other way around).
> 
> Suggested-by: Chris Wilson <chris@chris-wilson.co.uk>
> Signed-off-by: Daniele Ceraolo Spurio <daniele.ceraolospurio@intel.com>
> Cc: Chris Wilson <chris@chris-wilson.co.uk>
> ---
>  tests/gem_pread.c | 160 +++++++++++++++++++++++++++++++++++++-----------------
>  1 file changed, 111 insertions(+), 49 deletions(-)
> 
> diff --git a/tests/gem_pread.c b/tests/gem_pread.c
> index 39a46ed..89a9a5d 100644
> --- a/tests/gem_pread.c
> +++ b/tests/gem_pread.c
> @@ -26,6 +26,7 @@
>   */
>  
>  #include "igt.h"
> +#include "igt_vgem.h"
>  #include <unistd.h>
>  #include <stdlib.h>
>  #include <stdint.h>
> @@ -73,25 +74,91 @@ static const char *bytes_per_sec(char *buf, double v)
>         return buf;
>  }
>  
> +static void do_read_loop(int fd, const char *name, uint32_t handle,
> +                        uint32_t *dst, int size)
> +{
> +       int count;
> +       double usecs;
> +       char buf[100];
> +       const char* bps;
> +       unsigned i;
> +
> +       for (count = 1; count <= 1<<17; count <<= 1) {
> +               struct timeval start, end;
> +
> +               memset(dst, 0, size);
> +               gettimeofday(&start, NULL);
> +               do_gem_read(fd, handle, dst, size, count);
> +               gettimeofday(&end, NULL);
> +               usecs = elapsed(&start, &end, count);
> +               bps = bytes_per_sec(buf, size/usecs*1e6);
> +               igt_info("Time to %s pread %d bytes x %6d:      %7.3fµs, %s\n",
> +                        name, size, count, usecs, bps);
> +               fflush(stdout);
> +
> +               for (i = 0; i < size / 4096; i++)
> +                       igt_assert_eq(dst[i * 1024], i);
> +       }
> +}

Which of course shouldn't exist in a plain test. We have benchmarks/ to
cover this. (Linking each benchmark to its conformance test would be
useful.)

> +
> +static uint32_t create_i915_bo(int fd, uint64_t size)
> +{
> +       uint32_t handle = gem_create(fd, size);
> +       uint32_t *ptr;
> +       unsigned i;

igt_skip_on(overflows_type(size, size_t));

We have an interesting challenge here with u64 and 32b intptr_t.

> +
> +       ptr = gem_mmap__cpu(fd, handle, 0, size, PROT_WRITE);
> +       gem_set_domain(fd, handle, I915_GEM_DOMAIN_CPU, I915_GEM_DOMAIN_CPU);
> +       for (i = 0; i < size / 4096; i++)

for (size_t i = 0; i < size/4096; i++)

> +               ptr[i * 1024] = i;
> +       munmap(ptr, size);
> +       return handle;
> +}
> +
> +/*
> + * imported BOs are not backed by struct page and therefore the preads go
> + * through different driver paths compared to a normal bo
> + */
> +static uint32_t create_foreign_bo(int fd, uint64_t size)
> +{
> +       struct vgem_bo scratch;
> +       int vgem;
> +       uint32_t handle;
> +       uint32_t *ptr;
> +       unsigned i;
> +
> +       vgem = drm_open_driver(DRIVER_VGEM);
>  
> -uint32_t *src, dst;
> -int fd, count;
> +       scratch.width = 1024;
> +       scratch.height = size / 4096;
> +       scratch.bpp = 32;
> +       handle = vgem_create_and_import(vgem, &scratch, fd, NULL);
> +       igt_assert_eq(size, scratch.size);
> +
> +       ptr = vgem_mmap(vgem, &scratch, PROT_WRITE);
> +       for (i = 0; i < size / 4096; i++)
> +               ptr[i * 1024] = i;
> +       munmap(ptr, scratch.size);
> +
> +       close(vgem);
> +
> +       return handle;
> +}
>  
>  int main(int argc, char **argv)
>  {
> +       int fd;
> +       uint32_t *dst;
> +       uint32_t handle;
>         int object_size = 0;
> -       double usecs;
> -       char buf[100];
> -       const char* bps;
>         const struct {
> -               int level;
> -               const char *name;
> -       } cache[] = {
> -               { 0, "uncached" },
> -               { 1, "snoop" },
> -               { 2, "display" },
> -               { -1 },
> -       }, *c;
> +               const char *prefix;
> +               uint32_t (*bo_create)(int fd, uint64_t size);
> +       } modes[] = {
> +               { "", create_i915_bo },
> +               { "foreign-bo-", create_foreign_bo },
> +               { NULL, NULL }
> +       }, *m;
>  
>         igt_subtest_init(argc, argv);
>         igt_skip_on_simulation();
> @@ -104,49 +171,44 @@ int main(int argc, char **argv)
>  
>         igt_fixture {
>                 fd = drm_open_driver(DRIVER_INTEL);
> -
> -               dst = gem_create(fd, object_size);
> -               src = malloc(object_size);
> -       }
> -
> -       igt_subtest("basic") {
> -               for (count = 1; count <= 1<<17; count <<= 1) {
> -                       struct timeval start, end;
> -
> -                       gettimeofday(&start, NULL);
> -                       do_gem_read(fd, dst, src, object_size, count);
> -                       gettimeofday(&end, NULL);
> -                       usecs = elapsed(&start, &end, count);
> -                       bps = bytes_per_sec(buf, object_size/usecs*1e6);
> -                       igt_info("Time to pread %d bytes x %6d: %7.3fµs, %s\n",
> -                                object_size, count, usecs, bps);
> -                       fflush(stdout);
> -               }
> +               dst = malloc(object_size);
> +               igt_assert(dst);
>         }
>  
> -       for (c = cache; c->level != -1; c++) {
> -               igt_subtest(c->name) {
> -                       gem_set_caching(fd, dst, c->level);
> -
> -                       for (count = 1; count <= 1<<17; count <<= 1) {
> -                               struct timeval start, end;
> -
> -                               gettimeofday(&start, NULL);
> -                               do_gem_read(fd, dst, src, object_size, count);
> -                               gettimeofday(&end, NULL);
> -                               usecs = elapsed(&start, &end, count);
> -                               bps = bytes_per_sec(buf, object_size/usecs*1e6);
> -                               igt_info("Time to %s pread %d bytes x %6d:      %7.3fµs, %s\n",
> -                                        c->name, object_size, count, usecs, bps);
> -                               fflush(stdout);
> +       for (m = modes; m->bo_create != NULL; m++) {
> +               igt_subtest_group {
> +                       const struct {
> +                               int level;
> +                               const char *name;
> +                       } cache[] = {
> +                               { 0, "uncached" },
> +                               { 1, "snoop" },
> +                               { 2, "display" },
> +                               { -1 },
> +                       }, *c;
> +
> +                       igt_fixture
> +                               handle = m->bo_create(fd, object_size);
> +
> +                       igt_subtest_f("%sbasic", m->prefix)
> +                               do_read_loop(fd, "basic", handle, dst,
> +                                            object_size);
> +
> +                       for (c = cache; c->level != -1; c++) {
> +                               igt_subtest_f("%s%s", m->prefix, c->name) {
> +                                       gem_set_caching(fd, handle, c->level);
> +                                       do_read_loop(fd, c->name, handle, dst,
> +                                                    object_size);
> +                               }
>                         }

Oh dear. We need stateless tests as well, i.e. since the handle is
common the driver execution paths will vary depending upon the sequence
of subtests; and in particular running this by hand will give a
different result to CI running each subtest individually.
-Chris

Patch
diff mbox

diff --git a/tests/gem_pread.c b/tests/gem_pread.c
index 39a46ed..89a9a5d 100644
--- a/tests/gem_pread.c
+++ b/tests/gem_pread.c
@@ -26,6 +26,7 @@ 
  */
 
 #include "igt.h"
+#include "igt_vgem.h"
 #include <unistd.h>
 #include <stdlib.h>
 #include <stdint.h>
@@ -73,25 +74,91 @@  static const char *bytes_per_sec(char *buf, double v)
 	return buf;
 }
 
+static void do_read_loop(int fd, const char *name, uint32_t handle,
+			 uint32_t *dst, int size)
+{
+	int count;
+	double usecs;
+	char buf[100];
+	const char* bps;
+	unsigned i;
+
+	for (count = 1; count <= 1<<17; count <<= 1) {
+		struct timeval start, end;
+
+		memset(dst, 0, size);
+		gettimeofday(&start, NULL);
+		do_gem_read(fd, handle, dst, size, count);
+		gettimeofday(&end, NULL);
+		usecs = elapsed(&start, &end, count);
+		bps = bytes_per_sec(buf, size/usecs*1e6);
+		igt_info("Time to %s pread %d bytes x %6d:	%7.3fµs, %s\n",
+			 name, size, count, usecs, bps);
+		fflush(stdout);
+
+		for (i = 0; i < size / 4096; i++)
+			igt_assert_eq(dst[i * 1024], i);
+	}
+}
+
+static uint32_t create_i915_bo(int fd, uint64_t size)
+{
+	uint32_t handle = gem_create(fd, size);
+	uint32_t *ptr;
+	unsigned i;
+
+	ptr = gem_mmap__cpu(fd, handle, 0, size, PROT_WRITE);
+	gem_set_domain(fd, handle, I915_GEM_DOMAIN_CPU, I915_GEM_DOMAIN_CPU);
+	for (i = 0; i < size / 4096; i++)
+		ptr[i * 1024] = i;
+	munmap(ptr, size);
+	return handle;
+}
+
+/*
+ * imported BOs are not backed by struct page and therefore the preads go
+ * through different driver paths compared to a normal bo
+ */
+static uint32_t create_foreign_bo(int fd, uint64_t size)
+{
+	struct vgem_bo scratch;
+	int vgem;
+	uint32_t handle;
+	uint32_t *ptr;
+	unsigned i;
+
+	vgem = drm_open_driver(DRIVER_VGEM);
 
-uint32_t *src, dst;
-int fd, count;
+	scratch.width = 1024;
+	scratch.height = size / 4096;
+	scratch.bpp = 32;
+	handle = vgem_create_and_import(vgem, &scratch, fd, NULL);
+	igt_assert_eq(size, scratch.size);
+
+	ptr = vgem_mmap(vgem, &scratch, PROT_WRITE);
+	for (i = 0; i < size / 4096; i++)
+		ptr[i * 1024] = i;
+	munmap(ptr, scratch.size);
+
+	close(vgem);
+
+	return handle;
+}
 
 int main(int argc, char **argv)
 {
+	int fd;
+	uint32_t *dst;
+	uint32_t handle;
 	int object_size = 0;
-	double usecs;
-	char buf[100];
-	const char* bps;
 	const struct {
-		int level;
-		const char *name;
-	} cache[] = {
-		{ 0, "uncached" },
-		{ 1, "snoop" },
-		{ 2, "display" },
-		{ -1 },
-	}, *c;
+		const char *prefix;
+		uint32_t (*bo_create)(int fd, uint64_t size);
+	} modes[] = {
+		{ "", create_i915_bo },
+		{ "foreign-bo-", create_foreign_bo },
+		{ NULL, NULL }
+	}, *m;
 
 	igt_subtest_init(argc, argv);
 	igt_skip_on_simulation();
@@ -104,49 +171,44 @@  int main(int argc, char **argv)
 
 	igt_fixture {
 		fd = drm_open_driver(DRIVER_INTEL);
-
-		dst = gem_create(fd, object_size);
-		src = malloc(object_size);
-	}
-
-	igt_subtest("basic") {
-		for (count = 1; count <= 1<<17; count <<= 1) {
-			struct timeval start, end;
-
-			gettimeofday(&start, NULL);
-			do_gem_read(fd, dst, src, object_size, count);
-			gettimeofday(&end, NULL);
-			usecs = elapsed(&start, &end, count);
-			bps = bytes_per_sec(buf, object_size/usecs*1e6);
-			igt_info("Time to pread %d bytes x %6d:	%7.3fµs, %s\n",
-				 object_size, count, usecs, bps);
-			fflush(stdout);
-		}
+		dst = malloc(object_size);
+		igt_assert(dst);
 	}
 
-	for (c = cache; c->level != -1; c++) {
-		igt_subtest(c->name) {
-			gem_set_caching(fd, dst, c->level);
-
-			for (count = 1; count <= 1<<17; count <<= 1) {
-				struct timeval start, end;
-
-				gettimeofday(&start, NULL);
-				do_gem_read(fd, dst, src, object_size, count);
-				gettimeofday(&end, NULL);
-				usecs = elapsed(&start, &end, count);
-				bps = bytes_per_sec(buf, object_size/usecs*1e6);
-				igt_info("Time to %s pread %d bytes x %6d:	%7.3fµs, %s\n",
-					 c->name, object_size, count, usecs, bps);
-				fflush(stdout);
+	for (m = modes; m->bo_create != NULL; m++) {
+		igt_subtest_group {
+			const struct {
+				int level;
+				const char *name;
+			} cache[] = {
+				{ 0, "uncached" },
+				{ 1, "snoop" },
+				{ 2, "display" },
+				{ -1 },
+			}, *c;
+
+			igt_fixture
+				handle = m->bo_create(fd, object_size);
+
+			igt_subtest_f("%sbasic", m->prefix)
+				do_read_loop(fd, "basic", handle, dst,
+					     object_size);
+
+			for (c = cache; c->level != -1; c++) {
+				igt_subtest_f("%s%s", m->prefix, c->name) {
+					gem_set_caching(fd, handle, c->level);
+					do_read_loop(fd, c->name, handle, dst,
+						     object_size);
+				}
 			}
+
+			igt_fixture
+				gem_close(fd, handle);
 		}
 	}
 
 	igt_fixture {
-		free(src);
-		gem_close(fd, dst);
-
+		free(dst);
 		close(fd);
 	}