Re: [PATCH] x86: Add test for TPR threshold and vTPR check on VM-entry

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On 30/11/2017 01:37, Krish Sadhukhan wrote:
> This test checks that a nested VM-entry fails if the "use TPR shadow"
> VM-execution control is set, the "virtual-interrupt delivery"
> VM-execution control is clear, "virtualize APIC accesses" is clear and
> bits 3:0 of TPR threshold is greater than bits 7:4 of vTPR.
> 
> Signed-off-by: Krish Sadhukhan <krish.sadhukhan@xxxxxxxxxx>
> Signed-off-by: Jim Mattson <jmattson@xxxxxxxxxx>
> ---
>  x86/vmx.h       |   1 +
>  x86/vmx_tests.c | 123 +++++++++++++++++++++++++++++++++++++++++++++++---------
>  2 files changed, 106 insertions(+), 18 deletions(-)

Thanks, queued.  However I haven't pushed it yet because VMX tests are
currently broken (my fault).

Thanks,

Paolo

> diff --git a/x86/vmx.h b/x86/vmx.h
> index f0b8776..bdcaac0 100644
> --- a/x86/vmx.h
> +++ b/x86/vmx.h
> @@ -388,6 +388,7 @@ enum Ctrl0 {
>  };
>  
>  enum Ctrl1 {
> +	CPU_VIRT_APIC_ACCESSES	= 1ul << 0,
>  	CPU_EPT			= 1ul << 1,
>  	CPU_DESC_TABLE		= 1ul << 2,
>  	CPU_RDTSCP		= 1ul << 3,
> diff --git a/x86/vmx_tests.c b/x86/vmx_tests.c
> index e8c97f2..6c10281 100644
> --- a/x86/vmx_tests.c
> +++ b/x86/vmx_tests.c
> @@ -3476,18 +3476,58 @@ static void test_apic_virt_addr(void)
>  				 "virtual-APIC address", "Use TPR shadow", true);
>  }
>  
> -static void try_tpr_threshold(unsigned val)
> +static void set_vtpr(unsigned vtpr)
> +{
> +	*(u32 *)phys_to_virt(vmcs_read(APIC_VIRT_ADDR) + APIC_TASKPRI) = vtpr;
> +}
> +
> +static void try_tpr_threshold_and_vtpr(unsigned threshold, unsigned vtpr)
> +{
> +	bool valid = true;
> +	u32 primary = vmcs_read(CPU_EXEC_CTRL0);
> +	u32 secondary = vmcs_read(CPU_EXEC_CTRL1);
> +
> +	if ((primary & CPU_TPR_SHADOW) &&
> +	    (!(primary & CPU_SECONDARY) ||
> +	     !(secondary & (CPU_VINTD | CPU_VIRT_APIC_ACCESSES))))
> +		valid = (threshold & 0xf) <= ((vtpr >> 4) & 0xf);
> +
> +	set_vtpr(vtpr);
> +	report_prefix_pushf("TPR threshold 0x%x, VTPR.class 0x%x",
> +	    threshold, (vtpr >> 4) & 0xf);
> +	test_vmx_controls(valid, false);
> +	report_prefix_pop();
> +}
> +
> +/*
> + * Test interesting vTPR values for a given TPR threshold.
> + */
> +static void test_vtpr_values(unsigned threshold)
> +{
> +	try_tpr_threshold_and_vtpr(threshold, threshold - 1);
> +	try_tpr_threshold_and_vtpr(threshold, threshold);
> +	try_tpr_threshold_and_vtpr(threshold, threshold + 1);
> +}
> +
> +static void try_tpr_threshold(unsigned threshold)
>  {
>  	bool valid = true;
>  
> -	if ((vmcs_read(CPU_EXEC_CTRL0) & CPU_TPR_SHADOW) &&
> -	    !((vmcs_read(CPU_EXEC_CTRL0) & CPU_SECONDARY) &&
> -	      (vmcs_read(CPU_EXEC_CTRL1) & CPU_VINTD)))
> -		valid = !(val >> 4);
> -	report_prefix_pushf("TPR threshold 0x%x", val);
> -	vmcs_write(TPR_THRESHOLD, val);
> +	u32 primary = vmcs_read(CPU_EXEC_CTRL0);
> +	u32 secondary = vmcs_read(CPU_EXEC_CTRL1);
> +
> +	if ((primary & CPU_TPR_SHADOW) && !((primary & CPU_SECONDARY) &&
> +	    (secondary & CPU_VINTD)))
> +		valid = !(threshold >> 4);
> +
> +	set_vtpr(-1);
> +	vmcs_write(TPR_THRESHOLD, threshold);
> +	report_prefix_pushf("TPR threshold 0x%x, VTPR.class 0xf", threshold);
>  	test_vmx_controls(valid, false);
>  	report_prefix_pop();
> +
> +	if (valid)
> +		test_vtpr_values(threshold);
>  }
>  
>  /*
> @@ -3506,10 +3546,21 @@ static void test_tpr_threshold_values(void)
>  }
>  
>  /*
> - * If the "use TPR shadow" VM-execution control is 1 and the
> - * "virtual-interrupt delivery" VM-execution control is 0, bits 31:4
> - * of the TPR threshold VM-execution control field must be 0.
> - * [Intel SDM]
> + * This test covers the following two VM entry checks:
> + *
> + *      i) If the "use TPR shadow" VM-execution control is 1 and the
> + *         "virtual-interrupt delivery" VM-execution control is 0, bits
> + *         31:4 of the TPR threshold VM-execution control field must
> +	   be 0.
> + *         [Intel SDM]
> + *
> + *      ii) If the "use TPR shadow" VM-execution control is 1, the
> + *          "virtual-interrupt delivery" VM-execution control is 0
> + *          and the "virtualize APIC accesses" VM-execution control
> + *          is 0, the value of bits 3:0 of the TPR threshold VM-execution
> + *          control field must not be greater than the value of bits
> + *          7:4 of VTPR.
> + *          [Intel SDM]
>   */
>  static void test_tpr_threshold(void)
>  {
> @@ -3524,7 +3575,7 @@ static void test_tpr_threshold(void)
>  	vmcs_write(APIC_VIRT_ADDR, virt_to_phys(virtual_apic_page));
>  
>  	vmcs_write(CPU_EXEC_CTRL0, primary & ~(CPU_TPR_SHADOW | CPU_SECONDARY));
> -	report_prefix_pushf("Use TPR shadow disabled");
> +	report_prefix_pushf("Use TPR shadow disabled, secondary controls disabled");
>  	test_tpr_threshold_values();
>  	report_prefix_pop();
>  	vmcs_write(CPU_EXEC_CTRL0, vmcs_read(CPU_EXEC_CTRL0) | CPU_TPR_SHADOW);
> @@ -3532,23 +3583,59 @@ static void test_tpr_threshold(void)
>  	test_tpr_threshold_values();
>  	report_prefix_pop();
>  
> -	if ((ctrl_cpu_rev[0].clr & CPU_SECONDARY) &&
> -	    (ctrl_cpu_rev[1].clr & CPU_VINTD)) {
> -		u32 secondary = vmcs_read(CPU_EXEC_CTRL1);
> +	if (!((ctrl_cpu_rev[0].clr & CPU_SECONDARY) &&
> +	    (ctrl_cpu_rev[1].clr & (CPU_VINTD  | CPU_VIRT_APIC_ACCESSES))))
> +		return;
> +
> +	u32 secondary = vmcs_read(CPU_EXEC_CTRL1);
>  
> +	if (ctrl_cpu_rev[1].clr & CPU_VINTD) {
>  		vmcs_write(CPU_EXEC_CTRL1, CPU_VINTD);
> -		report_prefix_pushf("Use TPR shadow enabled; secondary controls disabled");
> +		report_prefix_pushf("Use TPR shadow enabled; secondary controls disabled; virtual-interrupt delivery enabled; virtualize APIC accesses disabled");
>  		test_tpr_threshold_values();
>  		report_prefix_pop();
> +
>  		vmcs_write(CPU_EXEC_CTRL0,
>  			   vmcs_read(CPU_EXEC_CTRL0) | CPU_SECONDARY);
> -		report_prefix_pushf("Use TPR shadow enabled; virtual-interrupt delivery enabled");
> +		report_prefix_pushf("Use TPR shadow enabled; secondary controls enabled; virtual-interrupt delivery enabled; virtualize APIC accesses disabled");
> +		test_tpr_threshold_values();
> +		report_prefix_pop();
> +	}
> +
> +	if (ctrl_cpu_rev[1].clr & CPU_VIRT_APIC_ACCESSES) {
> +		vmcs_write(CPU_EXEC_CTRL0,
> +			   vmcs_read(CPU_EXEC_CTRL0) & ~CPU_SECONDARY);
> +		vmcs_write(CPU_EXEC_CTRL1, CPU_VIRT_APIC_ACCESSES);
> +		report_prefix_pushf("Use TPR shadow enabled; secondary controls disabled; virtual-interrupt delivery enabled; virtualize APIC accesses enabled");
>  		test_tpr_threshold_values();
>  		report_prefix_pop();
>  
> -		vmcs_write(CPU_EXEC_CTRL1, secondary);
> +		vmcs_write(CPU_EXEC_CTRL0,
> +			   vmcs_read(CPU_EXEC_CTRL0) | CPU_SECONDARY);
> +		report_prefix_pushf("Use TPR shadow enabled; secondary controls enabled; virtual-interrupt delivery enabled; virtualize APIC accesses enabled");
> +		test_tpr_threshold_values();
> +		report_prefix_pop();
>  	}
>  
> +	if ((ctrl_cpu_rev[1].clr &
> +	     (CPU_VINTD | CPU_VIRT_APIC_ACCESSES)) ==
> +	    (CPU_VINTD | CPU_VIRT_APIC_ACCESSES)) {
> +		vmcs_write(CPU_EXEC_CTRL0,
> +			   vmcs_read(CPU_EXEC_CTRL0) & ~CPU_SECONDARY);
> +		vmcs_write(CPU_EXEC_CTRL1,
> +			   CPU_VINTD | CPU_VIRT_APIC_ACCESSES);
> +		report_prefix_pushf("Use TPR shadow enabled; secondary controls disabled; virtual-interrupt delivery enabled; virtualize APIC accesses enabled");
> +		test_tpr_threshold_values();
> +		report_prefix_pop();
> +
> +		vmcs_write(CPU_EXEC_CTRL0,
> +			   vmcs_read(CPU_EXEC_CTRL0) | CPU_SECONDARY);
> +		report_prefix_pushf("Use TPR shadow enabled; secondary controls enabled; virtual-interrupt delivery enabled; virtualize APIC accesses enabled");
> +		test_tpr_threshold_values();
> +		report_prefix_pop();
> +	}
> +
> +	vmcs_write(CPU_EXEC_CTRL1, secondary);
>  	vmcs_write(CPU_EXEC_CTRL0, primary);
>  }
>  
> 




[Index of Archives]     [KVM ARM]     [KVM ia64]     [KVM ppc]     [Virtualization Tools]     [Spice Development]     [Libvirt]     [Libvirt Users]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite Questions]     [Linux Kernel]     [Linux SCSI]     [XFree86]

  Powered by Linux