|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [PATCH v2 4/4] x86/HVM: defer p2m TLB flushes across a grant unmap batch
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@xxxxxxxxx>
---
Changes in v2:
- None.
---
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 5ecba6db65..7a2201d926 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;
@@ -76,6 +77,8 @@ int replace_grant_p2m_mapping(uint64_t addr, mfn_t frame,
batch->iommu_flags |= skipped->flags;
batch->dfn_first = min(batch->dfn_first, dfn_x(skipped->first));
batch->dfn_last = max(batch->dfn_last, dfn_x(skipped->last));
+ batch->tlb_flush |= p2m->need_flush;
+ p2m->need_flush = false;
}
if ( rc )
@@ -99,9 +102,12 @@ 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;
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 990411e2c7..ff6856928d 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 dfn_first, dfn_last;
};
--
2.47.3
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |