All of lore.kernel.org
 help / color / mirror / Atom feed
From: Matthew Auld <matthew.william.auld@gmail.com>
To: Jason Ekstrand <jason@jlekstrand.net>
Cc: "Thomas Hellström" <thomas.hellstrom@linux.intel.com>,
	"Daniel Vetter" <daniel.vetter@ffwll.ch>,
	"Intel GFX" <intel-gfx@lists.freedesktop.org>,
	"Maling list - DRI developers" <dri-devel@lists.freedesktop.org>,
	"Chris Wilson" <chris@chris-wilson.co.uk>,
	"Kenneth Graunke" <kenneth@whitecape.org>,
	"Matthew Auld" <matthew.auld@intel.com>
Subject: Re: [Intel-gfx] [PATCH 3/4] drm/i915/userptr: Probe existence of backing struct pages upon creation
Date: Thu, 22 Jul 2021 09:43:50 +0100	[thread overview]
Message-ID: <CAM0jSHPAhURYUVzdsaVKd+U8nYniO+vQVyU3zeYUyKddj4xW0Q@mail.gmail.com> (raw)
In-Reply-To: <CAOFGe9667Mi9pJWNmzQP6LmiWvTmHWN5UVVs7B046FDozcwcPw@mail.gmail.com>

On Wed, 21 Jul 2021 at 21:28, Jason Ekstrand <jason@jlekstrand.net> wrote:
>
> On Thu, Jul 15, 2021 at 5:16 AM Matthew Auld <matthew.auld@intel.com> wrote:
> >
> > From: Chris Wilson <chris@chris-wilson.co.uk>
> >
> > Jason Ekstrand requested a more efficient method than userptr+set-domain
> > to determine if the userptr object was backed by a complete set of pages
> > upon creation. To be more efficient than simply populating the userptr
> > using get_user_pages() (as done by the call to set-domain or execbuf),
> > we can walk the tree of vm_area_struct and check for gaps or vma not
> > backed by struct page (VM_PFNMAP). The question is how to handle
> > VM_MIXEDMAP which may be either struct page or pfn backed...
> >
> > With discrete are going to drop support for set_domain(), so offering a
> > way to probe the pages, without having to resort to dummy batches has
> > been requested.
> >
> > v2:
> > - add new query param for the PROPBE flag, so userspace can easily
> >   check if the kernel supports it(Jason).
> > - use mmap_read_{lock, unlock}.
> > - add some kernel-doc.
> >
> > Testcase: igt/gem_userptr_blits/probe
> > Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
> > Signed-off-by: Matthew Auld <matthew.auld@intel.com>
> > Cc: Thomas Hellström <thomas.hellstrom@linux.intel.com>
> > Cc: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
> > Cc: Tvrtko Ursulin <tvrtko.ursulin@linux.intel.com>
> > Cc: Jordan Justen <jordan.l.justen@intel.com>
> > Cc: Kenneth Graunke <kenneth@whitecape.org>
> > Cc: Jason Ekstrand <jason@jlekstrand.net>
> > Cc: Daniel Vetter <daniel.vetter@ffwll.ch>
> > Cc: Ramalingam C <ramalingam.c@intel.com>
> > ---
> >  drivers/gpu/drm/i915/gem/i915_gem_userptr.c | 40 ++++++++++++++++++++-
> >  drivers/gpu/drm/i915/i915_getparam.c        |  3 ++
> >  include/uapi/drm/i915_drm.h                 | 18 ++++++++++
> >  3 files changed, 60 insertions(+), 1 deletion(-)
> >
> > diff --git a/drivers/gpu/drm/i915/gem/i915_gem_userptr.c b/drivers/gpu/drm/i915/gem/i915_gem_userptr.c
> > index 56edfeff8c02..fd6880328596 100644
> > --- a/drivers/gpu/drm/i915/gem/i915_gem_userptr.c
> > +++ b/drivers/gpu/drm/i915/gem/i915_gem_userptr.c
> > @@ -422,6 +422,33 @@ static const struct drm_i915_gem_object_ops i915_gem_userptr_ops = {
> >
> >  #endif
> >
> > +static int
> > +probe_range(struct mm_struct *mm, unsigned long addr, unsigned long len)
> > +{
> > +       const unsigned long end = addr + len;
> > +       struct vm_area_struct *vma;
> > +       int ret = -EFAULT;
> > +
> > +       mmap_read_lock(mm);
> > +       for (vma = find_vma(mm, addr); vma; vma = vma->vm_next) {
> > +               if (vma->vm_start > addr)
>
> Why isn't this > end?  Are we somehow guaranteed that one vma covers
> the entire range?

AFAIK we are just making sure we don't have a hole(note that we also
update addr below), for example the user might have done a partial
munmap. There could be multiple vma's if the kernel was unable to
merge them. If we reach the vm_end >= end, then we know we have a
"valid" range.

>
> > +                       break;
> > +
> > +               if (vma->vm_flags & (VM_PFNMAP | VM_MIXEDMAP))
> > +                       break;
> > +
> > +               if (vma->vm_end >= end) {
> > +                       ret = 0;
> > +                       break;
> > +               }
> > +
> > +               addr = vma->vm_end;
> > +       }
> > +       mmap_read_unlock(mm);
> > +
> > +       return ret;
> > +}
> > +
> >  /*
> >   * Creates a new mm object that wraps some normal memory from the process
> >   * context - user memory.
> > @@ -477,7 +504,8 @@ i915_gem_userptr_ioctl(struct drm_device *dev,
> >         }
> >
> >         if (args->flags & ~(I915_USERPTR_READ_ONLY |
> > -                           I915_USERPTR_UNSYNCHRONIZED))
> > +                           I915_USERPTR_UNSYNCHRONIZED |
> > +                           I915_USERPTR_PROBE))
> >                 return -EINVAL;
> >
> >         if (i915_gem_object_size_2big(args->user_size))
> > @@ -504,6 +532,16 @@ i915_gem_userptr_ioctl(struct drm_device *dev,
> >                         return -ENODEV;
> >         }
> >
> > +       if (args->flags & I915_USERPTR_PROBE) {
> > +               /*
> > +                * Check that the range pointed to represents real struct
> > +                * pages and not iomappings (at this moment in time!)
> > +                */
> > +               ret = probe_range(current->mm, args->user_ptr, args->user_size);
> > +               if (ret)
> > +                       return ret;
> > +       }
> > +
> >  #ifdef CONFIG_MMU_NOTIFIER
> >         obj = i915_gem_object_alloc();
> >         if (obj == NULL)
> > diff --git a/drivers/gpu/drm/i915/i915_getparam.c b/drivers/gpu/drm/i915/i915_getparam.c
> > index 24e18219eb50..d6d2e1a10d14 100644
> > --- a/drivers/gpu/drm/i915/i915_getparam.c
> > +++ b/drivers/gpu/drm/i915/i915_getparam.c
> > @@ -163,6 +163,9 @@ int i915_getparam_ioctl(struct drm_device *dev, void *data,
> >         case I915_PARAM_PERF_REVISION:
> >                 value = i915_perf_ioctl_version();
> >                 break;
> > +       case I915_PARAM_HAS_USERPTR_PROBE:
> > +               value = true;
> > +               break;
> >         default:
> >                 DRM_DEBUG("Unknown parameter %d\n", param->param);
> >                 return -EINVAL;
> > diff --git a/include/uapi/drm/i915_drm.h b/include/uapi/drm/i915_drm.h
> > index e20eeeca7a1c..2e4112bf4d38 100644
> > --- a/include/uapi/drm/i915_drm.h
> > +++ b/include/uapi/drm/i915_drm.h
> > @@ -674,6 +674,9 @@ typedef struct drm_i915_irq_wait {
> >   */
> >  #define I915_PARAM_HAS_EXEC_TIMELINE_FENCES 55
> >
> > +/* Query if the kernel supports the I915_USERPTR_PROBE flag. */
> > +#define I915_PARAM_HAS_USERPTR_PROBE 56
> > +
> >  /* Must be kept compact -- no holes and well documented */
> >
> >  typedef struct drm_i915_getparam {
> > @@ -2178,12 +2181,27 @@ struct drm_i915_gem_userptr {
> >          * through the GTT. If the HW can't support readonly access, an error is
> >          * returned.
> >          *
> > +        * I915_USERPTR_PROBE:
> > +        *
> > +        * Probe the provided @user_ptr range and validate that the @user_ptr is
> > +        * indeed pointing to normal memory and that the range is also valid.
> > +        * For example if some garbage address is given to the kernel, then this
> > +        * should complain.
> > +        *
> > +        * Returns -EFAULT if the probe failed.
> > +        *
> > +        * Note that this doesn't populate the backing pages.
> > +        *
> > +        * The kernel supports this feature if I915_PARAM_HAS_USERPTR_PROBE
> > +        * returns a non-zero value.
> > +        *
> >          * I915_USERPTR_UNSYNCHRONIZED:
> >          *
> >          * NOT USED. Setting this flag will result in an error.
> >          */
> >         __u32 flags;
> >  #define I915_USERPTR_READ_ONLY 0x1
> > +#define I915_USERPTR_PROBE 0x2
> >  #define I915_USERPTR_UNSYNCHRONIZED 0x80000000
> >         /**
> >          * @handle: Returned handle for the object.
> > --
> > 2.26.3
> >
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/intel-gfx

WARNING: multiple messages have this Message-ID (diff)
From: Matthew Auld <matthew.william.auld@gmail.com>
To: Jason Ekstrand <jason@jlekstrand.net>
Cc: "Thomas Hellström" <thomas.hellstrom@linux.intel.com>,
	"Daniel Vetter" <daniel.vetter@ffwll.ch>,
	"Intel GFX" <intel-gfx@lists.freedesktop.org>,
	"Maling list - DRI developers" <dri-devel@lists.freedesktop.org>,
	"Chris Wilson" <chris@chris-wilson.co.uk>,
	"Kenneth Graunke" <kenneth@whitecape.org>,
	"Matthew Auld" <matthew.auld@intel.com>
Subject: Re: [Intel-gfx] [PATCH 3/4] drm/i915/userptr: Probe existence of backing struct pages upon creation
Date: Thu, 22 Jul 2021 09:43:50 +0100	[thread overview]
Message-ID: <CAM0jSHPAhURYUVzdsaVKd+U8nYniO+vQVyU3zeYUyKddj4xW0Q@mail.gmail.com> (raw)
In-Reply-To: <CAOFGe9667Mi9pJWNmzQP6LmiWvTmHWN5UVVs7B046FDozcwcPw@mail.gmail.com>

On Wed, 21 Jul 2021 at 21:28, Jason Ekstrand <jason@jlekstrand.net> wrote:
>
> On Thu, Jul 15, 2021 at 5:16 AM Matthew Auld <matthew.auld@intel.com> wrote:
> >
> > From: Chris Wilson <chris@chris-wilson.co.uk>
> >
> > Jason Ekstrand requested a more efficient method than userptr+set-domain
> > to determine if the userptr object was backed by a complete set of pages
> > upon creation. To be more efficient than simply populating the userptr
> > using get_user_pages() (as done by the call to set-domain or execbuf),
> > we can walk the tree of vm_area_struct and check for gaps or vma not
> > backed by struct page (VM_PFNMAP). The question is how to handle
> > VM_MIXEDMAP which may be either struct page or pfn backed...
> >
> > With discrete are going to drop support for set_domain(), so offering a
> > way to probe the pages, without having to resort to dummy batches has
> > been requested.
> >
> > v2:
> > - add new query param for the PROPBE flag, so userspace can easily
> >   check if the kernel supports it(Jason).
> > - use mmap_read_{lock, unlock}.
> > - add some kernel-doc.
> >
> > Testcase: igt/gem_userptr_blits/probe
> > Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
> > Signed-off-by: Matthew Auld <matthew.auld@intel.com>
> > Cc: Thomas Hellström <thomas.hellstrom@linux.intel.com>
> > Cc: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
> > Cc: Tvrtko Ursulin <tvrtko.ursulin@linux.intel.com>
> > Cc: Jordan Justen <jordan.l.justen@intel.com>
> > Cc: Kenneth Graunke <kenneth@whitecape.org>
> > Cc: Jason Ekstrand <jason@jlekstrand.net>
> > Cc: Daniel Vetter <daniel.vetter@ffwll.ch>
> > Cc: Ramalingam C <ramalingam.c@intel.com>
> > ---
> >  drivers/gpu/drm/i915/gem/i915_gem_userptr.c | 40 ++++++++++++++++++++-
> >  drivers/gpu/drm/i915/i915_getparam.c        |  3 ++
> >  include/uapi/drm/i915_drm.h                 | 18 ++++++++++
> >  3 files changed, 60 insertions(+), 1 deletion(-)
> >
> > diff --git a/drivers/gpu/drm/i915/gem/i915_gem_userptr.c b/drivers/gpu/drm/i915/gem/i915_gem_userptr.c
> > index 56edfeff8c02..fd6880328596 100644
> > --- a/drivers/gpu/drm/i915/gem/i915_gem_userptr.c
> > +++ b/drivers/gpu/drm/i915/gem/i915_gem_userptr.c
> > @@ -422,6 +422,33 @@ static const struct drm_i915_gem_object_ops i915_gem_userptr_ops = {
> >
> >  #endif
> >
> > +static int
> > +probe_range(struct mm_struct *mm, unsigned long addr, unsigned long len)
> > +{
> > +       const unsigned long end = addr + len;
> > +       struct vm_area_struct *vma;
> > +       int ret = -EFAULT;
> > +
> > +       mmap_read_lock(mm);
> > +       for (vma = find_vma(mm, addr); vma; vma = vma->vm_next) {
> > +               if (vma->vm_start > addr)
>
> Why isn't this > end?  Are we somehow guaranteed that one vma covers
> the entire range?

AFAIK we are just making sure we don't have a hole(note that we also
update addr below), for example the user might have done a partial
munmap. There could be multiple vma's if the kernel was unable to
merge them. If we reach the vm_end >= end, then we know we have a
"valid" range.

>
> > +                       break;
> > +
> > +               if (vma->vm_flags & (VM_PFNMAP | VM_MIXEDMAP))
> > +                       break;
> > +
> > +               if (vma->vm_end >= end) {
> > +                       ret = 0;
> > +                       break;
> > +               }
> > +
> > +               addr = vma->vm_end;
> > +       }
> > +       mmap_read_unlock(mm);
> > +
> > +       return ret;
> > +}
> > +
> >  /*
> >   * Creates a new mm object that wraps some normal memory from the process
> >   * context - user memory.
> > @@ -477,7 +504,8 @@ i915_gem_userptr_ioctl(struct drm_device *dev,
> >         }
> >
> >         if (args->flags & ~(I915_USERPTR_READ_ONLY |
> > -                           I915_USERPTR_UNSYNCHRONIZED))
> > +                           I915_USERPTR_UNSYNCHRONIZED |
> > +                           I915_USERPTR_PROBE))
> >                 return -EINVAL;
> >
> >         if (i915_gem_object_size_2big(args->user_size))
> > @@ -504,6 +532,16 @@ i915_gem_userptr_ioctl(struct drm_device *dev,
> >                         return -ENODEV;
> >         }
> >
> > +       if (args->flags & I915_USERPTR_PROBE) {
> > +               /*
> > +                * Check that the range pointed to represents real struct
> > +                * pages and not iomappings (at this moment in time!)
> > +                */
> > +               ret = probe_range(current->mm, args->user_ptr, args->user_size);
> > +               if (ret)
> > +                       return ret;
> > +       }
> > +
> >  #ifdef CONFIG_MMU_NOTIFIER
> >         obj = i915_gem_object_alloc();
> >         if (obj == NULL)
> > diff --git a/drivers/gpu/drm/i915/i915_getparam.c b/drivers/gpu/drm/i915/i915_getparam.c
> > index 24e18219eb50..d6d2e1a10d14 100644
> > --- a/drivers/gpu/drm/i915/i915_getparam.c
> > +++ b/drivers/gpu/drm/i915/i915_getparam.c
> > @@ -163,6 +163,9 @@ int i915_getparam_ioctl(struct drm_device *dev, void *data,
> >         case I915_PARAM_PERF_REVISION:
> >                 value = i915_perf_ioctl_version();
> >                 break;
> > +       case I915_PARAM_HAS_USERPTR_PROBE:
> > +               value = true;
> > +               break;
> >         default:
> >                 DRM_DEBUG("Unknown parameter %d\n", param->param);
> >                 return -EINVAL;
> > diff --git a/include/uapi/drm/i915_drm.h b/include/uapi/drm/i915_drm.h
> > index e20eeeca7a1c..2e4112bf4d38 100644
> > --- a/include/uapi/drm/i915_drm.h
> > +++ b/include/uapi/drm/i915_drm.h
> > @@ -674,6 +674,9 @@ typedef struct drm_i915_irq_wait {
> >   */
> >  #define I915_PARAM_HAS_EXEC_TIMELINE_FENCES 55
> >
> > +/* Query if the kernel supports the I915_USERPTR_PROBE flag. */
> > +#define I915_PARAM_HAS_USERPTR_PROBE 56
> > +
> >  /* Must be kept compact -- no holes and well documented */
> >
> >  typedef struct drm_i915_getparam {
> > @@ -2178,12 +2181,27 @@ struct drm_i915_gem_userptr {
> >          * through the GTT. If the HW can't support readonly access, an error is
> >          * returned.
> >          *
> > +        * I915_USERPTR_PROBE:
> > +        *
> > +        * Probe the provided @user_ptr range and validate that the @user_ptr is
> > +        * indeed pointing to normal memory and that the range is also valid.
> > +        * For example if some garbage address is given to the kernel, then this
> > +        * should complain.
> > +        *
> > +        * Returns -EFAULT if the probe failed.
> > +        *
> > +        * Note that this doesn't populate the backing pages.
> > +        *
> > +        * The kernel supports this feature if I915_PARAM_HAS_USERPTR_PROBE
> > +        * returns a non-zero value.
> > +        *
> >          * I915_USERPTR_UNSYNCHRONIZED:
> >          *
> >          * NOT USED. Setting this flag will result in an error.
> >          */
> >         __u32 flags;
> >  #define I915_USERPTR_READ_ONLY 0x1
> > +#define I915_USERPTR_PROBE 0x2
> >  #define I915_USERPTR_UNSYNCHRONIZED 0x80000000
> >         /**
> >          * @handle: Returned handle for the object.
> > --
> > 2.26.3
> >
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/intel-gfx
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

  reply	other threads:[~2021-07-22  8:44 UTC|newest]

Thread overview: 54+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-07-15 10:15 [PATCH 0/4] Some DG1 uAPI cleanup Matthew Auld
2021-07-15 10:15 ` [Intel-gfx] " Matthew Auld
2021-07-15 10:15 ` [PATCH 1/4] drm/i915/uapi: reject caching ioctls for discrete Matthew Auld
2021-07-15 10:15   ` [Intel-gfx] " Matthew Auld
2021-07-15 10:15 ` [PATCH 2/4] drm/i915/uapi: convert drm_i915_gem_userptr to kernel doc Matthew Auld
2021-07-15 10:15   ` [Intel-gfx] " Matthew Auld
2021-07-15 12:09   ` Maarten Lankhorst
2021-07-15 12:09     ` [Intel-gfx] " Maarten Lankhorst
2021-07-15 10:15 ` [PATCH 3/4] drm/i915/userptr: Probe existence of backing struct pages upon creation Matthew Auld
2021-07-15 10:15   ` [Intel-gfx] " Matthew Auld
2021-07-15 10:33   ` Tvrtko Ursulin
2021-07-15 10:33     ` [Intel-gfx] " Tvrtko Ursulin
2021-07-15 11:07     ` Daniel Vetter
2021-07-15 11:07       ` [Intel-gfx] " Daniel Vetter
2021-07-15 11:27       ` Tvrtko Ursulin
2021-07-15 11:27         ` [Intel-gfx] " Tvrtko Ursulin
2021-07-15 18:21         ` Kenneth Graunke
2021-07-15 18:21           ` [Intel-gfx] " Kenneth Graunke
2021-07-15 19:18           ` Jason Ekstrand
2021-07-15 19:18             ` [Intel-gfx] " Jason Ekstrand
2021-07-16  8:20           ` Tvrtko Ursulin
2021-07-16  8:20             ` [Intel-gfx] " Tvrtko Ursulin
2021-07-16 14:50           ` Daniel Vetter
2021-07-16 14:50             ` [Intel-gfx] " Daniel Vetter
2021-07-15 11:09     ` Matthew Auld
2021-07-15 11:09       ` Matthew Auld
2021-07-15 11:33       ` Tvrtko Ursulin
2021-07-15 11:33         ` Tvrtko Ursulin
2021-07-16 14:36   ` Tvrtko Ursulin
2021-07-16 14:36     ` [Intel-gfx] " Tvrtko Ursulin
2021-07-21 19:18   ` Kenneth Graunke
2021-07-21 19:18     ` [Intel-gfx] " Kenneth Graunke
2021-07-21 19:21   ` Kenneth Graunke
2021-07-21 19:21     ` [Intel-gfx] " Kenneth Graunke
2021-07-21 20:27   ` Jason Ekstrand
2021-07-21 20:27     ` [Intel-gfx] " Jason Ekstrand
2021-07-22  8:43     ` Matthew Auld [this message]
2021-07-22  8:43       ` Matthew Auld
2021-07-22 13:29       ` Jason Ekstrand
2021-07-22 13:29         ` Jason Ekstrand
2021-07-15 10:15 ` [PATCH 4/4] drm/i915/uapi: reject set_domain for discrete Matthew Auld
2021-07-15 10:15   ` [Intel-gfx] " Matthew Auld
2021-07-16 14:52   ` Tvrtko Ursulin
2021-07-16 14:52     ` [Intel-gfx] " Tvrtko Ursulin
2021-07-16 15:23     ` Jason Ekstrand
2021-07-16 15:23       ` [Intel-gfx] " Jason Ekstrand
2021-07-19  9:00       ` Tvrtko Ursulin
2021-07-19  9:00         ` [Intel-gfx] " Tvrtko Ursulin
2021-07-19  9:09       ` Matthew Auld
2021-07-19  9:09         ` [Intel-gfx] " Matthew Auld
2021-07-19 19:57         ` Jason Ekstrand
2021-07-19 19:57           ` [Intel-gfx] " Jason Ekstrand
2021-07-16 19:33 ` [Intel-gfx] ✓ Fi.CI.BAT: success for Some DG1 uAPI cleanup Patchwork
2021-07-17  1:36 ` [Intel-gfx] ✗ Fi.CI.IGT: failure " Patchwork

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=CAM0jSHPAhURYUVzdsaVKd+U8nYniO+vQVyU3zeYUyKddj4xW0Q@mail.gmail.com \
    --to=matthew.william.auld@gmail.com \
    --cc=chris@chris-wilson.co.uk \
    --cc=daniel.vetter@ffwll.ch \
    --cc=dri-devel@lists.freedesktop.org \
    --cc=intel-gfx@lists.freedesktop.org \
    --cc=jason@jlekstrand.net \
    --cc=kenneth@whitecape.org \
    --cc=matthew.auld@intel.com \
    --cc=thomas.hellstrom@linux.intel.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.