[Intel-gfx] [PATCH i-g-t v5] tests/gem_mmap_gtt: add huge BO test
Tvrtko Ursulin
tvrtko.ursulin at linux.intel.com
Tue Apr 14 04:23:06 PDT 2015
On 04/14/2015 12:14 PM, Joonas Lahtinen wrote:
> Add a straightforward test that allocates a BO that is bigger than
> (by 1 page currently) the mappable aperture, tests mmap access to it
> by CPU directly and through GTT in sequence.
>
> Currently it is expected for the GTT access to gracefully fail as
> all objects are attempted to get pinned to GTT completely for mmap
> access. Once the partial view support is merged to kernel, the test
> should pass for all parts.
>
> v2:
> - Corrected BO domain handling (Chris Wilson)
> - Check again after GTT access for added paranoia (Chris Wilson)
>
> v3:
> - Avoid flush by using pread (Chris Wilson)
> - Free gtt_pattern buffer too.
>
> v4:
> - Add more comments (Tvrtko Ursulin)
> - Use igt_require (Tvrtko Ursulin)
>
> v5:
> - Remove wrong message from igt_require_f (Tvrtko Ursulin)
> - After digging deeper to it, just igt_assert that the CPU
> mapping needs to succeed.
>
> Cc: Tvrtko Ursulin <tvrtko.ursulin at linux.intel.com>
> Cc: Chris Wilson <chris at chris-wilson.co.uk>
> Signed-off-by: Joonas Lahtinen <joonas.lahtinen at linux.intel.com>
> ---
> tests/gem_mmap_gtt.c | 106 +++++++++++++++++++++++++++++++++++++++++++++++++++
> 1 file changed, 106 insertions(+)
>
> diff --git a/tests/gem_mmap_gtt.c b/tests/gem_mmap_gtt.c
> index 115e398..487eecf 100644
> --- a/tests/gem_mmap_gtt.c
> +++ b/tests/gem_mmap_gtt.c
> @@ -41,6 +41,10 @@
> #include "drmtest.h"
> #include "igt_debugfs.h"
>
> +#ifndef PAGE_SIZE
> +#define PAGE_SIZE 4096
> +#endif
> +
> static int OBJECT_SIZE = 16*1024*1024;
>
> static void
> @@ -55,6 +59,20 @@ set_domain_cpu(int fd, uint32_t handle)
> gem_set_domain(fd, handle, I915_GEM_DOMAIN_CPU, I915_GEM_DOMAIN_CPU);
> }
>
> +static void
> +pread_bo(int fd, int handle, void *buf, int offset, int size)
> +{
> + struct drm_i915_gem_pread gem_pread;
> +
> + memset(&gem_pread, 0, sizeof(gem_pread));
> + gem_pread.handle = handle;
> + gem_pread.data_ptr = (uintptr_t)buf;
> + gem_pread.size = size;
> + gem_pread.offset = offset;
> +
> + igt_assert(ioctl(fd, DRM_IOCTL_I915_GEM_PREAD, &gem_pread) == 0);
> +}
> +
> static void *
> mmap_bo(int fd, uint32_t handle)
> {
> @@ -265,6 +283,92 @@ test_write_gtt(int fd)
> }
>
> static void
> +test_huge_bo(int fd)
> +{
> + uint32_t bo;
> + char *ptr_cpu;
> + char *ptr_gtt;
> + char *cpu_pattern;
> + char *gtt_pattern;
> + uint64_t mappable_aperture_pages = gem_mappable_aperture_size() /
> + PAGE_SIZE;
> + uint64_t huge_object_size = (mappable_aperture_pages + 1) * PAGE_SIZE;
> + uint64_t last_offset = huge_object_size - PAGE_SIZE;
> +
> + cpu_pattern = malloc(PAGE_SIZE);
> + gtt_pattern = malloc(PAGE_SIZE);
> + igt_assert(cpu_pattern && gtt_pattern);
> + memset(cpu_pattern, 0xaa, PAGE_SIZE);
> + memset(gtt_pattern, ~0xaa, PAGE_SIZE);
> +
> + bo = gem_create(fd, huge_object_size);
> +
> + /* Obtain CPU mapping for the object. */
> + ptr_cpu = gem_mmap__cpu(fd, bo, 0, huge_object_size,
> + PROT_READ | PROT_WRITE);
> + igt_assert(ptr_cpu);
> +
> + set_domain_cpu(fd, bo);
> +
> + /* Write first page through the mapping and assert reading it back
> + * works. */
> + memcpy(ptr_cpu, cpu_pattern, PAGE_SIZE);
> + igt_assert(memcmp(ptr_cpu, cpu_pattern, PAGE_SIZE) == 0);
> +
> + /* Write last page through the mapping and assert reading it back
> + * works. */
> + memcpy(ptr_cpu + last_offset, cpu_pattern, PAGE_SIZE);
> + igt_assert(memcmp(ptr_cpu + last_offset, cpu_pattern, PAGE_SIZE) == 0);
> +
> + /* Cross check that accessing two simultaneous pages works. */
> + igt_assert(memcmp(ptr_cpu, ptr_cpu + last_offset, PAGE_SIZE) == 0);
> +
> + munmap(ptr_cpu, huge_object_size);
> + ptr_cpu = NULL;
> +
> + /* Obtain mapping for the object through GTT. */
> + ptr_gtt = gem_mmap__gtt(fd, bo, huge_object_size,
> + PROT_READ | PROT_WRITE);
> + igt_require_f(ptr_gtt, "Huge BO GTT mapping not supported.\n");
> +
> + set_domain_gtt(fd, bo);
> +
> + /* Access through GTT should still provide the CPU written values. */
> + igt_assert(memcmp(ptr_gtt , cpu_pattern, PAGE_SIZE) == 0);
> + igt_assert(memcmp(ptr_gtt + last_offset, cpu_pattern, PAGE_SIZE) == 0);
> +
> + /* Try replacing first page through GTT mapping and make sure other page
> + * stays intact. */
> + memcpy(ptr_gtt, gtt_pattern, PAGE_SIZE);
> + igt_assert(memcmp(ptr_gtt , gtt_pattern, PAGE_SIZE) == 0);
> + igt_assert(memcmp(ptr_gtt + last_offset, cpu_pattern, PAGE_SIZE) == 0);
> +
> + /* And make sure that after writing, both pages contain what they
> + * should.*/
> + memcpy(ptr_gtt + last_offset, gtt_pattern, PAGE_SIZE);
> + igt_assert(memcmp(ptr_gtt , gtt_pattern, PAGE_SIZE) == 0);
> + igt_assert(memcmp(ptr_gtt + last_offset, gtt_pattern, PAGE_SIZE) == 0);
> +
> + munmap(ptr_gtt, huge_object_size);
> + ptr_gtt = NULL;
> +
> + /* Verify the page contents after GTT writes by reading without mapping.
> + * Mapping to CPU domain is avoided not to cause a huge flush.
> + */
> + pread_bo(fd, bo, cpu_pattern, 0, PAGE_SIZE);
> + igt_assert(memcmp(cpu_pattern, gtt_pattern, PAGE_SIZE) == 0);
> +
> + memset(cpu_pattern, 0x00, PAGE_SIZE);
> +
> + pread_bo(fd, bo, cpu_pattern, last_offset, PAGE_SIZE);
> + igt_assert(memcmp(cpu_pattern, gtt_pattern, PAGE_SIZE) == 0);
> +out:
> + gem_close(fd, bo);
> + free(cpu_pattern);
> + free(gtt_pattern);
> +}
> +
> +static void
> test_read(int fd)
> {
> void *dst;
> @@ -402,6 +506,8 @@ igt_main
> run_without_prefault(fd, test_write_gtt);
> igt_subtest("write-cpu-read-gtt")
> test_write_cpu_read_gtt(fd);
> + igt_subtest("huge-bo")
> + test_huge_bo(fd);
>
> igt_fixture
> close(fd);
>
I suspect in the future you may want to create a dedicated test for
partial views since there will be many more specific test cases, but for
now:
Reviewed-by: Tvrtko Ursulin <tvrtko.ursulin at intel.com>
Regards,
Tvrtko
More information about the Intel-gfx
mailing list