Re: [PATCH v3 5/7] drm/xe/mmio_gem: cache the dummy page per object

Matthew Auld <[email protected]>
Newsgroups org.freedesktop.lists.intel-xe
Message-ID <[email protected]>
On 23/07/2026 17:18, Ilia Levi wrote:
> Currently, when the fault handler provides a dummy page, it
> allocates a new one on every invocation and ties its lifetime to
> the drm_device via drmm_add_action_or_reset(). Concurrent faults
> after hot-unplug therefore accumulate pages that persist until
> device teardown.
> 
> Cache a single dummy page in the xe_mmio_gem object and use dma_resv
> lock to protect its allocation. Free it with the object.
> 
> v2: use dma_resv lock to protect the allocation (Matt Auld)
> 
> Assisted-by: GitHub-Copilot:claude-opus-4.6
> Signed-off-by: Ilia Levi <[email protected]>

Do we anticipate this be a real issue in practice? I think normal BO 
mmap path just allocates a new page without caching? Is that also a concern?

Reviewed-by: Matthew Auld <[email protected]>

> ---
>   drivers/gpu/drm/xe/xe_mmio_gem.c | 27 ++++++++++++++++-----------
>   1 file changed, 16 insertions(+), 11 deletions(-)
> 
> diff --git a/drivers/gpu/drm/xe/xe_mmio_gem.c b/drivers/gpu/drm/xe/xe_mmio_gem.c
> index 2838fcb4ff9f..5bd2759fc876 100644
> --- a/drivers/gpu/drm/xe/xe_mmio_gem.c
> +++ b/drivers/gpu/drm/xe/xe_mmio_gem.c
> @@ -5,9 +5,9 @@
>   
>   #include "xe_mmio_gem.h"
>   
> +#include <linux/dma-resv.h>
>   #include <drm/drm_drv.h>
>   #include <drm/drm_gem.h>
> -#include <drm/drm_managed.h>
>   
>   #include "xe_device_types.h"
>   
> @@ -37,6 +37,7 @@ static vm_fault_t xe_mmio_gem_vm_fault(struct vm_fault *);
>   struct xe_mmio_gem {
>   	struct drm_gem_object base;
>   	phys_addr_t phys_addr;
> +	struct page *dummy_page; /* protected by the GEM's dma_resv */
>   };
>   
>   static int xe_mmio_gem_vm_may_split(struct vm_area_struct *area, unsigned long addr)
> @@ -131,6 +132,8 @@ static void xe_mmio_gem_free(struct drm_gem_object *base)
>   {
>   	struct xe_mmio_gem *obj = to_xe_mmio_gem(base);
>   
> +	if (obj->dummy_page)
> +		__free_page(obj->dummy_page);
>   	drm_gem_object_release(base);
>   	kfree(obj);
>   }
> @@ -169,27 +172,29 @@ static int xe_mmio_gem_mmap(struct drm_gem_object *base, struct vm_area_struct *
>   	return 0;
>   }
>   
> -static void xe_mmio_gem_release_dummy_page(struct drm_device *dev, void *res)
> +static int alloc_dummy_page_if_needed(struct drm_gem_object *base)
>   {
> -	__free_page((struct page *)res);
> +	struct xe_mmio_gem *obj = to_xe_mmio_gem(base);
> +
> +	dma_resv_lock(base->resv, NULL);
> +	if (!obj->dummy_page)
> +		obj->dummy_page = alloc_page(GFP_KERNEL | __GFP_ZERO);
> +	dma_resv_unlock(base->resv);
> +
> +	return obj->dummy_page ? 0 : -ENOMEM;
>   }
>   
>   static vm_fault_t xe_mmio_gem_vm_fault_dummy_page(struct vm_fault *vmf)
>   {
>   	struct vm_area_struct *vma = vmf->vma;
>   	struct drm_gem_object *base = vma->vm_private_data;
> -	struct drm_device *dev = base->dev;
> -	struct page *page;
> +	struct xe_mmio_gem *obj = to_xe_mmio_gem(base);
>   	unsigned long pfn;
>   
> -	page = alloc_page(GFP_KERNEL | __GFP_ZERO);
> -	if (!page)
> -		return VM_FAULT_OOM;
> -
> -	if (drmm_add_action_or_reset(dev, xe_mmio_gem_release_dummy_page, page))
> +	if (alloc_dummy_page_if_needed(base))
>   		return VM_FAULT_OOM;
>   
> -	pfn = page_to_pfn(page);
> +	pfn = page_to_pfn(obj->dummy_page);
>   
>   	return vmf_insert_pfn_prot(vma, vmf->address, pfn,
>   				   vm_get_page_prot(vma->vm_flags));
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.