@@ -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)
{
@@ -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);
@@ -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
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 <bsd@redhat.com> --- x86/vmx.c | 20 ++++++++++++++++++++ x86/vmx.h | 1 + x86/vmx_tests.c | 14 +++++++------- 3 files changed, 28 insertions(+), 7 deletions(-)