Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

i915: Limit the length of an sg list to the requested length

The folio conversion changed the behaviour of shmem_sg_alloc_table() to
put the entire length of the last folio into the sg list, even if the sg
list should have been shorter. gen8_ggtt_insert_entries() relied on the
list being the right length and would overrun the end of the page tables.
Other functions may also have been affected.

Clamp the length of the last entry in the sg list to be the expected
length.

Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org>
Fixes: 0b62af28f249 ("i915: convert shmem_sg_free_table() to use a folio_batch")
Cc: stable@vger.kernel.org # 6.5.x
Link: https://gitlab.freedesktop.org/drm/intel/-/issues/9256
Link: https://lore.kernel.org/lkml/6287208.lOV4Wx5bFT@natalenko.name/
Reported-by: Oleksandr Natalenko <oleksandr@natalenko.name>
Tested-by: Oleksandr Natalenko <oleksandr@natalenko.name>
Reviewed-by: Andrzej Hajda <andrzej.hajda@intel.com>
Signed-off-by: Andrzej Hajda <andrzej.hajda@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20230919194855.347582-1-willy@infradead.org
(cherry picked from commit 26a8e32e6d77900819c0c730fbfb393692dbbeea)
Signed-off-by: Rodrigo Vivi <rodrigo.vivi@intel.com>

authored by

Matthew Wilcox (Oracle) and committed by
Rodrigo Vivi
863a8eb3 6465e260

+7 -4
+7 -4
drivers/gpu/drm/i915/gem/i915_gem_shmem.c
··· 100 100 st->nents = 0; 101 101 for (i = 0; i < page_count; i++) { 102 102 struct folio *folio; 103 + unsigned long nr_pages; 103 104 const unsigned int shrink[] = { 104 105 I915_SHRINK_BOUND | I915_SHRINK_UNBOUND, 105 106 0, ··· 151 150 } 152 151 } while (1); 153 152 153 + nr_pages = min_t(unsigned long, 154 + folio_nr_pages(folio), page_count - i); 154 155 if (!i || 155 156 sg->length >= max_segment || 156 157 folio_pfn(folio) != next_pfn) { ··· 160 157 sg = sg_next(sg); 161 158 162 159 st->nents++; 163 - sg_set_folio(sg, folio, folio_size(folio), 0); 160 + sg_set_folio(sg, folio, nr_pages * PAGE_SIZE, 0); 164 161 } else { 165 162 /* XXX: could overflow? */ 166 - sg->length += folio_size(folio); 163 + sg->length += nr_pages * PAGE_SIZE; 167 164 } 168 - next_pfn = folio_pfn(folio) + folio_nr_pages(folio); 169 - i += folio_nr_pages(folio) - 1; 165 + next_pfn = folio_pfn(folio) + nr_pages; 166 + i += nr_pages - 1; 170 167 171 168 /* Check that the i965g/gm workaround works. */ 172 169 GEM_BUG_ON(gfp & __GFP_DMA32 && next_pfn >= 0x00100000UL);