From: "Thomas Hellström" <thomas.hellstrom@linux.intel.com>
To: Matthew Auld <matthew.auld@intel.com>, intel-xe@lists.freedesktop.org
Cc: Matthew Brost <matthew.brost@intel.com>,
Dave Airlie <airlied@redhat.com>,
Rodrigo Vivi <rodrigo.vivi@intel.com>,
stable@vger.kernel.org
Subject: Re: [PATCH] drm/xe/dma-buf: Validate BOs on export to charge the exporter
Date: Wed, 11 Nov 2026 13:22:30 +0100 [thread overview]
Message-ID: <e009602187fd07904afb6672f6a36587fc59cb0f.camel@linux.intel.com> (raw)
In-Reply-To: <fc3a08df-bc2e-47bf-a0f8-a7e284e5f3c2@intel.com>
Hi, Matt
Thanks for reviewing!
On Wed, 2026-11-11 at 12:18 +0000, Matthew Auld wrote:
> On 11/11/2026 10:09, Thomas Hellström wrote:
> > xe_gem_prime_export() calls ttm_bo_setup_export() to make sure the
> > exporter is charged for the memory backing an exported BO. However,
> > that only populates a TTM_PL_SYSTEM tt. A BO that has been evicted,
> > or
> > that has deferred backing, will instead get its memory allocated
> > when
> > the importer maps it. For p2p imports this happens through
> > xe_bo_validate() in xe_dma_buf_map(), so the importer, not the
> > exporter, is charged for the allocation.
> >
> > Call xe_bo_validate() at export time instead, so that the BO is
> > moved
> > into its preferred placement and the exporter is charged.
>
> Is it maybe also worth mentioning somewhere the unreclaimable pages
> angle? I could be mistaken here, but I think that was maybe also the
> issue I saw in a workload. For example:
>
> 1. Create say 100G VRAM buffer. Use DEFERRED. This leaves lingering
> tt
> structure.
>
> 2. Validate it on native side. This is now resident in VRAM. But
> still
> has lingering tt.
>
> 3. Export it. This now populates 100G worth of TT pages due to
> lingering
> tt. But we now have a populated VRAM buffer which is also populated
> with
> 100G TT pages. That 100G TT pages is not reclaimable and is hidden
> from
> shrinker since this still just looks like normal VRAM buffer.
Since we have another patch to fix that, which I hope will go in before
this one, I think mentioning it here will be unnecessary.
>
> >
> > Do the purgeable checks and the validation in the same
> > xe_validation_guard() transaction, to avoid locking the BO twice.
> >
> > The commit message and code was drafted using LLM.
> >
> > Link:
> > https://patchwork.freedesktop.org/patch/747480/?series=172524&rev=1
> > Fixes: 91494dee1091 ("xe: populate buffers before exporting them.")
> > Cc: Matthew Brost <matthew.brost@intel.com>
> > Cc: Matthew Auld <matthew.auld@intel.com>
> > Cc: Dave Airlie <airlied@redhat.com>
> > Cc: Rodrigo Vivi <rodrigo.vivi@intel.com>
> > Cc: intel-xe@lists.freedesktop.org
> > Cc: <stable@vger.kernel.org> # v6.18+
> > Signed-off-by: Thomas Hellström <thomas.hellstrom@linux.intel.com>
>
> Reviewed-by: Matthew Auld <matthew.auld@intel.com>
Thanks!
Thomas
>
> > ---
> > drivers/gpu/drm/xe/xe_dma_buf.c | 76 +++++++++++++++++-----------
> > -----
> > 1 file changed, 39 insertions(+), 37 deletions(-)
> >
> > diff --git a/drivers/gpu/drm/xe/xe_dma_buf.c
> > b/drivers/gpu/drm/xe/xe_dma_buf.c
> > index 5bf13dc4b61d..90c9b90de552 100644
> > --- a/drivers/gpu/drm/xe/xe_dma_buf.c
> > +++ b/drivers/gpu/drm/xe/xe_dma_buf.c
> > @@ -263,60 +263,62 @@ struct drm_gem_object
> > *xe_dma_buf_to_gem(struct drm_device *dev,
> > struct dma_buf *xe_gem_prime_export(struct drm_gem_object *obj,
> > int flags)
> > {
> > struct xe_bo *bo = gem_to_xe_bo(obj);
> > + struct xe_validation_ctx ctx;
> > + struct drm_exec exec;
> > struct dma_buf *buf;
> > - struct ttm_operation_ctx ctx = {
> > - .interruptible = true,
> > - .no_wait_gpu = true,
> > - /* We opt to avoid OOM on system pages allocations
> > */
> > - .gfp_retry_mayfail = true,
> > - .allow_res_evict = false,
> > - };
> > - int ret;
> > + int ret = 0;
> >
> > if (bo->vm)
> > return ERR_PTR(-EPERM);
> >
> > - /*
> > - * Reject exporting purgeable BOs. DONTNEED BOs can be
> > purged
> > - * at any time, making the exported dma-buf unusable.
> > Purged BOs
> > - * have no backing store and are permanently invalid.
> > - */
> > - ret = xe_bo_lock(bo, true);
> > - if (ret)
> > - return ERR_PTR(ret);
> > + xe_validation_guard(&ctx, &xe_bo_device(bo)->val, &exec,
> > + (struct xe_val_flags) {.interruptible
> > = true}, ret) {
> > + ret = drm_exec_lock_obj(&exec, &bo->ttm.base);
> > + drm_exec_retry_on_contention(&exec);
> > + if (ret)
> > + break;
> >
> > - if (xe_bo_madv_is_dontneed(bo)) {
> > - ret = -EBUSY;
> > - goto out_unlock;
> > - }
> > + /*
> > + * Reject exporting purgeable BOs. DONTNEED BOs
> > can be purged
> > + * at any time, making the exported dma-buf
> > unusable. Purged BOs
> > + * have no backing store and are permanently
> > invalid.
> > + */
> > + if (xe_bo_madv_is_dontneed(bo)) {
> > + ret = -EBUSY;
> > + break;
> > + }
> >
> > - if (xe_bo_is_purged(bo)) {
> > - ret = -EINVAL;
> > - goto out_unlock;
> > - }
> > + if (xe_bo_is_purged(bo)) {
> > + ret = -EINVAL;
> > + break;
> > + }
> >
> > - xe_bo_willneed_get_locked(bo);
> > - xe_bo_unlock(bo);
> > + /*
> > + * Make sure the BO is backed in its preferred
> > placement so that
> > + * the exporter, rather than the importer, is
> > charged for the
> > + * memory allocation.
> > + */
> > + ret = xe_bo_validate(bo, NULL, false, &exec);
> > + drm_exec_retry_on_contention(&exec);
> > + xe_validation_retry_on_oom(&ctx, &ret);
> > + if (ret)
> > + break;
> >
> > - ret = ttm_bo_setup_export(&bo->ttm, &ctx);
> > + xe_bo_willneed_get_locked(bo);
> > + }
> > if (ret)
> > - goto out_put;
> > + return ERR_PTR(ret);
> >
> > buf = drm_gem_prime_export(obj, flags);
> > if (IS_ERR(buf)) {
> > - ret = PTR_ERR(buf);
> > - goto out_put;
> > + xe_bo_lock(bo, false);
> > + xe_bo_willneed_put_locked(bo);
> > + xe_bo_unlock(bo);
> > + return buf;
> > }
> >
> > buf->ops = &xe_dmabuf_ops;
> > return buf;
> > -
> > -out_put:
> > - xe_bo_lock(bo, false);
> > - xe_bo_willneed_put_locked(bo);
> > -out_unlock:
> > - xe_bo_unlock(bo);
> > - return ERR_PTR(ret);
> > }
> >
> > static struct drm_gem_object *
next prev parent reply other threads:[~2026-11-11 12:22 UTC|newest]
Thread overview: 8+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-11-11 10:09 [PATCH] drm/xe/dma-buf: Validate BOs on export to charge the exporter Thomas Hellström
2026-11-11 10:19 ` ✓ CI.KUnit: success for " Patchwork
2026-11-11 10:34 ` ✗ CI.checksparse: warning " Patchwork
2026-11-11 10:53 ` ✓ Xe.CI.BAT: success " Patchwork
2026-11-11 12:18 ` [PATCH] " Matthew Auld
2026-11-11 12:22 ` Thomas Hellström [this message]
2026-11-11 17:03 ` ✗ Xe.CI.FULL: failure for " Patchwork
2026-11-11 17:19 ` Thomas Hellström
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=e009602187fd07904afb6672f6a36587fc59cb0f.camel@linux.intel.com \
--to=thomas.hellstrom@linux.intel.com \
--cc=airlied@redhat.com \
--cc=intel-xe@lists.freedesktop.org \
--cc=matthew.auld@intel.com \
--cc=matthew.brost@intel.com \
--cc=rodrigo.vivi@intel.com \
--cc=stable@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox