[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <db2b5ea67d9275463f1b613e19fa7194858ca5a1.1770116051.git.isaku.yamahata@intel.com>
Date: Tue, 3 Feb 2026 10:16:53 -0800
From: isaku.yamahata@...el.com
To: kvm@...r.kernel.org
Cc: isaku.yamahata@...el.com,
isaku.yamahata@...il.com,
Paolo Bonzini <pbonzini@...hat.com>,
Sean Christopherson <seanjc@...gle.com>,
linux-kernel@...r.kernel.org
Subject: [PATCH 10/32] KVM: nVMX: Supports VMX tertiary controls and GUEST_APIC_TIMER bit
From: Isaku Yamahata <isaku.yamahata@...el.com>
Emulate MSR_IA32_VMX_PROCBASED_CTLS3 to advertise APIC timer virtualization
feature to the L2 guest.
Signed-off-by: Isaku Yamahata <isaku.yamahata@...el.com>
---
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
Powered by blists - more mailing lists