[Intel-gfx] [PATCH] drm/i915/buddy: document the unused header bits

Chris Wilson chris at chris-wilson.co.uk
Fri Jan 22 16:14:02 UTC 2021


Quoting Matthew Auld (2021-01-22 15:45:46)
> The largest possible order is (63-12), given that our min chunk size is
> 4K. 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 <matthew.auld at intel.com>
> ---
>  drivers/gpu/drm/i915/i915_buddy.c           |  3 ++
>  drivers/gpu/drm/i915/i915_buddy.h           |  7 ++-
>  drivers/gpu/drm/i915/selftests/i915_buddy.c | 47 +++++++++++++++++++++
>  3 files changed, 55 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/i915_buddy.c b/drivers/gpu/drm/i915/i915_buddy.c
> index 20babbdb297d..650613ae2a7b 100644
> --- a/drivers/gpu/drm/i915/i915_buddy.c
> +++ b/drivers/gpu/drm/i915/i915_buddy.c
> @@ -56,6 +56,9 @@ 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);

Ok...

> +       GEM_BUG_ON(order > I915_BUDDY_MAX_ORDER);

But this is really a contract on the incoming parameter and so should be
at the start of the function.

GEM_BUG_ON(block->header...) is a contract on our output.

> +
>         return block;
>  }
>  
> diff --git a/drivers/gpu/drm/i915/i915_buddy.h b/drivers/gpu/drm/i915/i915_buddy.h
> index ed41f3507cdc..d37e03587637 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 - 12)

Can we replace 12 with an ilog2() ?

PAGE_SIZE is mentioned as the lower limit, so 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..39c470a0e28d 100644
> --- a/drivers/gpu/drm/i915/selftests/i915_buddy.c
> +++ b/drivers/gpu/drm/i915/selftests/i915_buddy.c
> @@ -727,6 +727,52 @@ 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);

Create the biggest region possible.

> +       if (err)
> +               return err;
> +
> +       if (mm.max_order != I915_BUDDY_MAX_ORDER) {

Check that we made it as big as possible.

> +               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);

Allocate the largest single block.

> +       if (IS_ERR(block)) {
> +               err = PTR_ERR(block);
> +               goto out_fini;
> +       }
> +
> +       if (i915_buddy_block_order(block) != I915_BUDDY_MAX_ORDER) {

Check that it is as large we tried to allocate... But it should be
mm.max_order to check the actual limits in place.

> +               pr_err("block order(%d) != %d\n",
> +                      i915_buddy_block_order(block), I915_BUDDY_MAX_ORDER);
> +               err = -EINVAL;
> +               goto out_free;
> +       }
> +
> +       if (i915_buddy_block_size(&mm, block) != rounddown_pow_of_two(size)) {

Which is the largest buddy block within the range.

Hmm, this I don't think follows the I915_BUDDY_MAX_ORDER constraint.
What if we reduce the MAX_ORDER to be say 48? Then the buddy block will
correctly be (1<<48). So I think you just want size() == BIT_ULL(mm.max_order)

With those questions addressed however you see fit,
Reviewed-by: Chris Wilson <chris at chris-wilson.co.uk>
-Chris


More information about the Intel-gfx mailing list