[RFC PATCH i-g-t v3 2/4] lib: Add GEM minimum page size helper

Janusz Krzysztofik janusz.krzysztofik at linux.intel.com
Wed Oct 30 10:55:29 UTC 2019


Hi Chris,

On Wednesday, October 30, 2019 11:48:22 AM CET Chris Wilson wrote:
> Quoting Janusz Krzysztofik (2019-10-30 10:38:48)
> > Some tests assume 4kB page size while using softpin.  That assumption
> > may be wrong on future GEM backends with possibly larger minimum page
> > sizes.  As a result, those tests may either fail on softpin at offsets
> > which are incorrectly aligned, may silently skip such incorrectly
> > aligned addresses assuming them occupied by other users, or may always
> > succeed when examining invalid use patterns.
> > 
> > Provide a helper function that detects minimum page size and returns
> > the size order.  Tests may use it to calculate softpin offsets suitable
> > for actually used backing store.
> > 
> > Signed-off-by: Janusz Krzysztofik <janusz.krzysztofik at linux.intel.com>
> > Cc: Chris Wilson <chris at chris-wilson.co.uk>
> > Cc: Daniele Ceraolo Spurio <daniele.ceraolospurio at intel.com>
> > Cc: Stuart Summers <stuart.summers at intel.com>
> > ---
> >  lib/ioctl_wrappers.c | 82 ++++++++++++++++++++++++++++++++++++++++++++
> >  lib/ioctl_wrappers.h |  1 +
> >  2 files changed, 83 insertions(+)
> > 
> > diff --git a/lib/ioctl_wrappers.c b/lib/ioctl_wrappers.c
> > index 280fdd62..a4313832 100644
> > --- a/lib/ioctl_wrappers.c
> > +++ b/lib/ioctl_wrappers.c
> > @@ -54,6 +54,7 @@
> >  #include "intel_io.h"
> >  #include "igt_debugfs.h"
> >  #include "igt_sysfs.h"
> > +#include "igt_x86.h"
> >  #include "config.h"
> >  
> >  #ifdef HAVE_VALGRIND
> > @@ -1157,6 +1158,87 @@ bool gem_has_softpin(int fd)
> >         return has_softpin;
> >  }
> >  
> > +static int __min_page_size_order(int fd, struct drm_i915_gem_exec_object2 
*obj,
> > +                                struct drm_i915_gem_execbuffer2 *eb,
> > +                                uint64_t offset, int min_order, int 
max_order)
> > +{
> > +       static const uint32_t bbe = MI_BATCH_BUFFER_END;
> > +       uint64_t page_size = 1ull << max_order;
> > +       int order;
> > +
> > +       if (max_order > min_order) {
> > +               /* explore upper half of the max_order at offset area */
> > +               order = __min_page_size_order(fd, obj, eb, offset, 
min_order,
> > +                                             max_order - 1);
> > +               if (order < max_order)
> > +                       return order;
> > +       }
> > +
> > +       obj->offset = gen8_canonical_addr(offset - page_size);
> > +       gem_write(fd, obj->handle, 0, &bbe, sizeof(bbe));
> > +       if (!__gem_execbuf(fd, eb)) {
> > +               /* upper half not occupied, must be the minimum */
> > +               igt_debug("found min page size=%#llx, size order=%d\n",
> > +                         (long long)page_size, max_order);
> > +               return max_order;
> > +       }
> > +
> > +       if (max_order > min_order) {
> > +               /* explore lower half of in case the upper half was 
occupied */
> > +               page_size >>= 1;
> > +               order = __min_page_size_order(fd, obj, eb, offset - 
page_size,
> > +                                             min_order, max_order - 1);
> > +               if (order < max_order)
> > +                       return order;
> > +       }
> > +
> > +       return max_order + 1;
> > +}
> > +
> > +/**
> > + * gem_min_page_size_order:
> > + * @fd: open i915 drm file descriptor
> > + *
> > + * This function detects the minimum size of a gem object allocated from
> > + * a default backing store.  It is useful for calculating correctly 
aligned
> > + * softpin offsets.
> > + * Since size order to size conversion (size = 1 << order) is less 
trivial
> > + * than the opposite, the function returns the size order as more handy.
> > + *
> > + * Returns:
> > + * Size order of the minimum page size
> > + */
> > +int gem_min_page_size_order(int fd)
> > +{
> > +       struct drm_i915_gem_exec_object2 obj;
> > +       struct drm_i915_gem_execbuffer2 eb;
> > +       uint64_t gtt_size = gem_aperture_size(fd);
> > +       int min_order = 12;     /* current I915_GTT_PAGE_SIZE equivalent 
*/
> > +       uint64_t page_size = 1ull << min_order;
> > +       int max_order = 21;     /* current I915_GTT_MAX_PAGE_SIZE 
equivalent */
> > +
> > +       /* no softpin => 4kB page size */
> > +       if (!gem_has_softpin(fd))
> > +               return min_order;
> > +
> > +       memset(&obj, 0, sizeof(obj));
> > +       memset(&eb, 0, sizeof(eb));
> > +
> > +       obj.handle = gem_create(fd, page_size);
> > +       obj.flags = EXEC_OBJECT_PINNED | EXEC_OBJECT_SUPPORTS_48B_ADDRESS;
> > +       eb.buffers_ptr = to_user_pointer(&obj);
> > +       eb.buffer_count = 1;
> 
> for (int order = 12; order < 64; order++) {
> 	obj.offset = 1ull << order;
> 	if (__gem_execbuf(&eb) == 0)
> 		break;
> }

Your approach seems to not take into account that addresses may be possibly 
occupied by other users.  If that happens, result will be incorrect.  Am I 
missing something?

Thanks,
Janusz


> igt_assert(obj.offset < gem_aperture_size(fd));
> gem_close(obj.handle);
> return obj.offset;
> 
> Our primary metric here is min gtt alignment => gem_gtt_min_alignment();
> -Chris
> 






More information about the Intel-gfx-trybot mailing list