Hi Krish, I think this would be more succint as two loops: an outer loop that tested "use TPR shadow" values and an inner loop that tested combinations of the other three controls. But this looks fine to me as it is. Reviewed-by: Jim Mattson <jmattson@xxxxxxxxxx> On Fri, Jun 29, 2018 at 12:07 PM, Krish Sadhukhan <krish.sadhukhan@xxxxxxxxxx> wrote: > According to section "Checks on VMX Controls" in Intel SDM vol 3C, the > > following check needs to be enforced on vmentry of L2 guests: > > If the "use TPR shadow" VM-execution control is 0, the following > VM-execution controls must also be 0: "virtualize x2APIC mode", > "APIC-register virtualization" and "virtual-interrupt delivery". > > This unit-test validates the above vmentry check. > > Signed-off-by: Krish Sadhukhan <krish.sadhukhan@xxxxxxxxxx> > Reviewed-by: Karl Heubaum <karl.heubaum@xxxxxxxxxx> > --- > x86/vmx_tests.c | 108 > ++++++++++++++++++++++++++++++++++++++++++++++++++++++-- > 1 file changed, 106 insertions(+), 2 deletions(-) > > diff --git a/x86/vmx_tests.c b/x86/vmx_tests.c > index 38f10f4..64be48f 100644 > --- a/x86/vmx_tests.c > +++ b/x86/vmx_tests.c > @@ -3580,6 +3580,111 @@ static void test_apic_access_addr(void) > "virtualize APIC-accesses", true, false); > } > +/* > + * If the "use TPR shadow" VM-execution control is 0, the following > + * VM-execution controls must also be 0: > + * - virtualize x2APIC mode > + * - APIC-register virtualization > + * - virtual-interrupt delivery > + */ > +static void test_apic_virtual_ctls(void) > +{ > + u32 saved_primary = vmcs_read(CPU_EXEC_CTRL0); > + u32 saved_secondary = vmcs_read(CPU_EXEC_CTRL1); > + u32 primary = saved_primary; > + u32 secondary = saved_secondary; > + bool cpu_has_virt_x2apic = 0; > + bool cpu_has_apic_reg_virt = 0; > + bool cpu_has_vintd = 0; > + > + if (!((ctrl_cpu_rev[0].clr & (CPU_SECONDARY | CPU_TPR_SHADOW)) == > + (CPU_SECONDARY | CPU_TPR_SHADOW))) > + return; > + > + if ((ctrl_cpu_rev[1].clr & CPU_VIRT_X2APIC) == CPU_VIRT_X2APIC) > + cpu_has_virt_x2apic = 1; > + if ((ctrl_cpu_rev[1].clr & CPU_APIC_REG_VIRT) == CPU_APIC_REG_VIRT) > + cpu_has_apic_reg_virt = 1; > + if ((ctrl_cpu_rev[1].clr & CPU_VINTD) == CPU_VINTD) > + cpu_has_vintd = 1; > + > + primary |= CPU_SECONDARY; > + vmcs_write(CPU_EXEC_CTRL0, primary & ~CPU_TPR_SHADOW); > + > + if (cpu_has_virt_x2apic) { > + secondary &= ~(CPU_APIC_REG_VIRT | CPU_VINTD); > + vmcs_write(CPU_EXEC_CTRL1, secondary | CPU_VIRT_X2APIC); > + report_prefix_pushf("Use TPR shadow disabled; virtualize > x2APIC mode enabled"); > + test_vmx_controls(false, false); > + report_prefix_pop(); > + > + if (cpu_has_apic_reg_virt) { > + vmcs_write(CPU_EXEC_CTRL1, secondary | > + CPU_APIC_REG_VIRT); > + report_prefix_pushf("Use TPR shadow disabled; > virtualize x2APIC mode enabled; APIC-register virtualization enabled"); > + test_vmx_controls(false, false); > + report_prefix_pop(); > + } > + > + if (cpu_has_vintd) { > + secondary &= ~CPU_APIC_REG_VIRT; > + vmcs_write(CPU_EXEC_CTRL1, secondary | CPU_VINTD); > + report_prefix_pushf("Use TPR shadow disabled; > virtualize x2APIC mode enabled; virtual-interrupt delivery enabled"); > + test_vmx_controls(false, false); > + report_prefix_pop(); > + } > + } > + > + if (cpu_has_apic_reg_virt) { > + secondary &= ~(~CPU_VIRT_X2APIC | CPU_VINTD); > + vmcs_write(CPU_EXEC_CTRL1, secondary | CPU_APIC_REG_VIRT); > + report_prefix_pushf("Use TPR shadow disabled; APIC-register > virtualization enabled"); > + test_vmx_controls(false, false); > + report_prefix_pop(); > + > + if (cpu_has_vintd) { > + secondary &= ~CPU_VIRT_X2APIC; > + vmcs_write(CPU_EXEC_CTRL1, secondary | CPU_VINTD); > + report_prefix_pushf("Use TPR shadow disabled; > APIC-register virtualization enabled; virtual-interrupt delivery enabled"); > + test_vmx_controls(false, false); > + report_prefix_pop(); > + } > + } > + > + if (cpu_has_vintd) { > + secondary &= ~(~CPU_VIRT_X2APIC | CPU_APIC_REG_VIRT); > + vmcs_write(CPU_EXEC_CTRL1, secondary | CPU_VINTD); > + report_prefix_pushf("Use TPR shadow disabled; > virtual-interrupt delivery enabled"); > + test_vmx_controls(false, false); > + report_prefix_pop(); > + } > + > + if (cpu_has_virt_x2apic && cpu_has_apic_reg_virt && > + cpu_has_vintd) { > + > + vmcs_write(CPU_EXEC_CTRL1, secondary | (CPU_VIRT_X2APIC | > + CPU_APIC_REG_VIRT | CPU_VINTD)); > + report_prefix_pushf("Use TPR shadow disabled; virtualize > x2APIC mode enabled; APIC-register virtualization enabled; virtual-interrupt > delivery enabled"); > + test_vmx_controls(false, false); > + report_prefix_pop(); > + > + vmcs_write(CPU_EXEC_CTRL0, primary | CPU_TPR_SHADOW); > + report_prefix_pushf("Use TPR shadow enabled; virtualize > x2APIC mode enabled; APIC-register virtualization enabled; virtual-interrupt > delivery enabled"); > + test_vmx_controls(true, false); > + report_prefix_pop(); > + } > + > + vmcs_write(CPU_EXEC_CTRL0, saved_primary); > + vmcs_write(CPU_EXEC_CTRL1, saved_secondary); > +} > + > +static void test_apic_ctls(void) > +{ > + test_apic_virt_addr(); > + test_apic_access_addr(); > + test_apic_virtual_ctls(); > +} > + > static void set_vtpr(unsigned vtpr) > { > *(u32 *)phys_to_virt(vmcs_read(APIC_VIRT_ADDR) + APIC_TASKPRI) = > vtpr; > @@ -3846,8 +3951,7 @@ static void vmx_controls_test(void) > test_cr3_targets(); > test_io_bitmaps(); > test_msr_bitmap(); > - test_apic_virt_addr(); > - test_apic_access_addr(); > + test_apic_ctls(); > test_tpr_threshold(); > test_nmi_ctrls(); > } > -- > 2.9.5 >