The largest possible order is (63-PAGE_SHIFT), given that our min chunk
size is PAGE_SIZE. With that we should only need at most 6 bits to
represent all possible orders, giving us back 4 bits for other potential
uses.  Include a simple selftest to verify this.

Signed-off-by: Matthew Auld <[email protected]>
Reviewed-by: Chris Wilson <[email protected]>
---
 drivers/gpu/drm/i915/i915_buddy.c           |  3 ++
 drivers/gpu/drm/i915/i915_buddy.h           |  7 ++-
 drivers/gpu/drm/i915/selftests/i915_buddy.c | 48 +++++++++++++++++++++
 3 files changed, 56 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_buddy.c 
b/drivers/gpu/drm/i915/i915_buddy.c
index 20babbdb297d..3a2f6eecb2fc 100644
--- a/drivers/gpu/drm/i915/i915_buddy.c
+++ b/drivers/gpu/drm/i915/i915_buddy.c
@@ -48,6 +48,8 @@ static struct i915_buddy_block *i915_block_alloc(struct 
i915_buddy_block *parent
 {
        struct i915_buddy_block *block;
 
+       GEM_BUG_ON(order > I915_BUDDY_MAX_ORDER);
+
        block = kmem_cache_zalloc(global.slab_blocks, GFP_KERNEL);
        if (!block)
                return NULL;
@@ -56,6 +58,7 @@ static struct i915_buddy_block *i915_block_alloc(struct 
i915_buddy_block *parent
        block->header |= order;
        block->parent = parent;
 
+       GEM_BUG_ON(block->header & I915_BUDDY_HEADER_UNUSED);
        return block;
 }
 
diff --git a/drivers/gpu/drm/i915/i915_buddy.h 
b/drivers/gpu/drm/i915/i915_buddy.h
index ed41f3507cdc..9ce5200f4001 100644
--- a/drivers/gpu/drm/i915/i915_buddy.h
+++ b/drivers/gpu/drm/i915/i915_buddy.h
@@ -15,7 +15,9 @@ struct i915_buddy_block {
 #define   I915_BUDDY_ALLOCATED    (1 << 10)
 #define   I915_BUDDY_FREE         (2 << 10)
 #define   I915_BUDDY_SPLIT        (3 << 10)
-#define I915_BUDDY_HEADER_ORDER  GENMASK_ULL(9, 0)
+/* Free to be used, if needed in the future */
+#define I915_BUDDY_HEADER_UNUSED GENMASK_ULL(9, 6)
+#define I915_BUDDY_HEADER_ORDER  GENMASK_ULL(5, 0)
        u64 header;
 
        struct i915_buddy_block *left;
@@ -34,7 +36,8 @@ struct i915_buddy_block {
        struct list_head tmp_link;
 };
 
-#define I915_BUDDY_MAX_ORDER  I915_BUDDY_HEADER_ORDER
+/* Order-zero must be at least PAGE_SIZE */
+#define I915_BUDDY_MAX_ORDER (63 - PAGE_SHIFT)
 
 /*
  * Binary Buddy System.
diff --git a/drivers/gpu/drm/i915/selftests/i915_buddy.c 
b/drivers/gpu/drm/i915/selftests/i915_buddy.c
index 632b912b0bc9..f0f5c4df8dbc 100644
--- a/drivers/gpu/drm/i915/selftests/i915_buddy.c
+++ b/drivers/gpu/drm/i915/selftests/i915_buddy.c
@@ -727,6 +727,53 @@ static int igt_buddy_alloc_range(void *arg)
        return err;
 }
 
+static int igt_buddy_alloc_limit(void *arg)
+{
+       struct i915_buddy_block *block;
+       struct i915_buddy_mm mm;
+       const u64 size = U64_MAX;
+       int err;
+
+       err = i915_buddy_init(&mm, size, PAGE_SIZE);
+       if (err)
+               return err;
+
+       if (mm.max_order != I915_BUDDY_MAX_ORDER) {
+               pr_err("mm.max_order(%d) != %d\n",
+                      mm.max_order, I915_BUDDY_MAX_ORDER);
+               err = -EINVAL;
+               goto out_fini;
+       }
+
+       block = i915_buddy_alloc(&mm, mm.max_order);
+       if (IS_ERR(block)) {
+               err = PTR_ERR(block);
+               goto out_fini;
+       }
+
+       if (i915_buddy_block_order(block) != mm.max_order) {
+               pr_err("block order(%d) != %d\n",
+                      i915_buddy_block_order(block), mm.max_order);
+               err = -EINVAL;
+               goto out_free;
+       }
+
+       if (i915_buddy_block_size(&mm, block) !=
+           BIT_ULL(mm.max_order) * PAGE_SIZE) {
+               pr_err("block size(%llu) != %llu\n",
+                      i915_buddy_block_size(&mm, block),
+                      BIT_ULL(mm.max_order) * PAGE_SIZE);
+               err = -EINVAL;
+               goto out_free;
+       }
+
+out_free:
+       i915_buddy_free(&mm, block);
+out_fini:
+       i915_buddy_fini(&mm);
+       return err;
+}
+
 int i915_buddy_mock_selftests(void)
 {
        static const struct i915_subtest tests[] = {
@@ -735,6 +782,7 @@ int i915_buddy_mock_selftests(void)
                SUBTEST(igt_buddy_alloc_pathological),
                SUBTEST(igt_buddy_alloc_smoke),
                SUBTEST(igt_buddy_alloc_range),
+               SUBTEST(igt_buddy_alloc_limit),
        };
 
        return i915_subtests(tests, NULL);
-- 
2.26.2

_______________________________________________
Intel-gfx mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

Reply via email to