[Intel-gfx] [PATCH] drm/i915: Split out GTT fault handler to make it generic
Chris Wilson
chris at chris-wilson.co.uk
Tue Jun 4 11:00:56 UTC 2019
Quoting Abdiel Janulgue (2019-06-04 11:37:23)
> Allow reuse of the fault-handling code in preparation for having
> multiple fault handlers depending on the mmaping type and backing
> storage.
>
> Cc: Matthew Auld <matthew.auld at intel.com>
> Cc: Chris Wilson <chris at chris-wilson.co.uk>
> Cc: Joonas Lahtinen <joonas.lahtinen at linux.intel.com>
>
> Signed-off-by: Abdiel Janulgue <abdiel.janulgue at linux.intel.com>
> ---
> drivers/gpu/drm/i915/gem/i915_gem_mman.c | 208 ++++++++++++++---------
> 1 file changed, 132 insertions(+), 76 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/gem/i915_gem_mman.c b/drivers/gpu/drm/i915/gem/i915_gem_mman.c
> index c7b9b34de01b..ed20fab66d2f 100644
> --- a/drivers/gpu/drm/i915/gem/i915_gem_mman.c
> +++ b/drivers/gpu/drm/i915/gem/i915_gem_mman.c
> @@ -197,6 +197,133 @@ compute_partial_view(const struct drm_i915_gem_object *obj,
> return view;
> }
>
> +struct gem_object_fault {
> + struct drm_i915_gem_object *obj;
> + pgoff_t page_offset;
> + intel_wakeref_t wakeref;
> + int srcu;
> + bool pin_vma;
> + vm_fault_t error_ret;
> +};
> +
> +static vm_fault_t __vm_fault_from_error(struct drm_i915_private *i915,
> + int fault_ret)
> +{
> + switch (fault_ret) {
> + case -EIO:
> + /*
> + * We eat errors when the gpu is terminally wedged to avoid
> + * userspace unduly crashing (gl has no provisions for mmaps to
> + * fail). But any other -EIO isn't ours (e.g. swap in failure)
> + * and so needs to be reported.
> + */
> + if (!i915_terminally_wedged(i915))
> + return VM_FAULT_SIGBUS;
> + /* else: fall through */
> + case -EAGAIN:
> + /*
> + * EAGAIN means the gpu is hung and we'll wait for the error
> + * handler to reset everything when re-faulting in
> + * i915_mutex_lock_interruptible.
> + */
> + case 0:
> + case -ERESTARTSYS:
> + case -EINTR:
> + case -EBUSY:
> + /*
> + * EBUSY is ok: this just means that another thread
> + * already did the job.
> + */
> + return VM_FAULT_NOPAGE;
> + case -ENOMEM:
> + return VM_FAULT_OOM;
> + case -ENOSPC:
> + case -EFAULT:
> + return VM_FAULT_SIGBUS;
> + default:
> + WARN_ONCE(fault_ret, "unhandled error in %s: %i\n", __func__,
> + fault_ret);
> + return VM_FAULT_SIGBUS;
> + }
> +}
> +
> +static int __prepare_object_fault(struct vm_fault *vmf,
> + bool pin_vma,
> + struct gem_object_fault *f)
> +{
> + struct vm_area_struct *area = vmf->vma;
> + struct drm_i915_gem_object *obj = to_intel_bo(area->vm_private_data);
> + struct drm_device *dev = obj->base.dev;
> + struct drm_i915_private *dev_priv = to_i915(dev);
> + bool write = area->vm_flags & VM_WRITE;
> + int ret;
> +
> + /* Sanity check that we allow writing into this object */
> + if (i915_gem_object_is_readonly(obj) && write) {
> + f->error_ret = VM_FAULT_SIGBUS;
> + return -EACCES;
> + }
> +
> + f->obj = obj;
> + /* We don't use vmf->pgoff since that has the fake offset */
> + f->page_offset = (vmf->address - area->vm_start) >> PAGE_SHIFT;
> +
> + trace_i915_gem_object_fault(obj, f->page_offset, true, write);
> +
> + ret = i915_gem_object_pin_pages(obj);
> + if (ret)
> + goto err;
> +
> + f->wakeref = intel_runtime_pm_get(dev_priv);
Not every path requires the device reset.
> +
> + f->srcu = i915_reset_trylock(dev_priv);
Not every path requires interaction with reset handling.
> + if (f->srcu < 0) {
> + ret = f->srcu;
> + goto err_rpm;
> + }
> +
> + f->pin_vma = pin_vma;
> + if (f->pin_vma) {
> + ret = i915_mutex_lock_interruptible(dev);
Bah.
> + if (ret)
> + goto err_reset;
> + }
> +
> + /* Access to snoopable pages through the GTT is incoherent. */
> + if (obj->cache_level != I915_CACHE_NONE && !HAS_LLC(dev_priv)) {
And that is very, very specific to one path.
From the sampling here, this is not generic preamble.
-Chris
More information about the Intel-gfx
mailing list