drm/i915: Migrate platform-dependent mock hugepage selftests to live
authorJonathan Cavitt <jonathan.cavitt@intel.com>
Wed, 26 Apr 2023 21:28:48 +0000 (23:28 +0200)
committerAndrzej Hajda <andrzej.hajda@intel.com>
Fri, 28 Apr 2023 11:20:04 +0000 (13:20 +0200)
Convert the igt_mock_ppgtt_huge_fill and igt_mock_ppgtt_64K mock selftests
into live selftests as their requirements have recently become
platform-dependent. Additionally, apply necessary platform dependency
checks to these tests.

v8:
- handle properly 64K and 2M pages
v9:
- do not expect 64K pages if 2M are present
- fix hex printing
- obey commit message line limit

Signed-off-by: Jonathan Cavitt <jonathan.cavitt@intel.com>
Co-developed-by: Andrzej Hajda <andrzej.hajda@intel.com>
Signed-off-by: Andrzej Hajda <andrzej.hajda@intel.com>
Reviewed-by: Andi Shyti <andi.shyti@linux.intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20230425-hugepage-migrate-v8-1-7868d54eaa27@intel.com
drivers/gpu/drm/i915/gem/selftests/huge_pages.c

index defece0..cb5863f 100644 (file)
@@ -695,8 +695,7 @@ out_put:
        return err;
 }
 
-static void close_object_list(struct list_head *objects,
-                             struct i915_ppgtt *ppgtt)
+static void close_object_list(struct list_head *objects)
 {
        struct drm_i915_gem_object *obj, *on;
 
@@ -710,17 +709,36 @@ static void close_object_list(struct list_head *objects,
        }
 }
 
