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@xxxxxxxxxxxxxxxxxx> > Signed-off-by: Daniele Ceraolo Spurio <daniele.ceraolospurio@xxxxxxxxx> > Cc: Chris Wilson <chris@xxxxxxxxxxxxxxxxxx> > --- > 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 _______________________________________________ Intel-gfx mailing list Intel-gfx@xxxxxxxxxxxxxxxxxxxxx https://lists.freedesktop.org/mailman/listinfo/intel-gfx