[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [PATCH] x86/ept: limit calls to memory_type_changed()
memory_type_changed() is currently only implemented for Intel EPT, and results in the invalidation of EMT attributes on all the entries in the EPT page tables. Such invalidation causes EPT_MISCONFIG vmexits when the guest tries to access any gfns for the first time, which results in the recalculation of the EMT for the accessed page. The vmexit and the recalculations are expensive, and as such should be avoided when possible. Remove the call to memory_type_changed() from XEN_DOMCTL_memory_mapping: there are no modifications of the iomem_caps ranges anymore that could alter the return of cache_flush_permitted() from that domctl. Calls to memory_type_changed() resulting from changes to the domain iomem_caps or ioport_caps ranges are only relevant for EMT calculations if the IOMMU is not enabled, and the call has resulted in a change to the return value of cache_flush_permitted(). Signed-off-by: Roger Pau Monné <roger.pau@xxxxxxxxxx> --- I feel it's a bit weird to have calls to memory_type_changed() in common domctl code - for once the domctl that trigger the call doesn't change memory types, just adds or removes ranges from iomem_caps (which in turn affects the behaviour of epte_get_entry_emt()). --- xen/arch/x86/domctl.c | 18 ++++++++++++++++-- xen/common/domctl.c | 11 ++++++++--- 2 files changed, 24 insertions(+), 5 deletions(-) diff --git a/xen/arch/x86/domctl.c b/xen/arch/x86/domctl.c index 020df615bd..f1150dffa5 100644 --- a/xen/arch/x86/domctl.c +++ b/xen/arch/x86/domctl.c @@ -222,6 +222,7 @@ long arch_do_domctl( unsigned int fp = domctl->u.ioport_permission.first_port; unsigned int np = domctl->u.ioport_permission.nr_ports; int allow = domctl->u.ioport_permission.allow_access; + bool flush_permitted = cache_flush_permitted(d); if ( (fp + np) <= fp || (fp + np) > MAX_IOPORTS ) ret = -EINVAL; @@ -232,7 +233,13 @@ long arch_do_domctl( ret = ioports_permit_access(d, fp, fp + np - 1); else ret = ioports_deny_access(d, fp, fp + np - 1); - if ( !ret ) + if ( !ret && !is_iommu_enabled(d) && + flush_permitted != cache_flush_permitted(d) ) + /* + * Only flush if the output of cache_flush_permitted() changes and + * IOMMU is not enabled for the domain, otherwise it makes no + * difference for EMT calculation purposes. + */ memory_type_changed(d); break; } @@ -586,6 +593,7 @@ long arch_do_domctl( struct hvm_domain *hvm; struct g2m_ioport *g2m_ioport; int found = 0; + bool flush_permitted = cache_flush_permitted(d); ret = -EOPNOTSUPP; if ( !is_hvm_domain(d) ) @@ -666,7 +674,13 @@ long arch_do_domctl( "ioport_map: error %ld denying dom%d access to [%x,%x]\n", ret, d->domain_id, fmp, fmp + np - 1); } - if ( !ret ) + if ( !ret && !is_iommu_enabled(d) && + flush_permitted != cache_flush_permitted(d) ) + /* + * Only flush if the output of cache_flush_permitted() changes and + * IOMMU is not enabled for the domain, otherwise it makes no + * difference for EMT calculation purposes. + */ memory_type_changed(d); break; } diff --git a/xen/common/domctl.c b/xen/common/domctl.c index 452266710a..1f2f2dfcc2 100644 --- a/xen/common/domctl.c +++ b/xen/common/domctl.c @@ -703,6 +703,7 @@ long do_domctl(XEN_GUEST_HANDLE_PARAM(xen_domctl_t) u_domctl) unsigned long mfn = op->u.iomem_permission.first_mfn; unsigned long nr_mfns = op->u.iomem_permission.nr_mfns; int allow = op->u.iomem_permission.allow_access; + bool flush_permitted = cache_flush_permitted(d); ret = -EINVAL; if ( (mfn + nr_mfns - 1) < mfn ) /* wrap? */ @@ -716,7 +717,13 @@ long do_domctl(XEN_GUEST_HANDLE_PARAM(xen_domctl_t) u_domctl) ret = iomem_permit_access(d, mfn, mfn + nr_mfns - 1); else ret = iomem_deny_access(d, mfn, mfn + nr_mfns - 1); - if ( !ret ) + if ( !ret && !is_iommu_enabled(d) && + flush_permitted != cache_flush_permitted(d) ) + /* + * Only flush if the output of cache_flush_permitted() changes and + * IOMMU is not enabled for the domain, otherwise it makes no + * difference for effective cache attribute calculation purposes. + */ memory_type_changed(d); break; } @@ -778,8 +785,6 @@ long do_domctl(XEN_GUEST_HANDLE_PARAM(xen_domctl_t) u_domctl) "memory_map: error %ld removing dom%d access to [%lx,%lx]\n", ret, d->domain_id, mfn, mfn_end); } - /* Do this unconditionally to cover errors on above failure paths. */ - memory_type_changed(d); break; } -- 2.37.3
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |