* [PATCH v3 01/10] drm/shmem-helper: Add huge page fault handler
2025-10-04 9:30 [PATCH v3 00/10] drm: Reduce page tables overhead with THP Loïc Molinari
@ 2025-10-04 9:30 ` Loïc Molinari
2025-10-04 22:53 ` Matthew Wilcox
` (2 more replies)
2025-10-04 9:30 ` [PATCH v3 02/10] drm/gem: Introduce drm_gem_get_unmapped_area() fop Loïc Molinari
` (8 subsequent siblings)
9 siblings, 3 replies; 26+ messages in thread
From: Loïc Molinari @ 2025-10-04 9:30 UTC (permalink / raw)
To: Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann,
David Airlie, Simona Vetter, Jani Nikula, Joonas Lahtinen,
Rodrigo Vivi, Tvrtko Ursulin, Boris Brezillon, Rob Herring,
Steven Price, Liviu Dudau, Melissa Wen, Maíra Canal,
Hugh Dickins, Baolin Wang, Andrew Morton, Loïc Molinari,
Al Viro, Mikołaj Wasiak, Christian Brauner, Nitin Gote,
Andi Shyti, Christopher Healy
Cc: linux-kernel, dri-devel, intel-gfx, linux-mm, kernel, kernel test robot
This gives the mm subsystem the ability to propose the insertion of
PUD or PMD-sized mappings for the faulting addresses.
On builds with CONFIG_TRANSPARENT_HUGEPAGE enabled, if the mmap() user
address is aligned to a huge page size, if the GEM object is backed by
shmem buffers on mount points setting the 'huge=' option and if the
shmem backing store manages to allocate a huge folio, the CPU mapping
will then benefit from significantly increased memcpy() performance.
When these conditions are met on a system with 2 MiB huge pages, an
aligned copy of 2 MiB would raise a single page fault instead of 4096.
v2:
- set ret to VM_FAULT_FALLBACK in default switch statement
- ifdef out paddr declaration
Signed-off-by: Loïc Molinari <loic.molinari@collabora.com>
Reviewed-by: Boris Brezillon <boris.brezillon@collabora.com>
Reported-by: kernel test robot <lkp@intel.com>
Closes: https://lore.kernel.org/oe-kbuild-all/202509241315.8jjCyL7U-lkp@intel.com/
Closes: https://lore.kernel.org/oe-kbuild-all/202509241654.qJk1H5kr-lkp@intel.com/
Closes: https://lore.kernel.org/oe-kbuild-all/202509241920.PtSEkfd4-lkp@intel.com/
---
drivers/gpu/drm/drm_gem_shmem_helper.c | 56 ++++++++++++++++++++++++--
1 file changed, 52 insertions(+), 4 deletions(-)
diff --git a/drivers/gpu/drm/drm_gem_shmem_helper.c b/drivers/gpu/drm/drm_gem_shmem_helper.c
index 50594cf8e17c..22c4b09e10a3 100644
--- a/drivers/gpu/drm/drm_gem_shmem_helper.c
+++ b/drivers/gpu/drm/drm_gem_shmem_helper.c
@@ -573,7 +573,8 @@ int drm_gem_shmem_dumb_create(struct drm_file *file, struct drm_device *dev,
}
EXPORT_SYMBOL_GPL(drm_gem_shmem_dumb_create);
-static vm_fault_t drm_gem_shmem_fault(struct vm_fault *vmf)
+static vm_fault_t drm_gem_shmem_huge_fault(struct vm_fault *vmf,
+ unsigned int order)
{
struct vm_area_struct *vma = vmf->vma;
struct drm_gem_object *obj = vma->vm_private_data;
@@ -582,6 +583,10 @@ static vm_fault_t drm_gem_shmem_fault(struct vm_fault *vmf)
vm_fault_t ret;
struct page *page;
pgoff_t page_offset;
+ unsigned long pfn;
+#if defined(CONFIG_ARCH_SUPPORTS_PMD_PFNMAP) || defined(CONFIG_ARCH_SUPPORTS_PUD_PFNMAP)
+ unsigned long paddr;
+#endif
/* We don't use vmf->pgoff since that has the fake offset */
page_offset = (vmf->address - vma->vm_start) >> PAGE_SHIFT;
@@ -592,17 +597,57 @@ static vm_fault_t drm_gem_shmem_fault(struct vm_fault *vmf)
drm_WARN_ON_ONCE(obj->dev, !shmem->pages) ||
shmem->madv < 0) {
ret = VM_FAULT_SIGBUS;
- } else {
- page = shmem->pages[page_offset];
+ goto out;
+ }
- ret = vmf_insert_pfn(vma, vmf->address, page_to_pfn(page));
+ page = shmem->pages[page_offset];
+ pfn = page_to_pfn(page);
+
+ switch (order) {
+ case 0:
+ ret = vmf_insert_pfn(vma, vmf->address, pfn);
+ break;
+
+#ifdef CONFIG_ARCH_SUPPORTS_PMD_PFNMAP
+ case PMD_ORDER:
+ paddr = pfn << PAGE_SHIFT;
+ if (((vmf->address & ~PMD_MASK) == (paddr & ~PMD_MASK)) &&
+ (folio_order(page_folio(page)) == PMD_ORDER))
+ ret = vmf_insert_pfn_pmd(
+ vmf, pfn & (PMD_MASK >> PAGE_SHIFT), false);
+ else
+ ret = VM_FAULT_FALLBACK;
+ break;
+#endif
+
+#ifdef CONFIG_ARCH_SUPPORTS_PUD_PFNMAP
+ case PUD_ORDER:
+ paddr = pfn << PAGE_SHIFT;
+ if (((vmf->address & ~PUD_MASK) == (paddr & ~PUD_MASK)) &&
+ (folio_order(page_folio(page)) == PUD_ORDER))
+ ret = vmf_insert_pfn_pud(
+ vmf, pfn & (PUD_MASK >> PAGE_SHIFT), false);
+ else
+ ret = VM_FAULT_FALLBACK;
+ break;
+#endif
+
+ default:
+ ret = VM_FAULT_FALLBACK;
+ break;
}
+ out:
dma_resv_unlock(shmem->base.resv);
return ret;
}
+static vm_fault_t drm_gem_shmem_fault(struct vm_fault *vmf)
+{
+ return drm_gem_shmem_huge_fault(vmf, 0);
+}
+
static void drm_gem_shmem_vm_open(struct vm_area_struct *vma)
{
struct drm_gem_object *obj = vma->vm_private_data;
@@ -639,6 +684,9 @@ static void drm_gem_shmem_vm_close(struct vm_area_struct *vma)
const struct vm_operations_struct drm_gem_shmem_vm_ops = {
.fault = drm_gem_shmem_fault,
+#if defined(CONFIG_ARCH_SUPPORTS_PMD_PFNMAP) || defined(CONFIG_ARCH_SUPPORTS_PUD_PFNMAP)
+ .huge_fault = drm_gem_shmem_huge_fault,
+#endif
.open = drm_gem_shmem_vm_open,
.close = drm_gem_shmem_vm_close,
};
--
2.47.3
^ permalink raw reply [flat|nested] 26+ messages in thread* Re: [PATCH v3 01/10] drm/shmem-helper: Add huge page fault handler
2025-10-04 9:30 ` [PATCH v3 01/10] drm/shmem-helper: Add huge page fault handler Loïc Molinari
@ 2025-10-04 22:53 ` Matthew Wilcox
2025-10-06 6:52 ` Boris Brezillon
2025-10-06 16:01 ` Andi Shyti
2 siblings, 0 replies; 26+ messages in thread
From: Matthew Wilcox @ 2025-10-04 22:53 UTC (permalink / raw)
To: Loïc Molinari
Cc: Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann,
David Airlie, Simona Vetter, Jani Nikula, Joonas Lahtinen,
Rodrigo Vivi, Tvrtko Ursulin, Boris Brezillon, Rob Herring,
Steven Price, Liviu Dudau, Melissa Wen, Maíra Canal,
Hugh Dickins, Baolin Wang, Andrew Morton, Al Viro,
Mikołaj Wasiak, Christian Brauner, Nitin Gote, Andi Shyti,
Christopher Healy, linux-kernel, dri-devel, intel-gfx, linux-mm,
kernel, kernel test robot
On Sat, Oct 04, 2025 at 11:30:44AM +0200, Loïc Molinari wrote:
> -static vm_fault_t drm_gem_shmem_fault(struct vm_fault *vmf)
> +static vm_fault_t drm_gem_shmem_huge_fault(struct vm_fault *vmf,
> + unsigned int order)
From the mm side, we'd much rather you implemented ->map_pages than
->huge_fault. It's far more flexible; for example it'll support ARM's
contpte which ->huge_fault() doesn't.
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [PATCH v3 01/10] drm/shmem-helper: Add huge page fault handler
2025-10-04 9:30 ` [PATCH v3 01/10] drm/shmem-helper: Add huge page fault handler Loïc Molinari
2025-10-04 22:53 ` Matthew Wilcox
@ 2025-10-06 6:52 ` Boris Brezillon
2025-10-06 16:01 ` Andi Shyti
2 siblings, 0 replies; 26+ messages in thread
From: Boris Brezillon @ 2025-10-06 6:52 UTC (permalink / raw)
To: Loïc Molinari
Cc: Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann,
David Airlie, Simona Vetter, Jani Nikula, Joonas Lahtinen,
Rodrigo Vivi, Tvrtko Ursulin, Rob Herring, Steven Price,
Liviu Dudau, Melissa Wen, Maíra Canal, Hugh Dickins,
Baolin Wang, Andrew Morton, Al Viro, Mikołaj Wasiak,
Christian Brauner, Nitin Gote, Andi Shyti, Christopher Healy,
linux-kernel, dri-devel, intel-gfx, linux-mm, kernel,
kernel test robot
On Sat, 4 Oct 2025 11:30:44 +0200
Loïc Molinari <loic.molinari@collabora.com> wrote:
> This gives the mm subsystem the ability to propose the insertion of
> PUD or PMD-sized mappings for the faulting addresses.
>
> On builds with CONFIG_TRANSPARENT_HUGEPAGE enabled, if the mmap() user
> address is aligned to a huge page size, if the GEM object is backed by
> shmem buffers on mount points setting the 'huge=' option and if the
> shmem backing store manages to allocate a huge folio, the CPU mapping
> will then benefit from significantly increased memcpy() performance.
> When these conditions are met on a system with 2 MiB huge pages, an
> aligned copy of 2 MiB would raise a single page fault instead of 4096.
>
> v2:
> - set ret to VM_FAULT_FALLBACK in default switch statement
> - ifdef out paddr declaration
>
> Signed-off-by: Loïc Molinari <loic.molinari@collabora.com>
> Reviewed-by: Boris Brezillon <boris.brezillon@collabora.com>
> Reported-by: kernel test robot <lkp@intel.com>
> Closes: https://lore.kernel.org/oe-kbuild-all/202509241315.8jjCyL7U-lkp@intel.com/
> Closes: https://lore.kernel.org/oe-kbuild-all/202509241654.qJk1H5kr-lkp@intel.com/
> Closes: https://lore.kernel.org/oe-kbuild-all/202509241920.PtSEkfd4-lkp@intel.com/
I'm not sure those Closes/Reported-by tags are needed when you fix bugs
introduced in a previous revisions of the patchset.
> ---
> drivers/gpu/drm/drm_gem_shmem_helper.c | 56 ++++++++++++++++++++++++--
> 1 file changed, 52 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/gpu/drm/drm_gem_shmem_helper.c b/drivers/gpu/drm/drm_gem_shmem_helper.c
> index 50594cf8e17c..22c4b09e10a3 100644
> --- a/drivers/gpu/drm/drm_gem_shmem_helper.c
> +++ b/drivers/gpu/drm/drm_gem_shmem_helper.c
> @@ -573,7 +573,8 @@ int drm_gem_shmem_dumb_create(struct drm_file *file, struct drm_device *dev,
> }
> EXPORT_SYMBOL_GPL(drm_gem_shmem_dumb_create);
>
> -static vm_fault_t drm_gem_shmem_fault(struct vm_fault *vmf)
> +static vm_fault_t drm_gem_shmem_huge_fault(struct vm_fault *vmf,
> + unsigned int order)
> {
> struct vm_area_struct *vma = vmf->vma;
> struct drm_gem_object *obj = vma->vm_private_data;
> @@ -582,6 +583,10 @@ static vm_fault_t drm_gem_shmem_fault(struct vm_fault *vmf)
> vm_fault_t ret;
> struct page *page;
> pgoff_t page_offset;
> + unsigned long pfn;
> +#if defined(CONFIG_ARCH_SUPPORTS_PMD_PFNMAP) || defined(CONFIG_ARCH_SUPPORTS_PUD_PFNMAP)
> + unsigned long paddr;
> +#endif
>
> /* We don't use vmf->pgoff since that has the fake offset */
> page_offset = (vmf->address - vma->vm_start) >> PAGE_SHIFT;
> @@ -592,17 +597,57 @@ static vm_fault_t drm_gem_shmem_fault(struct vm_fault *vmf)
> drm_WARN_ON_ONCE(obj->dev, !shmem->pages) ||
> shmem->madv < 0) {
> ret = VM_FAULT_SIGBUS;
> - } else {
> - page = shmem->pages[page_offset];
> + goto out;
> + }
>
> - ret = vmf_insert_pfn(vma, vmf->address, page_to_pfn(page));
> + page = shmem->pages[page_offset];
> + pfn = page_to_pfn(page);
> +
> + switch (order) {
> + case 0:
> + ret = vmf_insert_pfn(vma, vmf->address, pfn);
> + break;
> +
> +#ifdef CONFIG_ARCH_SUPPORTS_PMD_PFNMAP
> + case PMD_ORDER:
> + paddr = pfn << PAGE_SHIFT;
> + if (((vmf->address & ~PMD_MASK) == (paddr & ~PMD_MASK)) &&
> + (folio_order(page_folio(page)) == PMD_ORDER))
> + ret = vmf_insert_pfn_pmd(
> + vmf, pfn & (PMD_MASK >> PAGE_SHIFT), false);
> + else
> + ret = VM_FAULT_FALLBACK;
> + break;
> +#endif
> +
> +#ifdef CONFIG_ARCH_SUPPORTS_PUD_PFNMAP
> + case PUD_ORDER:
> + paddr = pfn << PAGE_SHIFT;
> + if (((vmf->address & ~PUD_MASK) == (paddr & ~PUD_MASK)) &&
> + (folio_order(page_folio(page)) == PUD_ORDER))
> + ret = vmf_insert_pfn_pud(
> + vmf, pfn & (PUD_MASK >> PAGE_SHIFT), false);
> + else
> + ret = VM_FAULT_FALLBACK;
> + break;
> +#endif
> +
> + default:
> + ret = VM_FAULT_FALLBACK;
> + break;
> }
>
> + out:
> dma_resv_unlock(shmem->base.resv);
>
> return ret;
> }
>
> +static vm_fault_t drm_gem_shmem_fault(struct vm_fault *vmf)
> +{
> + return drm_gem_shmem_huge_fault(vmf, 0);
> +}
> +
> static void drm_gem_shmem_vm_open(struct vm_area_struct *vma)
> {
> struct drm_gem_object *obj = vma->vm_private_data;
> @@ -639,6 +684,9 @@ static void drm_gem_shmem_vm_close(struct vm_area_struct *vma)
>
> const struct vm_operations_struct drm_gem_shmem_vm_ops = {
> .fault = drm_gem_shmem_fault,
> +#if defined(CONFIG_ARCH_SUPPORTS_PMD_PFNMAP) || defined(CONFIG_ARCH_SUPPORTS_PUD_PFNMAP)
> + .huge_fault = drm_gem_shmem_huge_fault,
> +#endif
> .open = drm_gem_shmem_vm_open,
> .close = drm_gem_shmem_vm_close,
> };
^ permalink raw reply [flat|nested] 26+ messages in thread* Re: [PATCH v3 01/10] drm/shmem-helper: Add huge page fault handler
2025-10-04 9:30 ` [PATCH v3 01/10] drm/shmem-helper: Add huge page fault handler Loïc Molinari
2025-10-04 22:53 ` Matthew Wilcox
2025-10-06 6:52 ` Boris Brezillon
@ 2025-10-06 16:01 ` Andi Shyti
2 siblings, 0 replies; 26+ messages in thread
From: Andi Shyti @ 2025-10-06 16:01 UTC (permalink / raw)
To: Loïc Molinari
Cc: Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann,
David Airlie, Simona Vetter, Jani Nikula, Joonas Lahtinen,
Rodrigo Vivi, Tvrtko Ursulin, Boris Brezillon, Rob Herring,
Steven Price, Liviu Dudau, Melissa Wen, Maíra Canal,
Hugh Dickins, Baolin Wang, Andrew Morton, Al Viro,
Mikołaj Wasiak, Christian Brauner, Nitin Gote, Andi Shyti,
Christopher Healy, linux-kernel, dri-devel, intel-gfx, linux-mm,
kernel, kernel test robot
Hi Loic,
...
> + unsigned int order)
> {
> struct vm_area_struct *vma = vmf->vma;
> struct drm_gem_object *obj = vma->vm_private_data;
> @@ -582,6 +583,10 @@ static vm_fault_t drm_gem_shmem_fault(struct vm_fault *vmf)
> vm_fault_t ret;
we could initialize ret to VM_FAULT_FALLBACK and avoid the else's
and the default case.
> struct page *page;
> pgoff_t page_offset;
> + unsigned long pfn;
> +#if defined(CONFIG_ARCH_SUPPORTS_PMD_PFNMAP) || defined(CONFIG_ARCH_SUPPORTS_PUD_PFNMAP)
> + unsigned long paddr;
> +#endif
we could declare paddr inside the switch case in order to avoid
some extra ifdefs.
> /* We don't use vmf->pgoff since that has the fake offset */
> page_offset = (vmf->address - vma->vm_start) >> PAGE_SHIFT;
> @@ -592,17 +597,57 @@ static vm_fault_t drm_gem_shmem_fault(struct vm_fault *vmf)
> drm_WARN_ON_ONCE(obj->dev, !shmem->pages) ||
> shmem->madv < 0) {
> ret = VM_FAULT_SIGBUS;
> - } else {
> - page = shmem->pages[page_offset];
> + goto out;
> + }
>
> - ret = vmf_insert_pfn(vma, vmf->address, page_to_pfn(page));
> + page = shmem->pages[page_offset];
> + pfn = page_to_pfn(page);
> +
> + switch (order) {
> + case 0:
'0' needs to be defined, what does '0' mean? (I know what it
means, but for consistency I think it should have its own name).
Andi
> + ret = vmf_insert_pfn(vma, vmf->address, pfn);
> + break;
^ permalink raw reply [flat|nested] 26+ messages in thread
* [PATCH v3 02/10] drm/gem: Introduce drm_gem_get_unmapped_area() fop
2025-10-04 9:30 [PATCH v3 00/10] drm: Reduce page tables overhead with THP Loïc Molinari
2025-10-04 9:30 ` [PATCH v3 01/10] drm/shmem-helper: Add huge page fault handler Loïc Molinari
@ 2025-10-04 9:30 ` Loïc Molinari
2025-10-10 7:48 ` kernel test robot
2025-10-04 9:30 ` [PATCH v3 03/10] drm/gem: Add huge tmpfs mount point helper Loïc Molinari
` (7 subsequent siblings)
9 siblings, 1 reply; 26+ messages in thread
From: Loïc Molinari @ 2025-10-04 9:30 UTC (permalink / raw)
To: Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann,
David Airlie, Simona Vetter, Jani Nikula, Joonas Lahtinen,
Rodrigo Vivi, Tvrtko Ursulin, Boris Brezillon, Rob Herring,
Steven Price, Liviu Dudau, Melissa Wen, Maíra Canal,
Hugh Dickins, Baolin Wang, Andrew Morton, Loïc Molinari,
Al Viro, Mikołaj Wasiak, Christian Brauner, Nitin Gote,
Andi Shyti, Christopher Healy
Cc: linux-kernel, dri-devel, intel-gfx, linux-mm, kernel
mmap() calls on the drm file pointer currently always end up using
mm_get_unmapped_area() to get a free mapping region. On builds with
CONFIG_TRANSPARENT_HUGEPAGE enabled, this isn't ideal for GEM objects
backed by shmem buffers on mount points setting the 'huge=' option
because it can't correctly figure out the potentially huge address
alignment required.
This commit introduces the drm_gem_get_unmapped_area() function which
is meant to be used as a get_unmapped_area file operation on the drm
file pointer to lookup GEM objects based on their fake offsets and get
a properly aligned region by calling shmem_get_unmapped_area() with
the right file pointer. If a GEM object isn't available at the given
offset or if the caller isn't granted access to it, the function falls
back to mm_get_unmapped_area().
This also makes drm_gem_get_unmapped_area() part of the default GEM
file operations so that all the drm drivers can benefit from more
efficient mappings thanks to the huge page fault handler introduced in
previous commit 'drm/shmem-helper: Add huge page fault handler'.
The shmem_get_unmapped_area() function needs to be exported so that
it can be used from the drm subsystem.
v3:
- add missing include: 'linux/sched/mm.h'
- forward to shmem layer in !CONFIG_TRANSPARENT_HUGEPAGE builds
Signed-off-by: Loïc Molinari <loic.molinari@collabora.com>
---
drivers/gpu/drm/drm_gem.c | 107 ++++++++++++++++++++++++++++++--------
include/drm/drm_gem.h | 4 ++
mm/shmem.c | 1 +
3 files changed, 90 insertions(+), 22 deletions(-)
diff --git a/drivers/gpu/drm/drm_gem.c b/drivers/gpu/drm/drm_gem.c
index cbeb76b2124f..f5a10ff363c9 100644
--- a/drivers/gpu/drm/drm_gem.c
+++ b/drivers/gpu/drm/drm_gem.c
@@ -36,6 +36,7 @@
#include <linux/module.h>
#include <linux/pagemap.h>
#include <linux/pagevec.h>
+#include <linux/sched/mm.h>
#include <linux/shmem_fs.h>
#include <linux/slab.h>
#include <linux/string_helpers.h>
@@ -1187,36 +1188,27 @@ int drm_gem_mmap_obj(struct drm_gem_object *obj, unsigned long obj_size,
}
EXPORT_SYMBOL(drm_gem_mmap_obj);
-/**
- * drm_gem_mmap - memory map routine for GEM objects
- * @filp: DRM file pointer
- * @vma: VMA for the area to be mapped
- *
- * If a driver supports GEM object mapping, mmap calls on the DRM file
- * descriptor will end up here.
- *
- * Look up the GEM object based on the offset passed in (vma->vm_pgoff will
- * contain the fake offset we created when the GTT map ioctl was called on
- * the object) and map it with a call to drm_gem_mmap_obj().
- *
- * If the caller is not granted access to the buffer object, the mmap will fail
- * with EACCES. Please see the vma manager for more information.
+/*
+ * Look up a GEM object in offset space based on the exact start address. The
+ * caller must be granted access to the object. Returns a GEM object on success
+ * or a negative error code on failure. The returned GEM object needs to be
+ * released with drm_gem_object_put().
*/
-int drm_gem_mmap(struct file *filp, struct vm_area_struct *vma)
+static struct drm_gem_object *
+drm_gem_object_lookup_from_offset(struct file *filp, unsigned long start,
+ unsigned long pages)
{
struct drm_file *priv = filp->private_data;
struct drm_device *dev = priv->minor->dev;
struct drm_gem_object *obj = NULL;
struct drm_vma_offset_node *node;
- int ret;
if (drm_dev_is_unplugged(dev))
- return -ENODEV;
+ return ERR_PTR(-ENODEV);
drm_vma_offset_lock_lookup(dev->vma_offset_manager);
node = drm_vma_offset_exact_lookup_locked(dev->vma_offset_manager,
- vma->vm_pgoff,
- vma_pages(vma));
+ start, pages);
if (likely(node)) {
obj = container_of(node, struct drm_gem_object, vma_node);
/*
@@ -1235,14 +1227,85 @@ int drm_gem_mmap(struct file *filp, struct vm_area_struct *vma)
drm_vma_offset_unlock_lookup(dev->vma_offset_manager);
if (!obj)
- return -EINVAL;
+ return ERR_PTR(-EINVAL);
if (!drm_vma_node_is_allowed(node, priv)) {
drm_gem_object_put(obj);
- return -EACCES;
+ return ERR_PTR(-EACCES);
}
- ret = drm_gem_mmap_obj(obj, drm_vma_node_size(node) << PAGE_SHIFT,
+ return obj;
+}
+
+/**
+ * drm_gem_get_unmapped_area - get memory mapping region routine for GEM objects
+ * @filp: DRM file pointer
+ * @uaddr: User address hint
+ * @len: Mapping length
+ * @pgoff: Offset (in pages)
+ * @flags: Mapping flags
+ *
+ * If a driver supports GEM object mapping, before ending up in drm_gem_mmap(),
+ * mmap calls on the DRM file descriptor will first try to find a free linear
+ * address space large enough for a mapping. Since GEM objects are backed by
+ * shmem buffers, this should preferably be handled by the shmem virtual memory
+ * filesystem which can appropriately align addresses to huge page sizes when
+ * needed.
+ *
+ * Look up the GEM object based on the offset passed in (vma->vm_pgoff will
+ * contain the fake offset we created) and call shmem_get_unmapped_area() with
+ * the right file pointer.
+ *
+ * If a GEM object is not available at the given offset or if the caller is not
+ * granted access to it, fall back to mm_get_unmapped_area().
+ */
+unsigned long drm_gem_get_unmapped_area(struct file *filp, unsigned long uaddr,
+ unsigned long len, unsigned long pgoff,
+ unsigned long flags)
+{
+ struct drm_gem_object *obj;
+ unsigned long ret;
+
+ obj = drm_gem_object_lookup_from_offset(filp, pgoff, len >> PAGE_SHIFT);
+ if (IS_ERR(obj))
+ return mm_get_unmapped_area(current->mm, filp, uaddr, len, 0,
+ flags);
+
+ ret = shmem_get_unmapped_area(obj->filp, uaddr, len, 0, flags);
+
+ drm_gem_object_put(obj);
+
+ return ret;
+}
+EXPORT_SYMBOL(drm_gem_get_unmapped_area);
+
+/**
+ * drm_gem_mmap - memory map routine for GEM objects
+ * @filp: DRM file pointer
+ * @vma: VMA for the area to be mapped
+ *
+ * If a driver supports GEM object mapping, mmap calls on the DRM file
+ * descriptor will end up here.
+ *
+ * Look up the GEM object based on the offset passed in (vma->vm_pgoff will
+ * contain the fake offset we created) and map it with a call to
+ * drm_gem_mmap_obj().
+ *
+ * If the caller is not granted access to the buffer object, the mmap will fail
+ * with EACCES. Please see the vma manager for more information.
+ */
+int drm_gem_mmap(struct file *filp, struct vm_area_struct *vma)
+{
+ struct drm_gem_object *obj;
+ int ret;
+
+ obj = drm_gem_object_lookup_from_offset(filp, vma->vm_pgoff,
+ vma_pages(vma));
+ if (IS_ERR(obj))
+ return PTR_ERR(obj);
+
+ ret = drm_gem_mmap_obj(obj,
+ drm_vma_node_size(&obj->vma_node) << PAGE_SHIFT,
vma);
drm_gem_object_put(obj);
diff --git a/include/drm/drm_gem.h b/include/drm/drm_gem.h
index 8d48d2af2649..7c8bd67d087c 100644
--- a/include/drm/drm_gem.h
+++ b/include/drm/drm_gem.h
@@ -469,6 +469,7 @@ struct drm_gem_object {
.poll = drm_poll,\
.read = drm_read,\
.llseek = noop_llseek,\
+ .get_unmapped_area = drm_gem_get_unmapped_area,\
.mmap = drm_gem_mmap, \
.fop_flags = FOP_UNSIGNED_OFFSET
@@ -506,6 +507,9 @@ void drm_gem_vm_close(struct vm_area_struct *vma);
int drm_gem_mmap_obj(struct drm_gem_object *obj, unsigned long obj_size,
struct vm_area_struct *vma);
int drm_gem_mmap(struct file *filp, struct vm_area_struct *vma);
+unsigned long drm_gem_get_unmapped_area(struct file *filp, unsigned long uaddr,
+ unsigned long len, unsigned long pgoff,
+ unsigned long flags);
/**
* drm_gem_object_get - acquire a GEM buffer object reference
diff --git a/mm/shmem.c b/mm/shmem.c
index e2c76a30802b..b2f41b430daa 100644
--- a/mm/shmem.c
+++ b/mm/shmem.c
@@ -2915,6 +2915,7 @@ unsigned long shmem_get_unmapped_area(struct file *file,
return addr;
return inflated_addr;
}
+EXPORT_SYMBOL_GPL(shmem_get_unmapped_area);
#ifdef CONFIG_NUMA
static int shmem_set_policy(struct vm_area_struct *vma, struct mempolicy *mpol)
--
2.47.3
^ permalink raw reply [flat|nested] 26+ messages in thread* Re: [PATCH v3 02/10] drm/gem: Introduce drm_gem_get_unmapped_area() fop
2025-10-04 9:30 ` [PATCH v3 02/10] drm/gem: Introduce drm_gem_get_unmapped_area() fop Loïc Molinari
@ 2025-10-10 7:48 ` kernel test robot
0 siblings, 0 replies; 26+ messages in thread
From: kernel test robot @ 2025-10-10 7:48 UTC (permalink / raw)
To: Loïc Molinari, Maarten Lankhorst, Maxime Ripard,
Thomas Zimmermann, David Airlie, Simona Vetter, Jani Nikula,
Joonas Lahtinen, Rodrigo Vivi, Tvrtko Ursulin, Boris Brezillon,
Rob Herring, Steven Price, Liviu Dudau, Melissa Wen,
Maíra Canal, Hugh Dickins, Baolin Wang, Andrew Morton,
Al Viro, Christian Brauner, Nitin Gote, Andi Shyti,
Christopher Healy
Cc: llvm, oe-kbuild-all, Linux Memory Management List, linux-kernel,
dri-devel, intel-gfx, kernel
Hi Loïc,
kernel test robot noticed the following build errors:
[auto build test ERROR on drm-misc/drm-misc-next]
[also build test ERROR on linus/master v6.17 next-20251009]
[cannot apply to akpm-mm/mm-everything]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]
url: https://github.com/intel-lab-lkp/linux/commits/Lo-c-Molinari/drm-shmem-helper-Add-huge-page-fault-handler/20251004-173347
base: git://anongit.freedesktop.org/drm/drm-misc drm-misc-next
patch link: https://lore.kernel.org/r/20251004093054.21388-3-loic.molinari%40collabora.com
patch subject: [PATCH v3 02/10] drm/gem: Introduce drm_gem_get_unmapped_area() fop
config: riscv-randconfig-001-20251010 (https://download.01.org/0day-ci/archive/20251010/202510101507.UiRzhiAP-lkp@intel.com/config)
compiler: clang version 22.0.0git (https://github.com/llvm/llvm-project 39f292ffa13d7ca0d1edff27ac8fd55024bb4d19)
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20251010/202510101507.UiRzhiAP-lkp@intel.com/reproduce)
If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202510101507.UiRzhiAP-lkp@intel.com/
All errors (new ones prefixed by >>):
In file included from drivers/gpu/drm/drm_gem.c:28:
In file included from include/linux/dma-buf.h:16:
In file included from include/linux/iosys-map.h:10:
In file included from include/linux/io.h:12:
In file included from arch/riscv/include/asm/io.h:136:
include/asm-generic/io.h:804:2: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
804 | insb(addr, buffer, count);
| ^~~~~~~~~~~~~~~~~~~~~~~~~
arch/riscv/include/asm/io.h:104:53: note: expanded from macro 'insb'
104 | #define insb(addr, buffer, count) __insb(PCI_IOBASE + (addr), buffer, count)
| ~~~~~~~~~~ ^
In file included from drivers/gpu/drm/drm_gem.c:28:
In file included from include/linux/dma-buf.h:16:
In file included from include/linux/iosys-map.h:10:
In file included from include/linux/io.h:12:
In file included from arch/riscv/include/asm/io.h:136:
include/asm-generic/io.h:812:2: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
812 | insw(addr, buffer, count);
| ^~~~~~~~~~~~~~~~~~~~~~~~~
arch/riscv/include/asm/io.h:105:53: note: expanded from macro 'insw'
105 | #define insw(addr, buffer, count) __insw(PCI_IOBASE + (addr), buffer, count)
| ~~~~~~~~~~ ^
In file included from drivers/gpu/drm/drm_gem.c:28:
In file included from include/linux/dma-buf.h:16:
In file included from include/linux/iosys-map.h:10:
In file included from include/linux/io.h:12:
In file included from arch/riscv/include/asm/io.h:136:
include/asm-generic/io.h:820:2: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
820 | insl(addr, buffer, count);
| ^~~~~~~~~~~~~~~~~~~~~~~~~
arch/riscv/include/asm/io.h:106:53: note: expanded from macro 'insl'
106 | #define insl(addr, buffer, count) __insl(PCI_IOBASE + (addr), buffer, count)
| ~~~~~~~~~~ ^
In file included from drivers/gpu/drm/drm_gem.c:28:
In file included from include/linux/dma-buf.h:16:
In file included from include/linux/iosys-map.h:10:
In file included from include/linux/io.h:12:
In file included from arch/riscv/include/asm/io.h:136:
include/asm-generic/io.h:829:2: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
829 | outsb(addr, buffer, count);
| ^~~~~~~~~~~~~~~~~~~~~~~~~~
arch/riscv/include/asm/io.h:118:55: note: expanded from macro 'outsb'
118 | #define outsb(addr, buffer, count) __outsb(PCI_IOBASE + (addr), buffer, count)
| ~~~~~~~~~~ ^
In file included from drivers/gpu/drm/drm_gem.c:28:
In file included from include/linux/dma-buf.h:16:
In file included from include/linux/iosys-map.h:10:
In file included from include/linux/io.h:12:
In file included from arch/riscv/include/asm/io.h:136:
include/asm-generic/io.h:838:2: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
838 | outsw(addr, buffer, count);
| ^~~~~~~~~~~~~~~~~~~~~~~~~~
arch/riscv/include/asm/io.h:119:55: note: expanded from macro 'outsw'
119 | #define outsw(addr, buffer, count) __outsw(PCI_IOBASE + (addr), buffer, count)
| ~~~~~~~~~~ ^
In file included from drivers/gpu/drm/drm_gem.c:28:
In file included from include/linux/dma-buf.h:16:
In file included from include/linux/iosys-map.h:10:
In file included from include/linux/io.h:12:
In file included from arch/riscv/include/asm/io.h:136:
include/asm-generic/io.h:847:2: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
847 | outsl(addr, buffer, count);
| ^~~~~~~~~~~~~~~~~~~~~~~~~~
arch/riscv/include/asm/io.h:120:55: note: expanded from macro 'outsl'
120 | #define outsl(addr, buffer, count) __outsl(PCI_IOBASE + (addr), buffer, count)
| ~~~~~~~~~~ ^
In file included from drivers/gpu/drm/drm_gem.c:28:
In file included from include/linux/dma-buf.h:16:
In file included from include/linux/iosys-map.h:10:
In file included from include/linux/io.h:12:
In file included from arch/riscv/include/asm/io.h:136:
include/asm-generic/io.h:1175:55: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
1175 | return (port > MMIO_UPPER_LIMIT) ? NULL : PCI_IOBASE + port;
| ~~~~~~~~~~ ^
>> drivers/gpu/drm/drm_gem.c:1271:10: error: call to undeclared function 'mm_get_unmapped_area'; ISO C99 and later do not support implicit function declarations [-Wimplicit-function-declaration]
1271 | return mm_get_unmapped_area(current->mm, filp, uaddr, len, 0,
| ^
drivers/gpu/drm/drm_gem.c:1271:10: note: did you mean '__get_unmapped_area'?
include/linux/mm.h:3337:1: note: '__get_unmapped_area' declared here
3337 | __get_unmapped_area(struct file *file, unsigned long addr, unsigned long len,
| ^
7 warnings and 1 error generated.
vim +/mm_get_unmapped_area +1271 drivers/gpu/drm/drm_gem.c
1239
1240 /**
1241 * drm_gem_get_unmapped_area - get memory mapping region routine for GEM objects
1242 * @filp: DRM file pointer
1243 * @uaddr: User address hint
1244 * @len: Mapping length
1245 * @pgoff: Offset (in pages)
1246 * @flags: Mapping flags
1247 *
1248 * If a driver supports GEM object mapping, before ending up in drm_gem_mmap(),
1249 * mmap calls on the DRM file descriptor will first try to find a free linear
1250 * address space large enough for a mapping. Since GEM objects are backed by
1251 * shmem buffers, this should preferably be handled by the shmem virtual memory
1252 * filesystem which can appropriately align addresses to huge page sizes when
1253 * needed.
1254 *
1255 * Look up the GEM object based on the offset passed in (vma->vm_pgoff will
1256 * contain the fake offset we created) and call shmem_get_unmapped_area() with
1257 * the right file pointer.
1258 *
1259 * If a GEM object is not available at the given offset or if the caller is not
1260 * granted access to it, fall back to mm_get_unmapped_area().
1261 */
1262 unsigned long drm_gem_get_unmapped_area(struct file *filp, unsigned long uaddr,
1263 unsigned long len, unsigned long pgoff,
1264 unsigned long flags)
1265 {
1266 struct drm_gem_object *obj;
1267 unsigned long ret;
1268
1269 obj = drm_gem_object_lookup_from_offset(filp, pgoff, len >> PAGE_SHIFT);
1270 if (IS_ERR(obj))
> 1271 return mm_get_unmapped_area(current->mm, filp, uaddr, len, 0,
1272 flags);
1273
1274 ret = shmem_get_unmapped_area(obj->filp, uaddr, len, 0, flags);
1275
1276 drm_gem_object_put(obj);
1277
1278 return ret;
1279 }
1280 EXPORT_SYMBOL(drm_gem_get_unmapped_area);
1281
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
^ permalink raw reply [flat|nested] 26+ messages in thread
* [PATCH v3 03/10] drm/gem: Add huge tmpfs mount point helper
2025-10-04 9:30 [PATCH v3 00/10] drm: Reduce page tables overhead with THP Loïc Molinari
2025-10-04 9:30 ` [PATCH v3 01/10] drm/shmem-helper: Add huge page fault handler Loïc Molinari
2025-10-04 9:30 ` [PATCH v3 02/10] drm/gem: Introduce drm_gem_get_unmapped_area() fop Loïc Molinari
@ 2025-10-04 9:30 ` Loïc Molinari
2025-10-04 20:34 ` Al Viro
` (2 more replies)
2025-10-04 9:30 ` [PATCH v3 04/10] drm/i915: Use " Loïc Molinari
` (6 subsequent siblings)
9 siblings, 3 replies; 26+ messages in thread
From: Loïc Molinari @ 2025-10-04 9:30 UTC (permalink / raw)
To: Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann,
David Airlie, Simona Vetter, Jani Nikula, Joonas Lahtinen,
Rodrigo Vivi, Tvrtko Ursulin, Boris Brezillon, Rob Herring,
Steven Price, Liviu Dudau, Melissa Wen, Maíra Canal,
Hugh Dickins, Baolin Wang, Andrew Morton, Loïc Molinari,
Al Viro, Mikołaj Wasiak, Christian Brauner, Nitin Gote,
Andi Shyti, Christopher Healy
Cc: linux-kernel, dri-devel, intel-gfx, linux-mm, kernel
Add the drm_gem_huge_mnt_create() helper to avoid code duplication in
the i915, V3D, Panfrost and Panthor drivers. It creates and mounts a
dedicated huge tmpfs mountpoint, for the lifetime of a drm device,
used at GEM object initialization.
The next commits will port drivers to this helper.
v3:
- store huge tmpfs mountpoint in drm_device
Signed-off-by: Loïc Molinari <loic.molinari@collabora.com>
---
drivers/gpu/drm/drm_gem.c | 67 +++++++++++++++++++++++++++++++++++++++
include/drm/drm_device.h | 11 +++++++
include/drm/drm_gem.h | 1 +
3 files changed, 79 insertions(+)
diff --git a/drivers/gpu/drm/drm_gem.c b/drivers/gpu/drm/drm_gem.c
index f5a10ff363c9..b4e4947210ef 100644
--- a/drivers/gpu/drm/drm_gem.c
+++ b/drivers/gpu/drm/drm_gem.c
@@ -29,6 +29,7 @@
#include <linux/export.h>
#include <linux/file.h>
#include <linux/fs.h>
+#include <linux/fs_context.h>
#include <linux/iosys-map.h>
#include <linux/mem_encrypt.h>
#include <linux/mm.h>
@@ -82,6 +83,72 @@
* up at a later date, and as our interface with shmfs for memory allocation.
*/
+static int drm_gem_add_fc_param(struct fs_context *fc, const char *key,
+ const char *value)
+{
+ return vfs_parse_fs_string(fc, key, value, strlen(value));
+}
+
+static void drm_gem_huge_mnt_free(struct drm_device *dev, void *data)
+{
+ drm_WARN_ON(dev, dev->huge_mnt == NULL);
+
+ kern_unmount(dev->huge_mnt);
+ dev->huge_mnt = NULL;
+}
+
+/**
+ * drm_gem_huge_mnt_create - Create, mount and use a huge tmpfs mountpoint
+ * @dev: drm_device a huge tmpfs mountpoint should be used with
+ * @value: huge tmpfs mount option value
+ *
+ * This function creates and mounts a dedicated huge tmpfs mountpoint for the
+ * lifetime of the drm device @dev which is used at GEM object initialization
+ * with drm_gem_object_init().
+ *
+ * The most common option value @value is "within_size" which only allocates
+ * huge pages if the page will be fully within the GEM object size. "always",
+ * "advise" and "never" are supported too but the latter would just create a
+ * mountpoint similar to the default one (`shm_mnt`). See shmemfs and
+ * Transparent Hugepage for more information.
+ *
+ * Returns:
+ * 0 on success or a negative error code on failure. Returns -EEXIST if called
+ * more than once for the lifetime of the drm device.
+ */
+int drm_gem_huge_mnt_create(struct drm_device *dev, const char *value)
+{
+ struct file_system_type *type;
+ struct fs_context *fc;
+ int ret;
+
+ if (!IS_ENABLED(CONFIG_TRANSPARENT_HUGEPAGE))
+ return -EOPNOTSUPP;
+
+ type = get_fs_type("tmpfs");
+ if (unlikely(!type))
+ return -EOPNOTSUPP;
+
+ if (unlikely(dev->huge_mnt))
+ return -EEXIST;
+
+ fc = fs_context_for_mount(type, SB_KERNMOUNT);
+ if (IS_ERR(fc))
+ return PTR_ERR(fc);
+ ret = drm_gem_add_fc_param(fc, "source", "tmpfs");
+ if (unlikely(ret))
+ return -ENOPARAM;
+ ret = drm_gem_add_fc_param(fc, "huge", value);
+ if (unlikely(ret))
+ return -ENOPARAM;
+
+ dev->huge_mnt = fc_mount_longterm(fc);
+ put_fs_context(fc);
+
+ return drmm_add_action_or_reset(dev, drm_gem_huge_mnt_free, NULL);
+}
+EXPORT_SYMBOL_GPL(drm_gem_huge_mnt_create);
+
static void
drm_gem_init_release(struct drm_device *dev, void *ptr)
{
diff --git a/include/drm/drm_device.h b/include/drm/drm_device.h
index 59fd3f4d5995..895b0ced972e 100644
--- a/include/drm/drm_device.h
+++ b/include/drm/drm_device.h
@@ -3,6 +3,7 @@
#include <linux/list.h>
#include <linux/kref.h>
+#include <linux/mount.h>
#include <linux/mutex.h>
#include <linux/idr.h>
#include <linux/sched.h>
@@ -168,6 +169,16 @@ struct drm_device {
*/
struct drm_master *master;
+ /**
+ * @huge_mnt:
+ *
+ * Huge tmpfs mountpoint used at GEM object initialization
+ * drm_gem_object_init(). Drivers can call drm_gem_huge_mnt_create() to
+ * create a huge tmfps mountpoint. The default tmpfs mountpoint
+ * (`shm_mnt`) is used if NULL.
+ */
+ struct vfsmount *huge_mnt;
+
/**
* @driver_features: per-device driver features
*
diff --git a/include/drm/drm_gem.h b/include/drm/drm_gem.h
index 7c8bd67d087c..7285a62d9afc 100644
--- a/include/drm/drm_gem.h
+++ b/include/drm/drm_gem.h
@@ -492,6 +492,7 @@ struct drm_gem_object {
DRM_GEM_FOPS,\
}
+int drm_gem_huge_mnt_create(struct drm_device *dev, const char *value);
void drm_gem_object_release(struct drm_gem_object *obj);
void drm_gem_object_free(struct kref *kref);
int drm_gem_object_init(struct drm_device *dev,
--
2.47.3
^ permalink raw reply [flat|nested] 26+ messages in thread* Re: [PATCH v3 03/10] drm/gem: Add huge tmpfs mount point helper
2025-10-04 9:30 ` [PATCH v3 03/10] drm/gem: Add huge tmpfs mount point helper Loïc Molinari
@ 2025-10-04 20:34 ` Al Viro
2025-10-06 6:58 ` Boris Brezillon
2025-10-06 7:02 ` Boris Brezillon
2 siblings, 0 replies; 26+ messages in thread
From: Al Viro @ 2025-10-04 20:34 UTC (permalink / raw)
To: Loïc Molinari
Cc: Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann,
David Airlie, Simona Vetter, Jani Nikula, Joonas Lahtinen,
Rodrigo Vivi, Tvrtko Ursulin, Boris Brezillon, Rob Herring,
Steven Price, Liviu Dudau, Melissa Wen, Maíra Canal,
Hugh Dickins, Baolin Wang, Andrew Morton, Mikołaj Wasiak,
Christian Brauner, Nitin Gote, Andi Shyti, Christopher Healy,
linux-kernel, dri-devel, intel-gfx, linux-mm, kernel
On Sat, Oct 04, 2025 at 11:30:46AM +0200, Loïc Molinari wrote:
> +static int drm_gem_add_fc_param(struct fs_context *fc, const char *key,
> + const char *value)
> +{
> + return vfs_parse_fs_string(fc, key, value, strlen(value));
> +}
Documentation/filesystems/porting.rst:
**mandatory**
Calling conventions for vfs_parse_fs_string() have changed; it does *not*
take length anymore (value ? strlen(value) : 0 is used). If you want
a different length, use
vfs_parse_fs_qstr(fc, key, &QSTR_LEN(value, len))
instead.
IOW, your drm_gem_add_fc_param(fc, key, value) is an exact equivalent
of vfs_parse_fs_string(fc, key, value) now.
^ permalink raw reply [flat|nested] 26+ messages in thread* Re: [PATCH v3 03/10] drm/gem: Add huge tmpfs mount point helper
2025-10-04 9:30 ` [PATCH v3 03/10] drm/gem: Add huge tmpfs mount point helper Loïc Molinari
2025-10-04 20:34 ` Al Viro
@ 2025-10-06 6:58 ` Boris Brezillon
2025-10-06 7:02 ` Boris Brezillon
2 siblings, 0 replies; 26+ messages in thread
From: Boris Brezillon @ 2025-10-06 6:58 UTC (permalink / raw)
To: Loïc Molinari
Cc: Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann,
David Airlie, Simona Vetter, Jani Nikula, Joonas Lahtinen,
Rodrigo Vivi, Tvrtko Ursulin, Rob Herring, Steven Price,
Liviu Dudau, Melissa Wen, Maíra Canal, Hugh Dickins,
Baolin Wang, Andrew Morton, Al Viro, Mikołaj Wasiak,
Christian Brauner, Nitin Gote, Andi Shyti, Christopher Healy,
linux-kernel, dri-devel, intel-gfx, linux-mm, kernel
On Sat, 4 Oct 2025 11:30:46 +0200
Loïc Molinari <loic.molinari@collabora.com> wrote:
> Add the drm_gem_huge_mnt_create() helper to avoid code duplication in
> the i915, V3D, Panfrost and Panthor drivers. It creates and mounts a
> dedicated huge tmpfs mountpoint, for the lifetime of a drm device,
> used at GEM object initialization.
>
> The next commits will port drivers to this helper.
>
> v3:
> - store huge tmpfs mountpoint in drm_device
>
> Signed-off-by: Loïc Molinari <loic.molinari@collabora.com>
> ---
> drivers/gpu/drm/drm_gem.c | 67 +++++++++++++++++++++++++++++++++++++++
> include/drm/drm_device.h | 11 +++++++
> include/drm/drm_gem.h | 1 +
> 3 files changed, 79 insertions(+)
>
> diff --git a/drivers/gpu/drm/drm_gem.c b/drivers/gpu/drm/drm_gem.c
> index f5a10ff363c9..b4e4947210ef 100644
> --- a/drivers/gpu/drm/drm_gem.c
> +++ b/drivers/gpu/drm/drm_gem.c
> @@ -29,6 +29,7 @@
> #include <linux/export.h>
> #include <linux/file.h>
> #include <linux/fs.h>
> +#include <linux/fs_context.h>
> #include <linux/iosys-map.h>
> #include <linux/mem_encrypt.h>
> #include <linux/mm.h>
> @@ -82,6 +83,72 @@
> * up at a later date, and as our interface with shmfs for memory allocation.
> */
>
> +static int drm_gem_add_fc_param(struct fs_context *fc, const char *key,
> + const char *value)
> +{
> + return vfs_parse_fs_string(fc, key, value, strlen(value));
> +}
> +
> +static void drm_gem_huge_mnt_free(struct drm_device *dev, void *data)
> +{
> + drm_WARN_ON(dev, dev->huge_mnt == NULL);
> +
> + kern_unmount(dev->huge_mnt);
> + dev->huge_mnt = NULL;
> +}
> +
> +/**
> + * drm_gem_huge_mnt_create - Create, mount and use a huge tmpfs mountpoint
> + * @dev: drm_device a huge tmpfs mountpoint should be used with
> + * @value: huge tmpfs mount option value
> + *
> + * This function creates and mounts a dedicated huge tmpfs mountpoint for the
> + * lifetime of the drm device @dev which is used at GEM object initialization
> + * with drm_gem_object_init().
> + *
> + * The most common option value @value is "within_size" which only allocates
> + * huge pages if the page will be fully within the GEM object size. "always",
> + * "advise" and "never" are supported too but the latter would just create a
> + * mountpoint similar to the default one (`shm_mnt`). See shmemfs and
> + * Transparent Hugepage for more information.
> + *
> + * Returns:
> + * 0 on success or a negative error code on failure. Returns -EEXIST if called
> + * more than once for the lifetime of the drm device.
> + */
> +int drm_gem_huge_mnt_create(struct drm_device *dev, const char *value)
> +{
> + struct file_system_type *type;
> + struct fs_context *fc;
> + int ret;
> +
> + if (!IS_ENABLED(CONFIG_TRANSPARENT_HUGEPAGE))
> + return -EOPNOTSUPP;
If we return 0 here, we can get rid of the
if (IS_ENABLED(CONFIG_TRANSPARENT_HUGEPAGE))
tests in all the drivers and let them call drm_gem_huge_mnt_create()
unconditionally.
> +
> + type = get_fs_type("tmpfs");
> + if (unlikely(!type))
> + return -EOPNOTSUPP;
> +
> + if (unlikely(dev->huge_mnt))
> + return -EEXIST;
> +
> + fc = fs_context_for_mount(type, SB_KERNMOUNT);
> + if (IS_ERR(fc))
> + return PTR_ERR(fc);
> + ret = drm_gem_add_fc_param(fc, "source", "tmpfs");
> + if (unlikely(ret))
> + return -ENOPARAM;
> + ret = drm_gem_add_fc_param(fc, "huge", value);
> + if (unlikely(ret))
> + return -ENOPARAM;
> +
> + dev->huge_mnt = fc_mount_longterm(fc);
> + put_fs_context(fc);
> +
> + return drmm_add_action_or_reset(dev, drm_gem_huge_mnt_free, NULL);
> +}
> +EXPORT_SYMBOL_GPL(drm_gem_huge_mnt_create);
> +
> static void
> drm_gem_init_release(struct drm_device *dev, void *ptr)
> {
> diff --git a/include/drm/drm_device.h b/include/drm/drm_device.h
> index 59fd3f4d5995..895b0ced972e 100644
> --- a/include/drm/drm_device.h
> +++ b/include/drm/drm_device.h
> @@ -3,6 +3,7 @@
>
> #include <linux/list.h>
> #include <linux/kref.h>
> +#include <linux/mount.h>
> #include <linux/mutex.h>
> #include <linux/idr.h>
> #include <linux/sched.h>
> @@ -168,6 +169,16 @@ struct drm_device {
> */
> struct drm_master *master;
>
> + /**
> + * @huge_mnt:
> + *
> + * Huge tmpfs mountpoint used at GEM object initialization
> + * drm_gem_object_init(). Drivers can call drm_gem_huge_mnt_create() to
> + * create a huge tmfps mountpoint. The default tmpfs mountpoint
> + * (`shm_mnt`) is used if NULL.
> + */
> + struct vfsmount *huge_mnt;
> +
> /**
> * @driver_features: per-device driver features
> *
> diff --git a/include/drm/drm_gem.h b/include/drm/drm_gem.h
> index 7c8bd67d087c..7285a62d9afc 100644
> --- a/include/drm/drm_gem.h
> +++ b/include/drm/drm_gem.h
> @@ -492,6 +492,7 @@ struct drm_gem_object {
> DRM_GEM_FOPS,\
> }
>
> +int drm_gem_huge_mnt_create(struct drm_device *dev, const char *value);
> void drm_gem_object_release(struct drm_gem_object *obj);
> void drm_gem_object_free(struct kref *kref);
> int drm_gem_object_init(struct drm_device *dev,
^ permalink raw reply [flat|nested] 26+ messages in thread* Re: [PATCH v3 03/10] drm/gem: Add huge tmpfs mount point helper
2025-10-04 9:30 ` [PATCH v3 03/10] drm/gem: Add huge tmpfs mount point helper Loïc Molinari
2025-10-04 20:34 ` Al Viro
2025-10-06 6:58 ` Boris Brezillon
@ 2025-10-06 7:02 ` Boris Brezillon
2 siblings, 0 replies; 26+ messages in thread
From: Boris Brezillon @ 2025-10-06 7:02 UTC (permalink / raw)
To: Loïc Molinari
Cc: Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann,
David Airlie, Simona Vetter, Jani Nikula, Joonas Lahtinen,
Rodrigo Vivi, Tvrtko Ursulin, Rob Herring, Steven Price,
Liviu Dudau, Melissa Wen, Maíra Canal, Hugh Dickins,
Baolin Wang, Andrew Morton, Al Viro, Mikołaj Wasiak,
Christian Brauner, Nitin Gote, Andi Shyti, Christopher Healy,
linux-kernel, dri-devel, intel-gfx, linux-mm, kernel
On Sat, 4 Oct 2025 11:30:46 +0200
Loïc Molinari <loic.molinari@collabora.com> wrote:
> Add the drm_gem_huge_mnt_create() helper to avoid code duplication in
> the i915, V3D, Panfrost and Panthor drivers. It creates and mounts a
> dedicated huge tmpfs mountpoint, for the lifetime of a drm device,
> used at GEM object initialization.
>
> The next commits will port drivers to this helper.
>
> v3:
> - store huge tmpfs mountpoint in drm_device
>
> Signed-off-by: Loïc Molinari <loic.molinari@collabora.com>
> ---
> drivers/gpu/drm/drm_gem.c | 67 +++++++++++++++++++++++++++++++++++++++
> include/drm/drm_device.h | 11 +++++++
> include/drm/drm_gem.h | 1 +
> 3 files changed, 79 insertions(+)
>
> diff --git a/drivers/gpu/drm/drm_gem.c b/drivers/gpu/drm/drm_gem.c
> index f5a10ff363c9..b4e4947210ef 100644
> --- a/drivers/gpu/drm/drm_gem.c
> +++ b/drivers/gpu/drm/drm_gem.c
> @@ -29,6 +29,7 @@
> #include <linux/export.h>
> #include <linux/file.h>
> #include <linux/fs.h>
> +#include <linux/fs_context.h>
> #include <linux/iosys-map.h>
> #include <linux/mem_encrypt.h>
> #include <linux/mm.h>
> @@ -82,6 +83,72 @@
> * up at a later date, and as our interface with shmfs for memory allocation.
> */
>
> +static int drm_gem_add_fc_param(struct fs_context *fc, const char *key,
> + const char *value)
> +{
> + return vfs_parse_fs_string(fc, key, value, strlen(value));
> +}
> +
> +static void drm_gem_huge_mnt_free(struct drm_device *dev, void *data)
> +{
> + drm_WARN_ON(dev, dev->huge_mnt == NULL);
> +
> + kern_unmount(dev->huge_mnt);
> + dev->huge_mnt = NULL;
> +}
> +
> +/**
> + * drm_gem_huge_mnt_create - Create, mount and use a huge tmpfs mountpoint
> + * @dev: drm_device a huge tmpfs mountpoint should be used with
> + * @value: huge tmpfs mount option value
> + *
> + * This function creates and mounts a dedicated huge tmpfs mountpoint for the
> + * lifetime of the drm device @dev which is used at GEM object initialization
> + * with drm_gem_object_init().
> + *
> + * The most common option value @value is "within_size" which only allocates
> + * huge pages if the page will be fully within the GEM object size. "always",
> + * "advise" and "never" are supported too but the latter would just create a
> + * mountpoint similar to the default one (`shm_mnt`). See shmemfs and
> + * Transparent Hugepage for more information.
> + *
> + * Returns:
> + * 0 on success or a negative error code on failure. Returns -EEXIST if called
> + * more than once for the lifetime of the drm device.
> + */
> +int drm_gem_huge_mnt_create(struct drm_device *dev, const char *value)
> +{
> + struct file_system_type *type;
> + struct fs_context *fc;
> + int ret;
> +
> + if (!IS_ENABLED(CONFIG_TRANSPARENT_HUGEPAGE))
> + return -EOPNOTSUPP;
> +
> + type = get_fs_type("tmpfs");
> + if (unlikely(!type))
> + return -EOPNOTSUPP;
> +
> + if (unlikely(dev->huge_mnt))
> + return -EEXIST;
Do we even care about reporting an error when the huge mount point
already exists? Can we just return 0 in that case, which simplifies the
call sites since they don't have to check for EEXIST anymore.
> +
> + fc = fs_context_for_mount(type, SB_KERNMOUNT);
> + if (IS_ERR(fc))
> + return PTR_ERR(fc);
> + ret = drm_gem_add_fc_param(fc, "source", "tmpfs");
> + if (unlikely(ret))
> + return -ENOPARAM;
> + ret = drm_gem_add_fc_param(fc, "huge", value);
> + if (unlikely(ret))
> + return -ENOPARAM;
> +
> + dev->huge_mnt = fc_mount_longterm(fc);
> + put_fs_context(fc);
> +
> + return drmm_add_action_or_reset(dev, drm_gem_huge_mnt_free, NULL);
> +}
> +EXPORT_SYMBOL_GPL(drm_gem_huge_mnt_create);
> +
> static void
> drm_gem_init_release(struct drm_device *dev, void *ptr)
> {
> diff --git a/include/drm/drm_device.h b/include/drm/drm_device.h
> index 59fd3f4d5995..895b0ced972e 100644
> --- a/include/drm/drm_device.h
> +++ b/include/drm/drm_device.h
> @@ -3,6 +3,7 @@
>
> #include <linux/list.h>
> #include <linux/kref.h>
> +#include <linux/mount.h>
> #include <linux/mutex.h>
> #include <linux/idr.h>
> #include <linux/sched.h>
> @@ -168,6 +169,16 @@ struct drm_device {
> */
> struct drm_master *master;
>
> + /**
> + * @huge_mnt:
> + *
> + * Huge tmpfs mountpoint used at GEM object initialization
> + * drm_gem_object_init(). Drivers can call drm_gem_huge_mnt_create() to
> + * create a huge tmfps mountpoint. The default tmpfs mountpoint
> + * (`shm_mnt`) is used if NULL.
> + */
> + struct vfsmount *huge_mnt;
> +
> /**
> * @driver_features: per-device driver features
> *
> diff --git a/include/drm/drm_gem.h b/include/drm/drm_gem.h
> index 7c8bd67d087c..7285a62d9afc 100644
> --- a/include/drm/drm_gem.h
> +++ b/include/drm/drm_gem.h
> @@ -492,6 +492,7 @@ struct drm_gem_object {
> DRM_GEM_FOPS,\
> }
>
> +int drm_gem_huge_mnt_create(struct drm_device *dev, const char *value);
> void drm_gem_object_release(struct drm_gem_object *obj);
> void drm_gem_object_free(struct kref *kref);
> int drm_gem_object_init(struct drm_device *dev,
^ permalink raw reply [flat|nested] 26+ messages in thread
* [PATCH v3 04/10] drm/i915: Use huge tmpfs mount point helper
2025-10-04 9:30 [PATCH v3 00/10] drm: Reduce page tables overhead with THP Loïc Molinari
` (2 preceding siblings ...)
2025-10-04 9:30 ` [PATCH v3 03/10] drm/gem: Add huge tmpfs mount point helper Loïc Molinari
@ 2025-10-04 9:30 ` Loïc Molinari
2025-10-04 9:30 ` [PATCH v3 05/10] drm/v3d: " Loïc Molinari
` (5 subsequent siblings)
9 siblings, 0 replies; 26+ messages in thread
From: Loïc Molinari @ 2025-10-04 9:30 UTC (permalink / raw)
To: Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann,
David Airlie, Simona Vetter, Jani Nikula, Joonas Lahtinen,
Rodrigo Vivi, Tvrtko Ursulin, Boris Brezillon, Rob Herring,
Steven Price, Liviu Dudau, Melissa Wen, Maíra Canal,
Hugh Dickins, Baolin Wang, Andrew Morton, Loïc Molinari,
Al Viro, Mikołaj Wasiak, Christian Brauner, Nitin Gote,
Andi Shyti, Christopher Healy
Cc: linux-kernel, dri-devel, intel-gfx, linux-mm, kernel
Make use of the new drm_gem_huge_mnt_create() helper to avoid code
duplication. Now that it's just a few lines long, the single function
in i915_gemfs.c is moved into v3d_gem_shmem.c.
v3:
- use huge tmpfs mountpoint in drm_device
- move i915_gemfs.c into i915_gem_shmem.c
Signed-off-by: Loïc Molinari <loic.molinari@collabora.com>
---
drivers/gpu/drm/i915/Makefile | 3 +-
drivers/gpu/drm/i915/gem/i915_gem_shmem.c | 52 +++++++++----
drivers/gpu/drm/i915/gem/i915_gemfs.c | 74 -------------------
drivers/gpu/drm/i915/gem/i915_gemfs.h | 14 ----
.../gpu/drm/i915/gem/selftests/huge_pages.c | 10 +--
drivers/gpu/drm/i915/i915_drv.h | 5 --
6 files changed, 45 insertions(+), 113 deletions(-)
delete mode 100644 drivers/gpu/drm/i915/gem/i915_gemfs.c
delete mode 100644 drivers/gpu/drm/i915/gem/i915_gemfs.h
diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile
index 853543443072..716291c3dcd3 100644
--- a/drivers/gpu/drm/i915/Makefile
+++ b/drivers/gpu/drm/i915/Makefile
@@ -162,8 +162,7 @@ gem-y += \
gem/i915_gem_ttm_move.o \
gem/i915_gem_ttm_pm.o \
gem/i915_gem_userptr.o \
- gem/i915_gem_wait.o \
- gem/i915_gemfs.o
+ gem/i915_gem_wait.o
i915-y += \
$(gem-y) \
i915_active.o \
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_shmem.c b/drivers/gpu/drm/i915/gem/i915_gem_shmem.c
index e3d188455f67..3344d6f5846e 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_shmem.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_shmem.c
@@ -9,14 +9,15 @@
#include <linux/uio.h>
#include <drm/drm_cache.h>
+#include <drm/drm_gem.h>
#include "gem/i915_gem_region.h"
#include "i915_drv.h"
#include "i915_gem_object.h"
#include "i915_gem_tiling.h"
-#include "i915_gemfs.h"
#include "i915_scatterlist.h"
#include "i915_trace.h"
+#include "i915_utils.h"
/*
* Move folios to appropriate lru and release the batch, decrementing the
@@ -506,9 +507,9 @@ static int __create_shmem(struct drm_i915_private *i915,
if (BITS_PER_LONG == 64 && size > MAX_LFS_FILESIZE)
return -E2BIG;
- if (i915->mm.gemfs)
- filp = shmem_file_setup_with_mnt(i915->mm.gemfs, "i915", size,
- flags);
+ if (i915->drm.huge_mnt)
+ filp = shmem_file_setup_with_mnt(i915->drm.huge_mnt, "i915",
+ size, flags);
else
filp = shmem_file_setup("i915", size, flags);
if (IS_ERR(filp))
@@ -628,21 +629,46 @@ i915_gem_object_create_shmem_from_data(struct drm_i915_private *i915,
static int init_shmem(struct intel_memory_region *mem)
{
- i915_gemfs_init(mem->i915);
- intel_memory_region_set_name(mem, "system");
+ struct drm_i915_private *i915 = mem->i915;
+ int err;
- return 0; /* We have fallback to the kernel mnt if gemfs init failed. */
-}
+ /*
+ * By creating our own shmemfs mountpoint, we can pass in
+ * mount flags that better match our usecase.
+ *
+ * One example, although it is probably better with a per-file
+ * control, is selecting huge page allocations ("huge=within_size").
+ * However, we only do so on platforms which benefit from it, or to
+ * offset the overhead of iommu lookups, where with latter it is a net
+ * win even on platforms which would otherwise see some performance
+ * regressions such a slow reads issue on Broadwell and Skylake.
+ */
-static int release_shmem(struct intel_memory_region *mem)
-{
- i915_gemfs_fini(mem->i915);
- return 0;
+ if (GRAPHICS_VER(i915) < 11 && !i915_vtd_active(i915))
+ goto no_thp;
+
+ if (!IS_ENABLED(CONFIG_TRANSPARENT_HUGEPAGE))
+ goto no_thp;
+
+ err = drm_gem_huge_mnt_create(&i915->drm, "within_size");
+ if (err && err != -EEXIST) {
+ drm_notice(&i915->drm,
+ "Transparent Hugepage support is recommended for optimal performance%s\n",
+ GRAPHICS_VER(i915) >= 11 ? " on this platform!" :
+ " when IOMMU is enabled!");
+ goto no_thp;
+ }
+
+ drm_info(&i915->drm, "Using Transparent Hugepages\n");
+
+ no_thp:
+ intel_memory_region_set_name(mem, "system");
+
+ return 0; /* We have fallback to the kernel mnt if huge mnt failed. */
}
static const struct intel_memory_region_ops shmem_region_ops = {
.init = init_shmem,
- .release = release_shmem,
.init_object = shmem_object_init,
};
diff --git a/drivers/gpu/drm/i915/gem/i915_gemfs.c b/drivers/gpu/drm/i915/gem/i915_gemfs.c
deleted file mode 100644
index a09e2eb47175..000000000000
--- a/drivers/gpu/drm/i915/gem/i915_gemfs.c
+++ /dev/null
@@ -1,74 +0,0 @@
-// SPDX-License-Identifier: MIT
-/*
- * Copyright © 2017 Intel Corporation
- */
-
-#include <linux/fs.h>
-#include <linux/mount.h>
-#include <linux/fs_context.h>
-
-#include "i915_drv.h"
-#include "i915_gemfs.h"
-#include "i915_utils.h"
-
-static int add_param(struct fs_context *fc, const char *key, const char *val)
-{
- return vfs_parse_fs_string(fc, key, val, strlen(val));
-}
-
-void i915_gemfs_init(struct drm_i915_private *i915)
-{
- struct file_system_type *type;
- struct fs_context *fc;
- struct vfsmount *gemfs;
- int ret;
-
- /*
- * By creating our own shmemfs mountpoint, we can pass in
- * mount flags that better match our usecase.
- *
- * One example, although it is probably better with a per-file
- * control, is selecting huge page allocations ("huge=within_size").
- * However, we only do so on platforms which benefit from it, or to
- * offset the overhead of iommu lookups, where with latter it is a net
- * win even on platforms which would otherwise see some performance
- * regressions such a slow reads issue on Broadwell and Skylake.
- */
-
- if (GRAPHICS_VER(i915) < 11 && !i915_vtd_active(i915))
- return;
-
- if (!IS_ENABLED(CONFIG_TRANSPARENT_HUGEPAGE))
- goto err;
-
- type = get_fs_type("tmpfs");
- if (!type)
- goto err;
-
- fc = fs_context_for_mount(type, SB_KERNMOUNT);
- if (IS_ERR(fc))
- goto err;
- ret = add_param(fc, "source", "tmpfs");
- if (!ret)
- ret = add_param(fc, "huge", "within_size");
- if (!ret)
- gemfs = fc_mount_longterm(fc);
- put_fs_context(fc);
- if (ret)
- goto err;
-
- i915->mm.gemfs = gemfs;
- drm_info(&i915->drm, "Using Transparent Hugepages\n");
- return;
-
-err:
- drm_notice(&i915->drm,
- "Transparent Hugepage support is recommended for optimal performance%s\n",
- GRAPHICS_VER(i915) >= 11 ? " on this platform!" :
- " when IOMMU is enabled!");
-}
-
-void i915_gemfs_fini(struct drm_i915_private *i915)
-{
- kern_unmount(i915->mm.gemfs);
-}
diff --git a/drivers/gpu/drm/i915/gem/i915_gemfs.h b/drivers/gpu/drm/i915/gem/i915_gemfs.h
deleted file mode 100644
index 16d4333c9a4e..000000000000
--- a/drivers/gpu/drm/i915/gem/i915_gemfs.h
+++ /dev/null
@@ -1,14 +0,0 @@
-/* SPDX-License-Identifier: MIT */
-/*
- * Copyright © 2017 Intel Corporation
- */
-
-#ifndef __I915_GEMFS_H__
-#define __I915_GEMFS_H__
-
-struct drm_i915_private;
-
-void i915_gemfs_init(struct drm_i915_private *i915);
-void i915_gemfs_fini(struct drm_i915_private *i915);
-
-#endif
diff --git a/drivers/gpu/drm/i915/gem/selftests/huge_pages.c b/drivers/gpu/drm/i915/gem/selftests/huge_pages.c
index bd08605a1611..b41a38af63fd 100644
--- a/drivers/gpu/drm/i915/gem/selftests/huge_pages.c
+++ b/drivers/gpu/drm/i915/gem/selftests/huge_pages.c
@@ -1316,7 +1316,7 @@ typedef struct drm_i915_gem_object *
static inline bool igt_can_allocate_thp(struct drm_i915_private *i915)
{
- return i915->mm.gemfs && has_transparent_hugepage();
+ return i915->drm.huge_mnt && has_transparent_hugepage();
}
static struct drm_i915_gem_object *
@@ -1761,7 +1761,7 @@ static int igt_tmpfs_fallback(void *arg)
struct drm_i915_private *i915 = arg;
struct i915_address_space *vm;
struct i915_gem_context *ctx;
- struct vfsmount *gemfs = i915->mm.gemfs;
+ struct vfsmount *huge_mnt = i915->drm.huge_mnt;
struct drm_i915_gem_object *obj;
struct i915_vma *vma;
struct file *file;
@@ -1782,10 +1782,10 @@ static int igt_tmpfs_fallback(void *arg)
/*
* Make sure that we don't burst into a ball of flames upon falling back
* to tmpfs, which we rely on if on the off-chance we encounter a failure
- * when setting up gemfs.
+ * when setting up a huge mountpoint.
*/
- i915->mm.gemfs = NULL;
+ i915->drm.huge_mnt = NULL;
obj = i915_gem_object_create_shmem(i915, PAGE_SIZE);
if (IS_ERR(obj)) {
@@ -1819,7 +1819,7 @@ static int igt_tmpfs_fallback(void *arg)
out_put:
i915_gem_object_put(obj);
out_restore:
- i915->mm.gemfs = gemfs;
+ i915->drm.huge_mnt = huge_mnt;
i915_vm_put(vm);
out:
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 2f3965feada1..49987f4c6ffe 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -142,11 +142,6 @@ struct i915_gem_mm {
*/
atomic_t free_count;
- /**
- * tmpfs instance used for shmem backed objects
- */
- struct vfsmount *gemfs;
-
struct intel_memory_region *regions[INTEL_REGION_UNKNOWN];
struct notifier_block oom_notifier;
--
2.47.3
^ permalink raw reply [flat|nested] 26+ messages in thread* [PATCH v3 05/10] drm/v3d: Use huge tmpfs mount point helper
2025-10-04 9:30 [PATCH v3 00/10] drm: Reduce page tables overhead with THP Loïc Molinari
` (3 preceding siblings ...)
2025-10-04 9:30 ` [PATCH v3 04/10] drm/i915: Use " Loïc Molinari
@ 2025-10-04 9:30 ` Loïc Molinari
2025-10-06 7:07 ` Boris Brezillon
2025-10-04 9:30 ` [PATCH v3 06/10] drm/gem: Get rid of *_with_mnt helpers Loïc Molinari
` (4 subsequent siblings)
9 siblings, 1 reply; 26+ messages in thread
From: Loïc Molinari @ 2025-10-04 9:30 UTC (permalink / raw)
To: Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann,
David Airlie, Simona Vetter, Jani Nikula, Joonas Lahtinen,
Rodrigo Vivi, Tvrtko Ursulin, Boris Brezillon, Rob Herring,
Steven Price, Liviu Dudau, Melissa Wen, Maíra Canal,
Hugh Dickins, Baolin Wang, Andrew Morton, Loïc Molinari,
Al Viro, Mikołaj Wasiak, Christian Brauner, Nitin Gote,
Andi Shyti, Christopher Healy
Cc: linux-kernel, dri-devel, intel-gfx, linux-mm, kernel
Make use of the new drm_gem_huge_mnt_create() helper to avoid code
duplication. Now that it's just a few lines long, the single function
in v3d_gemfs.c is moved into v3d_gem.c.
v3:
- use huge tmpfs mountpoint in drm_device
- move v3d_gemfs.c into v3d_gem.c
Signed-off-by: Loïc Molinari <loic.molinari@collabora.com>
---
drivers/gpu/drm/v3d/Makefile | 3 +-
drivers/gpu/drm/v3d/v3d_bo.c | 5 +--
drivers/gpu/drm/v3d/v3d_drv.c | 2 +-
drivers/gpu/drm/v3d/v3d_drv.h | 11 +-----
drivers/gpu/drm/v3d/v3d_gem.c | 33 ++++++++++++++++-
drivers/gpu/drm/v3d/v3d_gemfs.c | 65 ---------------------------------
6 files changed, 36 insertions(+), 83 deletions(-)
delete mode 100644 drivers/gpu/drm/v3d/v3d_gemfs.c
diff --git a/drivers/gpu/drm/v3d/Makefile b/drivers/gpu/drm/v3d/Makefile
index fcf710926057..b7d673f1153b 100644
--- a/drivers/gpu/drm/v3d/Makefile
+++ b/drivers/gpu/drm/v3d/Makefile
@@ -13,8 +13,7 @@ v3d-y := \
v3d_trace_points.o \
v3d_sched.o \
v3d_sysfs.o \
- v3d_submit.o \
- v3d_gemfs.o
+ v3d_submit.o
v3d-$(CONFIG_DEBUG_FS) += v3d_debugfs.o
diff --git a/drivers/gpu/drm/v3d/v3d_bo.c b/drivers/gpu/drm/v3d/v3d_bo.c
index c41476ddde68..6b9909bfce82 100644
--- a/drivers/gpu/drm/v3d/v3d_bo.c
+++ b/drivers/gpu/drm/v3d/v3d_bo.c
@@ -112,7 +112,7 @@ v3d_bo_create_finish(struct drm_gem_object *obj)
if (IS_ERR(sgt))
return PTR_ERR(sgt);
- if (!v3d->gemfs)
+ if (!obj->dev->huge_mnt)
align = SZ_4K;
else if (obj->size >= SZ_1M)
align = SZ_1M;
@@ -148,12 +148,11 @@ struct v3d_bo *v3d_bo_create(struct drm_device *dev, struct drm_file *file_priv,
size_t unaligned_size)
{
struct drm_gem_shmem_object *shmem_obj;
- struct v3d_dev *v3d = to_v3d_dev(dev);
struct v3d_bo *bo;
int ret;
shmem_obj = drm_gem_shmem_create_with_mnt(dev, unaligned_size,
- v3d->gemfs);
+ dev->huge_mnt);
if (IS_ERR(shmem_obj))
return ERR_CAST(shmem_obj);
bo = to_v3d_bo(&shmem_obj->base);
diff --git a/drivers/gpu/drm/v3d/v3d_drv.c b/drivers/gpu/drm/v3d/v3d_drv.c
index c5a3bbbc74c5..19ec0ea7f38e 100644
--- a/drivers/gpu/drm/v3d/v3d_drv.c
+++ b/drivers/gpu/drm/v3d/v3d_drv.c
@@ -106,7 +106,7 @@ static int v3d_get_param_ioctl(struct drm_device *dev, void *data,
args->value = v3d->perfmon_info.max_counters;
return 0;
case DRM_V3D_PARAM_SUPPORTS_SUPER_PAGES:
- args->value = !!v3d->gemfs;
+ args->value = !!dev->huge_mnt;
return 0;
case DRM_V3D_PARAM_GLOBAL_RESET_COUNTER:
mutex_lock(&v3d->reset_lock);
diff --git a/drivers/gpu/drm/v3d/v3d_drv.h b/drivers/gpu/drm/v3d/v3d_drv.h
index 0317f3d7452a..0b4fcb788168 100644
--- a/drivers/gpu/drm/v3d/v3d_drv.h
+++ b/drivers/gpu/drm/v3d/v3d_drv.h
@@ -156,11 +156,6 @@ struct v3d_dev {
struct drm_mm mm;
spinlock_t mm_lock;
- /*
- * tmpfs instance used for shmem backed objects
- */
- struct vfsmount *gemfs;
-
struct work_struct overflow_mem_work;
struct v3d_queue_state queue[V3D_MAX_QUEUES];
@@ -567,6 +562,7 @@ extern const struct dma_fence_ops v3d_fence_ops;
struct dma_fence *v3d_fence_create(struct v3d_dev *v3d, enum v3d_queue q);
/* v3d_gem.c */
+extern bool super_pages;
int v3d_gem_init(struct drm_device *dev);
void v3d_gem_destroy(struct drm_device *dev);
void v3d_reset_sms(struct v3d_dev *v3d);
@@ -574,11 +570,6 @@ void v3d_reset(struct v3d_dev *v3d);
void v3d_invalidate_caches(struct v3d_dev *v3d);
void v3d_clean_caches(struct v3d_dev *v3d);
-/* v3d_gemfs.c */
-extern bool super_pages;
-void v3d_gemfs_init(struct v3d_dev *v3d);
-void v3d_gemfs_fini(struct v3d_dev *v3d);
-
/* v3d_submit.c */
void v3d_job_cleanup(struct v3d_job *job);
void v3d_job_put(struct v3d_job *job);
diff --git a/drivers/gpu/drm/v3d/v3d_gem.c b/drivers/gpu/drm/v3d/v3d_gem.c
index c77d90aa9b82..1cf5ebe99c90 100644
--- a/drivers/gpu/drm/v3d/v3d_gem.c
+++ b/drivers/gpu/drm/v3d/v3d_gem.c
@@ -258,6 +258,36 @@ v3d_invalidate_caches(struct v3d_dev *v3d)
v3d_invalidate_slices(v3d, 0);
}
+static void
+v3d_huge_mnt_init(struct v3d_dev *v3d)
+{
+ int err;
+
+ /*
+ * By creating our own shmemfs mountpoint, we can pass in
+ * mount flags that better match our usecase. However, we
+ * only do so on platforms which benefit from it.
+ */
+ if (!IS_ENABLED(CONFIG_TRANSPARENT_HUGEPAGE))
+ goto err;
+
+ /* The user doesn't want to enable Super Pages */
+ if (!super_pages)
+ goto err;
+
+ err = drm_gem_huge_mnt_create(&v3d->drm, "within_size");
+ if (err && err != -EEXIST)
+ goto err;
+
+ drm_info(&v3d->drm, "Using Transparent Hugepages\n");
+
+ return;
+
+err:
+ drm_notice(&v3d->drm,
+ "Transparent Hugepage support is recommended for optimal performance on this platform!\n");
+}
+
int
v3d_gem_init(struct drm_device *dev)
{
@@ -308,7 +338,7 @@ v3d_gem_init(struct drm_device *dev)
v3d_init_hw_state(v3d);
v3d_mmu_set_page_table(v3d);
- v3d_gemfs_init(v3d);
+ v3d_huge_mnt_init(v3d);
ret = v3d_sched_init(v3d);
if (ret) {
@@ -328,7 +358,6 @@ v3d_gem_destroy(struct drm_device *dev)
enum v3d_queue q;
v3d_sched_fini(v3d);
- v3d_gemfs_fini(v3d);
/* Waiting for jobs to finish would need to be done before
* unregistering V3D.
diff --git a/drivers/gpu/drm/v3d/v3d_gemfs.c b/drivers/gpu/drm/v3d/v3d_gemfs.c
deleted file mode 100644
index 8ec6ed82b3d9..000000000000
--- a/drivers/gpu/drm/v3d/v3d_gemfs.c
+++ /dev/null
@@ -1,65 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0+
-/* Copyright (C) 2024 Raspberry Pi */
-
-#include <linux/fs.h>
-#include <linux/mount.h>
-#include <linux/fs_context.h>
-
-#include "v3d_drv.h"
-
-static int add_param(struct fs_context *fc, const char *key, const char *val)
-{
- return vfs_parse_fs_string(fc, key, val, strlen(val));
-}
-
-void v3d_gemfs_init(struct v3d_dev *v3d)
-{
- struct file_system_type *type;
- struct fs_context *fc;
- struct vfsmount *gemfs;
- int ret;
-
- /*
- * By creating our own shmemfs mountpoint, we can pass in
- * mount flags that better match our usecase. However, we
- * only do so on platforms which benefit from it.
- */
- if (!IS_ENABLED(CONFIG_TRANSPARENT_HUGEPAGE))
- goto err;
-
- /* The user doesn't want to enable Super Pages */
- if (!super_pages)
- goto err;
-
- type = get_fs_type("tmpfs");
- if (!type)
- goto err;
-
- fc = fs_context_for_mount(type, SB_KERNMOUNT);
- if (IS_ERR(fc))
- goto err;
- ret = add_param(fc, "source", "tmpfs");
- if (!ret)
- ret = add_param(fc, "huge", "within_size");
- if (!ret)
- gemfs = fc_mount_longterm(fc);
- put_fs_context(fc);
- if (ret)
- goto err;
-
- v3d->gemfs = gemfs;
- drm_info(&v3d->drm, "Using Transparent Hugepages\n");
-
- return;
-
-err:
- v3d->gemfs = NULL;
- drm_notice(&v3d->drm,
- "Transparent Hugepage support is recommended for optimal performance on this platform!\n");
-}
-
-void v3d_gemfs_fini(struct v3d_dev *v3d)
-{
- if (v3d->gemfs)
- kern_unmount(v3d->gemfs);
-}
--
2.47.3
^ permalink raw reply [flat|nested] 26+ messages in thread* Re: [PATCH v3 05/10] drm/v3d: Use huge tmpfs mount point helper
2025-10-04 9:30 ` [PATCH v3 05/10] drm/v3d: " Loïc Molinari
@ 2025-10-06 7:07 ` Boris Brezillon
0 siblings, 0 replies; 26+ messages in thread
From: Boris Brezillon @ 2025-10-06 7:07 UTC (permalink / raw)
To: Loïc Molinari
Cc: Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann,
David Airlie, Simona Vetter, Jani Nikula, Joonas Lahtinen,
Rodrigo Vivi, Tvrtko Ursulin, Rob Herring, Steven Price,
Liviu Dudau, Melissa Wen, Maíra Canal, Hugh Dickins,
Baolin Wang, Andrew Morton, Al Viro, Mikołaj Wasiak,
Christian Brauner, Nitin Gote, Andi Shyti, Christopher Healy,
linux-kernel, dri-devel, intel-gfx, linux-mm, kernel
On Sat, 4 Oct 2025 11:30:48 +0200
Loïc Molinari <loic.molinari@collabora.com> wrote:
> +static void
> +v3d_huge_mnt_init(struct v3d_dev *v3d)
> +{
> + int err;
> +
> + /*
> + * By creating our own shmemfs mountpoint, we can pass in
> + * mount flags that better match our usecase. However, we
> + * only do so on platforms which benefit from it.
> + */
> + if (!IS_ENABLED(CONFIG_TRANSPARENT_HUGEPAGE))
> + goto err;
> +
> + /* The user doesn't want to enable Super Pages */
> + if (!super_pages)
> + goto err;
> +
> + err = drm_gem_huge_mnt_create(&v3d->drm, "within_size");
> + if (err && err != -EEXIST)
> + goto err;
> +
> + drm_info(&v3d->drm, "Using Transparent Hugepages\n");
> +
> + return;
> +
> +err:
> + drm_notice(&v3d->drm,
> + "Transparent Hugepage support is recommended for optimal performance on this platform!\n");
With the changes suggested on patch 3, this can be shrunk a little bit:
int err = 0;
if (super_pages)
err = drm_gem_huge_mnt_create(&v3d->drm, "within_size");
if (v3d->drm.huge_mnt)
drm_info(&v3d->drm, "Using Transparent Hugepages\n");
else if (!err)
drm_notice(&v3d->drm,
"Transparent Hugepage support is recommended for optimal performance on this platform!\n");
else
drm_warn(&v3d->drm, "Couldn't create THP mount point (err=%d)\n", err);
^ permalink raw reply [flat|nested] 26+ messages in thread
* [PATCH v3 06/10] drm/gem: Get rid of *_with_mnt helpers
2025-10-04 9:30 [PATCH v3 00/10] drm: Reduce page tables overhead with THP Loïc Molinari
` (4 preceding siblings ...)
2025-10-04 9:30 ` [PATCH v3 05/10] drm/v3d: " Loïc Molinari
@ 2025-10-04 9:30 ` Loïc Molinari
2025-10-06 7:17 ` Boris Brezillon
2025-10-04 9:30 ` [PATCH v3 07/10] drm/panthor: Introduce huge tmpfs mount point option Loïc Molinari
` (3 subsequent siblings)
9 siblings, 1 reply; 26+ messages in thread
From: Loïc Molinari @ 2025-10-04 9:30 UTC (permalink / raw)
To: Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann,
David Airlie, Simona Vetter, Jani Nikula, Joonas Lahtinen,
Rodrigo Vivi, Tvrtko Ursulin, Boris Brezillon, Rob Herring,
Steven Price, Liviu Dudau, Melissa Wen, Maíra Canal,
Hugh Dickins, Baolin Wang, Andrew Morton, Loïc Molinari,
Al Viro, Mikołaj Wasiak, Christian Brauner, Nitin Gote,
Andi Shyti, Christopher Healy
Cc: linux-kernel, dri-devel, intel-gfx, linux-mm, kernel
drm_gem_object_init_with_mnt() and drm_gem_shmem_create_with_mnt() can
be removed now that the drivers use drm_gem_huge_mnt_create().
Signed-off-by: Loïc Molinari <loic.molinari@collabora.com>
---
drivers/gpu/drm/drm_gem.c | 34 ++++++-----------------
drivers/gpu/drm/drm_gem_shmem_helper.c | 38 ++++++--------------------
drivers/gpu/drm/v3d/v3d_bo.c | 3 +-
include/drm/drm_gem.h | 3 --
include/drm/drm_gem_shmem_helper.h | 3 --
5 files changed, 17 insertions(+), 64 deletions(-)
diff --git a/drivers/gpu/drm/drm_gem.c b/drivers/gpu/drm/drm_gem.c
index b4e4947210ef..a29f57943b93 100644
--- a/drivers/gpu/drm/drm_gem.c
+++ b/drivers/gpu/drm/drm_gem.c
@@ -181,28 +181,26 @@ drm_gem_init(struct drm_device *dev)
}
/**
- * drm_gem_object_init_with_mnt - initialize an allocated shmem-backed GEM
- * object in a given shmfs mountpoint
+ * drm_gem_object_init - initialize an allocated shmem-backed GEM object
*
* @dev: drm_device the object should be initialized for
* @obj: drm_gem_object to initialize
* @size: object size
- * @gemfs: tmpfs mount where the GEM object will be created. If NULL, use
- * the usual tmpfs mountpoint (`shm_mnt`).
*
* Initialize an already allocated GEM object of the specified size with
- * shmfs backing store.
+ * shmfs backing store. A huge mountpoint can be used by calling
+ * drm_gem_huge_mnt_create() beforehand.
*/
-int drm_gem_object_init_with_mnt(struct drm_device *dev,
- struct drm_gem_object *obj, size_t size,
- struct vfsmount *gemfs)
+int drm_gem_object_init(struct drm_device *dev, struct drm_gem_object *obj,
+ size_t size)
{
struct file *filp;
drm_gem_private_object_init(dev, obj, size);
- if (gemfs)
- filp = shmem_file_setup_with_mnt(gemfs, "drm mm object", size,
+ if (dev->huge_mnt)
+ filp = shmem_file_setup_with_mnt(dev->huge_mnt,
+ "drm mm object", size,
VM_NORESERVE);
else
filp = shmem_file_setup("drm mm object", size, VM_NORESERVE);
@@ -214,22 +212,6 @@ int drm_gem_object_init_with_mnt(struct drm_device *dev,
return 0;
}
-EXPORT_SYMBOL(drm_gem_object_init_with_mnt);
-
-/**
- * drm_gem_object_init - initialize an allocated shmem-backed GEM object
- * @dev: drm_device the object should be initialized for
- * @obj: drm_gem_object to initialize
- * @size: object size
- *
- * Initialize an already allocated GEM object of the specified size with
- * shmfs backing store.
- */
-int drm_gem_object_init(struct drm_device *dev, struct drm_gem_object *obj,
- size_t size)
-{
- return drm_gem_object_init_with_mnt(dev, obj, size, NULL);
-}
EXPORT_SYMBOL(drm_gem_object_init);
/**
diff --git a/drivers/gpu/drm/drm_gem_shmem_helper.c b/drivers/gpu/drm/drm_gem_shmem_helper.c
index 22c4b09e10a3..5c1c1e8040b4 100644
--- a/drivers/gpu/drm/drm_gem_shmem_helper.c
+++ b/drivers/gpu/drm/drm_gem_shmem_helper.c
@@ -49,7 +49,7 @@ static const struct drm_gem_object_funcs drm_gem_shmem_funcs = {
};
static int __drm_gem_shmem_init(struct drm_device *dev, struct drm_gem_shmem_object *shmem,
- size_t size, bool private, struct vfsmount *gemfs)
+ size_t size, bool private)
{
struct drm_gem_object *obj = &shmem->base;
int ret = 0;
@@ -61,7 +61,7 @@ static int __drm_gem_shmem_init(struct drm_device *dev, struct drm_gem_shmem_obj
drm_gem_private_object_init(dev, obj, size);
shmem->map_wc = false; /* dma-buf mappings use always writecombine */
} else {
- ret = drm_gem_object_init_with_mnt(dev, obj, size, gemfs);
+ ret = drm_gem_object_init(dev, obj, size);
}
if (ret) {
drm_gem_private_object_fini(obj);
@@ -102,13 +102,12 @@ static int __drm_gem_shmem_init(struct drm_device *dev, struct drm_gem_shmem_obj
*/
int drm_gem_shmem_init(struct drm_device *dev, struct drm_gem_shmem_object *shmem, size_t size)
{
- return __drm_gem_shmem_init(dev, shmem, size, false, NULL);
+ return __drm_gem_shmem_init(dev, shmem, size, false);
}
EXPORT_SYMBOL_GPL(drm_gem_shmem_init);
static struct drm_gem_shmem_object *
-__drm_gem_shmem_create(struct drm_device *dev, size_t size, bool private,
- struct vfsmount *gemfs)
+__drm_gem_shmem_create(struct drm_device *dev, size_t size, bool private)
{
struct drm_gem_shmem_object *shmem;
struct drm_gem_object *obj;
@@ -128,7 +127,7 @@ __drm_gem_shmem_create(struct drm_device *dev, size_t size, bool private,
obj = &shmem->base;
}
- ret = __drm_gem_shmem_init(dev, shmem, size, private, gemfs);
+ ret = __drm_gem_shmem_init(dev, shmem, size, private);
if (ret) {
kfree(obj);
return ERR_PTR(ret);
@@ -149,31 +148,10 @@ __drm_gem_shmem_create(struct drm_device *dev, size_t size, bool private,
*/
struct drm_gem_shmem_object *drm_gem_shmem_create(struct drm_device *dev, size_t size)
{
- return __drm_gem_shmem_create(dev, size, false, NULL);
+ return __drm_gem_shmem_create(dev, size, false);
}
EXPORT_SYMBOL_GPL(drm_gem_shmem_create);
-/**
- * drm_gem_shmem_create_with_mnt - Allocate an object with the given size in a
- * given mountpoint
- * @dev: DRM device
- * @size: Size of the object to allocate
- * @gemfs: tmpfs mount where the GEM object will be created
- *
- * This function creates a shmem GEM object in a given tmpfs mountpoint.
- *
- * Returns:
- * A struct drm_gem_shmem_object * on success or an ERR_PTR()-encoded negative
- * error code on failure.
- */
-struct drm_gem_shmem_object *drm_gem_shmem_create_with_mnt(struct drm_device *dev,
- size_t size,
- struct vfsmount *gemfs)
-{
- return __drm_gem_shmem_create(dev, size, false, gemfs);
-}
-EXPORT_SYMBOL_GPL(drm_gem_shmem_create_with_mnt);
-
/**
* drm_gem_shmem_release - Release resources associated with a shmem GEM object.
* @shmem: shmem GEM object
@@ -878,7 +856,7 @@ drm_gem_shmem_prime_import_sg_table(struct drm_device *dev,
size_t size = PAGE_ALIGN(attach->dmabuf->size);
struct drm_gem_shmem_object *shmem;
- shmem = __drm_gem_shmem_create(dev, size, true, NULL);
+ shmem = __drm_gem_shmem_create(dev, size, true);
if (IS_ERR(shmem))
return ERR_CAST(shmem);
@@ -926,7 +904,7 @@ struct drm_gem_object *drm_gem_shmem_prime_import_no_map(struct drm_device *dev,
size = PAGE_ALIGN(attach->dmabuf->size);
- shmem = __drm_gem_shmem_create(dev, size, true, NULL);
+ shmem = __drm_gem_shmem_create(dev, size, true);
if (IS_ERR(shmem)) {
ret = PTR_ERR(shmem);
goto fail_detach;
diff --git a/drivers/gpu/drm/v3d/v3d_bo.c b/drivers/gpu/drm/v3d/v3d_bo.c
index 6b9909bfce82..ef9e9c15da3c 100644
--- a/drivers/gpu/drm/v3d/v3d_bo.c
+++ b/drivers/gpu/drm/v3d/v3d_bo.c
@@ -151,8 +151,7 @@ struct v3d_bo *v3d_bo_create(struct drm_device *dev, struct drm_file *file_priv,
struct v3d_bo *bo;
int ret;
- shmem_obj = drm_gem_shmem_create_with_mnt(dev, unaligned_size,
- dev->huge_mnt);
+ shmem_obj = drm_gem_shmem_create(dev, unaligned_size);
if (IS_ERR(shmem_obj))
return ERR_CAST(shmem_obj);
bo = to_v3d_bo(&shmem_obj->base);
diff --git a/include/drm/drm_gem.h b/include/drm/drm_gem.h
index 7285a62d9afc..42d9066b1785 100644
--- a/include/drm/drm_gem.h
+++ b/include/drm/drm_gem.h
@@ -497,9 +497,6 @@ void drm_gem_object_release(struct drm_gem_object *obj);
void drm_gem_object_free(struct kref *kref);
int drm_gem_object_init(struct drm_device *dev,
struct drm_gem_object *obj, size_t size);
-int drm_gem_object_init_with_mnt(struct drm_device *dev,
- struct drm_gem_object *obj, size_t size,
- struct vfsmount *gemfs);
void drm_gem_private_object_init(struct drm_device *dev,
struct drm_gem_object *obj, size_t size);
void drm_gem_private_object_fini(struct drm_gem_object *obj);
diff --git a/include/drm/drm_gem_shmem_helper.h b/include/drm/drm_gem_shmem_helper.h
index 589f7bfe7506..6b6478f5ca24 100644
--- a/include/drm/drm_gem_shmem_helper.h
+++ b/include/drm/drm_gem_shmem_helper.h
@@ -109,9 +109,6 @@ struct drm_gem_shmem_object {
int drm_gem_shmem_init(struct drm_device *dev, struct drm_gem_shmem_object *shmem, size_t size);
struct drm_gem_shmem_object *drm_gem_shmem_create(struct drm_device *dev, size_t size);
-struct drm_gem_shmem_object *drm_gem_shmem_create_with_mnt(struct drm_device *dev,
- size_t size,
- struct vfsmount *gemfs);
void drm_gem_shmem_release(struct drm_gem_shmem_object *shmem);
void drm_gem_shmem_free(struct drm_gem_shmem_object *shmem);
--
2.47.3
^ permalink raw reply [flat|nested] 26+ messages in thread* Re: [PATCH v3 06/10] drm/gem: Get rid of *_with_mnt helpers
2025-10-04 9:30 ` [PATCH v3 06/10] drm/gem: Get rid of *_with_mnt helpers Loïc Molinari
@ 2025-10-06 7:17 ` Boris Brezillon
0 siblings, 0 replies; 26+ messages in thread
From: Boris Brezillon @ 2025-10-06 7:17 UTC (permalink / raw)
To: Loïc Molinari
Cc: Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann,
David Airlie, Simona Vetter, Jani Nikula, Joonas Lahtinen,
Rodrigo Vivi, Tvrtko Ursulin, Rob Herring, Steven Price,
Liviu Dudau, Melissa Wen, Maíra Canal, Hugh Dickins,
Baolin Wang, Andrew Morton, Al Viro, Mikołaj Wasiak,
Christian Brauner, Nitin Gote, Andi Shyti, Christopher Healy,
linux-kernel, dri-devel, intel-gfx, linux-mm, kernel
On Sat, 4 Oct 2025 11:30:49 +0200
Loïc Molinari <loic.molinari@collabora.com> wrote:
> drm_gem_object_init_with_mnt() and drm_gem_shmem_create_with_mnt() can
> be removed now that the drivers use drm_gem_huge_mnt_create().
>
> Signed-off-by: Loïc Molinari <loic.molinari@collabora.com>
Reviewed-by: Boris Brezillon <boris.brezillon@collabora.com>
> ---
> drivers/gpu/drm/drm_gem.c | 34 ++++++-----------------
> drivers/gpu/drm/drm_gem_shmem_helper.c | 38 ++++++--------------------
> drivers/gpu/drm/v3d/v3d_bo.c | 3 +-
> include/drm/drm_gem.h | 3 --
> include/drm/drm_gem_shmem_helper.h | 3 --
> 5 files changed, 17 insertions(+), 64 deletions(-)
>
> diff --git a/drivers/gpu/drm/drm_gem.c b/drivers/gpu/drm/drm_gem.c
> index b4e4947210ef..a29f57943b93 100644
> --- a/drivers/gpu/drm/drm_gem.c
> +++ b/drivers/gpu/drm/drm_gem.c
> @@ -181,28 +181,26 @@ drm_gem_init(struct drm_device *dev)
> }
>
> /**
> - * drm_gem_object_init_with_mnt - initialize an allocated shmem-backed GEM
> - * object in a given shmfs mountpoint
> + * drm_gem_object_init - initialize an allocated shmem-backed GEM object
> *
> * @dev: drm_device the object should be initialized for
> * @obj: drm_gem_object to initialize
> * @size: object size
> - * @gemfs: tmpfs mount where the GEM object will be created. If NULL, use
> - * the usual tmpfs mountpoint (`shm_mnt`).
> *
> * Initialize an already allocated GEM object of the specified size with
> - * shmfs backing store.
> + * shmfs backing store. A huge mountpoint can be used by calling
> + * drm_gem_huge_mnt_create() beforehand.
> */
> -int drm_gem_object_init_with_mnt(struct drm_device *dev,
> - struct drm_gem_object *obj, size_t size,
> - struct vfsmount *gemfs)
> +int drm_gem_object_init(struct drm_device *dev, struct drm_gem_object *obj,
> + size_t size)
> {
> struct file *filp;
>
> drm_gem_private_object_init(dev, obj, size);
>
> - if (gemfs)
> - filp = shmem_file_setup_with_mnt(gemfs, "drm mm object", size,
> + if (dev->huge_mnt)
> + filp = shmem_file_setup_with_mnt(dev->huge_mnt,
> + "drm mm object", size,
> VM_NORESERVE);
> else
> filp = shmem_file_setup("drm mm object", size, VM_NORESERVE);
> @@ -214,22 +212,6 @@ int drm_gem_object_init_with_mnt(struct drm_device *dev,
>
> return 0;
> }
> -EXPORT_SYMBOL(drm_gem_object_init_with_mnt);
> -
> -/**
> - * drm_gem_object_init - initialize an allocated shmem-backed GEM object
> - * @dev: drm_device the object should be initialized for
> - * @obj: drm_gem_object to initialize
> - * @size: object size
> - *
> - * Initialize an already allocated GEM object of the specified size with
> - * shmfs backing store.
> - */
> -int drm_gem_object_init(struct drm_device *dev, struct drm_gem_object *obj,
> - size_t size)
> -{
> - return drm_gem_object_init_with_mnt(dev, obj, size, NULL);
> -}
> EXPORT_SYMBOL(drm_gem_object_init);
>
> /**
> diff --git a/drivers/gpu/drm/drm_gem_shmem_helper.c b/drivers/gpu/drm/drm_gem_shmem_helper.c
> index 22c4b09e10a3..5c1c1e8040b4 100644
> --- a/drivers/gpu/drm/drm_gem_shmem_helper.c
> +++ b/drivers/gpu/drm/drm_gem_shmem_helper.c
> @@ -49,7 +49,7 @@ static const struct drm_gem_object_funcs drm_gem_shmem_funcs = {
> };
>
> static int __drm_gem_shmem_init(struct drm_device *dev, struct drm_gem_shmem_object *shmem,
> - size_t size, bool private, struct vfsmount *gemfs)
> + size_t size, bool private)
> {
> struct drm_gem_object *obj = &shmem->base;
> int ret = 0;
> @@ -61,7 +61,7 @@ static int __drm_gem_shmem_init(struct drm_device *dev, struct drm_gem_shmem_obj
> drm_gem_private_object_init(dev, obj, size);
> shmem->map_wc = false; /* dma-buf mappings use always writecombine */
> } else {
> - ret = drm_gem_object_init_with_mnt(dev, obj, size, gemfs);
> + ret = drm_gem_object_init(dev, obj, size);
> }
> if (ret) {
> drm_gem_private_object_fini(obj);
> @@ -102,13 +102,12 @@ static int __drm_gem_shmem_init(struct drm_device *dev, struct drm_gem_shmem_obj
> */
> int drm_gem_shmem_init(struct drm_device *dev, struct drm_gem_shmem_object *shmem, size_t size)
> {
> - return __drm_gem_shmem_init(dev, shmem, size, false, NULL);
> + return __drm_gem_shmem_init(dev, shmem, size, false);
> }
> EXPORT_SYMBOL_GPL(drm_gem_shmem_init);
>
> static struct drm_gem_shmem_object *
> -__drm_gem_shmem_create(struct drm_device *dev, size_t size, bool private,
> - struct vfsmount *gemfs)
> +__drm_gem_shmem_create(struct drm_device *dev, size_t size, bool private)
> {
> struct drm_gem_shmem_object *shmem;
> struct drm_gem_object *obj;
> @@ -128,7 +127,7 @@ __drm_gem_shmem_create(struct drm_device *dev, size_t size, bool private,
> obj = &shmem->base;
> }
>
> - ret = __drm_gem_shmem_init(dev, shmem, size, private, gemfs);
> + ret = __drm_gem_shmem_init(dev, shmem, size, private);
> if (ret) {
> kfree(obj);
> return ERR_PTR(ret);
> @@ -149,31 +148,10 @@ __drm_gem_shmem_create(struct drm_device *dev, size_t size, bool private,
> */
> struct drm_gem_shmem_object *drm_gem_shmem_create(struct drm_device *dev, size_t size)
> {
> - return __drm_gem_shmem_create(dev, size, false, NULL);
> + return __drm_gem_shmem_create(dev, size, false);
> }
> EXPORT_SYMBOL_GPL(drm_gem_shmem_create);
>
> -/**
> - * drm_gem_shmem_create_with_mnt - Allocate an object with the given size in a
> - * given mountpoint
> - * @dev: DRM device
> - * @size: Size of the object to allocate
> - * @gemfs: tmpfs mount where the GEM object will be created
> - *
> - * This function creates a shmem GEM object in a given tmpfs mountpoint.
> - *
> - * Returns:
> - * A struct drm_gem_shmem_object * on success or an ERR_PTR()-encoded negative
> - * error code on failure.
> - */
> -struct drm_gem_shmem_object *drm_gem_shmem_create_with_mnt(struct drm_device *dev,
> - size_t size,
> - struct vfsmount *gemfs)
> -{
> - return __drm_gem_shmem_create(dev, size, false, gemfs);
> -}
> -EXPORT_SYMBOL_GPL(drm_gem_shmem_create_with_mnt);
> -
> /**
> * drm_gem_shmem_release - Release resources associated with a shmem GEM object.
> * @shmem: shmem GEM object
> @@ -878,7 +856,7 @@ drm_gem_shmem_prime_import_sg_table(struct drm_device *dev,
> size_t size = PAGE_ALIGN(attach->dmabuf->size);
> struct drm_gem_shmem_object *shmem;
>
> - shmem = __drm_gem_shmem_create(dev, size, true, NULL);
> + shmem = __drm_gem_shmem_create(dev, size, true);
> if (IS_ERR(shmem))
> return ERR_CAST(shmem);
>
> @@ -926,7 +904,7 @@ struct drm_gem_object *drm_gem_shmem_prime_import_no_map(struct drm_device *dev,
>
> size = PAGE_ALIGN(attach->dmabuf->size);
>
> - shmem = __drm_gem_shmem_create(dev, size, true, NULL);
> + shmem = __drm_gem_shmem_create(dev, size, true);
> if (IS_ERR(shmem)) {
> ret = PTR_ERR(shmem);
> goto fail_detach;
> diff --git a/drivers/gpu/drm/v3d/v3d_bo.c b/drivers/gpu/drm/v3d/v3d_bo.c
> index 6b9909bfce82..ef9e9c15da3c 100644
> --- a/drivers/gpu/drm/v3d/v3d_bo.c
> +++ b/drivers/gpu/drm/v3d/v3d_bo.c
> @@ -151,8 +151,7 @@ struct v3d_bo *v3d_bo_create(struct drm_device *dev, struct drm_file *file_priv,
> struct v3d_bo *bo;
> int ret;
>
> - shmem_obj = drm_gem_shmem_create_with_mnt(dev, unaligned_size,
> - dev->huge_mnt);
> + shmem_obj = drm_gem_shmem_create(dev, unaligned_size);
> if (IS_ERR(shmem_obj))
> return ERR_CAST(shmem_obj);
> bo = to_v3d_bo(&shmem_obj->base);
> diff --git a/include/drm/drm_gem.h b/include/drm/drm_gem.h
> index 7285a62d9afc..42d9066b1785 100644
> --- a/include/drm/drm_gem.h
> +++ b/include/drm/drm_gem.h
> @@ -497,9 +497,6 @@ void drm_gem_object_release(struct drm_gem_object *obj);
> void drm_gem_object_free(struct kref *kref);
> int drm_gem_object_init(struct drm_device *dev,
> struct drm_gem_object *obj, size_t size);
> -int drm_gem_object_init_with_mnt(struct drm_device *dev,
> - struct drm_gem_object *obj, size_t size,
> - struct vfsmount *gemfs);
> void drm_gem_private_object_init(struct drm_device *dev,
> struct drm_gem_object *obj, size_t size);
> void drm_gem_private_object_fini(struct drm_gem_object *obj);
> diff --git a/include/drm/drm_gem_shmem_helper.h b/include/drm/drm_gem_shmem_helper.h
> index 589f7bfe7506..6b6478f5ca24 100644
> --- a/include/drm/drm_gem_shmem_helper.h
> +++ b/include/drm/drm_gem_shmem_helper.h
> @@ -109,9 +109,6 @@ struct drm_gem_shmem_object {
>
> int drm_gem_shmem_init(struct drm_device *dev, struct drm_gem_shmem_object *shmem, size_t size);
> struct drm_gem_shmem_object *drm_gem_shmem_create(struct drm_device *dev, size_t size);
> -struct drm_gem_shmem_object *drm_gem_shmem_create_with_mnt(struct drm_device *dev,
> - size_t size,
> - struct vfsmount *gemfs);
> void drm_gem_shmem_release(struct drm_gem_shmem_object *shmem);
> void drm_gem_shmem_free(struct drm_gem_shmem_object *shmem);
>
^ permalink raw reply [flat|nested] 26+ messages in thread
* [PATCH v3 07/10] drm/panthor: Introduce huge tmpfs mount point option
2025-10-04 9:30 [PATCH v3 00/10] drm: Reduce page tables overhead with THP Loïc Molinari
` (5 preceding siblings ...)
2025-10-04 9:30 ` [PATCH v3 06/10] drm/gem: Get rid of *_with_mnt helpers Loïc Molinari
@ 2025-10-04 9:30 ` Loïc Molinari
2025-10-06 7:28 ` Boris Brezillon
2025-10-06 7:34 ` Boris Brezillon
2025-10-04 9:30 ` [PATCH v3 08/10] drm/panthor: Improve IOMMU map/unmap debugging logs Loïc Molinari
` (2 subsequent siblings)
9 siblings, 2 replies; 26+ messages in thread
From: Loïc Molinari @ 2025-10-04 9:30 UTC (permalink / raw)
To: Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann,
David Airlie, Simona Vetter, Jani Nikula, Joonas Lahtinen,
Rodrigo Vivi, Tvrtko Ursulin, Boris Brezillon, Rob Herring,
Steven Price, Liviu Dudau, Melissa Wen, Maíra Canal,
Hugh Dickins, Baolin Wang, Andrew Morton, Loïc Molinari,
Al Viro, Mikołaj Wasiak, Christian Brauner, Nitin Gote,
Andi Shyti, Christopher Healy
Cc: linux-kernel, dri-devel, intel-gfx, linux-mm, kernel
Introduce the 'panthor.transparent_hugepage' boolean module parameter
(false by default). When the parameter is set to true, a new tmpfs
mount point is created and mounted using the 'huge=within_size'
option. It's then used at GEM object creation instead of the default
'shm_mnt' mount point in order to enable Transparent Hugepage (THP)
for the object (without having to rely on a system wide parameter).
v3:
- use huge tmpfs mountpoint in drm_device
Signed-off-by: Loïc Molinari <loic.molinari@collabora.com>
---
drivers/gpu/drm/panthor/panthor_device.c | 3 +++
drivers/gpu/drm/panthor/panthor_drv.c | 7 +++++++
drivers/gpu/drm/panthor/panthor_drv.h | 11 +++++++++++
drivers/gpu/drm/panthor/panthor_gem.c | 19 +++++++++++++++++++
drivers/gpu/drm/panthor/panthor_gem.h | 2 ++
5 files changed, 42 insertions(+)
create mode 100644 drivers/gpu/drm/panthor/panthor_drv.h
diff --git a/drivers/gpu/drm/panthor/panthor_device.c b/drivers/gpu/drm/panthor/panthor_device.c
index 81df49880bd8..3c0387156bb9 100644
--- a/drivers/gpu/drm/panthor/panthor_device.c
+++ b/drivers/gpu/drm/panthor/panthor_device.c
@@ -17,6 +17,7 @@
#include "panthor_devfreq.h"
#include "panthor_device.h"
#include "panthor_fw.h"
+#include "panthor_gem.h"
#include "panthor_gpu.h"
#include "panthor_hw.h"
#include "panthor_mmu.h"
@@ -269,6 +270,8 @@ int panthor_device_init(struct panthor_device *ptdev)
if (ret)
goto err_unplug_fw;
+ panthor_gem_init(ptdev);
+
/* ~3 frames */
pm_runtime_set_autosuspend_delay(ptdev->base.dev, 50);
pm_runtime_use_autosuspend(ptdev->base.dev);
diff --git a/drivers/gpu/drm/panthor/panthor_drv.c b/drivers/gpu/drm/panthor/panthor_drv.c
index fdbe89ef7f43..a2be3b904ca2 100644
--- a/drivers/gpu/drm/panthor/panthor_drv.c
+++ b/drivers/gpu/drm/panthor/panthor_drv.c
@@ -1556,6 +1556,7 @@ static const struct file_operations panthor_drm_driver_fops = {
.read = drm_read,
.llseek = noop_llseek,
.mmap = panthor_mmap,
+ .get_unmapped_area = drm_gem_get_unmapped_area,
.show_fdinfo = drm_show_fdinfo,
.fop_flags = FOP_UNSIGNED_OFFSET,
};
@@ -1623,6 +1624,12 @@ static const struct drm_driver panthor_drm_driver = {
#endif
};
+#ifdef CONFIG_TRANSPARENT_HUGEPAGE
+bool panthor_transparent_hugepage;
+module_param_named(transparent_hugepage, panthor_transparent_hugepage, bool, 0400);
+MODULE_PARM_DESC(transparent_hugepage, "Use a dedicated tmpfs mount point with Transparent Hugepage enabled (false = default)");
+#endif
+
static int panthor_probe(struct platform_device *pdev)
{
struct panthor_device *ptdev;
diff --git a/drivers/gpu/drm/panthor/panthor_drv.h b/drivers/gpu/drm/panthor/panthor_drv.h
new file mode 100644
index 000000000000..27fe9b6f77bd
--- /dev/null
+++ b/drivers/gpu/drm/panthor/panthor_drv.h
@@ -0,0 +1,11 @@
+// SPDX-License-Identifier: GPL-2.0 or MIT
+/* Copyright 2025 Amazon.com, Inc. or its affiliates */
+
+#ifndef __PANTHOR_DRV_H__
+#define __PANTHOR_DRV_H__
+
+#ifdef CONFIG_TRANSPARENT_HUGEPAGE
+extern bool panthor_transparent_hugepage;
+#endif
+
+#endif
diff --git a/drivers/gpu/drm/panthor/panthor_gem.c b/drivers/gpu/drm/panthor/panthor_gem.c
index 156c7a0b62a2..49b7d288bfdf 100644
--- a/drivers/gpu/drm/panthor/panthor_gem.c
+++ b/drivers/gpu/drm/panthor/panthor_gem.c
@@ -1,6 +1,7 @@
// SPDX-License-Identifier: GPL-2.0 or MIT
/* Copyright 2019 Linaro, Ltd, Rob Herring <robh@kernel.org> */
/* Copyright 2023 Collabora ltd. */
+/* Copyright 2025 Amazon.com, Inc. or its affiliates */
#include <linux/cleanup.h>
#include <linux/dma-buf.h>
@@ -11,10 +12,28 @@
#include <drm/panthor_drm.h>
#include "panthor_device.h"
+#include "panthor_drv.h"
#include "panthor_fw.h"
#include "panthor_gem.h"
#include "panthor_mmu.h"
+void panthor_gem_init(struct panthor_device *ptdev)
+{
+ int err;
+
+ if (!panthor_transparent_hugepage)
+ return;
+
+ err = drm_gem_huge_mnt_create(&ptdev->base, "within_size");
+ if (err && err != -EEXIST) {
+ drm_warn(&ptdev->base, "Can't use Transparent Hugepage (%d)\n",
+ -err);
+ return;
+ }
+
+ drm_info(&ptdev->base, "Using Transparent Hugepage\n");
+}
+
#ifdef CONFIG_DEBUG_FS
static void panthor_gem_debugfs_bo_init(struct panthor_gem_object *bo)
{
diff --git a/drivers/gpu/drm/panthor/panthor_gem.h b/drivers/gpu/drm/panthor/panthor_gem.h
index 80c6e24112d0..2eefe9104e5e 100644
--- a/drivers/gpu/drm/panthor/panthor_gem.h
+++ b/drivers/gpu/drm/panthor/panthor_gem.h
@@ -136,6 +136,8 @@ struct panthor_gem_object *to_panthor_bo(struct drm_gem_object *obj)
return container_of(to_drm_gem_shmem_obj(obj), struct panthor_gem_object, base);
}
+void panthor_gem_init(struct panthor_device *ptdev);
+
struct drm_gem_object *panthor_gem_create_object(struct drm_device *ddev, size_t size);
int
--
2.47.3
^ permalink raw reply [flat|nested] 26+ messages in thread* Re: [PATCH v3 07/10] drm/panthor: Introduce huge tmpfs mount point option
2025-10-04 9:30 ` [PATCH v3 07/10] drm/panthor: Introduce huge tmpfs mount point option Loïc Molinari
@ 2025-10-06 7:28 ` Boris Brezillon
2025-10-15 13:09 ` Loïc Molinari
2025-10-06 7:34 ` Boris Brezillon
1 sibling, 1 reply; 26+ messages in thread
From: Boris Brezillon @ 2025-10-06 7:28 UTC (permalink / raw)
To: Loïc Molinari
Cc: Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann,
David Airlie, Simona Vetter, Jani Nikula, Joonas Lahtinen,
Rodrigo Vivi, Tvrtko Ursulin, Rob Herring, Steven Price,
Liviu Dudau, Melissa Wen, Maíra Canal, Hugh Dickins,
Baolin Wang, Andrew Morton, Al Viro, Mikołaj Wasiak,
Christian Brauner, Nitin Gote, Andi Shyti, Christopher Healy,
linux-kernel, dri-devel, intel-gfx, linux-mm, kernel
On Sat, 4 Oct 2025 11:30:50 +0200
Loïc Molinari <loic.molinari@collabora.com> wrote:
> Introduce the 'panthor.transparent_hugepage' boolean module parameter
> (false by default). When the parameter is set to true, a new tmpfs
> mount point is created and mounted using the 'huge=within_size'
> option. It's then used at GEM object creation instead of the default
> 'shm_mnt' mount point in order to enable Transparent Hugepage (THP)
> for the object (without having to rely on a system wide parameter).
>
> v3:
> - use huge tmpfs mountpoint in drm_device
>
> Signed-off-by: Loïc Molinari <loic.molinari@collabora.com>
> ---
> drivers/gpu/drm/panthor/panthor_device.c | 3 +++
> drivers/gpu/drm/panthor/panthor_drv.c | 7 +++++++
> drivers/gpu/drm/panthor/panthor_drv.h | 11 +++++++++++
> drivers/gpu/drm/panthor/panthor_gem.c | 19 +++++++++++++++++++
> drivers/gpu/drm/panthor/panthor_gem.h | 2 ++
> 5 files changed, 42 insertions(+)
> create mode 100644 drivers/gpu/drm/panthor/panthor_drv.h
>
> diff --git a/drivers/gpu/drm/panthor/panthor_device.c b/drivers/gpu/drm/panthor/panthor_device.c
> index 81df49880bd8..3c0387156bb9 100644
> --- a/drivers/gpu/drm/panthor/panthor_device.c
> +++ b/drivers/gpu/drm/panthor/panthor_device.c
> @@ -17,6 +17,7 @@
> #include "panthor_devfreq.h"
> #include "panthor_device.h"
> #include "panthor_fw.h"
> +#include "panthor_gem.h"
> #include "panthor_gpu.h"
> #include "panthor_hw.h"
> #include "panthor_mmu.h"
> @@ -269,6 +270,8 @@ int panthor_device_init(struct panthor_device *ptdev)
> if (ret)
> goto err_unplug_fw;
>
> + panthor_gem_init(ptdev);
> +
> /* ~3 frames */
> pm_runtime_set_autosuspend_delay(ptdev->base.dev, 50);
> pm_runtime_use_autosuspend(ptdev->base.dev);
> diff --git a/drivers/gpu/drm/panthor/panthor_drv.c b/drivers/gpu/drm/panthor/panthor_drv.c
> index fdbe89ef7f43..a2be3b904ca2 100644
> --- a/drivers/gpu/drm/panthor/panthor_drv.c
> +++ b/drivers/gpu/drm/panthor/panthor_drv.c
> @@ -1556,6 +1556,7 @@ static const struct file_operations panthor_drm_driver_fops = {
> .read = drm_read,
> .llseek = noop_llseek,
> .mmap = panthor_mmap,
> + .get_unmapped_area = drm_gem_get_unmapped_area,
> .show_fdinfo = drm_show_fdinfo,
> .fop_flags = FOP_UNSIGNED_OFFSET,
> };
> @@ -1623,6 +1624,12 @@ static const struct drm_driver panthor_drm_driver = {
> #endif
> };
>
> +#ifdef CONFIG_TRANSPARENT_HUGEPAGE
> +bool panthor_transparent_hugepage;
> +module_param_named(transparent_hugepage, panthor_transparent_hugepage, bool, 0400);
> +MODULE_PARM_DESC(transparent_hugepage, "Use a dedicated tmpfs mount point with Transparent Hugepage enabled (false = default)");
nit: I'd go for a slightly shorter name, like [panthor_]enable_thp.
The patch is
Reviewed-by: Boris Brezillon <boris.brezillon@collabora.com>
regardless.
> +#endif
> +
> static int panthor_probe(struct platform_device *pdev)
> {
> struct panthor_device *ptdev;
> diff --git a/drivers/gpu/drm/panthor/panthor_drv.h b/drivers/gpu/drm/panthor/panthor_drv.h
> new file mode 100644
> index 000000000000..27fe9b6f77bd
> --- /dev/null
> +++ b/drivers/gpu/drm/panthor/panthor_drv.h
> @@ -0,0 +1,11 @@
> +// SPDX-License-Identifier: GPL-2.0 or MIT
> +/* Copyright 2025 Amazon.com, Inc. or its affiliates */
> +
> +#ifndef __PANTHOR_DRV_H__
> +#define __PANTHOR_DRV_H__
> +
> +#ifdef CONFIG_TRANSPARENT_HUGEPAGE
> +extern bool panthor_transparent_hugepage;
> +#endif
> +
> +#endif
> diff --git a/drivers/gpu/drm/panthor/panthor_gem.c b/drivers/gpu/drm/panthor/panthor_gem.c
> index 156c7a0b62a2..49b7d288bfdf 100644
> --- a/drivers/gpu/drm/panthor/panthor_gem.c
> +++ b/drivers/gpu/drm/panthor/panthor_gem.c
> @@ -1,6 +1,7 @@
> // SPDX-License-Identifier: GPL-2.0 or MIT
> /* Copyright 2019 Linaro, Ltd, Rob Herring <robh@kernel.org> */
> /* Copyright 2023 Collabora ltd. */
> +/* Copyright 2025 Amazon.com, Inc. or its affiliates */
>
> #include <linux/cleanup.h>
> #include <linux/dma-buf.h>
> @@ -11,10 +12,28 @@
> #include <drm/panthor_drm.h>
>
> #include "panthor_device.h"
> +#include "panthor_drv.h"
> #include "panthor_fw.h"
> #include "panthor_gem.h"
> #include "panthor_mmu.h"
>
> +void panthor_gem_init(struct panthor_device *ptdev)
> +{
> + int err;
> +
> + if (!panthor_transparent_hugepage)
> + return;
> +
> + err = drm_gem_huge_mnt_create(&ptdev->base, "within_size");
> + if (err && err != -EEXIST) {
> + drm_warn(&ptdev->base, "Can't use Transparent Hugepage (%d)\n",
> + -err);
> + return;
> + }
> +
> + drm_info(&ptdev->base, "Using Transparent Hugepage\n");
> +}
> +
> #ifdef CONFIG_DEBUG_FS
> static void panthor_gem_debugfs_bo_init(struct panthor_gem_object *bo)
> {
> diff --git a/drivers/gpu/drm/panthor/panthor_gem.h b/drivers/gpu/drm/panthor/panthor_gem.h
> index 80c6e24112d0..2eefe9104e5e 100644
> --- a/drivers/gpu/drm/panthor/panthor_gem.h
> +++ b/drivers/gpu/drm/panthor/panthor_gem.h
> @@ -136,6 +136,8 @@ struct panthor_gem_object *to_panthor_bo(struct drm_gem_object *obj)
> return container_of(to_drm_gem_shmem_obj(obj), struct panthor_gem_object, base);
> }
>
> +void panthor_gem_init(struct panthor_device *ptdev);
> +
> struct drm_gem_object *panthor_gem_create_object(struct drm_device *ddev, size_t size);
>
> int
^ permalink raw reply [flat|nested] 26+ messages in thread* Re: [PATCH v3 07/10] drm/panthor: Introduce huge tmpfs mount point option
2025-10-06 7:28 ` Boris Brezillon
@ 2025-10-15 13:09 ` Loïc Molinari
2025-10-15 13:12 ` Boris Brezillon
0 siblings, 1 reply; 26+ messages in thread
From: Loïc Molinari @ 2025-10-15 13:09 UTC (permalink / raw)
To: Boris Brezillon
Cc: Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann,
David Airlie, Simona Vetter, Jani Nikula, Joonas Lahtinen,
Rodrigo Vivi, Tvrtko Ursulin, Rob Herring, Steven Price,
Liviu Dudau, Melissa Wen, Maíra Canal, Hugh Dickins,
Baolin Wang, Andrew Morton, Al Viro, Mikołaj Wasiak,
Christian Brauner, Nitin Gote, Andi Shyti, Christopher Healy,
linux-kernel, dri-devel, intel-gfx, linux-mm, kernel
On 06/10/2025 09:28, Boris Brezillon wrote:
> On Sat, 4 Oct 2025 11:30:50 +0200
> Loïc Molinari <loic.molinari@collabora.com> wrote:
>
>> diff --git a/drivers/gpu/drm/panthor/panthor_drv.c b/drivers/gpu/drm/panthor/panthor_drv.c
>> index fdbe89ef7f43..a2be3b904ca2 100644
>> --- a/drivers/gpu/drm/panthor/panthor_drv.c
>> +++ b/drivers/gpu/drm/panthor/panthor_drv.c
>> @@ -1623,6 +1624,12 @@ static const struct drm_driver panthor_drm_driver = {
>> #endif
>> };
>>
>> +#ifdef CONFIG_TRANSPARENT_HUGEPAGE
>> +bool panthor_transparent_hugepage;
>> +module_param_named(transparent_hugepage, panthor_transparent_hugepage, bool, 0400);
>> +MODULE_PARM_DESC(transparent_hugepage, "Use a dedicated tmpfs mount point with Transparent Hugepage enabled (false = default)");
>
> nit: I'd go for a slightly shorter name, like [panthor_]enable_thp.
For v4, in order to be consistent with the "transparent_hugepage*"
kernel parameters, I'd prefer to keep the "panthor.transparent_hugepage"
(and "panfrost.transparent_hugepage") module parameter name
I could keep the parameter name as is and change the variable name though.
> The patch is
>
> Reviewed-by: Boris Brezillon <boris.brezillon@collabora.com>
>
> regardless.
>
^ permalink raw reply [flat|nested] 26+ messages in thread* Re: [PATCH v3 07/10] drm/panthor: Introduce huge tmpfs mount point option
2025-10-15 13:09 ` Loïc Molinari
@ 2025-10-15 13:12 ` Boris Brezillon
0 siblings, 0 replies; 26+ messages in thread
From: Boris Brezillon @ 2025-10-15 13:12 UTC (permalink / raw)
To: Loïc Molinari
Cc: Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann,
David Airlie, Simona Vetter, Jani Nikula, Joonas Lahtinen,
Rodrigo Vivi, Tvrtko Ursulin, Rob Herring, Steven Price,
Liviu Dudau, Melissa Wen, Maíra Canal, Hugh Dickins,
Baolin Wang, Andrew Morton, Al Viro, Mikołaj Wasiak,
Christian Brauner, Nitin Gote, Andi Shyti, Christopher Healy,
linux-kernel, dri-devel, intel-gfx, linux-mm, kernel
On Wed, 15 Oct 2025 15:09:31 +0200
Loïc Molinari <loic.molinari@collabora.com> wrote:
> On 06/10/2025 09:28, Boris Brezillon wrote:
> > On Sat, 4 Oct 2025 11:30:50 +0200
> > Loïc Molinari <loic.molinari@collabora.com> wrote:
> >
> >> diff --git a/drivers/gpu/drm/panthor/panthor_drv.c b/drivers/gpu/drm/panthor/panthor_drv.c
> >> index fdbe89ef7f43..a2be3b904ca2 100644
> >> --- a/drivers/gpu/drm/panthor/panthor_drv.c
> >> +++ b/drivers/gpu/drm/panthor/panthor_drv.c
> >> @@ -1623,6 +1624,12 @@ static const struct drm_driver panthor_drm_driver = {
> >> #endif
> >> };
> >>
> >> +#ifdef CONFIG_TRANSPARENT_HUGEPAGE
> >> +bool panthor_transparent_hugepage;
> >> +module_param_named(transparent_hugepage, panthor_transparent_hugepage, bool, 0400);
> >> +MODULE_PARM_DESC(transparent_hugepage, "Use a dedicated tmpfs mount point with Transparent Hugepage enabled (false = default)");
> >
> > nit: I'd go for a slightly shorter name, like [panthor_]enable_thp.
>
> For v4, in order to be consistent with the "transparent_hugepage*"
> kernel parameters, I'd prefer to keep the "panthor.transparent_hugepage"
> (and "panfrost.transparent_hugepage") module parameter name
>
> I could keep the parameter name as is and change the variable name though.
Fair enough. Let's just keep things as they are in this version.
>
> > The patch is
> >
> > Reviewed-by: Boris Brezillon <boris.brezillon@collabora.com>
> >
> > regardless.
> >
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [PATCH v3 07/10] drm/panthor: Introduce huge tmpfs mount point option
2025-10-04 9:30 ` [PATCH v3 07/10] drm/panthor: Introduce huge tmpfs mount point option Loïc Molinari
2025-10-06 7:28 ` Boris Brezillon
@ 2025-10-06 7:34 ` Boris Brezillon
1 sibling, 0 replies; 26+ messages in thread
From: Boris Brezillon @ 2025-10-06 7:34 UTC (permalink / raw)
To: Loïc Molinari
Cc: Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann,
David Airlie, Simona Vetter, Jani Nikula, Joonas Lahtinen,
Rodrigo Vivi, Tvrtko Ursulin, Rob Herring, Steven Price,
Liviu Dudau, Melissa Wen, Maíra Canal, Hugh Dickins,
Baolin Wang, Andrew Morton, Al Viro, Mikołaj Wasiak,
Christian Brauner, Nitin Gote, Andi Shyti, Christopher Healy,
linux-kernel, dri-devel, intel-gfx, linux-mm, kernel
On Sat, 4 Oct 2025 11:30:50 +0200
Loïc Molinari <loic.molinari@collabora.com> wrote:
> Introduce the 'panthor.transparent_hugepage' boolean module parameter
> (false by default). When the parameter is set to true, a new tmpfs
> mount point is created and mounted using the 'huge=within_size'
> option. It's then used at GEM object creation instead of the default
> 'shm_mnt' mount point in order to enable Transparent Hugepage (THP)
> for the object (without having to rely on a system wide parameter).
>
> v3:
> - use huge tmpfs mountpoint in drm_device
>
> Signed-off-by: Loïc Molinari <loic.molinari@collabora.com>
> ---
> drivers/gpu/drm/panthor/panthor_device.c | 3 +++
> drivers/gpu/drm/panthor/panthor_drv.c | 7 +++++++
> drivers/gpu/drm/panthor/panthor_drv.h | 11 +++++++++++
> drivers/gpu/drm/panthor/panthor_gem.c | 19 +++++++++++++++++++
> drivers/gpu/drm/panthor/panthor_gem.h | 2 ++
> 5 files changed, 42 insertions(+)
> create mode 100644 drivers/gpu/drm/panthor/panthor_drv.h
>
> diff --git a/drivers/gpu/drm/panthor/panthor_device.c b/drivers/gpu/drm/panthor/panthor_device.c
> index 81df49880bd8..3c0387156bb9 100644
> --- a/drivers/gpu/drm/panthor/panthor_device.c
> +++ b/drivers/gpu/drm/panthor/panthor_device.c
> @@ -17,6 +17,7 @@
> #include "panthor_devfreq.h"
> #include "panthor_device.h"
> #include "panthor_fw.h"
> +#include "panthor_gem.h"
> #include "panthor_gpu.h"
> #include "panthor_hw.h"
> #include "panthor_mmu.h"
> @@ -269,6 +270,8 @@ int panthor_device_init(struct panthor_device *ptdev)
> if (ret)
> goto err_unplug_fw;
>
> + panthor_gem_init(ptdev);
> +
> /* ~3 frames */
> pm_runtime_set_autosuspend_delay(ptdev->base.dev, 50);
> pm_runtime_use_autosuspend(ptdev->base.dev);
> diff --git a/drivers/gpu/drm/panthor/panthor_drv.c b/drivers/gpu/drm/panthor/panthor_drv.c
> index fdbe89ef7f43..a2be3b904ca2 100644
> --- a/drivers/gpu/drm/panthor/panthor_drv.c
> +++ b/drivers/gpu/drm/panthor/panthor_drv.c
> @@ -1556,6 +1556,7 @@ static const struct file_operations panthor_drm_driver_fops = {
> .read = drm_read,
> .llseek = noop_llseek,
> .mmap = panthor_mmap,
> + .get_unmapped_area = drm_gem_get_unmapped_area,
> .show_fdinfo = drm_show_fdinfo,
> .fop_flags = FOP_UNSIGNED_OFFSET,
> };
> @@ -1623,6 +1624,12 @@ static const struct drm_driver panthor_drm_driver = {
> #endif
> };
>
> +#ifdef CONFIG_TRANSPARENT_HUGEPAGE
> +bool panthor_transparent_hugepage;
> +module_param_named(transparent_hugepage, panthor_transparent_hugepage, bool, 0400);
> +MODULE_PARM_DESC(transparent_hugepage, "Use a dedicated tmpfs mount point with Transparent Hugepage enabled (false = default)");
> +#endif
> +
> static int panthor_probe(struct platform_device *pdev)
> {
> struct panthor_device *ptdev;
> diff --git a/drivers/gpu/drm/panthor/panthor_drv.h b/drivers/gpu/drm/panthor/panthor_drv.h
> new file mode 100644
> index 000000000000..27fe9b6f77bd
> --- /dev/null
> +++ b/drivers/gpu/drm/panthor/panthor_drv.h
> @@ -0,0 +1,11 @@
> +// SPDX-License-Identifier: GPL-2.0 or MIT
> +/* Copyright 2025 Amazon.com, Inc. or its affiliates */
> +
> +#ifndef __PANTHOR_DRV_H__
> +#define __PANTHOR_DRV_H__
> +
> +#ifdef CONFIG_TRANSPARENT_HUGEPAGE
> +extern bool panthor_transparent_hugepage;
> +#endif
> +
> +#endif
> diff --git a/drivers/gpu/drm/panthor/panthor_gem.c b/drivers/gpu/drm/panthor/panthor_gem.c
> index 156c7a0b62a2..49b7d288bfdf 100644
> --- a/drivers/gpu/drm/panthor/panthor_gem.c
> +++ b/drivers/gpu/drm/panthor/panthor_gem.c
> @@ -1,6 +1,7 @@
> // SPDX-License-Identifier: GPL-2.0 or MIT
> /* Copyright 2019 Linaro, Ltd, Rob Herring <robh@kernel.org> */
> /* Copyright 2023 Collabora ltd. */
> +/* Copyright 2025 Amazon.com, Inc. or its affiliates */
>
> #include <linux/cleanup.h>
> #include <linux/dma-buf.h>
> @@ -11,10 +12,28 @@
> #include <drm/panthor_drm.h>
>
> #include "panthor_device.h"
> +#include "panthor_drv.h"
> #include "panthor_fw.h"
> #include "panthor_gem.h"
> #include "panthor_mmu.h"
>
> +void panthor_gem_init(struct panthor_device *ptdev)
> +{
> + int err;
> +
> + if (!panthor_transparent_hugepage)
> + return;
> +
> + err = drm_gem_huge_mnt_create(&ptdev->base, "within_size");
> + if (err && err != -EEXIST) {
> + drm_warn(&ptdev->base, "Can't use Transparent Hugepage (%d)\n",
> + -err);
> + return;
> + }
> +
> + drm_info(&ptdev->base, "Using Transparent Hugepage\n");
if (err)
drm_warn(&ptdev->base, "Can't use Transparent Hugepage (err=%d)\n", err);
else
drm_info(&ptdev->base, "Using Transparent Hugepage\n");
> +}
> +
> #ifdef CONFIG_DEBUG_FS
> static void panthor_gem_debugfs_bo_init(struct panthor_gem_object *bo)
> {
> diff --git a/drivers/gpu/drm/panthor/panthor_gem.h b/drivers/gpu/drm/panthor/panthor_gem.h
> index 80c6e24112d0..2eefe9104e5e 100644
> --- a/drivers/gpu/drm/panthor/panthor_gem.h
> +++ b/drivers/gpu/drm/panthor/panthor_gem.h
> @@ -136,6 +136,8 @@ struct panthor_gem_object *to_panthor_bo(struct drm_gem_object *obj)
> return container_of(to_drm_gem_shmem_obj(obj), struct panthor_gem_object, base);
> }
>
> +void panthor_gem_init(struct panthor_device *ptdev);
> +
> struct drm_gem_object *panthor_gem_create_object(struct drm_device *ddev, size_t size);
>
> int
^ permalink raw reply [flat|nested] 26+ messages in thread
* [PATCH v3 08/10] drm/panthor: Improve IOMMU map/unmap debugging logs
2025-10-04 9:30 [PATCH v3 00/10] drm: Reduce page tables overhead with THP Loïc Molinari
` (6 preceding siblings ...)
2025-10-04 9:30 ` [PATCH v3 07/10] drm/panthor: Introduce huge tmpfs mount point option Loïc Molinari
@ 2025-10-04 9:30 ` Loïc Molinari
2025-10-04 9:30 ` [PATCH v3 09/10] drm/panfrost: Introduce huge tmpfs mount point option Loïc Molinari
2025-10-04 9:30 ` [PATCH v3 10/10] Documentation/gpu/drm-mm: Add THP paragraph to GEM mapping section Loïc Molinari
9 siblings, 0 replies; 26+ messages in thread
From: Loïc Molinari @ 2025-10-04 9:30 UTC (permalink / raw)
To: Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann,
David Airlie, Simona Vetter, Jani Nikula, Joonas Lahtinen,
Rodrigo Vivi, Tvrtko Ursulin, Boris Brezillon, Rob Herring,
Steven Price, Liviu Dudau, Melissa Wen, Maíra Canal,
Hugh Dickins, Baolin Wang, Andrew Morton, Loïc Molinari,
Al Viro, Mikołaj Wasiak, Christian Brauner, Nitin Gote,
Andi Shyti, Christopher Healy
Cc: linux-kernel, dri-devel, intel-gfx, linux-mm, kernel
Log the number of pages and their sizes actually mapped/unmapped by
the IOMMU page table driver. Since a map/unmap op is often split in
several ops depending on the underlying scatter/gather table, add the
start address and the total size to the debugging logs in order to
help understand which batch an op is part of.
Signed-off-by: Loïc Molinari <loic.molinari@collabora.com>
Reviewed-by: Boris Brezillon <boris.brezillon@collabora.com>
---
drivers/gpu/drm/panthor/panthor_mmu.c | 19 ++++++++++++++-----
1 file changed, 14 insertions(+), 5 deletions(-)
diff --git a/drivers/gpu/drm/panthor/panthor_mmu.c b/drivers/gpu/drm/panthor/panthor_mmu.c
index 6dec4354e378..aefbd83d1a75 100644
--- a/drivers/gpu/drm/panthor/panthor_mmu.c
+++ b/drivers/gpu/drm/panthor/panthor_mmu.c
@@ -917,10 +917,9 @@ static int panthor_vm_unmap_pages(struct panthor_vm *vm, u64 iova, u64 size)
{
struct panthor_device *ptdev = vm->ptdev;
struct io_pgtable_ops *ops = vm->pgtbl_ops;
+ u64 start_iova = iova;
u64 offset = 0;
- drm_dbg(&ptdev->base, "unmap: as=%d, iova=%llx, len=%llx", vm->as.id, iova, size);
-
while (offset < size) {
size_t unmapped_sz = 0, pgcount;
size_t pgsize = get_pgsize(iova + offset, size - offset, &pgcount);
@@ -935,6 +934,12 @@ static int panthor_vm_unmap_pages(struct panthor_vm *vm, u64 iova, u64 size)
panthor_vm_flush_range(vm, iova, offset + unmapped_sz);
return -EINVAL;
}
+
+ drm_dbg(&ptdev->base,
+ "unmap: as=%d, iova=0x%llx, sz=%llu, va=0x%llx, pgcnt=%zu, pgsz=%zu",
+ vm->as.id, start_iova, size, iova + offset,
+ unmapped_sz / pgsize, pgsize);
+
offset += unmapped_sz;
}
@@ -950,6 +955,7 @@ panthor_vm_map_pages(struct panthor_vm *vm, u64 iova, int prot,
struct scatterlist *sgl;
struct io_pgtable_ops *ops = vm->pgtbl_ops;
u64 start_iova = iova;
+ u64 start_size = size;
int ret;
if (!size)
@@ -969,15 +975,18 @@ panthor_vm_map_pages(struct panthor_vm *vm, u64 iova, int prot,
len = min_t(size_t, len, size);
size -= len;
- drm_dbg(&ptdev->base, "map: as=%d, iova=%llx, paddr=%pad, len=%zx",
- vm->as.id, iova, &paddr, len);
-
while (len) {
size_t pgcount, mapped = 0;
size_t pgsize = get_pgsize(iova | paddr, len, &pgcount);
ret = ops->map_pages(ops, iova, paddr, pgsize, pgcount, prot,
GFP_KERNEL, &mapped);
+
+ drm_dbg(&ptdev->base,
+ "map: as=%d, iova=0x%llx, sz=%llu, va=0x%llx, pa=%pad, pgcnt=%zu, pgsz=%zu",
+ vm->as.id, start_iova, start_size, iova, &paddr,
+ mapped / pgsize, pgsize);
+
iova += mapped;
paddr += mapped;
len -= mapped;
--
2.47.3
^ permalink raw reply [flat|nested] 26+ messages in thread* [PATCH v3 09/10] drm/panfrost: Introduce huge tmpfs mount point option
2025-10-04 9:30 [PATCH v3 00/10] drm: Reduce page tables overhead with THP Loïc Molinari
` (7 preceding siblings ...)
2025-10-04 9:30 ` [PATCH v3 08/10] drm/panthor: Improve IOMMU map/unmap debugging logs Loïc Molinari
@ 2025-10-04 9:30 ` Loïc Molinari
2025-10-06 7:33 ` Boris Brezillon
2025-10-04 9:30 ` [PATCH v3 10/10] Documentation/gpu/drm-mm: Add THP paragraph to GEM mapping section Loïc Molinari
9 siblings, 1 reply; 26+ messages in thread
From: Loïc Molinari @ 2025-10-04 9:30 UTC (permalink / raw)
To: Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann,
David Airlie, Simona Vetter, Jani Nikula, Joonas Lahtinen,
Rodrigo Vivi, Tvrtko Ursulin, Boris Brezillon, Rob Herring,
Steven Price, Liviu Dudau, Melissa Wen, Maíra Canal,
Hugh Dickins, Baolin Wang, Andrew Morton, Loïc Molinari,
Al Viro, Mikołaj Wasiak, Christian Brauner, Nitin Gote,
Andi Shyti, Christopher Healy
Cc: linux-kernel, dri-devel, intel-gfx, linux-mm, kernel
Introduce the 'panfrost.transparent_hugepage' boolean module parameter
(false by default). When the parameter is set to true, a new tmpfs
mount point is created and mounted using the 'huge=within_size'
option. It's then used at GEM object creation instead of the default
'shm_mnt' mount point in order to enable Transparent Hugepage (THP)
for the object (without having to rely on a system wide parameter).
v3:
- use huge tmpfs mountpoint in drm_device
Signed-off-by: Loïc Molinari <loic.molinari@collabora.com>
---
drivers/gpu/drm/panfrost/panfrost_device.c | 3 +++
drivers/gpu/drm/panfrost/panfrost_drv.c | 6 ++++++
drivers/gpu/drm/panfrost/panfrost_drv.h | 11 +++++++++++
drivers/gpu/drm/panfrost/panfrost_gem.c | 19 +++++++++++++++++++
drivers/gpu/drm/panfrost/panfrost_gem.h | 2 ++
5 files changed, 41 insertions(+)
create mode 100644 drivers/gpu/drm/panfrost/panfrost_drv.h
diff --git a/drivers/gpu/drm/panfrost/panfrost_device.c b/drivers/gpu/drm/panfrost/panfrost_device.c
index 04bec27449cb..a189bfaac959 100644
--- a/drivers/gpu/drm/panfrost/panfrost_device.c
+++ b/drivers/gpu/drm/panfrost/panfrost_device.c
@@ -12,6 +12,7 @@
#include "panfrost_device.h"
#include "panfrost_devfreq.h"
#include "panfrost_features.h"
+#include "panfrost_gem.h"
#include "panfrost_issues.h"
#include "panfrost_gpu.h"
#include "panfrost_job.h"
@@ -266,6 +267,8 @@ int panfrost_device_init(struct panfrost_device *pfdev)
if (err)
goto out_job;
+ panfrost_gem_init(pfdev);
+
return 0;
out_job:
panfrost_job_fini(pfdev);
diff --git a/drivers/gpu/drm/panfrost/panfrost_drv.c b/drivers/gpu/drm/panfrost/panfrost_drv.c
index 22350ce8a08f..e376e70a3379 100644
--- a/drivers/gpu/drm/panfrost/panfrost_drv.c
+++ b/drivers/gpu/drm/panfrost/panfrost_drv.c
@@ -862,6 +862,12 @@ static const struct drm_driver panfrost_drm_driver = {
#endif
};
+#ifdef CONFIG_TRANSPARENT_HUGEPAGE
+bool panfrost_transparent_hugepage;
+module_param_named(transparent_hugepage, panfrost_transparent_hugepage, bool, 0400);
+MODULE_PARM_DESC(transparent_hugepage, "Use a dedicated tmpfs mount point with Transparent Hugepage enabled (false = default)");
+#endif
+
static int panfrost_probe(struct platform_device *pdev)
{
struct panfrost_device *pfdev;
diff --git a/drivers/gpu/drm/panfrost/panfrost_drv.h b/drivers/gpu/drm/panfrost/panfrost_drv.h
new file mode 100644
index 000000000000..60454611b6a6
--- /dev/null
+++ b/drivers/gpu/drm/panfrost/panfrost_drv.h
@@ -0,0 +1,11 @@
+// SPDX-License-Identifier: GPL-2.0 or MIT
+/* Copyright 2025 Amazon.com, Inc. or its affiliates */
+
+#ifndef __PANFROST_DRV_H__
+#define __PANFROST_DRV_H__
+
+#ifdef CONFIG_TRANSPARENT_HUGEPAGE
+extern bool panfrost_transparent_hugepage;
+#endif
+
+#endif
diff --git a/drivers/gpu/drm/panfrost/panfrost_gem.c b/drivers/gpu/drm/panfrost/panfrost_gem.c
index 85d6289a6eda..c3883a639e13 100644
--- a/drivers/gpu/drm/panfrost/panfrost_gem.c
+++ b/drivers/gpu/drm/panfrost/panfrost_gem.c
@@ -1,5 +1,6 @@
// SPDX-License-Identifier: GPL-2.0
/* Copyright 2019 Linaro, Ltd, Rob Herring <robh@kernel.org> */
+/* Copyright 2025 Amazon.com, Inc. or its affiliates */
#include <linux/cleanup.h>
#include <linux/err.h>
@@ -9,9 +10,27 @@
#include <drm/panfrost_drm.h>
#include "panfrost_device.h"
+#include "panfrost_drv.h"
#include "panfrost_gem.h"
#include "panfrost_mmu.h"
+void panfrost_gem_init(struct panfrost_device *pfdev)
+{
+ int err;
+
+ if (!panfrost_transparent_hugepage)
+ return;
+
+ err = drm_gem_huge_mnt_create(pfdev->ddev, "within_size");
+ if (err && err != -EEXIST) {
+ drm_warn(pfdev->ddev, "Can't use Transparent Hugepage (%d)\n",
+ -err);
+ return;
+ }
+
+ drm_info(pfdev->ddev, "Using Transparent Hugepage\n");
+}
+
#ifdef CONFIG_DEBUG_FS
static void panfrost_gem_debugfs_bo_add(struct panfrost_device *pfdev,
struct panfrost_gem_object *bo)
diff --git a/drivers/gpu/drm/panfrost/panfrost_gem.h b/drivers/gpu/drm/panfrost/panfrost_gem.h
index 8de3e76f2717..1a62529ff06f 100644
--- a/drivers/gpu/drm/panfrost/panfrost_gem.h
+++ b/drivers/gpu/drm/panfrost/panfrost_gem.h
@@ -124,6 +124,8 @@ drm_mm_node_to_panfrost_mapping(struct drm_mm_node *node)
return container_of(node, struct panfrost_gem_mapping, mmnode);
}
+void panfrost_gem_init(struct panfrost_device *pfdev);
+
struct drm_gem_object *panfrost_gem_create_object(struct drm_device *dev, size_t size);
struct drm_gem_object *
--
2.47.3
^ permalink raw reply [flat|nested] 26+ messages in thread* Re: [PATCH v3 09/10] drm/panfrost: Introduce huge tmpfs mount point option
2025-10-04 9:30 ` [PATCH v3 09/10] drm/panfrost: Introduce huge tmpfs mount point option Loïc Molinari
@ 2025-10-06 7:33 ` Boris Brezillon
0 siblings, 0 replies; 26+ messages in thread
From: Boris Brezillon @ 2025-10-06 7:33 UTC (permalink / raw)
To: Loïc Molinari
Cc: Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann,
David Airlie, Simona Vetter, Jani Nikula, Joonas Lahtinen,
Rodrigo Vivi, Tvrtko Ursulin, Rob Herring, Steven Price,
Liviu Dudau, Melissa Wen, Maíra Canal, Hugh Dickins,
Baolin Wang, Andrew Morton, Al Viro, Mikołaj Wasiak,
Christian Brauner, Nitin Gote, Andi Shyti, Christopher Healy,
linux-kernel, dri-devel, intel-gfx, linux-mm, kernel
On Sat, 4 Oct 2025 11:30:52 +0200
Loïc Molinari <loic.molinari@collabora.com> wrote:
> Introduce the 'panfrost.transparent_hugepage' boolean module parameter
> (false by default). When the parameter is set to true, a new tmpfs
> mount point is created and mounted using the 'huge=within_size'
> option. It's then used at GEM object creation instead of the default
> 'shm_mnt' mount point in order to enable Transparent Hugepage (THP)
> for the object (without having to rely on a system wide parameter).
>
> v3:
> - use huge tmpfs mountpoint in drm_device
>
> Signed-off-by: Loïc Molinari <loic.molinari@collabora.com>
Reviewed-by: Boris Brezillon <boris.brezillon@collabora.com>
A couple minor nits below.
> ---
> drivers/gpu/drm/panfrost/panfrost_device.c | 3 +++
> drivers/gpu/drm/panfrost/panfrost_drv.c | 6 ++++++
> drivers/gpu/drm/panfrost/panfrost_drv.h | 11 +++++++++++
> drivers/gpu/drm/panfrost/panfrost_gem.c | 19 +++++++++++++++++++
> drivers/gpu/drm/panfrost/panfrost_gem.h | 2 ++
> 5 files changed, 41 insertions(+)
> create mode 100644 drivers/gpu/drm/panfrost/panfrost_drv.h
>
> diff --git a/drivers/gpu/drm/panfrost/panfrost_device.c b/drivers/gpu/drm/panfrost/panfrost_device.c
> index 04bec27449cb..a189bfaac959 100644
> --- a/drivers/gpu/drm/panfrost/panfrost_device.c
> +++ b/drivers/gpu/drm/panfrost/panfrost_device.c
> @@ -12,6 +12,7 @@
> #include "panfrost_device.h"
> #include "panfrost_devfreq.h"
> #include "panfrost_features.h"
> +#include "panfrost_gem.h"
> #include "panfrost_issues.h"
> #include "panfrost_gpu.h"
> #include "panfrost_job.h"
> @@ -266,6 +267,8 @@ int panfrost_device_init(struct panfrost_device *pfdev)
> if (err)
> goto out_job;
>
> + panfrost_gem_init(pfdev);
> +
> return 0;
> out_job:
> panfrost_job_fini(pfdev);
> diff --git a/drivers/gpu/drm/panfrost/panfrost_drv.c b/drivers/gpu/drm/panfrost/panfrost_drv.c
> index 22350ce8a08f..e376e70a3379 100644
> --- a/drivers/gpu/drm/panfrost/panfrost_drv.c
> +++ b/drivers/gpu/drm/panfrost/panfrost_drv.c
> @@ -862,6 +862,12 @@ static const struct drm_driver panfrost_drm_driver = {
> #endif
> };
>
> +#ifdef CONFIG_TRANSPARENT_HUGEPAGE
> +bool panfrost_transparent_hugepage;
> +module_param_named(transparent_hugepage, panfrost_transparent_hugepage, bool, 0400);
> +MODULE_PARM_DESC(transparent_hugepage, "Use a dedicated tmpfs mount point with Transparent Hugepage enabled (false = default)");
Same here, I'd go for [panfrost_]enable_thp.
> +#endif
> +
> static int panfrost_probe(struct platform_device *pdev)
> {
> struct panfrost_device *pfdev;
> diff --git a/drivers/gpu/drm/panfrost/panfrost_drv.h b/drivers/gpu/drm/panfrost/panfrost_drv.h
> new file mode 100644
> index 000000000000..60454611b6a6
> --- /dev/null
> +++ b/drivers/gpu/drm/panfrost/panfrost_drv.h
> @@ -0,0 +1,11 @@
> +// SPDX-License-Identifier: GPL-2.0 or MIT
> +/* Copyright 2025 Amazon.com, Inc. or its affiliates */
> +
> +#ifndef __PANFROST_DRV_H__
> +#define __PANFROST_DRV_H__
> +
> +#ifdef CONFIG_TRANSPARENT_HUGEPAGE
> +extern bool panfrost_transparent_hugepage;
> +#endif
> +
> +#endif
> diff --git a/drivers/gpu/drm/panfrost/panfrost_gem.c b/drivers/gpu/drm/panfrost/panfrost_gem.c
> index 85d6289a6eda..c3883a639e13 100644
> --- a/drivers/gpu/drm/panfrost/panfrost_gem.c
> +++ b/drivers/gpu/drm/panfrost/panfrost_gem.c
> @@ -1,5 +1,6 @@
> // SPDX-License-Identifier: GPL-2.0
> /* Copyright 2019 Linaro, Ltd, Rob Herring <robh@kernel.org> */
> +/* Copyright 2025 Amazon.com, Inc. or its affiliates */
>
> #include <linux/cleanup.h>
> #include <linux/err.h>
> @@ -9,9 +10,27 @@
>
> #include <drm/panfrost_drm.h>
> #include "panfrost_device.h"
> +#include "panfrost_drv.h"
> #include "panfrost_gem.h"
> #include "panfrost_mmu.h"
>
> +void panfrost_gem_init(struct panfrost_device *pfdev)
> +{
> + int err;
> +
> + if (!panfrost_transparent_hugepage)
> + return;
> +
> + err = drm_gem_huge_mnt_create(pfdev->ddev, "within_size");
> + if (err && err != -EEXIST) {
> + drm_warn(pfdev->ddev, "Can't use Transparent Hugepage (%d)\n",
> + -err);
I think errors are printed as negative values elsewhere, so I'd stick to err
not -err here.
> + return;
> + }
> +
> + drm_info(pfdev->ddev, "Using Transparent Hugepage\n");
Here's a shorter version of the same thing (I dropped the EEXIST based on
my comment on patch 3).
if (err)
drm_warn(pfdev->ddev, "Can't use Transparent Hugepage (err=%d)\n", err);
else
drm_info(pfdev->ddev, "Using Transparent Hugepage\n");
> +}
> +
> #ifdef CONFIG_DEBUG_FS
> static void panfrost_gem_debugfs_bo_add(struct panfrost_device *pfdev,
> struct panfrost_gem_object *bo)
> diff --git a/drivers/gpu/drm/panfrost/panfrost_gem.h b/drivers/gpu/drm/panfrost/panfrost_gem.h
> index 8de3e76f2717..1a62529ff06f 100644
> --- a/drivers/gpu/drm/panfrost/panfrost_gem.h
> +++ b/drivers/gpu/drm/panfrost/panfrost_gem.h
> @@ -124,6 +124,8 @@ drm_mm_node_to_panfrost_mapping(struct drm_mm_node *node)
> return container_of(node, struct panfrost_gem_mapping, mmnode);
> }
>
> +void panfrost_gem_init(struct panfrost_device *pfdev);
> +
> struct drm_gem_object *panfrost_gem_create_object(struct drm_device *dev, size_t size);
>
> struct drm_gem_object *
^ permalink raw reply [flat|nested] 26+ messages in thread
* [PATCH v3 10/10] Documentation/gpu/drm-mm: Add THP paragraph to GEM mapping section
2025-10-04 9:30 [PATCH v3 00/10] drm: Reduce page tables overhead with THP Loïc Molinari
` (8 preceding siblings ...)
2025-10-04 9:30 ` [PATCH v3 09/10] drm/panfrost: Introduce huge tmpfs mount point option Loïc Molinari
@ 2025-10-04 9:30 ` Loïc Molinari
2025-10-04 22:40 ` Bagas Sanjaya
9 siblings, 1 reply; 26+ messages in thread
From: Loïc Molinari @ 2025-10-04 9:30 UTC (permalink / raw)
To: Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann,
David Airlie, Simona Vetter, Jani Nikula, Joonas Lahtinen,
Rodrigo Vivi, Tvrtko Ursulin, Boris Brezillon, Rob Herring,
Steven Price, Liviu Dudau, Melissa Wen, Maíra Canal,
Hugh Dickins, Baolin Wang, Andrew Morton, Loïc Molinari,
Al Viro, Mikołaj Wasiak, Christian Brauner, Nitin Gote,
Andi Shyti, Christopher Healy
Cc: linux-kernel, dri-devel, intel-gfx, linux-mm, kernel
Add a paragraph to the GEM objects mapping section explaining how
transparent huge pages are handled by GEM.
Signed-off-by: Loïc Molinari <loic.molinari@collabora.com>
---
Documentation/gpu/drm-mm.rst | 17 ++++++++++++++++-
1 file changed, 16 insertions(+), 1 deletion(-)
diff --git a/Documentation/gpu/drm-mm.rst b/Documentation/gpu/drm-mm.rst
index d55751cad67c..0ce6e27f8463 100644
--- a/Documentation/gpu/drm-mm.rst
+++ b/Documentation/gpu/drm-mm.rst
@@ -283,6 +283,8 @@ made up of several fields, the more interesting ones being:
void (*open)(struct vm_area_struct * area);
void (*close)(struct vm_area_struct * area);
vm_fault_t (*fault)(struct vm_fault *vmf);
+ vm_fault_t (*huge_fault)(struct vm_fault *vmf,
+ unsigned int order);
};
@@ -290,7 +292,7 @@ The open and close operations must update the GEM object reference
count. Drivers can use the drm_gem_vm_open() and drm_gem_vm_close() helper
functions directly as open and close handlers.
-The fault operation handler is responsible for mapping individual pages
+The fault operation handlers are responsible for mapping individual pages
to userspace when a page fault occurs. Depending on the memory
allocation scheme, drivers can allocate pages at fault time, or can
decide to allocate memory for the GEM object at the time the object is
@@ -299,6 +301,19 @@ created.
Drivers that want to map the GEM object upfront instead of handling page
faults can implement their own mmap file operation handler.
+In order to reduce page table overhead, if the internal shmem mountpoint
+"shm_mnt" is configured to use transparent huge pages (for builds with
+CONFIG_TRANSPARENT_HUGEPAGE enabled) and if the shmem backing store
+manages to allocate huge pages, faulty addresses within huge pages will
+be mapped into the tables using the huge page fault handler. In such
+cases, mmap() user address alignment for GEM objects is handled by
+providing a custom get_unmapped_area properly forwarding to the shmem
+backing store. For most drivers, which don't create a huge mountpoint by
+default or through a module parameter, transparent huge pages can be
+enabled by either setting the "transparent_hugepage_shmem" kernel
+parameter or the "/sys/kernel/mm/transparent_hugepage/shmem_enabled"
+sysfs knob.
+
For platforms without MMU the GEM core provides a helper method
drm_gem_dma_get_unmapped_area(). The mmap() routines will call this to get a
proposed address for the mapping.
--
2.47.3
^ permalink raw reply [flat|nested] 26+ messages in thread* Re: [PATCH v3 10/10] Documentation/gpu/drm-mm: Add THP paragraph to GEM mapping section
2025-10-04 9:30 ` [PATCH v3 10/10] Documentation/gpu/drm-mm: Add THP paragraph to GEM mapping section Loïc Molinari
@ 2025-10-04 22:40 ` Bagas Sanjaya
0 siblings, 0 replies; 26+ messages in thread
From: Bagas Sanjaya @ 2025-10-04 22:40 UTC (permalink / raw)
To: Loïc Molinari, Maarten Lankhorst, Maxime Ripard,
Thomas Zimmermann, David Airlie, Simona Vetter, Jani Nikula,
Joonas Lahtinen, Rodrigo Vivi, Tvrtko Ursulin, Boris Brezillon,
Rob Herring, Steven Price, Liviu Dudau, Melissa Wen,
Maíra Canal, Hugh Dickins, Baolin Wang, Andrew Morton,
Al Viro, Mikołaj Wasiak, Christian Brauner, Nitin Gote,
Andi Shyti, Christopher Healy
Cc: linux-kernel, dri-devel, intel-gfx, linux-mm, kernel
[-- Attachment #1: Type: text/plain, Size: 1989 bytes --]
On Sat, Oct 04, 2025 at 11:30:53AM +0200, Loïc Molinari wrote:
> @@ -290,7 +292,7 @@ The open and close operations must update the GEM object reference
> count. Drivers can use the drm_gem_vm_open() and drm_gem_vm_close() helper
> functions directly as open and close handlers.
>
> -The fault operation handler is responsible for mapping individual pages
> +The fault operation handlers are responsible for mapping individual pages
> to userspace when a page fault occurs. Depending on the memory
> allocation scheme, drivers can allocate pages at fault time, or can
> decide to allocate memory for the GEM object at the time the object is
> @@ -299,6 +301,19 @@ created.
> Drivers that want to map the GEM object upfront instead of handling page
> faults can implement their own mmap file operation handler.
>
> +In order to reduce page table overhead, if the internal shmem mountpoint
> +"shm_mnt" is configured to use transparent huge pages (for builds with
> +CONFIG_TRANSPARENT_HUGEPAGE enabled) and if the shmem backing store
> +manages to allocate huge pages, faulty addresses within huge pages will
> +be mapped into the tables using the huge page fault handler. In such
> +cases, mmap() user address alignment for GEM objects is handled by
> +providing a custom get_unmapped_area properly forwarding to the shmem
> +backing store. For most drivers, which don't create a huge mountpoint by
> +default or through a module parameter, transparent huge pages can be
> +enabled by either setting the "transparent_hugepage_shmem" kernel
> +parameter or the "/sys/kernel/mm/transparent_hugepage/shmem_enabled"
> +sysfs knob.
> +
> For platforms without MMU the GEM core provides a helper method
> drm_gem_dma_get_unmapped_area(). The mmap() routines will call this to get a
> proposed address for the mapping.
LGTM, thanks!
Reviewed-by: Bagas Sanjaya <bagasdotme@gmail.com>
--
An old man doll... just what I always wanted! - Clara
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]
^ permalink raw reply [flat|nested] 26+ messages in thread