It's incorrect to assume the context in which invept
is called. Check what is supported and fallback if
single context invalidation isn't supported

Signed-off-by: Bandan Das <[email protected]>
---
 x86/vmx.c       | 20 ++++++++++++++++++++
 x86/vmx.h       |  1 +
 x86/vmx_tests.c | 14 +++++++-------
 3 files changed, 28 insertions(+), 7 deletions(-)

diff --git a/x86/vmx.c b/x86/vmx.c
index 1d28c6f..1182eef 100644
--- a/x86/vmx.c
+++ b/x86/vmx.c
@@ -288,6 +288,26 @@ unsigned long get_ept_pte(unsigned long *pml4,
        return pte;
 }
 
+void ept_sync(int type, u64 eptp)
+{
+       switch (type) {
+       case INVEPT_SINGLE:
+               if (ept_vpid.val & EPT_CAP_INVEPT_SINGLE) {
+                       invept(INVEPT_SINGLE, eptp);
+                       break;
+               }
+               /* else fall through */
+       case INVEPT_GLOBAL:
+               if (ept_vpid.val & EPT_CAP_INVEPT_ALL) {
+                       invept(INVEPT_GLOBAL, eptp);
+                       break;
+               }
+               /* else fall through */
+       default:
+               printf("WARNING: invept is not supported!\n");
+       }
+}
+
 int set_ept_pte(unsigned long *pml4, unsigned long guest_addr,
                int level, u64 pte_val)
 {
diff --git a/x86/vmx.h b/x86/vmx.h
index 351c3d9..26dd161 100644
--- a/x86/vmx.h
+++ b/x86/vmx.h
@@ -551,6 +551,7 @@ static inline void invept(unsigned long type, u64 eptp)
 }
 
 void print_vmexit_info();
+void ept_sync(int type, u64 eptp);
 void install_ept_entry(unsigned long *pml4, int pte_level,
                unsigned long guest_addr, unsigned long pte,
                unsigned long *pt_page);
diff --git a/x86/vmx_tests.c b/x86/vmx_tests.c
index 2c2d6c4..324f074 100644
--- a/x86/vmx_tests.c
+++ b/x86/vmx_tests.c
@@ -1116,21 +1116,21 @@ static int ept_exit_handler()
                case 1:
                        install_ept(pml4, (unsigned long)data_page1,
                                (unsigned long)data_page1, EPT_WA);
-                       invept(INVEPT_SINGLE, eptp);
+                       ept_sync(INVEPT_SINGLE, eptp);
                        break;
                case 2:
                        install_ept(pml4, (unsigned long)data_page1,
                                (unsigned long)data_page1,
                                EPT_RA | EPT_WA | EPT_EA |
                                (2 << EPT_MEM_TYPE_SHIFT));
-                       invept(INVEPT_SINGLE, eptp);
+                       ept_sync(INVEPT_SINGLE, eptp);
                        break;
                case 3:
                        data_page1_pte = get_ept_pte(pml4,
                                (unsigned long)data_page1, 1);
                        set_ept_pte(pml4, (unsigned long)data_page1, 
                                1, data_page1_pte & (~EPT_PRESENT));
-                       invept(INVEPT_SINGLE, eptp);
+                       ept_sync(INVEPT_SINGLE, eptp);
                        break;
                case 4:
                        data_page1_pte = get_ept_pte(pml4,
@@ -1139,7 +1139,7 @@ static int ept_exit_handler()
                        data_page1_pte_pte = get_ept_pte(pml4, data_page1_pte, 
2);
                        set_ept_pte(pml4, data_page1_pte, 2,
                                data_page1_pte_pte & (~EPT_PRESENT));
-                       invept(INVEPT_SINGLE, eptp);
+                       ept_sync(INVEPT_SINGLE, eptp);
                        break;
                // Should not reach here
                default:
@@ -1157,7 +1157,7 @@ static int ept_exit_handler()
                        install_ept(pml4, (unsigned long)data_page1,
                                (unsigned long)data_page1,
                                EPT_RA | EPT_WA | EPT_EA);
-                       invept(INVEPT_SINGLE, eptp);
+                       ept_sync(INVEPT_SINGLE, eptp);
                        break;
                // Should not reach here
                default:
@@ -1174,14 +1174,14 @@ static int ept_exit_handler()
                                set_stage(get_stage() + 1);
                        set_ept_pte(pml4, (unsigned long)data_page1, 
                                1, data_page1_pte | (EPT_PRESENT));
-                       invept(INVEPT_SINGLE, eptp);
+                       ept_sync(INVEPT_SINGLE, eptp);
                        break;
                case 4:
                        if (exit_qual == (EPT_VLT_RD | EPT_VLT_LADDR_VLD))
                                set_stage(get_stage() + 1);
                        set_ept_pte(pml4, data_page1_pte, 2,
                                data_page1_pte_pte | (EPT_PRESENT));
-                       invept(INVEPT_SINGLE, eptp);
+                       ept_sync(INVEPT_SINGLE, eptp);
                        break;
                default:
                        // Should not reach here
-- 
1.8.3.1

--
To unsubscribe from this list: send the line "unsubscribe kvm" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to