From 8103ecc1999eefc54b740d8d99f264ced1d9c54d Mon Sep 17 00:00:00 2001 From: Krzysztof Karas Date: Wed, 14 Jan 2026 16:04:21 +0000 Subject: [PATCH 1/4] drm/i915/selftests: Keep mock file open during unfaultable migrate with fill igt_mmap_migrate() tests migration with various parameters. In one of the cases, where FILL and UNFAULTABLE flags are set, during first stages of this test, a mock file is opened in igt_mmap_offset(), which results in allocating GEM objects for page table structures and scratch in GPU mappable memory. Then, also in igt_mmap_offset(), the file is closed (fput) and the cleanup of these objects is scheduled on a delayed worqueue, which is designed to execute after unspecified amount of time. Next, the test calls igt_fill_mappable() to fill mappable GPU memory. At this point, three scenarios are possible (N = max size of GPU memory for this test in MiB): 1) the objects allocated for the mock file get cleaned up after crucial part of the test is over, so the memory is full with the 1 MiB they occupy and N - 1 MiB added by igt_fill_mappable(), so the migration fails properly; 2) the object cleanup fires before igt_fill_mappable() completes, so the whole memory is populated with N MiB from igt_fill_mappable(), so migration fails as well; 3) the object cleanup is performed right after fill is done, so only N - 1 MiB are in the mappable portion of GPU memory, allowing the migration to succeed - we'd expect no space left to perform migration, but an object was able to fit in the remaining 1 MiB, which caused get_user() to succeed, so a page fault did not fail. The test incorrectly assumes that the GPU mappable memory state is unchanging during the test. Amend this by keeping the mock file open until migration and page fault checking is complete. Closes: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/13929 Signed-off-by: Krzysztof Karas Reviewed-by: Sebastian Brzezinka Acked-by: Andi Shyti Link: https://lore.kernel.org/r/6xc74s3mbmtliqxihtxbok32jobhc26vfm5mu6cod4ywov6utf@ujp3rmqcwmr3 Signed-off-by: Andi Shyti --- .../drm/i915/gem/selftests/i915_gem_mman.c | 27 +++++++++--- drivers/gpu/drm/i915/selftests/igt_mmap.c | 43 ++++++++++++------- drivers/gpu/drm/i915/selftests/igt_mmap.h | 8 ++++ 3 files changed, 56 insertions(+), 22 deletions(-) diff --git a/drivers/gpu/drm/i915/gem/selftests/i915_gem_mman.c b/drivers/gpu/drm/i915/gem/selftests/i915_gem_mman.c index 78734c404a6d..3802a6222146 100644 --- a/drivers/gpu/drm/i915/gem/selftests/i915_gem_mman.c +++ b/drivers/gpu/drm/i915/gem/selftests/i915_gem_mman.c @@ -1157,6 +1157,7 @@ static int __igt_mmap_migrate(struct intel_memory_region **placements, struct drm_i915_gem_object *obj; struct i915_request *rq = NULL; struct vm_area_struct *area; + struct file *mock_file; unsigned long addr; LIST_HEAD(objects); u64 offset; @@ -1176,16 +1177,25 @@ static int __igt_mmap_migrate(struct intel_memory_region **placements, goto out_put; /* - * This will eventually create a GEM context, due to opening dummy drm - * file, which needs a tiny amount of mappable device memory for the top - * level paging structures(and perhaps scratch), so make sure we - * allocate early, to avoid tears. + * Pretend to open("/dev/dri/card0"), which will eventually create a GEM + * context along with multiple GEM objects (for paging structures and + * scratch) that are placed in mappable portion of GPU memory. + * Calling fput() on the file places objects' cleanup routines in delayed + * worqueues, which execute after unspecified amount of time. + * Keep the file open until migration and page fault checks are done to + * make sure object cleanup is not executed after igt_fill_mappable() + * finishes and before migration is attempted - that would leave a gap + * large enough for the migration to succeed, when we'd expect it to fail. */ - addr = igt_mmap_offset(i915, offset, obj->base.size, - PROT_WRITE, MAP_SHARED); + mock_file = mock_drm_getfile(i915->drm.primary, O_RDWR); + if (IS_ERR(mock_file)) + return PTR_ERR(mock_file); + + addr = igt_mmap_offset_with_file(i915, offset, obj->base.size, + PROT_WRITE, MAP_SHARED, mock_file); if (IS_ERR_VALUE(addr)) { err = addr; - goto out_put; + goto out_fput; } mmap_read_lock(current->mm); @@ -1292,6 +1302,9 @@ static int __igt_mmap_migrate(struct intel_memory_region **placements, out_addr: vm_munmap(addr, obj->base.size); +out_fput: + fput(mock_file); + out_put: i915_gem_object_put(obj); igt_close_objects(i915, &objects); diff --git a/drivers/gpu/drm/i915/selftests/igt_mmap.c b/drivers/gpu/drm/i915/selftests/igt_mmap.c index e920a461bd36..106d5c0dfcbc 100644 --- a/drivers/gpu/drm/i915/selftests/igt_mmap.c +++ b/drivers/gpu/drm/i915/selftests/igt_mmap.c @@ -9,14 +9,14 @@ #include "i915_drv.h" #include "igt_mmap.h" -unsigned long igt_mmap_offset(struct drm_i915_private *i915, - u64 offset, - unsigned long size, - unsigned long prot, - unsigned long flags) +unsigned long igt_mmap_offset_with_file(struct drm_i915_private *i915, + u64 offset, + unsigned long size, + unsigned long prot, + unsigned long flags, + struct file *file) { struct drm_vma_offset_node *node; - struct file *file; unsigned long addr; int err; @@ -31,22 +31,35 @@ unsigned long igt_mmap_offset(struct drm_i915_private *i915, return -ENOENT; } - /* Pretend to open("/dev/dri/card0") */ - file = mock_drm_getfile(i915->drm.primary, O_RDWR); - if (IS_ERR(file)) - return PTR_ERR(file); - err = drm_vma_node_allow(node, file->private_data); if (err) { - addr = err; - goto out_file; + return err; } addr = vm_mmap(file, 0, drm_vma_node_size(node) << PAGE_SHIFT, prot, flags, drm_vma_node_offset_addr(node)); drm_vma_node_revoke(node, file->private_data); -out_file: - fput(file); + + return addr; +} + +unsigned long igt_mmap_offset(struct drm_i915_private *i915, + u64 offset, + unsigned long size, + unsigned long prot, + unsigned long flags) +{ + struct file *file; + unsigned long addr; + + /* Pretend to open("/dev/dri/card0") */ + file = mock_drm_getfile(i915->drm.primary, O_RDWR); + if (IS_ERR(file)) + return PTR_ERR(file); + + addr = igt_mmap_offset_with_file(i915, offset, size, prot, flags, file); + fput(file); + return addr; } diff --git a/drivers/gpu/drm/i915/selftests/igt_mmap.h b/drivers/gpu/drm/i915/selftests/igt_mmap.h index acbe34d81a6d..7b177b44cd3c 100644 --- a/drivers/gpu/drm/i915/selftests/igt_mmap.h +++ b/drivers/gpu/drm/i915/selftests/igt_mmap.h @@ -11,6 +11,7 @@ struct drm_i915_private; struct drm_vma_offset_node; +struct file; unsigned long igt_mmap_offset(struct drm_i915_private *i915, u64 offset, @@ -18,4 +19,11 @@ unsigned long igt_mmap_offset(struct drm_i915_private *i915, unsigned long prot, unsigned long flags); +unsigned long igt_mmap_offset_with_file(struct drm_i915_private *i915, + u64 offset, + unsigned long size, + unsigned long prot, + unsigned long flags, + struct file *file); + #endif /* IGT_MMAP_H */ From 945d0fec02f6c22b182d51d8da39aa1b0df9f622 Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann Date: Fri, 27 Feb 2026 14:31:04 +0100 Subject: [PATCH 2/4] drm/i915: Test for imported buffers with drm_gem_is_imported() Instead of testing import_attach for imported GEM buffers, invoke drm_gem_is_imported() to do the test. The test itself does not change. Signed-off-by: Thomas Zimmermann Cc: Jani Nikula Cc: Joonas Lahtinen Cc: Rodrigo Vivi Cc: Tvrtko Ursulin Cc: intel-gfx@lists.freedesktop.org Reviewed-by: Tvrtko Ursulin Signed-off-by: Tvrtko Ursulin Link: https://lore.kernel.org/r/20260227133113.235940-5-tzimmermann@suse.de --- drivers/gpu/drm/i915/gem/i915_gem_object.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/i915/gem/i915_gem_object.c b/drivers/gpu/drm/i915/gem/i915_gem_object.c index 1f38e367c60b..27f5351f046a 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_object.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_object.c @@ -371,12 +371,12 @@ void __i915_gem_object_pages_fini(struct drm_i915_gem_object *obj) * and ttm_bo_cleanup_memtype_use() shouldn't be invoked for * dma-buf, so it's safe to take the lock. */ - if (obj->base.import_attach) + if (drm_gem_is_imported(&obj->base)) i915_gem_object_lock(obj, NULL); __i915_gem_object_put_pages(obj); - if (obj->base.import_attach) + if (drm_gem_is_imported(&obj->base)) i915_gem_object_unlock(obj); GEM_BUG_ON(i915_gem_object_has_pages(obj)); @@ -390,7 +390,7 @@ void __i915_gem_free_object(struct drm_i915_gem_object *obj) bitmap_free(obj->bit_17); - if (obj->base.import_attach) + if (drm_gem_is_imported(&obj->base)) drm_prime_gem_destroy(&obj->base, NULL); drm_gem_free_mmap_offset(&obj->base); From 2a99ecca1fdfc3838dda2f7b85bd3216fbf51867 Mon Sep 17 00:00:00 2001 From: Konstantin Khorenko Date: Mon, 9 Feb 2026 12:27:09 +0100 Subject: [PATCH 3/4] drm/i915/guc: Fix corrupted copyright symbols in selftest files MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace broken UTF-8 sequences (Unicode replacement characters) with proper "©" text in copyright headers. Signed-off-by: Konstantin Khorenko Reviewed-by: Andi Shyti Signed-off-by: Andi Shyti Link: https://lore.kernel.org/r/20260209112709.2551603-1-khorenko@virtuozzo.com --- drivers/gpu/drm/i915/gt/uc/selftest_guc.c | 2 +- drivers/gpu/drm/i915/gt/uc/selftest_guc_multi_lrc.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/uc/selftest_guc.c b/drivers/gpu/drm/i915/gt/uc/selftest_guc.c index 68feb55654f7..0ef294bef00b 100644 --- a/drivers/gpu/drm/i915/gt/uc/selftest_guc.c +++ b/drivers/gpu/drm/i915/gt/uc/selftest_guc.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MIT /* - * Copyright �� 2021 Intel Corporation + * Copyright © 2021 Intel Corporation */ #include "gt/intel_gt_print.h" diff --git a/drivers/gpu/drm/i915/gt/uc/selftest_guc_multi_lrc.c b/drivers/gpu/drm/i915/gt/uc/selftest_guc_multi_lrc.c index a40e7c32e613..28e8a092f4e7 100644 --- a/drivers/gpu/drm/i915/gt/uc/selftest_guc_multi_lrc.c +++ b/drivers/gpu/drm/i915/gt/uc/selftest_guc_multi_lrc.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MIT /* - * Copyright �� 2019 Intel Corporation + * Copyright © 2019 Intel Corporation */ #include "gt/intel_gt_print.h" From 06249b4e691a75694c014a61708c007fb5755f60 Mon Sep 17 00:00:00 2001 From: Janusz Krzysztofik Date: Tue, 24 Feb 2026 10:49:06 +0100 Subject: [PATCH 4/4] drm/i915: Fix potential overflow of shmem scatterlist length When a scatterlists table of a GEM shmem object of size 4 GB or more is populated with pages allocated from a folio, unsigned int .length attribute of a scatterlist may get overflowed if total byte length of pages allocated to that single scatterlist happens to reach or cross the 4GB limit. As a consequence, users of the object may suffer from hitting unexpected, premature end of the object's backing pages. [278.780187] ------------[ cut here ]------------ [278.780377] WARNING: CPU: 1 PID: 2326 at drivers/gpu/drm/i915/i915_mm.c:55 remap_sg+0x199/0x1d0 [i915] ... [278.780654] CPU: 1 UID: 0 PID: 2326 Comm: gem_mmap_offset Tainted: G S U 6.17.0-rc1-CI_DRM_16981-ged823aaa0607+ #1 PREEMPT(voluntary) [278.780656] Tainted: [S]=CPU_OUT_OF_SPEC, [U]=USER [278.780658] Hardware name: Intel Corporation Meteor Lake Client Platform/MTL-P LP5x T3 RVP, BIOS MTLPFWI1.R00.3471.D91.2401310918 01/31/2024 [278.780659] RIP: 0010:remap_sg+0x199/0x1d0 [i915] ... [278.780786] Call Trace: [278.780787] [278.780788] ? __apply_to_page_range+0x3e6/0x910 [278.780795] ? __pfx_remap_sg+0x10/0x10 [i915] [278.780906] apply_to_page_range+0x14/0x30 [278.780908] remap_io_sg+0x14d/0x260 [i915] [278.781013] vm_fault_cpu+0xd2/0x330 [i915] [278.781137] __do_fault+0x3a/0x1b0 [278.781140] do_fault+0x322/0x640 [278.781143] __handle_mm_fault+0x938/0xfd0 [278.781150] handle_mm_fault+0x12c/0x300 [278.781152] ? lock_mm_and_find_vma+0x4b/0x760 [278.781155] do_user_addr_fault+0x2d6/0x8e0 [278.781160] exc_page_fault+0x96/0x2c0 [278.781165] asm_exc_page_fault+0x27/0x30 ... That issue was apprehended by the author of a change that introduced it, and potential risk even annotated with a comment, but then never addressed. When adding folio pages to a scatterlist table, take care of byte length of any single scatterlist not exceeding max_segment. Fixes: 0b62af28f249b ("i915: convert shmem_sg_free_table() to use a folio_batch") Closes: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/14809 Cc: Matthew Wilcox (Oracle) Cc: Andrew Morton Cc: stable@vger.kernel.org # v6.5+ Signed-off-by: Janusz Krzysztofik Reviewed-by: Andi Shyti Signed-off-by: Andi Shyti Link: https://lore.kernel.org/r/20260224094944.2447913-2-janusz.krzysztofik@linux.intel.com --- drivers/gpu/drm/i915/gem/i915_gem_shmem.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/i915/gem/i915_gem_shmem.c b/drivers/gpu/drm/i915/gem/i915_gem_shmem.c index 26dda55a07ff..6c0c4cf1517a 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_shmem.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_shmem.c @@ -151,8 +151,12 @@ int shmem_sg_alloc_table(struct drm_i915_private *i915, struct sg_table *st, } } while (1); - nr_pages = min_t(unsigned long, - folio_nr_pages(folio), page_count - i); + nr_pages = min_array(((unsigned long[]) { + folio_nr_pages(folio), + page_count - i, + max_segment / PAGE_SIZE, + }), 3); + if (!i || sg->length >= max_segment || folio_pfn(folio) != next_pfn) { @@ -162,7 +166,9 @@ int shmem_sg_alloc_table(struct drm_i915_private *i915, struct sg_table *st, st->nents++; sg_set_folio(sg, folio, nr_pages * PAGE_SIZE, 0); } else { - /* XXX: could overflow? */ + nr_pages = min_t(unsigned long, nr_pages, + (max_segment - sg->length) / PAGE_SIZE); + sg->length += nr_pages * PAGE_SIZE; } next_pfn = folio_pfn(folio) + nr_pages;