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>
Acked-by: Kevin Tian <kevin.tian@intel.com>
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);
}
}
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: