All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Thomas Hellström" <thomas.hellstrom@linux.intel.com>
To: Matthew Auld <matthew.auld@intel.com>,
	"Prabhakaran, Krishna" <krishna.prabhakaran@intel.com>,
	intel-gfx@lists.freedesktop.org
Cc: jani.nikula@linux.intel.com, joonas.lahtinen@linux.intel.com,
	 rodrigo.vivi@intel.com, tursulin@ursulin.net,
	dri-devel@lists.freedesktop.org
Subject: Re: [PATCH v2] drm/i915/dmabuf: avoid global wbinvd on dma-buf import
Date: Thu, 20 Aug 2026 12:39:53 +0200	[thread overview]
Message-ID: <f4a4d6b6a4b353e2993a0e556b93da8501846d40.camel@linux.intel.com> (raw)
In-Reply-To: <d3fa2250-3530-44d5-9661-032f195f8ad0@intel.com>

On Thu, 2026-08-20 at 10:23 +0100, Matthew Auld wrote:
> On 16/08/2026 02:45, Prabhakaran, Krishna wrote:
> > From: Krishna Prabhakaran <krishna.prabhakaran@intel.com>
> > 
> > When i915 needs to make an imported dma-buf coherent for GPU access
> > on
> > non-LLC platforms, or for objects that bypass LLC, it currently
> > calls
> > wbinvd_on_all_cpus(). get_pages() runs whenever an imported buffer
> > is
> > pinned, so this triggers a whole-cache write-back and invalidate,
> > broadcast by IPI to every CPU, on every execbuf submission
> > involving an
> > imported dma-buf. That stalls the entire machine for milliseconds
> > and
> > starves latency-sensitive work on unrelated cores (e.g. USB
> > isochronous
> > audio serviced on the VMM's main thread).
> > 
> > Flush only the pages that actually need it instead:
> > 
> >   - If we imported one of our own dma-bufs, the backing object is
> >     struct-page backed once migrated to SMEM, so flush it directly
> > with
> >     drm_clflush_sg(), exactly as we flush our other objects. This
> > also
> >     avoids re-entering the exporter through dma_buf_vmap(), which
> > would
> >     recurse into i915_gem_object_pin_map() on the source object we
> >     already hold locked (and fails the
> > igt_dmabuf_import_same_driver
> >     selftest with -EBUSY).
> > 
> >   - For a foreign dma-buf the sg_table is not guaranteed to be
> > backed by
> >     struct pages, and the importer has no way to tell, so
> > drm_clflush_sg()
> >     cannot be used. vmap the buffer and flush that virtual range
> > with
> >     drm_clflush_virt_range() instead: x86 uses PIPT caches, so
> > flushing
> >     one virtual alias evicts the cache lines for every alias of the
> > same
> >     physical pages. The dma_resv lock required by dma_buf_vmap() is
> >     already held here via the imported object.
> > 
> > Fall back to wbinvd only when the buffer cannot be vmapped or is
> > backed
> > by I/O memory, where there is no CPU-side range to clflush.
> > 
> > Fixes: a035154da45d ("drm/i915/dmabuf: add paranoid flush-on-
> > acquire")
> > Signed-off-by: Krishna Prabhakaran <krishna.prabhakaran@intel.com>
> > ---
> > v2:
> >   - Flush our own imported dma-bufs directly with drm_clflush_sg()
> > instead of
> >     dma_buf_vmap(), which re-entered i915_gem_object_pin_map() on
> > the source
> >     object and failed igt_dmabuf_import_same_driver_smem with -
> > EBUSY (reported
> >     by Intel CI on v1). Foreign dma-bufs still use dma_buf_vmap() +
> >     drm_clflush_virt_range(); wbinvd only as fallback.
> >   - Link to v1:
> > https://patchwork.freedesktop.org/patch/744955/?series=171760
> > 
> >   drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c | 55
> > ++++++++++++++++++----
> >   1 file changed, 47 insertions(+), 8 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c
> > b/drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c
> > index b43d34c7d641..c798a90f1c0f 100644
> > --- a/drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c
> > +++ b/drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c
> > @@ -10,6 +10,8 @@
> >   
> >   #include <asm/smp.h>
> >   
> > +#include <drm/drm_cache.h>
> > +
> >   #include "gem/i915_gem_dmabuf.h"
> >   #include "i915_drv.h"
> >   #include "i915_gem_object.h"
> > @@ -249,16 +251,53 @@ static int
> > i915_gem_object_get_pages_dmabuf(struct drm_i915_gem_object *obj)
> >   	 * DG1 is special here since it still snoops transactions
> > even with
> >   	 * CACHE_NONE. This is not the case with other HAS_SNOOP
> > platforms. We
> >   	 * might need to revisit this as we add new discrete
> > platforms.
> > -	 *
> > -	 * XXX: Consider doing a vmap flush or something, where
> > possible.
> > -	 * Currently we just do a heavy handed
> > wbinvd_on_all_cpus() here since
> > -	 * the underlying sg_table might not even point to struct
> > pages, so we
> > -	 * can't just call drm_clflush_sg or similar, like we do
> > elsewhere in
> > -	 * the driver.
> >   	 */
> >   	if (i915_gem_object_can_bypass_llc(obj) ||
> > -	    (!HAS_LLC(i915) && !IS_DG1(i915)))
> > -		wbinvd_on_all_cpus();
> > +	    (!HAS_LLC(i915) && !IS_DG1(i915))) {
> 
> I think we can bump this now for dg2? I think we treat dgfx as always
> coherent with system memory. So maybe s/IS_DG1/IS_DGFX/ in a separate
> patch? Pretty sure the rest of the driver is the same.

+1

> 
> > +		struct dma_buf *dma_buf = obj->base.import_attach-
> > >dmabuf;
> > +
> > +		if (dma_buf->ops == &i915_dmabuf_ops) {
> > +			struct drm_i915_gem_object *dma_obj =
> > +				dma_buf_to_obj(dma_buf);
> > +
> > +			/*
> > +			 * We imported one of our own dma-bufs.
> > The backing
> > +			 * object is struct-page backed once
> > migrated to SMEM,
> > +			 * so flush it directly, the same way we
> > flush our
> > +			 * other objects. This also avoids re-
> > entering the
> > +			 * exporter through dma_buf_vmap(), which
> > would recurse
> > +			 * into i915_gem_object_pin_map() on the
> > source object
> > +			 * we already hold locked.
> > +			 */
> > +			if
> > (i915_gem_object_has_struct_page(dma_obj))
> > +				drm_clflush_sg(dma_obj->mm.pages);
> > +			else
> > +				wbinvd_on_all_cpus();
> 
> Do we need the flush under the else here? If it's not placed in
> system 
> memory what is this flushing, from i915 pov?
> 
> > +		} else {
> > +			struct iosys_map map;
> > +
> > +			/*
> > +			 * A foreign sg_table is not guaranteed to
> > be backed by
> > +			 * struct pages, so we cannot use
> > drm_clflush_sg(). vmap
> > +			 * the buffer and flush the virtual range
> > instead; x86
> > +			 * uses PIPT caches, so flushing one alias
> > evicts the
> > +			 * lines for every alias of the same
> > physical pages.
> > +			 *
> > +			 * We already hold the dma_resv lock via
> > the imported
> > +			 * obj, so use the locked dma_buf_vmap()
> > variant.
> > +			 */
> > +			if (!dma_buf_vmap(dma_buf, &map)) {
> > +				if (!map.is_iomem)
> > +					drm_clflush_virt_range(map
> > .vaddr,
> > +							      
> > obj->base.size);
> > +				else
> > +					wbinvd_on_all_cpus();

The need for this flush is a bit unfortunate. In theory iomem can be
mapped and wiped write-back, But I'm not sure how common that is...



> > +				dma_buf_vunmap(dma_buf, &map);



> > +			} else {
> > +				wbinvd_on_all_cpus();

Random idea, would it make sense to insert a GPU CLFLUSH into the
pipeline using MI_CLFLUSH (on hardware that supports it) or an
uncached but coherent MOCS / GPU PAT setting dummy blit?

Thanks,
Thomas


> > +			}
> > +		}
> > +	}
> >   
> >   	__i915_gem_object_set_pages(obj, sgt);
> >   
> > 
> > base-commit: 682ea2d28d18bb06f9fc663cb5ab7e80dc0e606a

  reply	other threads:[~2026-08-20 10:40 UTC|newest]

Thread overview: 11+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-08-16  1:45 [PATCH v2] drm/i915/dmabuf: avoid global wbinvd on dma-buf import Prabhakaran, Krishna
2026-08-16  2:24 ` ✓ i915.CI.BAT: success for " Patchwork
2026-08-17 20:25 ` ✗ i915.CI.Full: failure " Patchwork
2026-08-20  9:23 ` [PATCH v2] " Matthew Auld
2026-08-20 10:39   ` Thomas Hellström [this message]
2026-08-20 20:20     ` Prabhakaran, Krishna
2026-08-20 18:15   ` Prabhakaran, Krishna
2026-08-20 19:09   ` Prabhakaran, Krishna
2026-08-20 20:50 ` [PATCH v3] " Prabhakaran, Krishna
2026-08-21  9:09   ` Matthew Auld
2026-08-20 22:07 ` ✗ i915.CI.BAT: failure for drm/i915/dmabuf: avoid global wbinvd on dma-buf import (rev3) Patchwork

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=f4a4d6b6a4b353e2993a0e556b93da8501846d40.camel@linux.intel.com \
    --to=thomas.hellstrom@linux.intel.com \
    --cc=dri-devel@lists.freedesktop.org \
    --cc=intel-gfx@lists.freedesktop.org \
    --cc=jani.nikula@linux.intel.com \
    --cc=joonas.lahtinen@linux.intel.com \
    --cc=krishna.prabhakaran@intel.com \
    --cc=matthew.auld@intel.com \
    --cc=rodrigo.vivi@intel.com \
    --cc=tursulin@ursulin.net \
    /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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.