This test VMCLEARs and VMPTRLDs two VMCS's to put each VMCS into different states of active/not-active and current/not-current and then verifies that VMREAD/VMWRITE to the current VMCS work correctly. Signed-off-by: David Matlack <dmatlack@xxxxxxxxxx> --- x86/unittests.cfg | 6 ++++++ x86/vmx.c | 60 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 66 insertions(+) diff --git a/x86/unittests.cfg b/x86/unittests.cfg index 7973f2f62d26..0f2c94fb548d 100644 --- a/x86/unittests.cfg +++ b/x86/unittests.cfg @@ -236,6 +236,12 @@ extra_params = -cpu host,+vmx -append test_vmwrite_vmread arch = x86_64 groups = vmx +[vmx_test_vmcs_lifecycle] +file = vmx.flat +extra_params = -cpu host,+vmx -append test_vmcs_lifecycle +arch = x86_64 +groups = vmx + [vmx_test_vmx_caps] file = vmx.flat extra_params = -cpu host,+vmx -append test_vmx_caps diff --git a/x86/vmx.c b/x86/vmx.c index 47404fbbd782..7daa1d110c82 100644 --- a/x86/vmx.c +++ b/x86/vmx.c @@ -300,6 +300,64 @@ void test_vmwrite_vmread(void) free_page(vmcs); } +void test_vmcs_lifecycle(void) +{ + struct vmcs *vmcs[2] = {}; + int i; + + for (i = 0; i < ARRAY_SIZE(vmcs); i++) { + vmcs[i] = alloc_page(); + memset(vmcs[i], 0, PAGE_SIZE); + vmcs[i]->revision_id = basic.revision; + } + +#define VMPTRLD(_i) do { \ + assert(_i < ARRAY_SIZE(vmcs)); \ + assert(!make_vmcs_current(vmcs[_i])); \ + printf("VMPTRLD VMCS%d\n", (_i)); \ +} while (0) + +#define VMCLEAR(_i) do { \ + assert(_i < ARRAY_SIZE(vmcs)); \ + assert(!vmcs_clear(vmcs[_i])); \ + printf("VMCLEAR VMCS%d\n", (_i)); \ +} while (0) + + VMCLEAR(0); + VMPTRLD(0); + set_all_vmcs_fields(0); + report("current:VMCS0 active:[VMCS0]", check_all_vmcs_fields(0)); + + VMCLEAR(0); + VMPTRLD(0); + report("current:VMCS0 active:[VMCS0]", check_all_vmcs_fields(0)); + + VMCLEAR(1); + report("current:VMCS0 active:[VMCS0]", check_all_vmcs_fields(0)); + + VMPTRLD(1); + set_all_vmcs_fields(1); + report("current:VMCS1 active:[VMCS0,VCMS1]", check_all_vmcs_fields(1)); + + VMPTRLD(0); + report("current:VMCS0 active:[VMCS0,VCMS1]", check_all_vmcs_fields(0)); + VMPTRLD(1); + report("current:VMCS1 active:[VMCS0,VCMS1]", check_all_vmcs_fields(1)); + VMPTRLD(1); + report("current:VMCS1 active:[VMCS0,VCMS1]", check_all_vmcs_fields(1)); + + VMCLEAR(0); + report("current:VMCS1 active:[VCMS1]", check_all_vmcs_fields(1)); + + for (i = 0; i < ARRAY_SIZE(vmcs); i++) { + VMCLEAR(i); + free_page(vmcs[i]); + } + +#undef VMPTRLD +#undef VMCLEAR +} + void vmx_set_test_stage(u32 s) { barrier(); @@ -1472,6 +1530,8 @@ int main(int argc, const char *argv[]) test_vmptrst(); if (test_wanted("test_vmwrite_vmread", argv, argc)) test_vmwrite_vmread(); + if (test_wanted("test_vmcs_lifecycle", argv, argc)) + test_vmcs_lifecycle(); init_vmcs(&vmcs_root); if (vmx_run()) { -- 2.12.2.816.g2cccc81164-goog