Sparse VM_BIND support was introduced with Panthor DRM driver version
1.9. If a driver isn't advertising support for v1.9, then tests that
call DRM_PANTHOR_VM_BIND_OP_MAP_SPARSE should not be run.

So skip the sparse VM_BIND subtests when running against a driver older
than version 1.9.

Also add indentation to group the sparse tests together.

Signed-off-by: Deborah Brouwer <[email protected]>
---
 tests/panthor/panthor_vm.c | 660 +++++++++++++++++++++++----------------------
 1 file changed, 342 insertions(+), 318 deletions(-)

diff --git a/tests/panthor/panthor_vm.c b/tests/panthor/panthor_vm.c
index 9011df25e..0140b9e40 100644
--- a/tests/panthor/panthor_vm.c
+++ b/tests/panthor/panthor_vm.c
@@ -7,6 +7,20 @@
 #include "igt_sizes.h"
 #include "panthor_drm.h"
 
+static bool panthor_driver_version_at_least(int fd, int major, int minor)
+{
+       drmVersionPtr version = drmGetVersion(fd);
+       bool supported;
+
+       igt_assert(version);
+       supported = version->version_major > major ||
+                   (version->version_major == major &&
+                    version->version_minor >= minor);
+       drmFreeVersion(version);
+
+       return supported;
+}
+
 int igt_main() {
        int fd = -1;
 
@@ -288,324 +302,334 @@ int igt_main() {
                igt_panthor_vm_destroy(fd, vm_id, 0);
        }
 
-       igt_describe("Perform a simple sparse vm_bind operation");
-       igt_subtest("vm_bind_sparse") {
-               uint32_t vm_id;
-               uint64_t map_size = SZ_4K * 4;
-
-               igt_panthor_vm_create(fd, &vm_id, 0);
-               igt_assert(vm_id != 0);
-
-               igt_panthor_vm_bind_sparse(fd, vm_id, SZ_2M, map_size, 0);
-               igt_panthor_vm_destroy(fd, vm_id, 0);
-       }
-
-       igt_describe("Perform a partial hugepage-unaligned unmap of a sparsely 
bound region");
-       igt_subtest("vm_bind_sparse_partial_unmap_start_size_unaligned") {
-               uint32_t vm_id;
-               uint64_t map_size = SZ_2M * 3;
-               const int INITIAL_VA = SZ_4M;
-
-               igt_panthor_vm_create(fd, &vm_id, 0);
-               igt_assert(vm_id != 0);
-
-               igt_panthor_vm_bind_sparse(fd, vm_id, INITIAL_VA, map_size, 0);
-               igt_panthor_vm_bind(fd, vm_id, 0, INITIAL_VA, SZ_4K * 2,
-                                   DRM_PANTHOR_VM_BIND_OP_TYPE_UNMAP, 0);
-               igt_panthor_vm_destroy(fd, vm_id, 0);
-       }
-
-       igt_describe("Do a partial hugeapge-aligned unmap from start of 
sparsely-bound region");
-       igt_subtest("vm_bind_sparse_partial_unmap_start_size_aligned") {
-               uint32_t vm_id;
-               uint64_t map_size = SZ_2M * 3;
-               const int INITIAL_VA = SZ_4M;
-
-               igt_panthor_vm_create(fd, &vm_id, 0);
-               igt_assert(vm_id != 0);
-
-               igt_panthor_vm_bind_sparse(fd, vm_id, INITIAL_VA, map_size, 0);
-               igt_panthor_vm_bind(fd, vm_id, 0, INITIAL_VA, SZ_2M,
-                                   DRM_PANTHOR_VM_BIND_OP_TYPE_UNMAP, 0);
-               igt_panthor_vm_destroy(fd, vm_id, 0);
-       }
-
-       igt_describe("Do a partial hugeapge-unaligned unmap from start of 
sparsely-bound region");
-       
igt_subtest("vm_bind_sparse_partial_unmap_start_aligned_no_hugepage_multiple") {
-               uint32_t vm_id;
-               uint64_t map_size = SZ_2M * 3;
-               const int INITIAL_VA = SZ_4M;
-
-               igt_panthor_vm_create(fd, &vm_id, 0);
-               igt_assert(vm_id != 0);
-
-               igt_panthor_vm_bind_sparse(fd, vm_id, INITIAL_VA, map_size, 0);
-               igt_panthor_vm_bind(fd, vm_id, 0, INITIAL_VA, 4 * SZ_64K,
-                                   DRM_PANTHOR_VM_BIND_OP_TYPE_UNMAP, 0);
-               igt_panthor_vm_destroy(fd, vm_id, 0);
-       }
-
-       igt_describe("Do partial hugeapge-aligned unmap that left-intersects 
with sparse region");
-       igt_subtest("vm_bind_sparse_partial_unmap_below_start") {
-               uint32_t vm_id;
-               uint64_t map_size = SZ_2M * 3;
-               const int INITIAL_VA = SZ_4M;
-
-               igt_panthor_vm_create(fd, &vm_id, 0);
-               igt_assert(vm_id != 0);
-
-               igt_panthor_vm_bind_sparse(fd, vm_id, INITIAL_VA, map_size, 0);
-               igt_panthor_vm_bind(fd, vm_id, 0, INITIAL_VA - SZ_2M, SZ_2M * 3,
-                                   DRM_PANTHOR_VM_BIND_OP_TYPE_UNMAP, 0);
-               igt_panthor_vm_destroy(fd, vm_id, 0);
-       }
-
-       igt_describe("Do partial hugepage-aligned unmap that is proper subset 
of sparse region");
-       igt_subtest("vm_bind_sparse_partial_unmap_above_start") {
-               uint32_t vm_id;
-               uint64_t map_size = SZ_2M * 3;
-               const int INITIAL_VA = SZ_4M;
-
-               igt_panthor_vm_create(fd, &vm_id, 0);
-               igt_assert(vm_id != 0);
-
-               igt_panthor_vm_bind_sparse(fd, vm_id, INITIAL_VA, map_size, 0);
-               igt_panthor_vm_bind(fd, vm_id, 0, INITIAL_VA + SZ_2M, SZ_2M,
-                                   DRM_PANTHOR_VM_BIND_OP_TYPE_UNMAP, 0);
-               igt_panthor_vm_destroy(fd, vm_id, 0);
-       }
-
-       igt_describe("Do normal hugepage-aligned bind that intersects with 
sparsely-mapped region");
-       igt_subtest("vm_bind_sparse_remap") {
-               uint32_t vm_id;
-               struct panthor_bo bo;
-               uint64_t map_size = SZ_2M * 3;
-               const int INITIAL_VA = SZ_4M;
-
-               igt_panthor_vm_create(fd, &vm_id, 0);
-               igt_assert(vm_id != 0);
-
-               igt_panthor_vm_bind_sparse(fd, vm_id, INITIAL_VA, map_size, 0);
-
-               /* Now attempt normal VM_BIND's that intersect with the 
previous chunk */
-               igt_panthor_bo_create(fd, &bo, SZ_8M, 0, 0);
-               igt_panthor_vm_bind(fd, vm_id, bo.handle, INITIAL_VA + SZ_2M, 
SZ_2M * 2,
-                                   DRM_PANTHOR_VM_BIND_OP_TYPE_MAP, 0);
-
-               igt_panthor_vm_destroy(fd, vm_id, 0);
-       }
-
-       igt_describe("Do normal hugepage-unaligned bind that intersects with 
sparsely-mapped region");
-       igt_subtest("vm_bind_sparse_remap_start_unaligned") {
-               uint32_t vm_id;
-               struct panthor_bo bo;
-               uint64_t map_size = SZ_2M * 3;
-               const int INITIAL_VA = SZ_4M;
-
-               igt_panthor_vm_create(fd, &vm_id, 0);
-               igt_assert(vm_id != 0);
-
-               igt_panthor_vm_bind_sparse(fd, vm_id, INITIAL_VA, map_size, 0);
-
-               /* Now attempt normal VM_BIND's that intersect with the 
previous chunk */
-               igt_panthor_bo_create(fd, &bo, SZ_8M, 0, 0);
-               igt_panthor_vm_bind(fd, vm_id, bo.handle, INITIAL_VA + map_size 
- SZ_1M,
-                                   SZ_4M, DRM_PANTHOR_VM_BIND_OP_TYPE_MAP, 0);
-
-               igt_panthor_vm_destroy(fd, vm_id, 0);
-       }
-
-       igt_describe("Do normal hugepage-unaligned bind that intersects with 
sparsely-mapped region");
-       igt_subtest("vm_bind_sparse_remap_start_size_unaligned") {
-               uint32_t vm_id;
-               struct panthor_bo bo;
-               uint64_t map_size = SZ_2M * 3;
-               const int INITIAL_VA = SZ_4M;
-
-               igt_panthor_vm_create(fd, &vm_id, 0);
-               igt_assert(vm_id != 0);
-
-               igt_panthor_vm_bind_sparse(fd, vm_id, INITIAL_VA, map_size, 0);
-
-               /* Now attempt normal VM_BIND's that intersect with the 
previous chunk */
-               igt_panthor_bo_create(fd, &bo, SZ_8M, 0, 0);
-               igt_panthor_vm_bind(fd, vm_id, bo.handle, INITIAL_VA + map_size 
- SZ_1M,
-                                   SZ_1M, DRM_PANTHOR_VM_BIND_OP_TYPE_MAP, 0);
-
-               igt_panthor_vm_destroy(fd, vm_id, 0);
-       }
-
-       igt_describe("Do normal hugepage-aligned bind that intersects with 
sparsely-mapped region");
-       igt_subtest("vm_bind_sparse_remap_start_size_aligned") {
-               uint32_t vm_id;
-               struct panthor_bo bo;
-               uint64_t map_size = SZ_2M * 3;
-               const int INITIAL_VA = SZ_4M;
-
-               igt_panthor_vm_create(fd, &vm_id, 0);
-               igt_assert(vm_id != 0);
-
-               igt_panthor_vm_bind_sparse(fd, vm_id, INITIAL_VA, map_size, 0);
-
-               /* Now attempt normal VM_BIND's that intersect with the 
previous chunk */
-               igt_panthor_bo_create(fd, &bo, SZ_8M, 0, 0);
-               igt_panthor_vm_bind(fd, vm_id, bo.handle,
-                                   INITIAL_VA + map_size - SZ_2M, SZ_4M,
-                                   DRM_PANTHOR_VM_BIND_OP_TYPE_MAP, 0);
-
-               igt_panthor_vm_destroy(fd, vm_id, 0);
-       }
-
-       igt_describe("Do normal hugepage-aligned bind that splits original 
region in two");
-       igt_subtest("vm_bind_sparse_remap_aligned_split_original_va") {
-               uint32_t vm_id;
-               struct panthor_bo bo;
-               uint64_t map_size = SZ_2M * 3;
-               const int INITIAL_VA = SZ_4M;
-
-               igt_panthor_vm_create(fd, &vm_id, 0);
-               igt_assert(vm_id != 0);
-
-               igt_panthor_vm_bind_sparse(fd, vm_id, INITIAL_VA, map_size, 0);
-
-               /* Now attempt normal VM_BIND's that intersect with the 
previous chunk */
-               igt_panthor_bo_create(fd, &bo, SZ_8M, 0, 0);
-               igt_panthor_vm_bind(fd, vm_id, bo.handle, INITIAL_VA + SZ_2M,
-                                   SZ_2M, DRM_PANTHOR_VM_BIND_OP_TYPE_MAP, 0);
-
-               igt_panthor_vm_destroy(fd, vm_id, 0);
-       }
-
-       igt_describe("Do normal 2MiB aligned hugepage-size-unaligned bind over 
sparse region");
-       igt_subtest("vm_bind_sparse_remap_start_aligned_size_unaligned") {
-               uint32_t vm_id;
-               struct panthor_bo bo;
-               uint64_t map_size = SZ_2M * 3;
-               const int INITIAL_VA = SZ_4M;
-
-               igt_panthor_vm_create(fd, &vm_id, 0);
-               igt_assert(vm_id != 0);
-
-               igt_panthor_vm_bind_sparse(fd, vm_id, INITIAL_VA, map_size, 0);
-
-               /* Now attempt normal VM_BIND's that intersect with the 
previous chunk */
-               igt_panthor_bo_create(fd, &bo, SZ_8M, 0, 0);
-               igt_panthor_vm_bind(fd, vm_id, bo.handle, INITIAL_VA + SZ_2M,
-                                   SZ_1M, DRM_PANTHOR_VM_BIND_OP_TYPE_MAP, 0);
-
-               igt_panthor_vm_destroy(fd, vm_id, 0);
-       }
-
-       igt_describe("Do normal hugepage-aligned bind over left end of sparse 
region");
-       igt_subtest("vm_bind_sparse_remap_aligned_intersect_left") {
-               uint32_t vm_id;
-               struct panthor_bo bo;
-               uint64_t map_size = SZ_2M * 3;
-               const int INITIAL_VA = SZ_4M;
-
-               igt_panthor_vm_create(fd, &vm_id, 0);
-               igt_assert(vm_id != 0);
-
-               igt_panthor_vm_bind_sparse(fd, vm_id, INITIAL_VA, map_size, 0);
-
-               /* Now attempt normal VM_BIND's that intersect with the 
previous chunk */
-               igt_panthor_bo_create(fd, &bo, SZ_8M, 0, 0);
-               igt_panthor_vm_bind(fd, vm_id, bo.handle,
-                                   INITIAL_VA - SZ_2M, SZ_2M * 2,
-                                   DRM_PANTHOR_VM_BIND_OP_TYPE_MAP, 0);
-
-               igt_panthor_vm_destroy(fd, vm_id, 0);
-       }
-
-       igt_describe("Do normal hugepage-unaligned bind over left end of sparse 
region");
-       igt_subtest("vm_bind_sparse_remap_size_unaligned_intersect_left") {
-               uint32_t vm_id;
-               struct panthor_bo bo;
-               uint64_t map_size = SZ_2M * 3;
-               const int INITIAL_VA = SZ_4M;
-
-               igt_panthor_vm_create(fd, &vm_id, 0);
-               igt_assert(vm_id != 0);
-
-               igt_panthor_vm_bind_sparse(fd, vm_id, INITIAL_VA, map_size, 0);
-
-               /* Now attempt normal VM_BIND's that intersect with the 
previous chunk */
-               igt_panthor_bo_create(fd, &bo, SZ_8M, 0, 0);
-               igt_panthor_vm_bind(fd, vm_id, bo.handle,
-                                   INITIAL_VA - SZ_2M, SZ_1M * 3,
-                                   DRM_PANTHOR_VM_BIND_OP_TYPE_MAP, 0);
-
-               igt_panthor_vm_destroy(fd, vm_id, 0);
-       }
-
-       igt_describe("Do normal hugepage-unaligned bind over right end of 
sparse region");
-       igt_subtest("vm_bind_sparse_remap_start_aligned_intersect_right") {
-               uint32_t vm_id;
-               struct panthor_bo bo;
-               uint64_t map_size = SZ_2M * 3;
-               const int INITIAL_VA = SZ_4M;
-
-               igt_panthor_vm_create(fd, &vm_id, 0);
-               igt_assert(vm_id != 0);
-
-               igt_panthor_vm_bind_sparse(fd, vm_id, INITIAL_VA, map_size, 0);
-
-               /* Now attempt normal VM_BIND's that intersect with the 
previous chunk */
-               igt_panthor_bo_create(fd, &bo, SZ_8M, 0, 0);
-               igt_panthor_vm_bind(fd, vm_id, bo.handle,
-                                   INITIAL_VA + map_size - SZ_2M, SZ_2M + 
SZ_4K * 6,
-                                   DRM_PANTHOR_VM_BIND_OP_TYPE_MAP, 0);
-
-               igt_panthor_vm_destroy(fd, vm_id, 0);
-       }
-
-       igt_describe("Do normal hugepage-aligned bind that envelopes whole 
sparse region");
-       igt_subtest("vm_bind_sparse_remap_wrap_around_va") {
-               uint32_t vm_id;
-               struct panthor_bo bo;
-               uint64_t map_size = SZ_2M * 3;
-               const int INITIAL_VA = SZ_4M;
-
-               igt_panthor_vm_create(fd, &vm_id, 0);
-               igt_assert(vm_id != 0);
-
-               igt_panthor_vm_bind_sparse(fd, vm_id, INITIAL_VA, map_size, 0);
-
-               /* Now attempt normal VM_BIND's that intersect with the 
previous chunk */
-               igt_panthor_bo_create(fd, &bo, SZ_8M, 0, 0);
-               igt_panthor_vm_bind(fd, vm_id, bo.handle, INITIAL_VA - SZ_2M,
-                                   SZ_8M, DRM_PANTHOR_VM_BIND_OP_TYPE_MAP, 0);
-
-               igt_panthor_vm_destroy(fd, vm_id, 0);
-       }
-
-       igt_describe("Perform sparse binding operation whose range causes an 
overflow");
-       igt_subtest("vm_bind_sparse_overflow") {
-               uint32_t vm_id;
-               uint64_t map_size = ALIGN_DOWN(UINT64_MAX, SZ_2M) - (SZ_2M * 3);
-               const int INITIAL_VA = SZ_512M;
-
-               igt_panthor_vm_create(fd, &vm_id, 0);
-               igt_assert(vm_id != 0);
-
-               igt_panthor_vm_bind_sparse(fd, vm_id, INITIAL_VA, map_size, 
EINVAL);
-               igt_panthor_vm_destroy(fd, vm_id, 0);
-       }
-
-       igt_describe("Perform sparse unbind operation whose range causes an 
overflow");
-       igt_subtest("vm_unbind_sparse_overflow") {
-               uint32_t vm_id;
-               uint64_t map_size = SZ_2M * 3;
-               uint64_t unmap_size = ALIGN_DOWN(UINT64_MAX, SZ_2M) - map_size;
-               const int INITIAL_VA = SZ_512M;
-
-               igt_panthor_vm_create(fd, &vm_id, 0);
-               igt_assert(vm_id != 0);
-
-               igt_panthor_vm_bind_sparse(fd, vm_id, INITIAL_VA, map_size, 0);
-               igt_panthor_vm_bind(fd, vm_id, 0, INITIAL_VA, unmap_size,
-                                   DRM_PANTHOR_VM_BIND_OP_TYPE_UNMAP, EINVAL);
-               igt_panthor_vm_destroy(fd, vm_id, 0);
+       igt_subtest_group() {
+               igt_fixture() {
+                       bool sparse_supported = 
panthor_driver_version_at_least(fd, 1, 9);
+
+                       errno = 0;
+                       igt_require_f(sparse_supported,
+                                     "Sparse VM_BIND requires Panthor DRM 
driver version 1.9 or newer\n");
+               }
+
+               igt_describe("Perform a simple sparse vm_bind operation");
+               igt_subtest("vm_bind_sparse") {
+                       uint32_t vm_id;
+                       uint64_t map_size = SZ_4K * 4;
+
+                       igt_panthor_vm_create(fd, &vm_id, 0);
+                       igt_assert(vm_id != 0);
+
+                       igt_panthor_vm_bind_sparse(fd, vm_id, SZ_2M, map_size, 
0);
+                       igt_panthor_vm_destroy(fd, vm_id, 0);
+               }
+
+               igt_describe("Perform a partial hugepage-unaligned unmap of a 
sparsely bound region");
+               
igt_subtest("vm_bind_sparse_partial_unmap_start_size_unaligned") {
+                       uint32_t vm_id;
+                       uint64_t map_size = SZ_2M * 3;
+                       const int INITIAL_VA = SZ_4M;
+
+                       igt_panthor_vm_create(fd, &vm_id, 0);
+                       igt_assert(vm_id != 0);
+
+                       igt_panthor_vm_bind_sparse(fd, vm_id, INITIAL_VA, 
map_size, 0);
+                       igt_panthor_vm_bind(fd, vm_id, 0, INITIAL_VA, SZ_4K * 2,
+                                           DRM_PANTHOR_VM_BIND_OP_TYPE_UNMAP, 
0);
+                       igt_panthor_vm_destroy(fd, vm_id, 0);
+               }
+
+               igt_describe("Do a partial hugeapge-aligned unmap from start of 
sparsely-bound region");
+               igt_subtest("vm_bind_sparse_partial_unmap_start_size_aligned") {
+                       uint32_t vm_id;
+                       uint64_t map_size = SZ_2M * 3;
+                       const int INITIAL_VA = SZ_4M;
+
+                       igt_panthor_vm_create(fd, &vm_id, 0);
+                       igt_assert(vm_id != 0);
+
+                       igt_panthor_vm_bind_sparse(fd, vm_id, INITIAL_VA, 
map_size, 0);
+                       igt_panthor_vm_bind(fd, vm_id, 0, INITIAL_VA, SZ_2M,
+                                           DRM_PANTHOR_VM_BIND_OP_TYPE_UNMAP, 
0);
+                       igt_panthor_vm_destroy(fd, vm_id, 0);
+               }
+
+               igt_describe("Do a partial hugeapge-unaligned unmap from start 
of sparsely-bound region");
+               
igt_subtest("vm_bind_sparse_partial_unmap_start_aligned_no_hugepage_multiple") {
+                       uint32_t vm_id;
+                       uint64_t map_size = SZ_2M * 3;
+                       const int INITIAL_VA = SZ_4M;
+
+                       igt_panthor_vm_create(fd, &vm_id, 0);
+                       igt_assert(vm_id != 0);
+
+                       igt_panthor_vm_bind_sparse(fd, vm_id, INITIAL_VA, 
map_size, 0);
+                       igt_panthor_vm_bind(fd, vm_id, 0, INITIAL_VA, 4 * 
SZ_64K,
+                                           DRM_PANTHOR_VM_BIND_OP_TYPE_UNMAP, 
0);
+                       igt_panthor_vm_destroy(fd, vm_id, 0);
+               }
+
+               igt_describe("Do partial hugeapge-aligned unmap that 
left-intersects with sparse region");
+               igt_subtest("vm_bind_sparse_partial_unmap_below_start") {
+                       uint32_t vm_id;
+                       uint64_t map_size = SZ_2M * 3;
+                       const int INITIAL_VA = SZ_4M;
+
+                       igt_panthor_vm_create(fd, &vm_id, 0);
+                       igt_assert(vm_id != 0);
+
+                       igt_panthor_vm_bind_sparse(fd, vm_id, INITIAL_VA, 
map_size, 0);
+                       igt_panthor_vm_bind(fd, vm_id, 0, INITIAL_VA - SZ_2M, 
SZ_2M * 3,
+                                           DRM_PANTHOR_VM_BIND_OP_TYPE_UNMAP, 
0);
+                       igt_panthor_vm_destroy(fd, vm_id, 0);
+               }
+
+               igt_describe("Do partial hugepage-aligned unmap that is proper 
subset of sparse region");
+               igt_subtest("vm_bind_sparse_partial_unmap_above_start") {
+                       uint32_t vm_id;
+                       uint64_t map_size = SZ_2M * 3;
+                       const int INITIAL_VA = SZ_4M;
+
+                       igt_panthor_vm_create(fd, &vm_id, 0);
+                       igt_assert(vm_id != 0);
+
+                       igt_panthor_vm_bind_sparse(fd, vm_id, INITIAL_VA, 
map_size, 0);
+                       igt_panthor_vm_bind(fd, vm_id, 0, INITIAL_VA + SZ_2M, 
SZ_2M,
+                                           DRM_PANTHOR_VM_BIND_OP_TYPE_UNMAP, 
0);
+                       igt_panthor_vm_destroy(fd, vm_id, 0);
+               }
+
+               igt_describe("Do normal hugepage-aligned bind that intersects 
with sparsely-mapped region");
+               igt_subtest("vm_bind_sparse_remap") {
+                       uint32_t vm_id;
+                       struct panthor_bo bo;
+                       uint64_t map_size = SZ_2M * 3;
+                       const int INITIAL_VA = SZ_4M;
+
+                       igt_panthor_vm_create(fd, &vm_id, 0);
+                       igt_assert(vm_id != 0);
+
+                       igt_panthor_vm_bind_sparse(fd, vm_id, INITIAL_VA, 
map_size, 0);
+
+                       /* Now attempt normal VM_BIND's that intersect with the 
previous chunk */
+                       igt_panthor_bo_create(fd, &bo, SZ_8M, 0, 0);
+                       igt_panthor_vm_bind(fd, vm_id, bo.handle, INITIAL_VA + 
SZ_2M, SZ_2M * 2,
+                                           DRM_PANTHOR_VM_BIND_OP_TYPE_MAP, 0);
+
+                       igt_panthor_vm_destroy(fd, vm_id, 0);
+               }
+
+               igt_describe("Do normal hugepage-unaligned bind that intersects 
with sparsely-mapped region");
+               igt_subtest("vm_bind_sparse_remap_start_unaligned") {
+                       uint32_t vm_id;
+                       struct panthor_bo bo;
+                       uint64_t map_size = SZ_2M * 3;
+                       const int INITIAL_VA = SZ_4M;
+
+                       igt_panthor_vm_create(fd, &vm_id, 0);
+                       igt_assert(vm_id != 0);
+
+                       igt_panthor_vm_bind_sparse(fd, vm_id, INITIAL_VA, 
map_size, 0);
+
+                       /* Now attempt normal VM_BIND's that intersect with the 
previous chunk */
+                       igt_panthor_bo_create(fd, &bo, SZ_8M, 0, 0);
+                       igt_panthor_vm_bind(fd, vm_id, bo.handle, INITIAL_VA + 
map_size - SZ_1M,
+                                           SZ_4M, 
DRM_PANTHOR_VM_BIND_OP_TYPE_MAP, 0);
+
+                       igt_panthor_vm_destroy(fd, vm_id, 0);
+               }
+
+               igt_describe("Do normal hugepage-unaligned bind that intersects 
with sparsely-mapped region");
+               igt_subtest("vm_bind_sparse_remap_start_size_unaligned") {
+                       uint32_t vm_id;
+                       struct panthor_bo bo;
+                       uint64_t map_size = SZ_2M * 3;
+                       const int INITIAL_VA = SZ_4M;
+
+                       igt_panthor_vm_create(fd, &vm_id, 0);
+                       igt_assert(vm_id != 0);
+
+                       igt_panthor_vm_bind_sparse(fd, vm_id, INITIAL_VA, 
map_size, 0);
+
+                       /* Now attempt normal VM_BIND's that intersect with the 
previous chunk */
+                       igt_panthor_bo_create(fd, &bo, SZ_8M, 0, 0);
+                       igt_panthor_vm_bind(fd, vm_id, bo.handle, INITIAL_VA + 
map_size - SZ_1M,
+                                           SZ_1M, 
DRM_PANTHOR_VM_BIND_OP_TYPE_MAP, 0);
+
+                       igt_panthor_vm_destroy(fd, vm_id, 0);
+               }
+
+               igt_describe("Do normal hugepage-aligned bind that intersects 
with sparsely-mapped region");
+               igt_subtest("vm_bind_sparse_remap_start_size_aligned") {
+                       uint32_t vm_id;
+                       struct panthor_bo bo;
+                       uint64_t map_size = SZ_2M * 3;
+                       const int INITIAL_VA = SZ_4M;
+
+                       igt_panthor_vm_create(fd, &vm_id, 0);
+                       igt_assert(vm_id != 0);
+
+                       igt_panthor_vm_bind_sparse(fd, vm_id, INITIAL_VA, 
map_size, 0);
+
+                       /* Now attempt normal VM_BIND's that intersect with the 
previous chunk */
+                       igt_panthor_bo_create(fd, &bo, SZ_8M, 0, 0);
+                       igt_panthor_vm_bind(fd, vm_id, bo.handle,
+                                           INITIAL_VA + map_size - SZ_2M, 
SZ_4M,
+                                           DRM_PANTHOR_VM_BIND_OP_TYPE_MAP, 0);
+
+                       igt_panthor_vm_destroy(fd, vm_id, 0);
+               }
+
+               igt_describe("Do normal hugepage-aligned bind that splits 
original region in two");
+               igt_subtest("vm_bind_sparse_remap_aligned_split_original_va") {
+                       uint32_t vm_id;
+                       struct panthor_bo bo;
+                       uint64_t map_size = SZ_2M * 3;
+                       const int INITIAL_VA = SZ_4M;
+
+                       igt_panthor_vm_create(fd, &vm_id, 0);
+                       igt_assert(vm_id != 0);
+
+                       igt_panthor_vm_bind_sparse(fd, vm_id, INITIAL_VA, 
map_size, 0);
+
+                       /* Now attempt normal VM_BIND's that intersect with the 
previous chunk */
+                       igt_panthor_bo_create(fd, &bo, SZ_8M, 0, 0);
+                       igt_panthor_vm_bind(fd, vm_id, bo.handle, INITIAL_VA + 
SZ_2M,
+                                           SZ_2M, 
DRM_PANTHOR_VM_BIND_OP_TYPE_MAP, 0);
+
+                       igt_panthor_vm_destroy(fd, vm_id, 0);
+               }
+
+               igt_describe("Do normal 2MiB aligned hugepage-size-unaligned 
bind over sparse region");
+               
igt_subtest("vm_bind_sparse_remap_start_aligned_size_unaligned") {
+                       uint32_t vm_id;
+                       struct panthor_bo bo;
+                       uint64_t map_size = SZ_2M * 3;
+                       const int INITIAL_VA = SZ_4M;
+
+                       igt_panthor_vm_create(fd, &vm_id, 0);
+                       igt_assert(vm_id != 0);
+
+                       igt_panthor_vm_bind_sparse(fd, vm_id, INITIAL_VA, 
map_size, 0);
+
+                       /* Now attempt normal VM_BIND's that intersect with the 
previous chunk */
+                       igt_panthor_bo_create(fd, &bo, SZ_8M, 0, 0);
+                       igt_panthor_vm_bind(fd, vm_id, bo.handle, INITIAL_VA + 
SZ_2M,
+                                           SZ_1M, 
DRM_PANTHOR_VM_BIND_OP_TYPE_MAP, 0);
+
+                       igt_panthor_vm_destroy(fd, vm_id, 0);
+               }
+
+               igt_describe("Do normal hugepage-aligned bind over left end of 
sparse region");
+               igt_subtest("vm_bind_sparse_remap_aligned_intersect_left") {
+                       uint32_t vm_id;
+                       struct panthor_bo bo;
+                       uint64_t map_size = SZ_2M * 3;
+                       const int INITIAL_VA = SZ_4M;
+
+                       igt_panthor_vm_create(fd, &vm_id, 0);
+                       igt_assert(vm_id != 0);
+
+                       igt_panthor_vm_bind_sparse(fd, vm_id, INITIAL_VA, 
map_size, 0);
+
+                       /* Now attempt normal VM_BIND's that intersect with the 
previous chunk */
+                       igt_panthor_bo_create(fd, &bo, SZ_8M, 0, 0);
+                       igt_panthor_vm_bind(fd, vm_id, bo.handle,
+                                           INITIAL_VA - SZ_2M, SZ_2M * 2,
+                                           DRM_PANTHOR_VM_BIND_OP_TYPE_MAP, 0);
+
+                       igt_panthor_vm_destroy(fd, vm_id, 0);
+               }
+
+               igt_describe("Do normal hugepage-unaligned bind over left end 
of sparse region");
+               
igt_subtest("vm_bind_sparse_remap_size_unaligned_intersect_left") {
+                       uint32_t vm_id;
+                       struct panthor_bo bo;
+                       uint64_t map_size = SZ_2M * 3;
+                       const int INITIAL_VA = SZ_4M;
+
+                       igt_panthor_vm_create(fd, &vm_id, 0);
+                       igt_assert(vm_id != 0);
+
+                       igt_panthor_vm_bind_sparse(fd, vm_id, INITIAL_VA, 
map_size, 0);
+
+                       /* Now attempt normal VM_BIND's that intersect with the 
previous chunk */
+                       igt_panthor_bo_create(fd, &bo, SZ_8M, 0, 0);
+                       igt_panthor_vm_bind(fd, vm_id, bo.handle,
+                                           INITIAL_VA - SZ_2M, SZ_1M * 3,
+                                           DRM_PANTHOR_VM_BIND_OP_TYPE_MAP, 0);
+
+                       igt_panthor_vm_destroy(fd, vm_id, 0);
+               }
+
+               igt_describe("Do normal hugepage-unaligned bind over right end 
of sparse region");
+               
igt_subtest("vm_bind_sparse_remap_start_aligned_intersect_right") {
+                       uint32_t vm_id;
+                       struct panthor_bo bo;
+                       uint64_t map_size = SZ_2M * 3;
+                       const int INITIAL_VA = SZ_4M;
+
+                       igt_panthor_vm_create(fd, &vm_id, 0);
+                       igt_assert(vm_id != 0);
+
+                       igt_panthor_vm_bind_sparse(fd, vm_id, INITIAL_VA, 
map_size, 0);
+
+                       /* Now attempt normal VM_BIND's that intersect with the 
previous chunk */
+                       igt_panthor_bo_create(fd, &bo, SZ_8M, 0, 0);
+                       igt_panthor_vm_bind(fd, vm_id, bo.handle,
+                                           INITIAL_VA + map_size - SZ_2M, 
SZ_2M + SZ_4K * 6,
+                                           DRM_PANTHOR_VM_BIND_OP_TYPE_MAP, 0);
+
+                       igt_panthor_vm_destroy(fd, vm_id, 0);
+               }
+
+               igt_describe("Do normal hugepage-aligned bind that envelopes 
whole sparse region");
+               igt_subtest("vm_bind_sparse_remap_wrap_around_va") {
+                       uint32_t vm_id;
+                       struct panthor_bo bo;
+                       uint64_t map_size = SZ_2M * 3;
+                       const int INITIAL_VA = SZ_4M;
+
+                       igt_panthor_vm_create(fd, &vm_id, 0);
+                       igt_assert(vm_id != 0);
+
+                       igt_panthor_vm_bind_sparse(fd, vm_id, INITIAL_VA, 
map_size, 0);
+
+                       /* Now attempt normal VM_BIND's that intersect with the 
previous chunk */
+                       igt_panthor_bo_create(fd, &bo, SZ_8M, 0, 0);
+                       igt_panthor_vm_bind(fd, vm_id, bo.handle, INITIAL_VA - 
SZ_2M,
+                                           SZ_8M, 
DRM_PANTHOR_VM_BIND_OP_TYPE_MAP, 0);
+
+                       igt_panthor_vm_destroy(fd, vm_id, 0);
+               }
+
+               igt_describe("Perform sparse binding operation whose range 
causes an overflow");
+               igt_subtest("vm_bind_sparse_overflow") {
+                       uint32_t vm_id;
+                       uint64_t map_size = ALIGN_DOWN(UINT64_MAX, SZ_2M) - 
(SZ_2M * 3);
+                       const int INITIAL_VA = SZ_512M;
+
+                       igt_panthor_vm_create(fd, &vm_id, 0);
+                       igt_assert(vm_id != 0);
+
+                       igt_panthor_vm_bind_sparse(fd, vm_id, INITIAL_VA, 
map_size, EINVAL);
+                       igt_panthor_vm_destroy(fd, vm_id, 0);
+               }
+
+               igt_describe("Perform sparse unbind operation whose range 
causes an overflow");
+               igt_subtest("vm_unbind_sparse_overflow") {
+                       uint32_t vm_id;
+                       uint64_t map_size = SZ_2M * 3;
+                       uint64_t unmap_size = ALIGN_DOWN(UINT64_MAX, SZ_2M) - 
map_size;
+                       const int INITIAL_VA = SZ_512M;
+
+                       igt_panthor_vm_create(fd, &vm_id, 0);
+                       igt_assert(vm_id != 0);
+
+                       igt_panthor_vm_bind_sparse(fd, vm_id, INITIAL_VA, 
map_size, 0);
+                       igt_panthor_vm_bind(fd, vm_id, 0, INITIAL_VA, 
unmap_size,
+                                           DRM_PANTHOR_VM_BIND_OP_TYPE_UNMAP, 
EINVAL);
+                       igt_panthor_vm_destroy(fd, vm_id, 0);
+               }
        }
 
        igt_fixture() {

---
base-commit: 970700a95acd74bb987287d10147b5f23380519b
change-id: 20260915-b4-panthor_version_sparse-5fbd31cc0d5d

Best regards,
-- 
Deborah Brouwer <[email protected]>

Reply via email to