[PATCH v2 01/36] KVM: VMX: Detect APIC timer virtualization bit
From: isaku . yamahata
Date: Thu Mar 05 2026 - 12:46:07 EST
From: Yang Zhong <yang.zhong@xxxxxxxxxxxxxxx>
Detect the APIC timer virtualization feature by setting the bit (bit 8) in
the tertiary processor-based VM-execution controls. Additionally, define
the new related VMCS fields necessary for managing this feature.
Do not enable the feature bit in the tertiary VM exec control yet until the
supporting logic is implemented.
Signed-off-by: Yang Zhong <yang.zhong@xxxxxxxxxxxxxxx>
Signed-off-by: Isaku Yamahata <isaku.yamahata@xxxxxxxxx>
---
Changes:
v1 -> v2:
- Change KVM_OPTIONAL_VMX_TERTIARY_VM_EXEC_CONTROL to include apic timer
virt bit to avoid compile time errors. Clear the bit when
adjust_vmx_controls64() is called instead.
---
arch/x86/include/asm/vmx.h | 6 ++++++
arch/x86/include/asm/vmxfeatures.h | 1 +
arch/x86/kvm/vmx/vmx.c | 20 +++++++++++++++++++-
arch/x86/kvm/vmx/vmx.h | 3 ++-
4 files changed, 28 insertions(+), 2 deletions(-)
diff --git a/arch/x86/include/asm/vmx.h b/arch/x86/include/asm/vmx.h
index 37080382df54..a9fe10cf1b4d 100644
--- a/arch/x86/include/asm/vmx.h
+++ b/arch/x86/include/asm/vmx.h
@@ -96,6 +96,7 @@ struct vmcs {
* Definitions of Tertiary Processor-Based VM-Execution Controls.
*/
#define TERTIARY_EXEC_IPI_VIRT VMCS_CONTROL_BIT(IPI_VIRT)
+#define TERTIARY_EXEC_GUEST_APIC_TIMER VMCS_CONTROL_BIT(GUEST_APIC_TIMER)
#define PIN_BASED_EXT_INTR_MASK VMCS_CONTROL_BIT(INTR_EXITING)
#define PIN_BASED_NMI_EXITING VMCS_CONTROL_BIT(NMI_EXITING)
@@ -204,6 +205,7 @@ enum vmcs_field {
VIRTUAL_PROCESSOR_ID = 0x00000000,
POSTED_INTR_NV = 0x00000002,
LAST_PID_POINTER_INDEX = 0x00000008,
+ GUEST_APIC_TIMER_VECTOR = 0x0000000a,
GUEST_ES_SELECTOR = 0x00000800,
GUEST_CS_SELECTOR = 0x00000802,
GUEST_SS_SELECTOR = 0x00000804,
@@ -274,6 +276,8 @@ enum vmcs_field {
SHARED_EPT_POINTER = 0x0000203C,
PID_POINTER_TABLE = 0x00002042,
PID_POINTER_TABLE_HIGH = 0x00002043,
+ GUEST_DEADLINE_VIR = 0x0000204e,
+ GUEST_DEADLINE_VIR_HIGH = 0x0000204f,
GUEST_PHYSICAL_ADDRESS = 0x00002400,
GUEST_PHYSICAL_ADDRESS_HIGH = 0x00002401,
VMCS_LINK_POINTER = 0x00002800,
@@ -298,6 +302,8 @@ enum vmcs_field {
GUEST_BNDCFGS_HIGH = 0x00002813,
GUEST_IA32_RTIT_CTL = 0x00002814,
GUEST_IA32_RTIT_CTL_HIGH = 0x00002815,
+ GUEST_DEADLINE_PHY = 0x00002830,
+ GUEST_DEADLINE_PHY_HIGH = 0x00002831,
HOST_IA32_PAT = 0x00002c00,
HOST_IA32_PAT_HIGH = 0x00002c01,
HOST_IA32_EFER = 0x00002c02,
diff --git a/arch/x86/include/asm/vmxfeatures.h b/arch/x86/include/asm/vmxfeatures.h
index 09b1d7e607c1..f2eb4243bae4 100644
--- a/arch/x86/include/asm/vmxfeatures.h
+++ b/arch/x86/include/asm/vmxfeatures.h
@@ -90,4 +90,5 @@
/* Tertiary Processor-Based VM-Execution Controls, word 3 */
#define VMX_FEATURE_IPI_VIRT ( 3*32+ 4) /* "ipi_virt" Enable IPI virtualization */
+#define VMX_FEATURE_GUEST_APIC_TIMER ( 3*32+ 8) /* Enable virtual APIC tsc deadline */
#endif /* _ASM_X86_VMXFEATURES_H */
diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c
index 9302c16571cd..4ccb2e42322d 100644
--- a/arch/x86/kvm/vmx/vmx.c
+++ b/arch/x86/kvm/vmx/vmx.c
@@ -2791,9 +2791,20 @@ static int setup_vmcs_config(struct vmcs_config *vmcs_conf,
if (_cpu_based_exec_control & CPU_BASED_ACTIVATE_TERTIARY_CONTROLS)
_cpu_based_3rd_exec_control =
- adjust_vmx_controls64(KVM_OPTIONAL_VMX_TERTIARY_VM_EXEC_CONTROL,
+ adjust_vmx_controls64(KVM_OPTIONAL_VMX_TERTIARY_VM_EXEC_CONTROL
+ /*
+ * Disable apic timer
+ * virtualization until the logic
+ * is imlemented.
+ * Once it's supported, add
+ * TERTIARY_EXEC_GUEST_APIC_TIMER.
+ */
+ & ~TERTIARY_EXEC_GUEST_APIC_TIMER,
MSR_IA32_VMX_PROCBASED_CTLS3);
+ if (!(_cpu_based_2nd_exec_control & SECONDARY_EXEC_VIRTUAL_INTR_DELIVERY))
+ _cpu_based_3rd_exec_control &= ~TERTIARY_EXEC_GUEST_APIC_TIMER;
+
if (adjust_vmx_controls(KVM_REQUIRED_VMX_VM_EXIT_CONTROLS,
KVM_OPTIONAL_VMX_VM_EXIT_CONTROLS,
MSR_IA32_VMX_EXIT_CTLS,
@@ -4636,6 +4647,13 @@ static u64 vmx_tertiary_exec_control(struct vcpu_vmx *vmx)
if (!enable_ipiv || !kvm_vcpu_apicv_active(&vmx->vcpu))
exec_control &= ~TERTIARY_EXEC_IPI_VIRT;
+ /*
+ * APIC timer virtualization is supported only for TSC deadline mode.
+ * Disable for one-shot/periodic mode. Dynamically set/clear the bit
+ * on the guest timer mode change. Disable on reset state.
+ */
+ exec_control &= ~TERTIARY_EXEC_GUEST_APIC_TIMER;
+
return exec_control;
}
diff --git a/arch/x86/kvm/vmx/vmx.h b/arch/x86/kvm/vmx/vmx.h
index 70bfe81dea54..9a61f6bd8cc0 100644
--- a/arch/x86/kvm/vmx/vmx.h
+++ b/arch/x86/kvm/vmx/vmx.h
@@ -575,7 +575,8 @@ static inline u8 vmx_get_rvi(void)
#define KVM_REQUIRED_VMX_TERTIARY_VM_EXEC_CONTROL 0
#define KVM_OPTIONAL_VMX_TERTIARY_VM_EXEC_CONTROL \
- (TERTIARY_EXEC_IPI_VIRT)
+ (TERTIARY_EXEC_IPI_VIRT | \
+ TERTIARY_EXEC_GUEST_APIC_TIMER)
#define BUILD_CONTROLS_SHADOW(lname, uname, bits) \
static inline void lname##_controls_set(struct vcpu_vmx *vmx, u##bits val) \
--
2.45.2