Re: [PATCH v2 5/5] KVM: nVMX: expose VPID capability to L1

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

 




On 08/10/2015 07:57, Wanpeng Li wrote:
> Expose VPID capability to L1. For nested guests, we don't do anything 
> specific for single context invalidation. Hence, only advertise support 
> for global context invalidation. The major benefit of nested VPID comes 
> from having separate vpids when switching between L1 and L2, and also 
> when L2's vCPUs not sched in/out on L1.
> 
> Reviewed-by: Wincy Van <fanwenyi0529@xxxxxxxxx>
> Signed-off-by: Wanpeng Li <wanpeng.li@xxxxxxxxxxx>
> ---
>  arch/x86/kvm/vmx.c | 36 ++++++++++++++++++++++++------------
>  1 file changed, 24 insertions(+), 12 deletions(-)
> 
> diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
> index 31d272e..22b4dc7 100644
> --- a/arch/x86/kvm/vmx.c
> +++ b/arch/x86/kvm/vmx.c
> @@ -442,7 +442,7 @@ struct nested_vmx {
>  	u32 nested_vmx_true_entry_ctls_low;
>  	u32 nested_vmx_misc_low;
>  	u32 nested_vmx_misc_high;
> -	u32 nested_vmx_ept_caps;
> +	u64 nested_vmx_ept_vpid_caps;

Considering that all VMX_VPID_ constants are off by 32, perhaps it's
simpler to have separate variables for nested_vmx_ept_caps and
nested_vmx_vpid_caps, and only rejoin them when reading the MSR.  It
will make this patch smaller too.

You can add the new field to struct nested_vmx in patch 3 (leaving it
initialized to 0, of course).

Paolo

>  };
>  
>  #define POSTED_INTR_ON  0
> @@ -2489,18 +2489,22 @@ static void nested_vmx_setup_ctls_msrs(struct vcpu_vmx *vmx)
>  		/* nested EPT: emulate EPT also to L1 */
>  		vmx->nested.nested_vmx_secondary_ctls_high |=
>  			SECONDARY_EXEC_ENABLE_EPT;
> -		vmx->nested.nested_vmx_ept_caps = VMX_EPT_PAGE_WALK_4_BIT |
> +		vmx->nested.nested_vmx_ept_vpid_caps = VMX_EPT_PAGE_WALK_4_BIT |
>  			 VMX_EPTP_WB_BIT | VMX_EPT_2MB_PAGE_BIT |
>  			 VMX_EPT_INVEPT_BIT;
> -		vmx->nested.nested_vmx_ept_caps &= vmx_capability.ept;
> +		vmx->nested.nested_vmx_ept_vpid_caps &= vmx_capability.ept;
>  		/*
>  		 * For nested guests, we don't do anything specific
>  		 * for single context invalidation. Hence, only advertise
>  		 * support for global context invalidation.
>  		 */
> -		vmx->nested.nested_vmx_ept_caps |= VMX_EPT_EXTENT_GLOBAL_BIT;
> +		vmx->nested.nested_vmx_ept_vpid_caps |= VMX_EPT_EXTENT_GLOBAL_BIT;
>  	} else
> -		vmx->nested.nested_vmx_ept_caps = 0;
> +		vmx->nested.nested_vmx_ept_vpid_caps = 0;
> +
> +	if (enable_vpid)
> +		vmx->nested.nested_vmx_ept_vpid_caps |= (VMX_VPID_INVVPID_BIT |
> +			VMX_VPID_EXTENT_GLOBAL_CONTEXT_BIT) << 32;
>  
>  	if (enable_unrestricted_guest)
>  		vmx->nested.nested_vmx_secondary_ctls_high |=
> @@ -2616,8 +2620,7 @@ static int vmx_get_vmx_msr(struct kvm_vcpu *vcpu, u32 msr_index, u64 *pdata)
>  			vmx->nested.nested_vmx_secondary_ctls_high);
>  		break;
>  	case MSR_IA32_VMX_EPT_VPID_CAP:
> -		/* Currently, no nested vpid support */
> -		*pdata = vmx->nested.nested_vmx_ept_caps;
> +		*pdata = vmx->nested.nested_vmx_ept_vpid_caps;
>  		break;
>  	default:
>  		return 1;
> @@ -7152,7 +7155,7 @@ static int handle_invept(struct kvm_vcpu *vcpu)
>  
>  	if (!(vmx->nested.nested_vmx_secondary_ctls_high &
>  	      SECONDARY_EXEC_ENABLE_EPT) ||
> -	    !(vmx->nested.nested_vmx_ept_caps & VMX_EPT_INVEPT_BIT)) {
> +	    !(vmx->nested.nested_vmx_ept_vpid_caps & VMX_EPT_INVEPT_BIT)) {
>  		kvm_queue_exception(vcpu, UD_VECTOR);
>  		return 1;
>  	}
> @@ -7168,7 +7171,7 @@ static int handle_invept(struct kvm_vcpu *vcpu)
>  	vmx_instruction_info = vmcs_read32(VMX_INSTRUCTION_INFO);
>  	type = kvm_register_readl(vcpu, (vmx_instruction_info >> 28) & 0xf);
>  
> -	types = (vmx->nested.nested_vmx_ept_caps >> VMX_EPT_EXTENT_SHIFT) & 6;
> +	types = (vmx->nested.nested_vmx_ept_vpid_caps >> VMX_EPT_EXTENT_SHIFT) & 6;
>  
>  	if (!(types & (1UL << type))) {
>  		nested_vmx_failValid(vcpu,
> @@ -7207,14 +7210,15 @@ static int handle_invept(struct kvm_vcpu *vcpu)
>  static int handle_invvpid(struct kvm_vcpu *vcpu)
>  {
>  	struct vcpu_vmx *vmx = to_vmx(vcpu);
> -	u32 vmx_instruction_info;
> +	u32 vmx_instruction_info, types;
>  	unsigned long type;
>  	gva_t gva;
>  	struct x86_exception e;
>  	int vpid;
>  
>  	if (!(vmx->nested.nested_vmx_secondary_ctls_high &
> -	      SECONDARY_EXEC_ENABLE_VPID)) {
> +	      SECONDARY_EXEC_ENABLE_VPID) ||
> +		!(vmx->nested.nested_vmx_ept_vpid_caps & (VMX_VPID_INVVPID_BIT << 32))) {
>  		kvm_queue_exception(vcpu, UD_VECTOR);
>  		return 1;
>  	}
> @@ -7225,6 +7229,14 @@ static int handle_invvpid(struct kvm_vcpu *vcpu)
>  	vmx_instruction_info = vmcs_read32(VMX_INSTRUCTION_INFO);
>  	type = kvm_register_readl(vcpu, (vmx_instruction_info >> 28) & 0xf);
>  
> +	types = (vmx->nested.nested_vmx_ept_vpid_caps >> VMX_VPID_EXTENT_SHIFT) & 0x7;
> +
> +	if (!(types & (1UL << type))) {
> +		nested_vmx_failValid(vcpu,
> +				VMXERR_INVALID_OPERAND_TO_INVEPT_INVVPID);
> +		return 1;
> +	}
> +
>  	/* according to the intel vmx instruction reference, the memory
>  	 * operand is read even if it isn't needed (e.g., for type==global)
>  	 */
> @@ -8798,7 +8810,7 @@ static void nested_ept_init_mmu_context(struct kvm_vcpu *vcpu)
>  {
>  	WARN_ON(mmu_is_nested(vcpu));
>  	kvm_init_shadow_ept_mmu(vcpu,
> -			to_vmx(vcpu)->nested.nested_vmx_ept_caps &
> +			to_vmx(vcpu)->nested.nested_vmx_ept_vpid_caps &
>  			VMX_EPT_EXECUTE_ONLY_BIT);
>  	vcpu->arch.mmu.set_cr3           = vmx_set_cr3;
>  	vcpu->arch.mmu.get_cr3           = nested_ept_get_cr3;
> 
--
To unsubscribe from this list: send the line "unsubscribe kvm" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html



[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