diff mbox

[v1] vvmx: fix ept_sync() for nested p2m

Message ID 20170628093545.944-1-sergey.dyasli@citrix.com (mailing list archive)
State New, archived
Headers show

Commit Message

Sergey Dyasli June 28, 2017, 9:35 a.m. UTC
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(-)

Comments

Andrew Cooper June 28, 2017, 4:51 p.m. UTC | #1
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>
Tian, Kevin June 30, 2017, 9:29 a.m. UTC | #2
> 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 mbox

Patch

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: