The Intel SDM states that following a VMCLEAR instruction, the VMCS given as an operand to VMCLEAR should be resident in memory. If the CPU caches VMCS data outside of memory, VMCLEAR must flush this cache to memory. Signed-off-by: David Matlack <dmatlack@xxxxxxxxxx> --- x86/vmx.c | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/x86/vmx.c b/x86/vmx.c index 7daa1d110c82..fd1aa3bc6c2e 100644 --- a/x86/vmx.c +++ b/x86/vmx.c @@ -487,6 +487,42 @@ print_vmentry_failure_info(struct vmentry_failure *failure) { } } +/* + * VMCLEAR should ensures all VMCS state is flushed to the VMCS + * region in memory. + */ +static void test_vmclear_flushing(void) +{ + struct vmcs *vmcs[3] = {}; + int i; + + for (i = 0; i < ARRAY_SIZE(vmcs); i++) { + vmcs[i] = alloc_page(); + memset(vmcs[i], 0, PAGE_SIZE); + } + + vmcs[0]->revision_id = basic.revision; + assert(!vmcs_clear(vmcs[0])); + assert(!make_vmcs_current(vmcs[0])); + set_all_vmcs_fields(0x86); + + assert(!vmcs_clear(vmcs[0])); + memcpy(vmcs[1], vmcs[0], basic.size); + assert(!make_vmcs_current(vmcs[1])); + report("test vmclear flush (current VMCS)", check_all_vmcs_fields(0x86)); + + set_all_vmcs_fields(0x87); + assert(!make_vmcs_current(vmcs[0])); + assert(!vmcs_clear(vmcs[1])); + memcpy(vmcs[2], vmcs[1], basic.size); + assert(!make_vmcs_current(vmcs[2])); + report("test vmclear flush (!current VMCS)", check_all_vmcs_fields(0x87)); + + for (i = 0; i < ARRAY_SIZE(vmcs); i++) { + assert(!vmcs_clear(vmcs[i])); + free_page(vmcs[i]); + } +} static void test_vmclear(void) { @@ -519,6 +555,7 @@ static void test_vmclear(void) /* Valid VMCS */ report("test vmclear with valid vmcs region", vmcs_clear(vmcs_root) == 0); + test_vmclear_flushing(); } static void test_vmxoff(void) -- 2.12.2.816.g2cccc81164-goog