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 3/3] x86/HVM: defer p2m TLB flushes across a grant unmap batch
Date: Fri, 30 Oct 2026 17:50:10 +0100 [thread overview]
Message-ID: <20261030165031.2560020-4-luca@edera.dev> (raw)
In-Reply-To: <20261030165031.2560020-1-luca@edera.dev>
A grant unmap by a translated caller also flushes the guest TLBs:
p2m_remove_page() sets need_flush of the host p2m, and put_gfn()
flushes when it drops the last level of the p2m lock. Each flush sends
an IPI to every other CPU in d->dirty_cpumask and waits for all of
them, so a PVH dom0 with busy vCPUs pays a round of IPIs for every page
it unmaps.
Defer that flush to the end of the batch, still before the pages are
released. Under the gfn lock of get_gfn_query() only the removal can
set need_flush, as the query neither allocates nor unshares, so no
other change's flush is deferred. p2m_free_ptp() still flushes before
it frees a table.
The final flush reaches the CPUs in d->dirty_cpumask at that time. A
CPU that left the mask in between has flushed already, as
__context_switch() clears it from the mask only after write_ptbase()
has flushed the guest TLBs. With EPT, each change also marks every CPU
for an INVEPT before its next VM entry.
Assisted-by: Claude Code:claude-opus-5-5
Signed-off-by: Luca Di Maio <luca@edera.dev>
---
xen/arch/x86/hvm/grant_table.c | 6 ++++++
xen/arch/x86/include/asm/hvm/vcpu.h | 1 +
2 files changed, 7 insertions(+)
diff --git a/xen/arch/x86/hvm/grant_table.c b/xen/arch/x86/hvm/grant_table.c
index 1d7f9b19f9..e340712dd6 100644
--- a/xen/arch/x86/hvm/grant_table.c
+++ b/xen/arch/x86/hvm/grant_table.c
@@ -41,6 +41,7 @@ int replace_grant_p2m_mapping(uint64_t addr, mfn_t frame,
p2m_type_t type;
mfn_t old_mfn;
struct domain *d = current->domain;
+ struct p2m_domain *p2m = p2m_get_hostp2m(d);
struct hvm_grant_unmap_batch *batch = ¤t->arch.hvm.grant_unmap_batch;
int rc;
@@ -72,6 +73,8 @@ int replace_grant_p2m_mapping(uint64_t addr, mfn_t frame,
batch->iommu_flags |= this_cpu(iommu_skipped_flush_flags);
batch->gfn_lo = min(batch->gfn_lo, gfn);
batch->gfn_hi = max(batch->gfn_hi, gfn);
+ batch->tlb_flush |= p2m->need_flush;
+ p2m->need_flush = false;
}
if ( rc )
@@ -95,10 +98,13 @@ void grant_p2m_unmap_batch_begin(void)
int grant_p2m_unmap_batch_end(void)
{
struct domain *d = current->domain;
+ struct p2m_domain *p2m = p2m_get_hostp2m(d);
struct hvm_grant_unmap_batch *batch = ¤t->arch.hvm.grant_unmap_batch;
unsigned int order;
batch->open = false;
+ if ( batch->tlb_flush )
+ p2m->tlb_flush(p2m);
if ( !batch->iommu_flags )
return 0;
diff --git a/xen/arch/x86/include/asm/hvm/vcpu.h b/xen/arch/x86/include/asm/hvm/vcpu.h
index 12b7e9b707..9638e50e91 100644
--- a/xen/arch/x86/include/asm/hvm/vcpu.h
+++ b/xen/arch/x86/include/asm/hvm/vcpu.h
@@ -111,6 +111,7 @@ struct altp2mvcpu {
/* Per vCPU, as the guest copies between the unmaps can sleep. */
struct hvm_grant_unmap_batch {
bool open;
+ bool tlb_flush;
unsigned int iommu_flags;
unsigned long gfn_lo, gfn_hi;
};
--
2.54.0
prev parent reply other threads:[~2026-10-30 16:51 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-30 16:50 [PATCH 0/3] x86/HVM: batch the flushes of grant unmaps Luca Di Maio
2026-10-30 16:50 ` [PATCH 1/3] IOMMU: record the flushes skipped under iommu_dont_flush_iotlb Luca Di Maio
2026-10-30 16:50 ` [PATCH 2/3] x86/HVM: defer IOTLB flushes across a grant unmap batch Luca Di Maio
2026-10-30 16:50 ` Luca Di Maio [this message]
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=20261030165031.2560020-4-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.