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