-static int igt_mock_ppgtt_huge_fill(void *arg)
+static int igt_ppgtt_huge_fill(void *arg)
 {
-       struct i915_ppgtt *ppgtt = arg;
-       struct drm_i915_private *i915 = ppgtt->vm.i915;
-       unsigned long max_pages = ppgtt->vm.total >> PAGE_SHIFT;
+       struct drm_i915_private *i915 = arg;
+       unsigned int supported = RUNTIME_INFO(i915)->page_sizes;
+       bool has_pte64 = GRAPHICS_VER_FULL(i915) >= IP_VER(12, 50);
+       struct i915_address_space *vm;
+       struct i915_gem_context *ctx;
+       unsigned long max_pages;
        unsigned long page_num;
+       struct file *file;
        bool single = false;
        LIST_HEAD(objects);
        IGT_TIMEOUT(end_time);
        int err = -ENODEV;
 
+       if (supported == I915_GTT_PAGE_SIZE_4K)
+               return 0;
+
+       file = mock_file(i915);
+       if (IS_ERR(file))
+               return PTR_ERR(file);
+
+       ctx = hugepage_ctx(i915, file);
+       if (IS_ERR(ctx)) {
+               err = PTR_ERR(ctx);
+               goto out;
+       }
+       vm = i915_gem_context_get_eb_vm(ctx);
+       max_pages = vm->total >> PAGE_SHIFT;
+
        for_each_prime_number_from(page_num, 1, max_pages) {
                struct drm_i915_gem_object *obj;
                u64 size = page_num << PAGE_SHIFT;
@@ -750,13 +768,14 @@ static int igt_mock_ppgtt_huge_fill(void *arg)
 
                list_add(&obj->st_link, &objects);
 
-               vma = i915_vma_instance(obj, &ppgtt->vm, NULL);
+               vma = i915_vma_instance(obj, vm, NULL);
                if (IS_ERR(vma)) {
                        err = PTR_ERR(vma);
                        break;
                }
 
-               err = i915_vma_pin(vma, 0, 0, PIN_USER);
+               /* vma start must be aligned to BIT(21) to allow 2M PTEs */
+               err = i915_vma_pin(vma, 0, BIT(21), PIN_USER);
                if (err)
                        break;
 
@@ -784,12 +803,13 @@ static int igt_mock_ppgtt_huge_fill(void *arg)
                GEM_BUG_ON(!expected_gtt);
                GEM_BUG_ON(size);
 
-               if (expected_gtt & I915_GTT_PAGE_SIZE_4K)
+               if (!has_pte64 && (obj->base.size < I915_GTT_PAGE_SIZE_2M ||
+                                  expected_gtt & I915_GTT_PAGE_SIZE_2M))
                        expected_gtt &= ~I915_GTT_PAGE_SIZE_64K;
 
                i915_vma_unpin(vma);
 
-               if (vma->page_sizes.sg & I915_GTT_PAGE_SIZE_64K) {
+               if (!has_pte64 && vma->page_sizes.sg & I915_GTT_PAGE_SIZE_64K) {
                        if (!IS_ALIGNED(vma->node.start,
                                        I915_GTT_PAGE_SIZE_2M)) {
                                pr_err("node.start(%llx) not aligned to 2M\n",
@@ -808,7 +828,7 @@ static int igt_mock_ppgtt_huge_fill(void *arg)
                }
 
                if (vma->resource->page_sizes_gtt != expected_gtt) {
-                       pr_err("gtt=%u, expected=%u, size=%zd, single=%s\n",
+                       pr_err("gtt=%#x, expected=%#x, size=0x%zx, single=%s\n",
                               vma->resource->page_sizes_gtt, expected_gtt,
                               obj->base.size, str_yes_no(!!single));
                        err = -EINVAL;
@@ -823,19 +843,25 @@ static int igt_mock_ppgtt_huge_fill(void *arg)
                single = !single;
        }
 
-       close_object_list(&objects, ppgtt);
+       close_object_list(&objects);
 
        if (err == -ENOMEM || err == -ENOSPC)
                err = 0;
 
+       i915_vm_put(vm);
+out:
+       fput(file);
        return err;
 }
 
-static int igt_mock_ppgtt_64K(void *arg)
+static int igt_ppgtt_64K(void *arg)
 {
-       struct i915_ppgtt *ppgtt = arg;
-       struct drm_i915_private *i915 = ppgtt->vm.i915;
+       struct drm_i915_private *i915 = arg;
+       bool has_pte64 = GRAPHICS_VER_FULL(i915) >= IP_VER(12, 50);
        struct drm_i915_gem_object *obj;
+       struct i915_address_space *vm;
+       struct i915_gem_context *ctx;
+       struct file *file;
        const struct object_info {
                unsigned int size;
                unsigned int gtt;
@@ -907,16 +933,41 @@ static int igt_mock_ppgtt_64K(void *arg)
        if (!HAS_PAGE_SIZES(i915, I915_GTT_PAGE_SIZE_64K))
                return 0;
 
+       file = mock_file(i915);
+       if (IS_ERR(file))
+               return PTR_ERR(file);
+
+       ctx = hugepage_ctx(i915, file);
+       if (IS_ERR(ctx)) {
+               err = PTR_ERR(ctx);
+               goto out;
+       }
+       vm = i915_gem_context_get_eb_vm(ctx);
+
        for (i = 0; i < ARRAY_SIZE(objects); ++i) {
                unsigned int size = objects[i].size;
                unsigned int expected_gtt = objects[i].gtt;
                unsigned int offset = objects[i].offset;
                unsigned int flags = PIN_USER;
 
+               /*
+                * For modern GTT models, the requirements for marking a page-table
+                * as 64K have been relaxed.  Account for this.
+                */
+               if (has_pte64) {
+                       expected_gtt = 0;
+                       if (size >= SZ_64K)
+                               expected_gtt |= I915_GTT_PAGE_SIZE_64K;
+                       if (size & (SZ_64K - 1))
+                               expected_gtt |= I915_GTT_PAGE_SIZE_4K;
+               }
+
                for (single = 0; single <= 1; single++) {
                        obj = fake_huge_pages_object(i915, size, !!single);
-                       if (IS_ERR(obj))
-                               return PTR_ERR(obj);
+                       if (IS_ERR(obj)) {
+                               err = PTR_ERR(obj);
+                               goto out_vm;
+                       }
 
                        err = i915_gem_object_pin_pages_unlocked(obj);
                        if (err)
@@ -928,7 +979,7 @@ static int igt_mock_ppgtt_64K(void *arg)
                         */
                        obj->mm.page_sizes.sg &= ~I915_GTT_PAGE_SIZE_2M;
 
-                       vma = i915_vma_instance(obj, &ppgtt->vm, NULL);
+                       vma = i915_vma_instance(obj, vm, NULL);
                        if (IS_ERR(vma)) {
                                err = PTR_ERR(vma);
                                goto out_object_unpin;
@@ -945,7 +996,8 @@ static int igt_mock_ppgtt_64K(void *arg)
                        if (err)
                                goto out_vma_unpin;
 
-                       if (!offset && vma->page_sizes.sg & I915_GTT_PAGE_SIZE_64K) {
+                       if (!has_pte64 && !offset &&
+                           vma->page_sizes.sg & I915_GTT_PAGE_SIZE_64K) {
                                if (!IS_ALIGNED(vma->node.start,
                                                I915_GTT_PAGE_SIZE_2M)) {
                                        pr_err("node.start(%llx) not aligned to 2M\n",
@@ -964,9 +1016,10 @@ static int igt_mock_ppgtt_64K(void *arg)
                        }
 
                        if (vma->resource->page_sizes_gtt != expected_gtt) {
-                               pr_err("gtt=%u, expected=%u, i=%d, single=%s\n",
+                               pr_err("gtt=%#x, expected=%#x, i=%d, single=%s offset=%#x size=%#x\n",
                                       vma->resource->page_sizes_gtt,
-                                      expected_gtt, i, str_yes_no(!!single));
+                                      expected_gtt, i, str_yes_no(!!single),
+                                      offset, size);
                                err = -EINVAL;
                                goto out_vma_unpin;
                        }
@@ -982,7 +1035,7 @@ static int igt_mock_ppgtt_64K(void *arg)
                }
        }
 
-       return 0;
+       goto out_vm;
 
 out_vma_unpin:
        i915_vma_unpin(vma);
@@ -992,7 +1045,10 @@ out_object_unpin:
        i915_gem_object_unlock(obj);
 out_object_put:
        i915_gem_object_put(obj);
-
+out_vm:
+       i915_vm_put(vm);
+out:
+       fput(file);
        return err;
 }
 
@@ -1910,8 +1966,6 @@ int i915_gem_huge_page_mock_selftests(void)
                SUBTEST(igt_mock_exhaust_device_supported_pages),
                SUBTEST(igt_mock_memory_region_huge_pages),
                SUBTEST(igt_mock_ppgtt_misaligned_dma),
-               SUBTEST(igt_mock_ppgtt_huge_fill),
-               SUBTEST(igt_mock_ppgtt_64K),
        };
        struct drm_i915_private *dev_priv;
        struct i915_ppgtt *ppgtt;
@@ -1962,6 +2016,8 @@ int i915_gem_huge_page_live_selftests(struct drm_i915_private *i915)
                SUBTEST(igt_ppgtt_sanity_check),
                SUBTEST(igt_ppgtt_compact),
                SUBTEST(igt_ppgtt_mixed),
+               SUBTEST(igt_ppgtt_huge_fill),
+               SUBTEST(igt_ppgtt_64K),
        };
 
        if (!HAS_PPGTT(i915)) {