From: Isaku Yamahata Emulate MSR_IA32_VMX_PROCBASED_CTLS3 to advertise APIC timer virtualization feature to the L2 guest. Signed-off-by: Isaku Yamahata --- arch/x86/kvm/vmx/capabilities.h | 1 + arch/x86/kvm/vmx/hyperv.c | 7 ++++++ arch/x86/kvm/vmx/nested.c | 42 +++++++++++++++++++++++++++++++++ arch/x86/kvm/vmx/nested.h | 5 ++++ arch/x86/kvm/x86.h | 2 +- 5 files changed, 56 insertions(+), 1 deletion(-) diff --git a/arch/x86/kvm/vmx/capabilities.h b/arch/x86/kvm/vmx/capabilities.h index ffc51fe9a455..f73a50c887ac 100644 --- a/arch/x86/kvm/vmx/capabilities.h +++ b/arch/x86/kvm/vmx/capabilities.h @@ -47,6 +47,7 @@ struct nested_vmx_msrs { u64 cr4_fixed1; u64 vmcs_enum; u64 vmfunc_controls; + u64 tertiary_ctls; }; struct vmcs_config { diff --git a/arch/x86/kvm/vmx/hyperv.c b/arch/x86/kvm/vmx/hyperv.c index fa41d036acd4..2731c2e4b0e5 100644 --- a/arch/x86/kvm/vmx/hyperv.c +++ b/arch/x86/kvm/vmx/hyperv.c @@ -141,6 +141,13 @@ void nested_evmcs_filter_control_msr(struct kvm_vcpu *vcpu, u32 msr_index, u64 * case MSR_IA32_VMX_PROCBASED_CTLS2: ctl_high &= evmcs_get_supported_ctls(EVMCS_2NDEXEC); break; + case MSR_IA32_VMX_PROCBASED_CTLS3: + /* + * tertiary procbased controls are 64-bit. 0 means unsupported, + * 1 supported. + */ + *pdata &= evmcs_get_supported_ctls(EVMCS_3RDEXEC); + return; case MSR_IA32_VMX_TRUE_PINBASED_CTLS: case MSR_IA32_VMX_PINBASED_CTLS: ctl_high &= evmcs_get_supported_ctls(EVMCS_PINCTRL); diff --git a/arch/x86/kvm/vmx/nested.c b/arch/x86/kvm/vmx/nested.c index b1b8f0c88ca5..8cd56e9f1cf0 100644 --- a/arch/x86/kvm/vmx/nested.c +++ b/arch/x86/kvm/vmx/nested.c @@ -215,6 +215,11 @@ static inline bool vmx_control_verify(u32 control, u32 low, u32 high) return fixed_bits_valid(control, low, high); } +static inline bool vmx_control64_verify(u64 control, u64 msr) +{ + return !(control & ~msr); +} + static inline u64 vmx_control_msr(u32 low, u32 high) { return low | ((u64)high << 32); @@ -1515,6 +1520,19 @@ int vmx_set_vmx_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info) case MSR_IA32_VMX_TRUE_ENTRY_CTLS: case MSR_IA32_VMX_PROCBASED_CTLS2: return vmx_restore_control_msr(vmx, msr_index, data); + case MSR_IA32_VMX_PROCBASED_CTLS3: + if (!__nested_cpu_supports_tertiary_ctls(&vmcs_config.nested)) + return -EINVAL; + + /* read-only for guest. */ + if (!msr_info->host_initiated) + return -EINVAL; + + if (!vmx_control64_verify(data, + vmcs_config.nested.tertiary_ctls)) + return -EINVAL; + vmx->nested.msrs.tertiary_ctls = data; + return 0; case MSR_IA32_VMX_MISC: return vmx_restore_vmx_misc(vmx, data); case MSR_IA32_VMX_CR0_FIXED0: @@ -1612,6 +1630,16 @@ int vmx_get_vmx_msr(struct nested_vmx_msrs *msrs, struct msr_data *msr_info) msrs->secondary_ctls_low, msrs->secondary_ctls_high); break; + case MSR_IA32_VMX_PROCBASED_CTLS3: + if (!__nested_cpu_supports_tertiary_ctls(&vmcs_config.nested)) + return KVM_MSR_RET_UNSUPPORTED; + + if (!msr_info->host_initiated && + !__nested_cpu_supports_tertiary_ctls(msrs)) + return -EINVAL; + + *pdata = msrs->tertiary_ctls; + break; case MSR_IA32_VMX_EPT_VPID_CAP: *pdata = msrs->ept_caps | ((u64)msrs->vpid_caps << 32); @@ -7314,6 +7342,18 @@ static void nested_vmx_setup_secondary_ctls(u32 ept_caps, msrs->secondary_ctls_high |= SECONDARY_EXEC_ENCLS_EXITING; } +static void nested_vmx_setup_tertiary_ctls(struct vmcs_config *vmcs_conf, + struct nested_vmx_msrs *msrs) +{ + msrs->tertiary_ctls = vmcs_conf->cpu_based_3rd_exec_ctrl; + + msrs->tertiary_ctls &= TERTIARY_EXEC_GUEST_APIC_TIMER; + + if (msrs->tertiary_ctls) + msrs->procbased_ctls_high |= + CPU_BASED_ACTIVATE_TERTIARY_CONTROLS; +} + static void nested_vmx_setup_misc_data(struct vmcs_config *vmcs_conf, struct nested_vmx_msrs *msrs) { @@ -7402,6 +7442,8 @@ void nested_vmx_setup_ctls_msrs(struct vmcs_config *vmcs_conf, u32 ept_caps) nested_vmx_setup_secondary_ctls(ept_caps, vmcs_conf, msrs); + nested_vmx_setup_tertiary_ctls(vmcs_conf, msrs); + nested_vmx_setup_misc_data(vmcs_conf, msrs); nested_vmx_setup_basic(msrs); diff --git a/arch/x86/kvm/vmx/nested.h b/arch/x86/kvm/vmx/nested.h index f51d7cac8a58..d6d89ae1daec 100644 --- a/arch/x86/kvm/vmx/nested.h +++ b/arch/x86/kvm/vmx/nested.h @@ -153,6 +153,11 @@ static inline bool nested_cpu_has_vmx_shadow_vmcs(struct kvm_vcpu *vcpu) SECONDARY_EXEC_SHADOW_VMCS; } +static inline bool __nested_cpu_supports_tertiary_ctls(struct nested_vmx_msrs *msrs) +{ + return msrs->procbased_ctls_high & CPU_BASED_ACTIVATE_TERTIARY_CONTROLS; +} + static inline bool nested_cpu_has(struct vmcs12 *vmcs12, u32 bit) { return vmcs12->cpu_based_vm_exec_control & bit; diff --git a/arch/x86/kvm/x86.h b/arch/x86/kvm/x86.h index fdab0ad49098..7ba7abf02bbd 100644 --- a/arch/x86/kvm/x86.h +++ b/arch/x86/kvm/x86.h @@ -92,7 +92,7 @@ do { \ * associated feature that KVM supports for nested virtualization. */ #define KVM_FIRST_EMULATED_VMX_MSR MSR_IA32_VMX_BASIC -#define KVM_LAST_EMULATED_VMX_MSR MSR_IA32_VMX_VMFUNC +#define KVM_LAST_EMULATED_VMX_MSR MSR_IA32_VMX_PROCBASED_CTLS3 #define KVM_DEFAULT_PLE_GAP 128 #define KVM_VMX_DEFAULT_PLE_WINDOW 4096 -- 2.45.2