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

Configure Feed

Select the types of activity you want to include in your feed.

drm/panfrost: Fix a page leak in panfrost_mmu_map_fault_addr() when THP is on

drm_gem_put_pages(), which we rely on for returning BO pages to shmem,
assume per-folio refcounting and not per-page. If we call
shmem_read_mapping_page() per-page, we break this assumption and leak
pages every time we get a huge page allocated.

v2:
- Rework the logic for() loop to better match the folio-granular
allocation scheme

Cc: Loïc Molinari <loic.molinari@collabora.com>
Fixes: c12e9fcb5a5a ("drm/panfrost: Introduce huge tmpfs mountpoint option")
Signed-off-by: Boris Brezillon <boris.brezillon@collabora.com>
Reviewed-by: Adrián Larumbe <adrian.larumbe@collabora.com>
Reviewed-by: Steven Price <steven.price@arm.com>
Link: https://patch.msgid.link/20260108123325.1088195-1-boris.brezillon@collabora.com
Signed-off-by: Adrián Larumbe <adrian.larumbe@collabora.com>

authored by

Boris Brezillon and committed by
Adrián Larumbe
b49c35ba 29f4e730

+25 -15
+25 -15
drivers/gpu/drm/panfrost/panfrost_mmu.c
··· 587 587 static int panfrost_mmu_map_fault_addr(struct panfrost_device *pfdev, int as, 588 588 u64 addr) 589 589 { 590 - int ret, i; 590 + int ret; 591 591 struct panfrost_gem_mapping *bomapping; 592 592 struct panfrost_gem_object *bo; 593 593 struct address_space *mapping; 594 594 struct drm_gem_object *obj; 595 - pgoff_t page_offset; 595 + pgoff_t page_offset, nr_pages; 596 596 struct sg_table *sgt; 597 597 struct page **pages; 598 598 ··· 613 613 addr &= ~((u64)SZ_2M - 1); 614 614 page_offset = addr >> PAGE_SHIFT; 615 615 page_offset -= bomapping->mmnode.start; 616 + nr_pages = bo->base.base.size >> PAGE_SHIFT; 616 617 617 618 obj = &bo->base.base; 618 619 ··· 627 626 goto err_unlock; 628 627 } 629 628 630 - pages = kvmalloc_array(bo->base.base.size >> PAGE_SHIFT, 631 - sizeof(struct page *), GFP_KERNEL | __GFP_ZERO); 629 + pages = kvmalloc_array(nr_pages, sizeof(struct page *), GFP_KERNEL | __GFP_ZERO); 632 630 if (!pages) { 633 631 kvfree(bo->sgts); 634 632 bo->sgts = NULL; ··· 649 649 mapping = bo->base.base.filp->f_mapping; 650 650 mapping_set_unevictable(mapping); 651 651 652 - for (i = page_offset; i < page_offset + NUM_FAULT_PAGES; i++) { 653 - /* Can happen if the last fault only partially filled this 654 - * section of the pages array before failing. In that case 655 - * we skip already filled pages. 656 - */ 657 - if (pages[i]) 658 - continue; 652 + for (pgoff_t pg = page_offset; pg < page_offset + NUM_FAULT_PAGES;) { 653 + bool already_owned = false; 654 + struct folio *folio; 659 655 660 - pages[i] = shmem_read_mapping_page(mapping, i); 661 - if (IS_ERR(pages[i])) { 662 - ret = PTR_ERR(pages[i]); 663 - pages[i] = NULL; 656 + folio = shmem_read_folio(mapping, pg); 657 + if (IS_ERR(folio)) { 658 + ret = PTR_ERR(folio); 664 659 goto err_unlock; 665 660 } 661 + 662 + pg &= ~(folio_nr_pages(folio) - 1); 663 + for (u32 i = 0; i < folio_nr_pages(folio) && pg < nr_pages; i++) { 664 + if (pages[pg]) 665 + already_owned = true; 666 + 667 + pages[pg++] = folio_page(folio, i); 668 + } 669 + 670 + /* We always fill the page array at a folio granularity so 671 + * there's no valid reason for a folio range to be partially 672 + * populated. 673 + */ 674 + if (drm_WARN_ON(&pfdev->base, already_owned)) 675 + folio_put(folio); 666 676 } 667 677 668 678 ret = sg_alloc_table_from_pages(sgt, pages + page_offset,