From: Luca Di Maio <luca@edera.dev>
To: xen-devel@lists.xenproject.org
Cc: "Luca Di Maio" <luca@edera.dev>,
"Jan Beulich" <jbeulich@suse.com>,
"Andrew Cooper" <andrew.cooper3@citrix.com>,
"Roger Pau Monné" <roger@xenproject.org>,
"Teddy Astie" <teddy.astie@vates.tech>,
"Stefano Stabellini" <sstabellini@kernel.org>,
"Julien Grall" <julien@xen.org>,
"Bertrand Marquis" <bertrand.marquis@arm.com>,
"Michal Orzel" <michal.orzel@amd.com>,
"Volodymyr Babchuk" <Volodymyr_Babchuk@epam.com>,
"Anthony PERARD" <anthony.perard@vates.tech>
Subject: [PATCH v2 2/4] IOMMU: record the flushes skipped under iommu_dont_flush_iotlb
Date: Fri, 6 Nov 2026 09:08:52 +0100 [thread overview]
Message-ID: <20261106080859.2285309-3-luca@edera.dev> (raw)
In-Reply-To: <20261106080859.2285309-1-luca@edera.dev>
While iommu_dont_flush_iotlb is set, iommu_legacy_map(),
iommu_legacy_unmap() and the shared-EPT path of ept_set_entry() skip
their IOTLB flush and drop its range and flags, so a caller deferring
the flush has to work out what to flush on its own.
Check the flag in iommu_iotlb_flush() instead, which all three call,
and record what it skips in the per-CPU iommu_skipped_flush: the
smallest range covering the skipped flushes, and their flags. No other
caller of iommu_iotlb_flush() runs while the flag is set, and the code
setting it clears it before its own flush. The next patch uses the
record for grant unmaps.
Assisted-by: Claude Code:claude-opus-5-5
Signed-off-by: Luca Di Maio <luca@edera.dev>
---
Changes in v2:
- Check the flag in iommu_iotlb_flush() rather than in its callers,
which also drops the duplicated flags in ept_set_entry() (Teddy).
- Record the range of the skipped flushes as well as their flags
(Teddy).
- Store the flags as unsigned int in struct iommu_skipped_flush, instead
of a uint8_t checked by a BUILD_BUG_ON() (Teddy, Jan).
---
xen/arch/x86/mm/p2m-ept.c | 2 +-
xen/drivers/passthrough/iommu.c | 17 +++++++++++++++--
xen/include/xen/iommu.h | 6 ++++++
3 files changed, 22 insertions(+), 3 deletions(-)
diff --git a/xen/arch/x86/mm/p2m-ept.c b/xen/arch/x86/mm/p2m-ept.c
index 204bdb054a..33c3d8fc58 100644
--- a/xen/arch/x86/mm/p2m-ept.c
+++ b/xen/arch/x86/mm/p2m-ept.c
@@ -976,7 +976,7 @@ out:
if ( rc == 0 && p2m_is_hostp2m(p2m) &&
need_modify_vtd_table )
{
- if ( iommu_use_hap_pt(d) && !this_cpu(iommu_dont_flush_iotlb) )
+ if ( iommu_use_hap_pt(d) )
rc = iommu_iotlb_flush(d, _dfn(gfn), 1ul << order,
(iommu_flags ? IOMMU_FLUSHF_added : 0) |
(vtd_pte_present ? IOMMU_FLUSHF_modified
diff --git a/xen/drivers/passthrough/iommu.c b/xen/drivers/passthrough/iommu.c
index 4b22ecfe65..8e97086601 100644
--- a/xen/drivers/passthrough/iommu.c
+++ b/xen/drivers/passthrough/iommu.c
@@ -64,6 +64,7 @@ bool __read_mostly iommu_hap_pt_share = true;
bool __read_mostly iommu_debug;
DEFINE_PER_CPU(bool, iommu_dont_flush_iotlb);
+DEFINE_PER_CPU(struct iommu_skipped_flush, iommu_skipped_flush);
static int __init cf_check parse_iommu_param(const char *s)
{
@@ -390,7 +391,7 @@ int iommu_legacy_map(struct domain *d, dfn_t dfn, mfn_t mfn,
ASSERT(!(flags & IOMMUF_preempt));
rc = iommu_map(d, dfn, mfn, page_count, flags, &flush_flags);
- if ( !this_cpu(iommu_dont_flush_iotlb) && !rc )
+ if ( !rc )
rc = iommu_iotlb_flush(d, dfn, page_count, flush_flags);
return rc;
@@ -458,7 +459,7 @@ int iommu_legacy_unmap(struct domain *d, dfn_t dfn, unsigned long page_count)
unsigned int flush_flags = 0;
int rc = iommu_unmap(d, dfn, page_count, 0, &flush_flags);
- if ( !this_cpu(iommu_dont_flush_iotlb) && !rc )
+ if ( !rc )
rc = iommu_iotlb_flush(d, dfn, page_count, flush_flags);
return rc;
@@ -488,6 +489,18 @@ int iommu_iotlb_flush(struct domain *d, dfn_t dfn, unsigned long page_count,
if ( dfn_eq(dfn, INVALID_DFN) )
return -EINVAL;
+ if ( this_cpu(iommu_dont_flush_iotlb) )
+ {
+ struct iommu_skipped_flush *skipped = &this_cpu(iommu_skipped_flush);
+
+ skipped->first = _dfn(min(dfn_x(skipped->first), dfn_x(dfn)));
+ skipped->last = _dfn(max(dfn_x(skipped->last),
+ dfn_x(dfn) + page_count - 1));
+ skipped->flags |= flush_flags;
+
+ return 0;
+ }
+
rc = iommu_call(hd->platform_ops, iotlb_flush, d, dfn, page_count,
flush_flags);
if ( unlikely(rc) )
diff --git a/xen/include/xen/iommu.h b/xen/include/xen/iommu.h
index 37c4a1dc82..a2aeaf8d41 100644
--- a/xen/include/xen/iommu.h
+++ b/xen/include/xen/iommu.h
@@ -502,6 +502,12 @@ void iommu_dev_iotlb_flush_timeout(struct domain *d, struct pci_dev *pdev);
*/
DECLARE_PER_CPU(bool, iommu_dont_flush_iotlb);
+struct iommu_skipped_flush {
+ dfn_t first, last;
+ unsigned int flags;
+};
+DECLARE_PER_CPU(struct iommu_skipped_flush, iommu_skipped_flush);
+
bool arch_iommu_use_permitted(const struct domain *d);
#ifdef CONFIG_X86
--
2.47.3
next prev parent reply other threads:[~2026-11-06 8:09 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-11-06 8:08 [PATCH v2 0/4] x86/HVM: batch the flushes of grant unmaps Luca Di Maio
2026-11-06 8:08 ` [PATCH v2 1/4] VT-d: round IOTLB flush ranges up to an aligned power of two Luca Di Maio
2026-11-06 8:08 ` Luca Di Maio [this message]
2026-11-06 8:08 ` [PATCH v2 3/4] x86/HVM: defer IOTLB flushes across a grant unmap batch Luca Di Maio
2026-11-06 8:08 ` [PATCH v2 4/4] x86/HVM: defer p2m TLB " Luca Di Maio
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=20261106080859.2285309-3-luca@edera.dev \
--to=luca@edera.dev \
--cc=Volodymyr_Babchuk@epam.com \
--cc=andrew.cooper3@citrix.com \
--cc=anthony.perard@vates.tech \
--cc=bertrand.marquis@arm.com \
--cc=jbeulich@suse.com \
--cc=julien@xen.org \
--cc=michal.orzel@amd.com \
--cc=roger@xenproject.org \
--cc=sstabellini@kernel.org \
--cc=teddy.astie@vates.tech \
--cc=xen-devel@lists.xenproject.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 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.