From 1ac5167b3a90c9820daa64cc65e319b2d958d686 Mon Sep 17 00:00:00 2001 From: Andi Shyti Date: Fri, 2 Aug 2024 10:38:49 +0200 Subject: drm/i915/gem: Adjust vma offset for framebuffer mmap offset When mapping a framebuffer object, the virtual memory area (VMA) offset ('vm_pgoff') should be adjusted by the start of the 'vma_node' associated with the object. This ensures that the VMA offset is correctly aligned with the corresponding offset within the GGTT aperture. Increment vm_pgoff by the start of the vma_node with the offset= provided by the user. Suggested-by: Chris Wilson Signed-off-by: Andi Shyti Reviewed-by: Jonathan Cavitt Reviewed-by: Rodrigo Vivi Cc: # v4.9+ [Joonas: Add Cc: stable] Signed-off-by: Joonas Lahtinen Link: https://patchwork.freedesktop.org/patch/msgid/20240802083850.103694-2-andi.shyti@linux.intel.com (cherry picked from commit 60a2066c50058086510c91f404eb582029650970) Signed-off-by: Joonas Lahtinen --- drivers/gpu/drm/i915/gem/i915_gem_mman.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/gpu/drm/i915/gem') diff --git a/drivers/gpu/drm/i915/gem/i915_gem_mman.c b/drivers/gpu/drm/i915/gem/i915_gem_mman.c index a2195e28b625..ce10dd259812 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_mman.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_mman.c @@ -1084,6 +1084,8 @@ int i915_gem_fb_mmap(struct drm_i915_gem_object *obj, struct vm_area_struct *vma mmo = mmap_offset_attach(obj, mmap_type, NULL); if (IS_ERR(mmo)) return PTR_ERR(mmo); + + vma->vm_pgoff += drm_vma_node_start(&mmo->vma_node); } /* -- cgit v1.2.3 From 8bdd9ef7e9b1b2a73e394712b72b22055e0e26c3 Mon Sep 17 00:00:00 2001 From: Andi Shyti Date: Fri, 2 Aug 2024 10:38:50 +0200 Subject: 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 Co-developed-by: Chris Wilson Signed-off-by: Chris Wilson Signed-off-by: Andi Shyti Cc: Joonas Lahtinen Cc: Matthew Auld Cc: Rodrigo Vivi Cc: # v4.9+ Reviewed-by: Jann Horn Reviewed-by: Jonathan Cavitt [Joonas: Add Requires: tag] Requires: 60a2066c5005 ("drm/i915/gem: Adjust vma offset for framebuffer mmap offset") Signed-off-by: Joonas Lahtinen Link: https://patchwork.freedesktop.org/patch/msgid/20240802083850.103694-3-andi.shyti@linux.intel.com (cherry picked from commit 97b6784753da06d9d40232328efc5c5367e53417) Signed-off-by: Joonas Lahtinen --- drivers/gpu/drm/i915/gem/i915_gem_mman.c | 53 ++++++++++++++++++++++++++++---- 1 file changed, 47 insertions(+), 6 deletions(-) (limited to 'drivers/gpu/drm/i915/gem') 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 @@ out: 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 @@ retry: 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; + /* 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; -- cgit v1.2.3 From 264b5b5980061d8c6a6a30c031cdec1179fe2bae Mon Sep 17 00:00:00 2001 From: David Gow Date: Sun, 4 Aug 2024 17:18:47 +0800 Subject: drm/i915: Allow evicting to use the requested placement In commit a78a8da51b36 ("drm/ttm: replace busy placement with flags v6"), the old system of having a separate placement list (for placements which should be used without eviction) and a 'busy' placement list (for placements which should be attempted if eviction is required) was replaced with a new one where placements could be marked 'FALLBACK' (to be attempted if eviction is required) or 'DESIRED' (to be attempted first, but not if eviction is required). i915 had always included the requested placement in the list of 'busy' placements: i.e., the placement could be used either if eviction is required or not. But when the new system was put in place, the requested (first) placement was marked 'DESIRED', so would never be used if eviction became necessary. While a bug in the original commit prevented this flag from working, when this was fixed in 4a0e7b3c ("drm/i915: fix applying placement flag"), it caused long hangs on DG2 systems with small BAR. Don't mark the requested placement DESIRED (or FALLBACK), allowing it to be used in both situations. This matches the old behaviour, and resolves the hangs. Thanks to Justin Brewer for bisecting the issue. Fixes: a78a8da51b36 ("drm/ttm: replace busy placement with flags v6") Fixes: 4a0e7b3c3753 ("drm/i915: fix applying placement flag") Link: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/11255 Signed-off-by: David Gow Reviewed-by: Jonathan Cavitt Reviewed-by: Andi Shyti Signed-off-by: Andi Shyti Link: https://patchwork.freedesktop.org/patch/msgid/20240804091851.122186-2-david@davidgow.net (cherry picked from commit 54bf0af90844fbf18f5be3272eda69198dfdb622) Signed-off-by: Joonas Lahtinen --- drivers/gpu/drm/i915/gem/i915_gem_ttm.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/gpu/drm/i915/gem') diff --git a/drivers/gpu/drm/i915/gem/i915_gem_ttm.c b/drivers/gpu/drm/i915/gem/i915_gem_ttm.c index e6f177183c0f..fb848fd8ba15 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_ttm.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_ttm.c @@ -165,7 +165,6 @@ i915_ttm_placement_from_obj(const struct drm_i915_gem_object *obj, i915_ttm_place_from_region(num_allowed ? obj->mm.placements[0] : obj->mm.region, &places[0], obj->bo_offset, obj->base.size, flags); - places[0].flags |= TTM_PL_FLAG_DESIRED; /* Cache this on object? */ for (i = 0; i < num_allowed; ++i) { -- cgit v1.2.3 From 787db3bb6ed5cee56fc97fecdd61517d89763f0a Mon Sep 17 00:00:00 2001 From: David Gow Date: Sun, 4 Aug 2024 17:18:48 +0800 Subject: drm/i915: Attempt to get pages without eviction first In commit a78a8da51b36 ("drm/ttm: replace busy placement with flags v6"), __i915_ttm_get_pages was updated to use flags instead of the separate 'busy' placement list. However, the behaviour was subtly changed. Originally, the function would attempt to use the preferred placement without eviction, and give an opportunity to restart the operation before falling back to allowing eviction. This was unintentionally changed, as the preferred placement was not given the TTM_PL_FLAG_DESIRED flag, and so eviction could be triggered in that first pass. This caused thrashing, and a significant performance regression on DG2 systems with small BAR. For example, Minecraft and Team Fortress 2 would drop to single-digit framerates. Restore the original behaviour by marking the initial placement as desired on that first attempt. Also, rework this to use a separate struct ttm_palcement, as the individual placements are marked 'const', so hot-patching the flags is even more dodgy than before. Thanks to Justin Brewer for bisecting this. Fixes: a78a8da51b36 ("drm/ttm: replace busy placement with flags v6") Link: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/11255 Signed-off-by: David Gow Reviewed-by: Jonathan Cavitt Reviewed-by: Andi Shyti Signed-off-by: Andi Shyti Link: https://patchwork.freedesktop.org/patch/msgid/20240804091851.122186-3-david@davidgow.net (cherry picked from commit 92653f2a572505adaf7f13f695c1907e71a1dc84) Signed-off-by: Joonas Lahtinen --- drivers/gpu/drm/i915/gem/i915_gem_ttm.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) (limited to 'drivers/gpu/drm/i915/gem') diff --git a/drivers/gpu/drm/i915/gem/i915_gem_ttm.c b/drivers/gpu/drm/i915/gem/i915_gem_ttm.c index fb848fd8ba15..5c72462d1f57 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_ttm.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_ttm.c @@ -778,13 +778,16 @@ static int __i915_ttm_get_pages(struct drm_i915_gem_object *obj, .interruptible = true, .no_wait_gpu = false, }; - int real_num_busy; + struct ttm_placement initial_placement; + struct ttm_place initial_place; int ret; /* First try only the requested placement. No eviction. */ - real_num_busy = placement->num_placement; - placement->num_placement = 1; - ret = ttm_bo_validate(bo, placement, &ctx); + initial_placement.num_placement = 1; + memcpy(&initial_place, placement->placement, sizeof(struct ttm_place)); + initial_place.flags |= TTM_PL_FLAG_DESIRED; + initial_placement.placement = &initial_place; + ret = ttm_bo_validate(bo, &initial_placement, &ctx); if (ret) { ret = i915_ttm_err_to_gem(ret); /* @@ -799,7 +802,6 @@ static int __i915_ttm_get_pages(struct drm_i915_gem_object *obj, * If the initial attempt fails, allow all accepted placements, * evicting if necessary. */ - placement->num_placement = real_num_busy; ret = ttm_bo_validate(bo, placement, &ctx); if (ret) return i915_ttm_err_to_gem(ret); -- cgit v1.2.3