Message ID | 20170628093545.944-1-sergey.dyasli@citrix.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
On 28/06/17 10:35, Sergey Dyasli wrote: > If ept_sync_domain() is called for np2m, the following happens: > > 1. *np2m*::ept_data::invalidate cpumask is updated > 2. IPIs are sent for CPUs in domain_dirty_cpumask forcing vmexits > 3. vmx_vmenter_helper() checks *hostp2m*::ept_data::invalidate > and does nothing > > Which is clearly a bug. Make ept_sync_domain() to update hostp2m's > invalidate mask in nested p2m case and make vmx_vmenter_helper() to > invalidate EPT translations for all EPTPs if nested virt is enabled. > > Signed-off-by: Sergey Dyasli <sergey.dyasli@citrix.com> Reviewed-by: Andrew Cooper <andrew.cooper3@citrix.com>
> From: Sergey Dyasli [mailto:sergey.dyasli@citrix.com] > Sent: Wednesday, June 28, 2017 5:36 PM > > If ept_sync_domain() is called for np2m, the following happens: > > 1. *np2m*::ept_data::invalidate cpumask is updated > 2. IPIs are sent for CPUs in domain_dirty_cpumask forcing vmexits > 3. vmx_vmenter_helper() checks *hostp2m*::ept_data::invalidate > and does nothing > > Which is clearly a bug. Make ept_sync_domain() to update hostp2m's > invalidate mask in nested p2m case and make vmx_vmenter_helper() to > invalidate EPT translations for all EPTPs if nested virt is enabled. > > Signed-off-by: Sergey Dyasli <sergey.dyasli@citrix.com> Acked-by: Kevin Tian <kevin.tian@intel.com>
diff --git a/xen/arch/x86/hvm/vmx/vmx.c b/xen/arch/x86/hvm/vmx/vmx.c index c53b24955a..a8bb550720 100644 --- a/xen/arch/x86/hvm/vmx/vmx.c +++ b/xen/arch/x86/hvm/vmx/vmx.c @@ -4278,7 +4278,10 @@ void vmx_vmenter_helper(const struct cpu_user_regs *regs) if ( cpumask_test_cpu(cpu, ept->invalidate) ) { cpumask_clear_cpu(cpu, ept->invalidate); - __invept(INVEPT_SINGLE_CONTEXT, ept->eptp, 0); + if ( nestedhvm_enabled(curr->domain) ) + __invept(INVEPT_ALL_CONTEXT, 0, 0); + else + __invept(INVEPT_SINGLE_CONTEXT, ept->eptp, 0); } } diff --git a/xen/arch/x86/mm/p2m-ept.c b/xen/arch/x86/mm/p2m-ept.c index ecab56fbec..8d9da9203c 100644 --- a/xen/arch/x86/mm/p2m-ept.c +++ b/xen/arch/x86/mm/p2m-ept.c @@ -1153,8 +1153,13 @@ static void ept_sync_domain_prepare(struct p2m_domain *p2m) struct domain *d = p2m->domain; struct ept_data *ept = &p2m->ept; - if ( nestedhvm_enabled(d) && !p2m_is_nestedp2m(p2m) ) - p2m_flush_nestedp2m(d); + if ( nestedhvm_enabled(d) ) + { + if ( p2m_is_nestedp2m(p2m) ) + ept = &p2m_get_hostp2m(d)->ept; + else + p2m_flush_nestedp2m(d); + } /* * Need to invalidate on all PCPUs because either:
If ept_sync_domain() is called for np2m, the following happens: 1. *np2m*::ept_data::invalidate cpumask is updated 2. IPIs are sent for CPUs in domain_dirty_cpumask forcing vmexits 3. vmx_vmenter_helper() checks *hostp2m*::ept_data::invalidate and does nothing Which is clearly a bug. Make ept_sync_domain() to update hostp2m's invalidate mask in nested p2m case and make vmx_vmenter_helper() to invalidate EPT translations for all EPTPs if nested virt is enabled. Signed-off-by: Sergey Dyasli <sergey.dyasli@citrix.com> --- xen/arch/x86/hvm/vmx/vmx.c | 5 ++++- xen/arch/x86/mm/p2m-ept.c | 9 +++++++-- 2 files changed, 11 insertions(+), 3 deletions(-)