|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [PATCH v2 2/4] IOMMU: record the flushes skipped under iommu_dont_flush_iotlb
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@xxxxxxxxx>
---
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
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |