[PATCH v2 24/36] KVM: nVMX: Introduce module parameter for nested APIC timer virtualization

From: isaku . yamahata

Date: Thu Mar 05 2026 - 12:59:26 EST


From: Isaku Yamahata <isaku.yamahata@xxxxxxxxx>

Introduce a new module parameter, nested_apic_timer_virt, to control the
nested virtualization of the APIC timer in KVM.

The nested_apic_timer_virt parameter is set to true by default on processor
platforms that support APIC timer virtualization. On platforms that do not
support this feature, the parameter will indicate that APIC timer
virtualization is not available.

Signed-off-by: Isaku Yamahata <isaku.yamahata@xxxxxxxxx>
---
Changes:
v1 -> v2:
- use 0444 instead of S_IRUGO.
---
arch/x86/kvm/vmx/capabilities.h | 1 +
arch/x86/kvm/vmx/nested.c | 13 ++++++++++++-
arch/x86/kvm/vmx/vmx.c | 2 +-
3 files changed, 14 insertions(+), 2 deletions(-)

diff --git a/arch/x86/kvm/vmx/capabilities.h b/arch/x86/kvm/vmx/capabilities.h
index 8d67be77f02c..861334e15c01 100644
--- a/arch/x86/kvm/vmx/capabilities.h
+++ b/arch/x86/kvm/vmx/capabilities.h
@@ -15,6 +15,7 @@ extern bool __read_mostly enable_ept;
extern bool __read_mostly enable_unrestricted_guest;
extern bool __read_mostly enable_ept_ad_bits;
extern bool __read_mostly enable_pml;
+extern bool __read_mostly enable_apic_timer_virt;
extern int __read_mostly pt_mode;

#define PT_MODE_SYSTEM 0
diff --git a/arch/x86/kvm/vmx/nested.c b/arch/x86/kvm/vmx/nested.c
index 3cd29b005afe..60c7256298ce 100644
--- a/arch/x86/kvm/vmx/nested.c
+++ b/arch/x86/kvm/vmx/nested.c
@@ -27,6 +27,10 @@ module_param_named(enable_shadow_vmcs, enable_shadow_vmcs, bool, S_IRUGO);
static bool __ro_after_init warn_on_missed_cc;
module_param(warn_on_missed_cc, bool, 0444);

+static bool __read_mostly enable_nested_apic_timer_virt = true;
+module_param_named(nested_apic_timer_virt, enable_nested_apic_timer_virt, bool,
+ 0444);
+
#define CC KVM_NESTED_VMENTER_CONSISTENCY_CHECK

/*
@@ -7453,13 +7457,20 @@ static void nested_vmx_setup_secondary_ctls(u32 ept_caps,
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;
+ enable_nested_apic_timer_virt &= enable_apic_timer_virt;

+ msrs->tertiary_ctls = vmcs_conf->cpu_based_3rd_exec_ctrl;
msrs->tertiary_ctls &= TERTIARY_EXEC_GUEST_APIC_TIMER;

+ if (!enable_nested_apic_timer_virt)
+ msrs->tertiary_ctls &= ~TERTIARY_EXEC_GUEST_APIC_TIMER;
+
if (msrs->tertiary_ctls)
msrs->procbased_ctls_high |=
CPU_BASED_ACTIVATE_TERTIARY_CONTROLS;
+
+ if (!(msrs->tertiary_ctls & TERTIARY_EXEC_GUEST_APIC_TIMER))
+ enable_nested_apic_timer_virt = false;
}

static void nested_vmx_setup_misc_data(struct vmcs_config *vmcs_conf,
diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c
index 0271514162df..4d5414af750b 100644
--- a/arch/x86/kvm/vmx/vmx.c
+++ b/arch/x86/kvm/vmx/vmx.c
@@ -119,7 +119,7 @@ module_param(enable_ipiv, bool, 0444);

module_param(enable_device_posted_irqs, bool, 0444);

-static bool __read_mostly enable_apic_timer_virt = true;
+bool __read_mostly enable_apic_timer_virt = true;
module_param_named(apic_timer_virt, enable_apic_timer_virt, bool, 0444);

/*
--
2.45.2