[PATCH 2/2] drm/i915/gem: Fix Virtual Memory mapping boundaries calculation
Cavitt, Jonathan
jonathan.cavitt at intel.com
Fri Aug 2 17:25:23 UTC 2024
-----Original Message-----
From: Intel-gfx <intel-gfx-bounces at lists.freedesktop.org> On Behalf Of Andi Shyti
Sent: Friday, August 2, 2024 1:39 AM
To: intel-gfx <intel-gfx at lists.freedesktop.org>; dri-devel <dri-devel at lists.freedesktop.org>
Cc: Jann Horn <jannh at chromium.org>; Jani Nikula <jani.nikula at linux.intel.com>; Joonas Lahtinen <joonas.lahtinen at linux.intel.com>; Vivi, Rodrigo <rodrigo.vivi at intel.com>; Tvrtko Ursulin <tursulin at ursulin.net>; Jann Horn <jannh at google.com>; Chris Wilson <chris.p.wilson at linux.intel.com>; Niemiec, Krzysztof <krzysztof.niemiec at intel.com>; Andi Shyti <andi.shyti at kernel.org>; Auld, Matthew <matthew.auld at intel.com>; Andi Shyti <andi.shyti at linux.intel.com>
Subject: [PATCH 2/2] drm/i915/gem: Fix Virtual Memory mapping boundaries calculation
>
> Calculating the size of the mapped area as the lesser value
> between the requested size and the actual size does not consider
> the partial mapping offset. This can cause page fault access.
>
> Fix the calculation of the starting and ending addresses, the
> total size is now deduced from the difference between the end and
> start addresses.
>
> Additionally, the calculations have been rewritten in a clearer
> and more understandable form.
>
> Fixes: c58305af1835 ("drm/i915: Use remap_io_mapping() to prefault all PTE in a single pass")
> Reported-by: Jann Horn <jannh at google.com>
> Co-developed-by: Chris Wilson <chris.p.wilson at linux.intel.com>
> Signed-off-by: Chris Wilson <chris.p.wilson at linux.intel.com>
> Signed-off-by: Andi Shyti <andi.shyti at linux.intel.com>
> Cc: Joonas Lahtinen <joonas.lahtinen at linux.intel.com>
> Cc: Matthew Auld <matthew.auld at intel.com>
> Cc: Rodrigo Vivi <rodrigo.vivi at intel.com>
> Cc: <stable at vger.kernel.org> # v4.9+
> ---
> drivers/gpu/drm/i915/gem/i915_gem_mman.c | 53 +++++++++++++++++++++---
> 1 file changed, 47 insertions(+), 6 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/gem/i915_gem_mman.c b/drivers/gpu/drm/i915/gem/i915_gem_mman.c
> index ce10dd259812..cac6d4184506 100644
> --- a/drivers/gpu/drm/i915/gem/i915_gem_mman.c
> +++ b/drivers/gpu/drm/i915/gem/i915_gem_mman.c
> @@ -290,6 +290,41 @@ static vm_fault_t vm_fault_cpu(struct vm_fault *vmf)
> return i915_error_to_vmf_fault(err);
> }
>
> +static void set_address_limits(struct vm_area_struct *area,
> + struct i915_vma *vma,
> + unsigned long obj_offset,
> + unsigned long *start_vaddr,
> + unsigned long *end_vaddr)
> +{
> + unsigned long vm_start, vm_end, vma_size; /* user's memory parameters */
> + long start, end; /* memory boundaries */
> +
> + /*
> + * Let's move into the ">> PAGE_SHIFT"
> + * domain to be sure not to lose bits
> + */
> + vm_start = area->vm_start >> PAGE_SHIFT;
> + vm_end = area->vm_end >> PAGE_SHIFT;
> + vma_size = vma->size >> PAGE_SHIFT;
> +
> + /*
> + * Calculate the memory boundaries by considering the offset
> + * provided by the user during memory mapping and the offset
> + * provided for the partial mapping.
> + */
> + start = vm_start;
> + start -= obj_offset;
> + start += vma->gtt_view.partial.offset;
> + end = start + vma_size;
> +
> + start = max_t(long, start, vm_start);
> + end = min_t(long, end, vm_end);
> +
> + /* Let's move back into the "<< PAGE_SHIFT" domain */
> + *start_vaddr = (unsigned long)start << PAGE_SHIFT;
> + *end_vaddr = (unsigned long)end << PAGE_SHIFT;
> +}
> +
> static vm_fault_t vm_fault_gtt(struct vm_fault *vmf)
> {
> #define MIN_CHUNK_PAGES (SZ_1M >> PAGE_SHIFT)
> @@ -302,14 +337,18 @@ static vm_fault_t vm_fault_gtt(struct vm_fault *vmf)
> struct i915_ggtt *ggtt = to_gt(i915)->ggtt;
> bool write = area->vm_flags & VM_WRITE;
> struct i915_gem_ww_ctx ww;
> + unsigned long obj_offset;
> + unsigned long start, end; /* memory boundaries */
> intel_wakeref_t wakeref;
> struct i915_vma *vma;
> pgoff_t page_offset;
> + unsigned long pfn;
> int srcu;
> int ret;
>
> - /* We don't use vmf->pgoff since that has the fake offset */
> + obj_offset = area->vm_pgoff - drm_vma_node_start(&mmo->vma_node);
> page_offset = (vmf->address - area->vm_start) >> PAGE_SHIFT;
> + page_offset += obj_offset;
>
> trace_i915_gem_object_fault(obj, page_offset, true, write);
>
> @@ -402,12 +441,14 @@ static vm_fault_t vm_fault_gtt(struct vm_fault *vmf)
> if (ret)
> goto err_unpin;
>
> + set_address_limits(area, vma, obj_offset, &start, &end);
> +
> + pfn = (ggtt->gmadr.start + i915_ggtt_offset(vma)) >> PAGE_SHIFT;
> + pfn += (start - area->vm_start) >> PAGE_SHIFT;
> + pfn += obj_offset - vma->gtt_view.partial.offset;
I don't know how viable it would be, but maybe we could
calculate pfn as a part of set_address_limits?
Just a suggestion, not blocking
Reviewed-by: Jonathan Cavitt <Jonathan.cavitt at intel.com>
-Jonathan Cavitt
> +
> /* Finally, remap it using the new GTT offset */
> - ret = remap_io_mapping(area,
> - area->vm_start + (vma->gtt_view.partial.offset << PAGE_SHIFT),
> - (ggtt->gmadr.start + i915_ggtt_offset(vma)) >> PAGE_SHIFT,
> - min_t(u64, vma->size, area->vm_end - area->vm_start),
> - &ggtt->iomap);
> + ret = remap_io_mapping(area, start, pfn, end - start, &ggtt->iomap);
> if (ret)
> goto err_fence;
>
> --
> 2.45.2
>
>
More information about the dri-devel
mailing list