Message ID | BLU437-SMTP68CD561CE0F1A444DE926580350@phx.gbl (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
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@gmail.com> > Signed-off-by: Wanpeng Li <wanpeng.li@hotmail.com> > --- > 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@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
On 10/13/15 10:44 PM, Paolo Bonzini wrote: > > 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@gmail.com> >> Signed-off-by: Wanpeng Li <wanpeng.li@hotmail.com> >> --- >> 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). Good point. I will do it after the new travel recently. :-) Regards, Wanpeng Li -- To unsubscribe from this list: send the line "unsubscribe kvm" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
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; }; #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;