According to the sub-section titled 'VM-Execution Control Fields' in the section titled 'Basic VM-Entry Checks' in Intel SDM vol. 3C, the following vmentry check must be enforced: If the “virtualize APIC-accesses” VM-execution control is 1, the APIC-access address must satisfy the following checks: - Bits 11:0 of the address must be 0. - The address should not set any bits beyond the processor’s physical-address width. This patch adds a unit-test to validate the vmentry check. Signed-off-by: Krish Sadhukhan <krish.sadhukhan@xxxxxxxxxx> Reviewed-by: Mihai Carabas <mihai.carabas@xxxxxxxxxx> --- x86/vmx_tests.c | 59 ++++++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 50 insertions(+), 9 deletions(-) diff --git a/x86/vmx_tests.c b/x86/vmx_tests.c index 613a8bd..d596d8c 100644 --- a/x86/vmx_tests.c +++ b/x86/vmx_tests.c @@ -3430,23 +3430,40 @@ static void test_vmcs_page_values(const char *name, static void test_vmcs_page_reference(u32 control_bit, enum Encoding field, const char *field_name, const char *control_name, - bool xfail_beyond_mapped_ram) + bool xfail_beyond_mapped_ram, + bool control_primary) { u32 primary = vmcs_read(CPU_EXEC_CTRL0); + u32 secondary = vmcs_read(CPU_EXEC_CTRL1); u64 page_addr; - if (!(ctrl_cpu_rev[0].clr & control_bit)) - return; + if (control_primary) { + if (!(ctrl_cpu_rev[0].clr & control_bit)) + return; + } else { + if (!(ctrl_cpu_rev[1].clr & control_bit)) + return; + } page_addr = vmcs_read(field); report_prefix_pushf("%s enabled", control_name); - vmcs_write(CPU_EXEC_CTRL0, primary | control_bit); + if (control_primary) { + vmcs_write(CPU_EXEC_CTRL0, primary | control_bit); + } else { + vmcs_write(CPU_EXEC_CTRL0, primary | CPU_SECONDARY); + vmcs_write(CPU_EXEC_CTRL1, secondary | control_bit); + } test_vmcs_page_values(field_name, field, false, xfail_beyond_mapped_ram); report_prefix_pop(); report_prefix_pushf("%s disabled", control_name); - vmcs_write(CPU_EXEC_CTRL0, primary & ~control_bit); + if (control_primary) { + vmcs_write(CPU_EXEC_CTRL0, primary & ~control_bit); + } else { + vmcs_write(CPU_EXEC_CTRL0, primary & ~CPU_SECONDARY); + vmcs_write(CPU_EXEC_CTRL1, secondary & ~control_bit); + } test_vmcs_page_values(field_name, field, true, false); report_prefix_pop(); @@ -3463,9 +3480,11 @@ static void test_vmcs_page_reference(u32 control_bit, enum Encoding field, static void test_io_bitmaps(void) { test_vmcs_page_reference(CPU_IO_BITMAP, IO_BITMAP_A, - "I/O bitmap A", "Use I/O bitmaps", false); + "I/O bitmap A", "Use I/O bitmaps", false, + true); test_vmcs_page_reference(CPU_IO_BITMAP, IO_BITMAP_B, - "I/O bitmap B", "Use I/O bitmaps", false); + "I/O bitmap B", "Use I/O bitmaps", false, + true); } /* @@ -3477,7 +3496,8 @@ static void test_io_bitmaps(void) static void test_msr_bitmap(void) { test_vmcs_page_reference(CPU_MSR_BITMAP, MSR_BITMAP, - "MSR bitmap", "Use MSR bitmaps", false); + "MSR bitmap", "Use MSR bitmaps", false, + true); } /* @@ -3491,7 +3511,27 @@ static void test_msr_bitmap(void) static void test_apic_virt_addr(void) { test_vmcs_page_reference(CPU_TPR_SHADOW, APIC_VIRT_ADDR, - "virtual-APIC address", "Use TPR shadow", true); + "virtual-APIC address", "Use TPR shadow", + true, true); +} + +/* + * If the "virtualize APIC-accesses" VM-execution control is 1, the + * APIC-access address must satisfy the following checks: + * - Bits 11:0 of the address must be 0. + * - The address should not set any bits beyond the processor's + * physical-address width. + * [Intel SDM] + */ +static void test_apic_access_addr(void) +{ + void *apic_access_page = alloc_page(); + + vmcs_write(APIC_ACCS_ADDR, virt_to_phys(apic_access_page)); + + test_vmcs_page_reference(CPU_VIRT_APIC_ACCESSES, APIC_ACCS_ADDR, + "APIC-access address", + "virtualize APIC-accesses", true, false); } static void set_vtpr(unsigned vtpr) @@ -3761,6 +3801,7 @@ static void vmx_controls_test(void) test_io_bitmaps(); test_msr_bitmap(); test_apic_virt_addr(); + test_apic_access_addr(); test_tpr_threshold(); test_nmi_ctrls(); } -- 2.9.5