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));