* [PATCH v4 0/7] KVM: SVM: Enable AVIC for Zen4+ (if x2AVIC)
@ 2025-09-19 21:59 Sean Christopherson
2025-09-19 21:59 ` [PATCH v4 1/7] KVM: SVM: Make svm_x86_ops globally visible, clean up on-HyperV usage Sean Christopherson
` (7 more replies)
0 siblings, 8 replies; 9+ messages in thread
From: Sean Christopherson @ 2025-09-19 21:59 UTC (permalink / raw)
To: Sean Christopherson, Paolo Bonzini, Vitaly Kuznetsov
Cc: kvm, linux-kernel, Naveen N Rao
Enable AVIC by default for Zen4+, so long as x2AVIC is supported (which should
be the case if AVIC is supported).
v4:
- Collect tags. [Naveen]
- Add missing "(AMD)" for Naveen's attribution. [Naveen]
- Make svm_x86_ops globally visible, to match TDX, instead of passing in
the struct as parameter to avic_hardware_setup(). [Naveen]
- s/avic_want_avic_enabled/avic_want_enabled. [Naveen]
- Print "AVIC enabled" in avic_harware_setup() so that it's close to the
"x2AVIC enabled" message. [Naveen]
v3: https://lore.kernel.org/all/owztdzclln5pmgsuxgzt54vneiejtngdkujaebr7r35zx3f4lj@xvvhwvumkkha
- Don't advise the user to enable force_avic. [Naveen]
- Gather AVIC related module params in avic.c (by moving code/helpers to
avic.c).
- Print "AVIC enabled" even when it's forced.
- Enable by default iff x2AVIC is supported.
- Use "auto" to select KVM's automatic/default behavior.
v2: https://lore.kernel.org/all/cover.1756993734.git.naveen@kernel.org
v1: http://lkml.kernel.org/r/20250626145122.2228258-1-naveen@kernel.org
Naveen N Rao (AMD) (1):
KVM: SVM: Enable AVIC by default for Zen4+ if x2AVIC is support
Sean Christopherson (6):
KVM: SVM: Make svm_x86_ops globally visible, clean up on-HyperV usage
KVM: SVM: Move x2AVIC MSR interception helper to avic.c
KVM: SVM: Update "APICv in x2APIC without x2AVIC" in avic.c, not svm.c
KVM: SVM: Always print "AVIC enabled" separately, even when force
enabled
KVM: SVM: Don't advise the user to do force_avic=y (when x2AVIC is
detected)
KVM: SVM: Move global "avic" variable to avic.c
arch/x86/kvm/svm/avic.c | 151 ++++++++++++++++++++++++++------
arch/x86/kvm/svm/svm.c | 64 +-------------
arch/x86/kvm/svm/svm.h | 6 +-
arch/x86/kvm/svm/svm_onhyperv.c | 28 +++++-
arch/x86/kvm/svm/svm_onhyperv.h | 31 +------
5 files changed, 158 insertions(+), 122 deletions(-)
base-commit: c8fbf7ceb2ae3f64b0c377c8c21f6df577a13eb4
--
2.51.0.470.ga7dc726c21-goog
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH v4 1/7] KVM: SVM: Make svm_x86_ops globally visible, clean up on-HyperV usage
2025-09-19 21:59 [PATCH v4 0/7] KVM: SVM: Enable AVIC for Zen4+ (if x2AVIC) Sean Christopherson
@ 2025-09-19 21:59 ` Sean Christopherson
2025-09-19 21:59 ` [PATCH v4 2/7] KVM: SVM: Move x2AVIC MSR interception helper to avic.c Sean Christopherson
` (6 subsequent siblings)
7 siblings, 0 replies; 9+ messages in thread
From: Sean Christopherson @ 2025-09-19 21:59 UTC (permalink / raw)
To: Sean Christopherson, Paolo Bonzini, Vitaly Kuznetsov
Cc: kvm, linux-kernel, Naveen N Rao
Make svm_x86_ops globally visible in anticipation of modifying the struct
in avic.c, and clean up the KVM-on-HyperV usage, as declaring _and using_
a local variable in a header that's only defined in one specific .c-file
is all kinds of ugly.
Opportunistically make svm_hv_enable_l2_tlb_flush() local to
svm_onhyperv.c, as the only reason it was visible was due to the
aforementioned shenanigans in svm_onhyperv.h.
Alternatively, svm_x86_ops could be explicitly passed to
svm_hv_hardware_setup() as a parameter. While that approach is slightly
safer, e.g. avoids "hidden" updates, for better or worse, the Intel side
of KVM has already chosen to expose vt_x86_ops (and vt_init_ops). Given
that svm_x86_ops is only truly consumed by kvm_ops_update, the odds of a
"hidden" update causing problems are extremely low. So, absent a strong
reason to rework the VMX/TDX code, make svm_x86_ops visible, as having all
updates use exactly "svm_x86_ops." is advantageous in its own right.
No functional change intended.
Signed-off-by: Sean Christopherson <seanjc@google.com>
---
arch/x86/kvm/svm/svm.c | 2 +-
arch/x86/kvm/svm/svm.h | 2 ++
arch/x86/kvm/svm/svm_onhyperv.c | 28 +++++++++++++++++++++++++++-
arch/x86/kvm/svm/svm_onhyperv.h | 31 +------------------------------
4 files changed, 31 insertions(+), 32 deletions(-)
diff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c
index 67f4eed01526..8117d79036bb 100644
--- a/arch/x86/kvm/svm/svm.c
+++ b/arch/x86/kvm/svm/svm.c
@@ -5032,7 +5032,7 @@ static void *svm_alloc_apic_backing_page(struct kvm_vcpu *vcpu)
return page_address(page);
}
-static struct kvm_x86_ops svm_x86_ops __initdata = {
+struct kvm_x86_ops svm_x86_ops __initdata = {
.name = KBUILD_MODNAME,
.check_processor_compatibility = svm_check_processor_compat,
diff --git a/arch/x86/kvm/svm/svm.h b/arch/x86/kvm/svm/svm.h
index 5d39c0b17988..1652a868c578 100644
--- a/arch/x86/kvm/svm/svm.h
+++ b/arch/x86/kvm/svm/svm.h
@@ -52,6 +52,8 @@ extern bool x2avic_enabled;
extern bool vnmi;
extern int lbrv;
+extern struct kvm_x86_ops svm_x86_ops __initdata;
+
/*
* Clean bits in VMCB.
* VMCB_ALL_CLEAN_MASK might also need to
diff --git a/arch/x86/kvm/svm/svm_onhyperv.c b/arch/x86/kvm/svm/svm_onhyperv.c
index 3971b3ea5d04..a8e78c0e5956 100644
--- a/arch/x86/kvm/svm/svm_onhyperv.c
+++ b/arch/x86/kvm/svm/svm_onhyperv.c
@@ -15,7 +15,7 @@
#include "kvm_onhyperv.h"
#include "svm_onhyperv.h"
-int svm_hv_enable_l2_tlb_flush(struct kvm_vcpu *vcpu)
+static int svm_hv_enable_l2_tlb_flush(struct kvm_vcpu *vcpu)
{
struct hv_vmcb_enlightenments *hve;
hpa_t partition_assist_page = hv_get_partition_assist_page(vcpu);
@@ -35,3 +35,29 @@ int svm_hv_enable_l2_tlb_flush(struct kvm_vcpu *vcpu)
return 0;
}
+__init void svm_hv_hardware_setup(void)
+{
+ if (npt_enabled &&
+ ms_hyperv.nested_features & HV_X64_NESTED_ENLIGHTENED_TLB) {
+ pr_info(KBUILD_MODNAME ": Hyper-V enlightened NPT TLB flush enabled\n");
+ svm_x86_ops.flush_remote_tlbs = hv_flush_remote_tlbs;
+ svm_x86_ops.flush_remote_tlbs_range = hv_flush_remote_tlbs_range;
+ }
+
+ if (ms_hyperv.nested_features & HV_X64_NESTED_DIRECT_FLUSH) {
+ int cpu;
+
+ pr_info(KBUILD_MODNAME ": Hyper-V Direct TLB Flush enabled\n");
+ for_each_online_cpu(cpu) {
+ struct hv_vp_assist_page *vp_ap =
+ hv_get_vp_assist_page(cpu);
+
+ if (!vp_ap)
+ continue;
+
+ vp_ap->nested_control.features.directhypercall = 1;
+ }
+ svm_x86_ops.enable_l2_tlb_flush =
+ svm_hv_enable_l2_tlb_flush;
+ }
+}
diff --git a/arch/x86/kvm/svm/svm_onhyperv.h b/arch/x86/kvm/svm/svm_onhyperv.h
index f85bc617ffe4..08f14e6f195c 100644
--- a/arch/x86/kvm/svm/svm_onhyperv.h
+++ b/arch/x86/kvm/svm/svm_onhyperv.h
@@ -13,9 +13,7 @@
#include "kvm_onhyperv.h"
#include "svm/hyperv.h"
-static struct kvm_x86_ops svm_x86_ops;
-
-int svm_hv_enable_l2_tlb_flush(struct kvm_vcpu *vcpu);
+__init void svm_hv_hardware_setup(void);
static inline bool svm_hv_is_enlightened_tlb_enabled(struct kvm_vcpu *vcpu)
{
@@ -40,33 +38,6 @@ static inline void svm_hv_init_vmcb(struct vmcb *vmcb)
hve->hv_enlightenments_control.msr_bitmap = 1;
}
-static inline __init void svm_hv_hardware_setup(void)
-{
- if (npt_enabled &&
- ms_hyperv.nested_features & HV_X64_NESTED_ENLIGHTENED_TLB) {
- pr_info(KBUILD_MODNAME ": Hyper-V enlightened NPT TLB flush enabled\n");
- svm_x86_ops.flush_remote_tlbs = hv_flush_remote_tlbs;
- svm_x86_ops.flush_remote_tlbs_range = hv_flush_remote_tlbs_range;
- }
-
- if (ms_hyperv.nested_features & HV_X64_NESTED_DIRECT_FLUSH) {
- int cpu;
-
- pr_info(KBUILD_MODNAME ": Hyper-V Direct TLB Flush enabled\n");
- for_each_online_cpu(cpu) {
- struct hv_vp_assist_page *vp_ap =
- hv_get_vp_assist_page(cpu);
-
- if (!vp_ap)
- continue;
-
- vp_ap->nested_control.features.directhypercall = 1;
- }
- svm_x86_ops.enable_l2_tlb_flush =
- svm_hv_enable_l2_tlb_flush;
- }
-}
-
static inline void svm_hv_vmcb_dirty_nested_enlightenments(
struct kvm_vcpu *vcpu)
{
--
2.51.0.470.ga7dc726c21-goog
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH v4 2/7] KVM: SVM: Move x2AVIC MSR interception helper to avic.c
2025-09-19 21:59 [PATCH v4 0/7] KVM: SVM: Enable AVIC for Zen4+ (if x2AVIC) Sean Christopherson
2025-09-19 21:59 ` [PATCH v4 1/7] KVM: SVM: Make svm_x86_ops globally visible, clean up on-HyperV usage Sean Christopherson
@ 2025-09-19 21:59 ` Sean Christopherson
2025-09-19 21:59 ` [PATCH v4 3/7] KVM: SVM: Update "APICv in x2APIC without x2AVIC" in avic.c, not svm.c Sean Christopherson
` (5 subsequent siblings)
7 siblings, 0 replies; 9+ messages in thread
From: Sean Christopherson @ 2025-09-19 21:59 UTC (permalink / raw)
To: Sean Christopherson, Paolo Bonzini, Vitaly Kuznetsov
Cc: kvm, linux-kernel, Naveen N Rao
Move svm_set_x2apic_msr_interception() to avic.c as it's only relevant
when x2AVIC is enabled/supported and only called by AVIC code. In
addition to scoping AVIC code to avic.c, this will allow burying the
global x2avic_enabled variable in avic.
Opportunistically rename the helper to explicitly scope it to "avic".
No functional change intended.
Reviewed-by: Naveen N Rao (AMD) <naveen@kernel.org>
Tested-by: Naveen N Rao (AMD) <naveen@kernel.org>
Signed-off-by: Sean Christopherson <seanjc@google.com>
---
arch/x86/kvm/svm/avic.c | 57 ++++++++++++++++++++++++++++++++++++++---
arch/x86/kvm/svm/svm.c | 49 -----------------------------------
arch/x86/kvm/svm/svm.h | 1 -
3 files changed, 54 insertions(+), 53 deletions(-)
diff --git a/arch/x86/kvm/svm/avic.c b/arch/x86/kvm/svm/avic.c
index a34c5c3b164e..478a18208a76 100644
--- a/arch/x86/kvm/svm/avic.c
+++ b/arch/x86/kvm/svm/avic.c
@@ -79,6 +79,57 @@ static bool next_vm_id_wrapped = 0;
static DEFINE_SPINLOCK(svm_vm_data_hash_lock);
bool x2avic_enabled;
+
+static void avic_set_x2apic_msr_interception(struct vcpu_svm *svm,
+ bool intercept)
+{
+ static const u32 x2avic_passthrough_msrs[] = {
+ X2APIC_MSR(APIC_ID),
+ X2APIC_MSR(APIC_LVR),
+ X2APIC_MSR(APIC_TASKPRI),
+ X2APIC_MSR(APIC_ARBPRI),
+ X2APIC_MSR(APIC_PROCPRI),
+ X2APIC_MSR(APIC_EOI),
+ X2APIC_MSR(APIC_RRR),
+ X2APIC_MSR(APIC_LDR),
+ X2APIC_MSR(APIC_DFR),
+ X2APIC_MSR(APIC_SPIV),
+ X2APIC_MSR(APIC_ISR),
+ X2APIC_MSR(APIC_TMR),
+ X2APIC_MSR(APIC_IRR),
+ X2APIC_MSR(APIC_ESR),
+ X2APIC_MSR(APIC_ICR),
+ X2APIC_MSR(APIC_ICR2),
+
+ /*
+ * Note! Always intercept LVTT, as TSC-deadline timer mode
+ * isn't virtualized by hardware, and the CPU will generate a
+ * #GP instead of a #VMEXIT.
+ */
+ X2APIC_MSR(APIC_LVTTHMR),
+ X2APIC_MSR(APIC_LVTPC),
+ X2APIC_MSR(APIC_LVT0),
+ X2APIC_MSR(APIC_LVT1),
+ X2APIC_MSR(APIC_LVTERR),
+ X2APIC_MSR(APIC_TMICT),
+ X2APIC_MSR(APIC_TMCCT),
+ X2APIC_MSR(APIC_TDCR),
+ };
+ int i;
+
+ if (intercept == svm->x2avic_msrs_intercepted)
+ return;
+
+ if (!x2avic_enabled)
+ return;
+
+ for (i = 0; i < ARRAY_SIZE(x2avic_passthrough_msrs); i++)
+ svm_set_intercept_for_msr(&svm->vcpu, x2avic_passthrough_msrs[i],
+ MSR_TYPE_RW, intercept);
+
+ svm->x2avic_msrs_intercepted = intercept;
+}
+
static void avic_activate_vmcb(struct vcpu_svm *svm)
{
struct vmcb *vmcb = svm->vmcb01.ptr;
@@ -99,7 +150,7 @@ static void avic_activate_vmcb(struct vcpu_svm *svm)
vmcb->control.int_ctl |= X2APIC_MODE_MASK;
vmcb->control.avic_physical_id |= X2AVIC_MAX_PHYSICAL_ID;
/* Disabling MSR intercept for x2APIC registers */
- svm_set_x2apic_msr_interception(svm, false);
+ avic_set_x2apic_msr_interception(svm, false);
} else {
/*
* Flush the TLB, the guest may have inserted a non-APIC
@@ -110,7 +161,7 @@ static void avic_activate_vmcb(struct vcpu_svm *svm)
/* For xAVIC and hybrid-xAVIC modes */
vmcb->control.avic_physical_id |= AVIC_MAX_PHYSICAL_ID;
/* Enabling MSR intercept for x2APIC registers */
- svm_set_x2apic_msr_interception(svm, true);
+ avic_set_x2apic_msr_interception(svm, true);
}
}
@@ -130,7 +181,7 @@ static void avic_deactivate_vmcb(struct vcpu_svm *svm)
return;
/* Enabling MSR intercept for x2APIC registers */
- svm_set_x2apic_msr_interception(svm, true);
+ avic_set_x2apic_msr_interception(svm, true);
}
/* Note:
diff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c
index 8117d79036bb..a70d3c0d65da 100644
--- a/arch/x86/kvm/svm/svm.c
+++ b/arch/x86/kvm/svm/svm.c
@@ -736,55 +736,6 @@ static void svm_recalc_lbr_msr_intercepts(struct kvm_vcpu *vcpu)
svm_set_intercept_for_msr(vcpu, MSR_IA32_DEBUGCTLMSR, MSR_TYPE_RW, intercept);
}
-void svm_set_x2apic_msr_interception(struct vcpu_svm *svm, bool intercept)
-{
- static const u32 x2avic_passthrough_msrs[] = {
- X2APIC_MSR(APIC_ID),
- X2APIC_MSR(APIC_LVR),
- X2APIC_MSR(APIC_TASKPRI),
- X2APIC_MSR(APIC_ARBPRI),
- X2APIC_MSR(APIC_PROCPRI),
- X2APIC_MSR(APIC_EOI),
- X2APIC_MSR(APIC_RRR),
- X2APIC_MSR(APIC_LDR),
- X2APIC_MSR(APIC_DFR),
- X2APIC_MSR(APIC_SPIV),
- X2APIC_MSR(APIC_ISR),
- X2APIC_MSR(APIC_TMR),
- X2APIC_MSR(APIC_IRR),
- X2APIC_MSR(APIC_ESR),
- X2APIC_MSR(APIC_ICR),
- X2APIC_MSR(APIC_ICR2),
-
- /*
- * Note! Always intercept LVTT, as TSC-deadline timer mode
- * isn't virtualized by hardware, and the CPU will generate a
- * #GP instead of a #VMEXIT.
- */
- X2APIC_MSR(APIC_LVTTHMR),
- X2APIC_MSR(APIC_LVTPC),
- X2APIC_MSR(APIC_LVT0),
- X2APIC_MSR(APIC_LVT1),
- X2APIC_MSR(APIC_LVTERR),
- X2APIC_MSR(APIC_TMICT),
- X2APIC_MSR(APIC_TMCCT),
- X2APIC_MSR(APIC_TDCR),
- };
- int i;
-
- if (intercept == svm->x2avic_msrs_intercepted)
- return;
-
- if (!x2avic_enabled)
- return;
-
- for (i = 0; i < ARRAY_SIZE(x2avic_passthrough_msrs); i++)
- svm_set_intercept_for_msr(&svm->vcpu, x2avic_passthrough_msrs[i],
- MSR_TYPE_RW, intercept);
-
- svm->x2avic_msrs_intercepted = intercept;
-}
-
void svm_vcpu_free_msrpm(void *msrpm)
{
__free_pages(virt_to_page(msrpm), get_order(MSRPM_SIZE));
diff --git a/arch/x86/kvm/svm/svm.h b/arch/x86/kvm/svm/svm.h
index 1652a868c578..37a7f5059a11 100644
--- a/arch/x86/kvm/svm/svm.h
+++ b/arch/x86/kvm/svm/svm.h
@@ -701,7 +701,6 @@ void svm_set_gif(struct vcpu_svm *svm, bool value);
int svm_invoke_exit_handler(struct kvm_vcpu *vcpu, u64 exit_code);
void set_msr_interception(struct kvm_vcpu *vcpu, u32 *msrpm, u32 msr,
int read, int write);
-void svm_set_x2apic_msr_interception(struct vcpu_svm *svm, bool disable);
void svm_complete_interrupt_delivery(struct kvm_vcpu *vcpu, int delivery_mode,
int trig_mode, int vec);
--
2.51.0.470.ga7dc726c21-goog
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH v4 3/7] KVM: SVM: Update "APICv in x2APIC without x2AVIC" in avic.c, not svm.c
2025-09-19 21:59 [PATCH v4 0/7] KVM: SVM: Enable AVIC for Zen4+ (if x2AVIC) Sean Christopherson
2025-09-19 21:59 ` [PATCH v4 1/7] KVM: SVM: Make svm_x86_ops globally visible, clean up on-HyperV usage Sean Christopherson
2025-09-19 21:59 ` [PATCH v4 2/7] KVM: SVM: Move x2AVIC MSR interception helper to avic.c Sean Christopherson
@ 2025-09-19 21:59 ` Sean Christopherson
2025-09-19 21:59 ` [PATCH v4 4/7] KVM: SVM: Always print "AVIC enabled" separately, even when force enabled Sean Christopherson
` (4 subsequent siblings)
7 siblings, 0 replies; 9+ messages in thread
From: Sean Christopherson @ 2025-09-19 21:59 UTC (permalink / raw)
To: Sean Christopherson, Paolo Bonzini, Vitaly Kuznetsov
Cc: kvm, linux-kernel, Naveen N Rao
Set the "allow_apicv_in_x2apic_without_x2apic_virtualization" flag as part
of avic_hardware_setup() instead of handling in svm_hardware_setup(), and
make x2avic_enabled local to avic.c (setting the flag was the only use in
svm.c).
Tag avic_hardware_setup() with __init as necessary (it should have been
tagged __init long ago).
No functional change intended (aside from the side effects of tagging
avic_hardware_setup() with __init).
Acked-by: Naveen N Rao (AMD) <naveen@kernel.org>
Tested-by: Naveen N Rao (AMD) <naveen@kernel.org>
Signed-off-by: Sean Christopherson <seanjc@google.com>
---
arch/x86/kvm/svm/avic.c | 6 ++++--
arch/x86/kvm/svm/svm.c | 2 --
arch/x86/kvm/svm/svm.h | 3 +--
3 files changed, 5 insertions(+), 6 deletions(-)
diff --git a/arch/x86/kvm/svm/avic.c b/arch/x86/kvm/svm/avic.c
index 478a18208a76..b4577401ce5f 100644
--- a/arch/x86/kvm/svm/avic.c
+++ b/arch/x86/kvm/svm/avic.c
@@ -77,7 +77,7 @@ static DEFINE_HASHTABLE(svm_vm_data_hash, SVM_VM_DATA_HASH_BITS);
static u32 next_vm_id = 0;
static bool next_vm_id_wrapped = 0;
static DEFINE_SPINLOCK(svm_vm_data_hash_lock);
-bool x2avic_enabled;
+static bool x2avic_enabled;
static void avic_set_x2apic_msr_interception(struct vcpu_svm *svm,
@@ -1147,7 +1147,7 @@ void avic_vcpu_unblocking(struct kvm_vcpu *vcpu)
* - Hypervisor can support both xAVIC and x2AVIC in the same guest.
* - The mode can be switched at run-time.
*/
-bool avic_hardware_setup(void)
+bool __init avic_hardware_setup(void)
{
if (!npt_enabled)
return false;
@@ -1182,6 +1182,8 @@ bool avic_hardware_setup(void)
x2avic_enabled = boot_cpu_has(X86_FEATURE_X2AVIC);
if (x2avic_enabled)
pr_info("x2AVIC enabled\n");
+ else
+ svm_x86_ops.allow_apicv_in_x2apic_without_x2apic_virtualization = true;
/*
* Disable IPI virtualization for AMD Family 17h CPUs (Zen1 and Zen2)
diff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c
index a70d3c0d65da..45ede8fcf5d2 100644
--- a/arch/x86/kvm/svm/svm.c
+++ b/arch/x86/kvm/svm/svm.c
@@ -5361,8 +5361,6 @@ static __init int svm_hardware_setup(void)
svm_x86_ops.vcpu_blocking = NULL;
svm_x86_ops.vcpu_unblocking = NULL;
svm_x86_ops.vcpu_get_apicv_inhibit_reasons = NULL;
- } else if (!x2avic_enabled) {
- svm_x86_ops.allow_apicv_in_x2apic_without_x2apic_virtualization = true;
}
if (vls) {
diff --git a/arch/x86/kvm/svm/svm.h b/arch/x86/kvm/svm/svm.h
index 37a7f5059a11..fbab3509a1ea 100644
--- a/arch/x86/kvm/svm/svm.h
+++ b/arch/x86/kvm/svm/svm.h
@@ -48,7 +48,6 @@ extern bool npt_enabled;
extern int nrips;
extern int vgif;
extern bool intercept_smi;
-extern bool x2avic_enabled;
extern bool vnmi;
extern int lbrv;
@@ -802,7 +801,7 @@ extern struct kvm_x86_nested_ops svm_nested_ops;
BIT(APICV_INHIBIT_REASON_PHYSICAL_ID_TOO_BIG) \
)
-bool avic_hardware_setup(void);
+bool __init avic_hardware_setup(void);
int avic_ga_log_notifier(u32 ga_tag);
void avic_vm_destroy(struct kvm *kvm);
int avic_vm_init(struct kvm *kvm);
--
2.51.0.470.ga7dc726c21-goog
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH v4 4/7] KVM: SVM: Always print "AVIC enabled" separately, even when force enabled
2025-09-19 21:59 [PATCH v4 0/7] KVM: SVM: Enable AVIC for Zen4+ (if x2AVIC) Sean Christopherson
` (2 preceding siblings ...)
2025-09-19 21:59 ` [PATCH v4 3/7] KVM: SVM: Update "APICv in x2APIC without x2AVIC" in avic.c, not svm.c Sean Christopherson
@ 2025-09-19 21:59 ` Sean Christopherson
2025-09-19 21:59 ` [PATCH v4 5/7] KVM: SVM: Don't advise the user to do force_avic=y (when x2AVIC is detected) Sean Christopherson
` (3 subsequent siblings)
7 siblings, 0 replies; 9+ messages in thread
From: Sean Christopherson @ 2025-09-19 21:59 UTC (permalink / raw)
To: Sean Christopherson, Paolo Bonzini, Vitaly Kuznetsov
Cc: kvm, linux-kernel, Naveen N Rao
Print the customary "AVIC enabled" informational message even when AVIC is
force enabled on a system that doesn't advertise supported for AVIC in
CPUID, as not printing the standard message can confuse users and tools.
Opportunistically clean up the scary message when AVIC is force enabled,
but keep it as separate message so that it is printed at level "warn",
versus the standard message only being printed for level "info".
Suggested-by: Naveen N Rao (AMD) <naveen@kernel.org>
Reviewed-by: Naveen N Rao (AMD) <naveen@kernel.org>
Tested-by: Naveen N Rao (AMD) <naveen@kernel.org>
Signed-off-by: Sean Christopherson <seanjc@google.com>
---
arch/x86/kvm/svm/avic.c | 19 +++++++++----------
1 file changed, 9 insertions(+), 10 deletions(-)
diff --git a/arch/x86/kvm/svm/avic.c b/arch/x86/kvm/svm/avic.c
index b4577401ce5f..b8b73c4103c6 100644
--- a/arch/x86/kvm/svm/avic.c
+++ b/arch/x86/kvm/svm/avic.c
@@ -1167,16 +1167,15 @@ bool __init avic_hardware_setup(void)
return false;
}
- if (boot_cpu_has(X86_FEATURE_AVIC)) {
- pr_info("AVIC enabled\n");
- } else if (force_avic) {
- /*
- * Some older systems does not advertise AVIC support.
- * See Revision Guide for specific AMD processor for more detail.
- */
- pr_warn("AVIC is not supported in CPUID but force enabled");
- pr_warn("Your system might crash and burn");
- }
+ /*
+ * Print a scary message if AVIC is force enabled to make it abundantly
+ * clear that ignoring CPUID could have repercussions. See Revision
+ * Guide for specific AMD processor for more details.
+ */
+ if (!boot_cpu_has(X86_FEATURE_AVIC))
+ pr_warn("AVIC unsupported in CPUID but force enabled, your system might crash and burn\n");
+
+ pr_info("AVIC enabled\n");
/* AVIC is a prerequisite for x2AVIC. */
x2avic_enabled = boot_cpu_has(X86_FEATURE_X2AVIC);
--
2.51.0.470.ga7dc726c21-goog
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH v4 5/7] KVM: SVM: Don't advise the user to do force_avic=y (when x2AVIC is detected)
2025-09-19 21:59 [PATCH v4 0/7] KVM: SVM: Enable AVIC for Zen4+ (if x2AVIC) Sean Christopherson
` (3 preceding siblings ...)
2025-09-19 21:59 ` [PATCH v4 4/7] KVM: SVM: Always print "AVIC enabled" separately, even when force enabled Sean Christopherson
@ 2025-09-19 21:59 ` Sean Christopherson
2025-09-19 21:59 ` [PATCH v4 6/7] KVM: SVM: Move global "avic" variable to avic.c Sean Christopherson
` (2 subsequent siblings)
7 siblings, 0 replies; 9+ messages in thread
From: Sean Christopherson @ 2025-09-19 21:59 UTC (permalink / raw)
To: Sean Christopherson, Paolo Bonzini, Vitaly Kuznetsov
Cc: kvm, linux-kernel, Naveen N Rao
Don't advise the end user to try to force enable AVIC when x2AVIC is
reported as supported in CPUID, as forcefully enabling AVIC isn't something
that should be done lightly. E.g. some Zen4 client systems hide AVIC but
leave x2AVIC behind, and while such a configuration is indeed due to buggy
firmware in the sense the reporting x2AVIC without AVIC is nonsensical,
KVM has no idea _why_ firmware disabled AVIC in the first place.
Suggesting that the user try to run with force_avic=y is sketchy even if
the user explicitly tries to enable AVIC, and will be downright
irresponsible once KVM starts enabling AVIC by default. Alternatively,
KVM could print the message only when the user explicitly asks for AVIC,
but running with force_avic=y isn't something that should be encouraged
for random users. force_avic is a useful knob for developers and perhaps
even advanced users, but isn't something that KVM should advertise broadly.
Opportunistically append a newline to the pr_warn() so that it prints out
immediately, and tweak the message to say that AVIC is unsupported instead
of disabled (disabled suggests that the kernel/KVM is somehow responsible).
Suggested-by: Naveen N Rao (AMD) <naveen@kernel.org>
Reviewed-by: Naveen N Rao (AMD) <naveen@kernel.org>
Tested-by: Naveen N Rao (AMD) <naveen@kernel.org>
Signed-off-by: Sean Christopherson <seanjc@google.com>
---
arch/x86/kvm/svm/avic.c | 6 ++----
1 file changed, 2 insertions(+), 4 deletions(-)
diff --git a/arch/x86/kvm/svm/avic.c b/arch/x86/kvm/svm/avic.c
index b8b73c4103c6..35dde7d89f56 100644
--- a/arch/x86/kvm/svm/avic.c
+++ b/arch/x86/kvm/svm/avic.c
@@ -1154,10 +1154,8 @@ bool __init avic_hardware_setup(void)
/* AVIC is a prerequisite for x2AVIC. */
if (!boot_cpu_has(X86_FEATURE_AVIC) && !force_avic) {
- if (boot_cpu_has(X86_FEATURE_X2AVIC)) {
- pr_warn(FW_BUG "Cannot support x2AVIC due to AVIC is disabled");
- pr_warn(FW_BUG "Try enable AVIC using force_avic option");
- }
+ if (boot_cpu_has(X86_FEATURE_X2AVIC))
+ pr_warn(FW_BUG "Cannot enable x2AVIC, AVIC is unsupported\n");
return false;
}
--
2.51.0.470.ga7dc726c21-goog
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH v4 6/7] KVM: SVM: Move global "avic" variable to avic.c
2025-09-19 21:59 [PATCH v4 0/7] KVM: SVM: Enable AVIC for Zen4+ (if x2AVIC) Sean Christopherson
` (4 preceding siblings ...)
2025-09-19 21:59 ` [PATCH v4 5/7] KVM: SVM: Don't advise the user to do force_avic=y (when x2AVIC is detected) Sean Christopherson
@ 2025-09-19 21:59 ` Sean Christopherson
2025-09-19 21:59 ` [PATCH v4 7/7] KVM: SVM: Enable AVIC by default for Zen4+ if x2AVIC is support Sean Christopherson
2025-09-24 18:07 ` [PATCH v4 0/7] KVM: SVM: Enable AVIC for Zen4+ (if x2AVIC) Sean Christopherson
7 siblings, 0 replies; 9+ messages in thread
From: Sean Christopherson @ 2025-09-19 21:59 UTC (permalink / raw)
To: Sean Christopherson, Paolo Bonzini, Vitaly Kuznetsov
Cc: kvm, linux-kernel, Naveen N Rao
Move "avic" to avic.c so that it's colocated with the other AVIC specific
globals and module params, and so that avic_hardware_setup() is a bit more
self-contained, e.g. similar to sev_hardware_setup().
Deliberately set enable_apicv in svm.c as it's already globally visible
(defined by kvm.ko, not by kvm-amd.ko), and to clearly capture the
dependency on enable_apicv being initialized (svm_hardware_setup() clears
several AVIC-specific hooks when enable_apicv is disabled).
Alternatively, clearing of the hooks (and enable_ipiv) could be moved to
avic_hardware_setup(), but that's not obviously better, e.g. it's helpful
to isolate the setting of enable_apicv when reading code from the generic
x86 side of the world.
No functional change intended.
Acked-by: Naveen N Rao (AMD) <naveen@kernel.org>
Tested-by: Naveen N Rao (AMD) <naveen@kernel.org>
Signed-off-by: Sean Christopherson <seanjc@google.com>
---
arch/x86/kvm/svm/avic.c | 33 +++++++++++++++++++++++++--------
arch/x86/kvm/svm/svm.c | 11 +----------
2 files changed, 26 insertions(+), 18 deletions(-)
diff --git a/arch/x86/kvm/svm/avic.c b/arch/x86/kvm/svm/avic.c
index 35dde7d89f56..ec214062d136 100644
--- a/arch/x86/kvm/svm/avic.c
+++ b/arch/x86/kvm/svm/avic.c
@@ -64,6 +64,14 @@
static_assert(__AVIC_GATAG(AVIC_VM_ID_MASK, AVIC_VCPU_IDX_MASK) == -1u);
+/*
+ * enable / disable AVIC. Because the defaults differ for APICv
+ * support between VMX and SVM we cannot use module_param_named.
+ */
+static bool avic;
+module_param(avic, bool, 0444);
+module_param(enable_ipiv, bool, 0444);
+
static bool force_avic;
module_param_unsafe(force_avic, bool, 0444);
@@ -1141,15 +1149,9 @@ void avic_vcpu_unblocking(struct kvm_vcpu *vcpu)
avic_vcpu_load(vcpu, vcpu->cpu);
}
-/*
- * Note:
- * - The module param avic enable both xAPIC and x2APIC mode.
- * - Hypervisor can support both xAVIC and x2AVIC in the same guest.
- * - The mode can be switched at run-time.
- */
-bool __init avic_hardware_setup(void)
+static bool __init avic_want_avic_enabled(void)
{
- if (!npt_enabled)
+ if (!avic || !npt_enabled)
return false;
/* AVIC is a prerequisite for x2AVIC. */
@@ -1173,6 +1175,21 @@ bool __init avic_hardware_setup(void)
if (!boot_cpu_has(X86_FEATURE_AVIC))
pr_warn("AVIC unsupported in CPUID but force enabled, your system might crash and burn\n");
+ return true;
+}
+
+/*
+ * Note:
+ * - The module param avic enable both xAPIC and x2APIC mode.
+ * - Hypervisor can support both xAVIC and x2AVIC in the same guest.
+ * - The mode can be switched at run-time.
+ */
+bool __init avic_hardware_setup(void)
+{
+ avic = avic_want_avic_enabled();
+ if (!avic)
+ return false;
+
pr_info("AVIC enabled\n");
/* AVIC is a prerequisite for x2AVIC. */
diff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c
index 45ede8fcf5d2..c7799fc72f29 100644
--- a/arch/x86/kvm/svm/svm.c
+++ b/arch/x86/kvm/svm/svm.c
@@ -158,14 +158,6 @@ module_param(lbrv, int, 0444);
static int tsc_scaling = true;
module_param(tsc_scaling, int, 0444);
-/*
- * enable / disable AVIC. Because the defaults differ for APICv
- * support between VMX and SVM we cannot use module_param_named.
- */
-static bool avic;
-module_param(avic, bool, 0444);
-module_param(enable_ipiv, bool, 0444);
-
module_param(enable_device_posted_irqs, bool, 0444);
bool __read_mostly dump_invalid_vmcb;
@@ -5354,8 +5346,7 @@ static __init int svm_hardware_setup(void)
goto err;
}
- enable_apicv = avic = avic && avic_hardware_setup();
-
+ enable_apicv = avic_hardware_setup();
if (!enable_apicv) {
enable_ipiv = false;
svm_x86_ops.vcpu_blocking = NULL;
--
2.51.0.470.ga7dc726c21-goog
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH v4 7/7] KVM: SVM: Enable AVIC by default for Zen4+ if x2AVIC is support
2025-09-19 21:59 [PATCH v4 0/7] KVM: SVM: Enable AVIC for Zen4+ (if x2AVIC) Sean Christopherson
` (5 preceding siblings ...)
2025-09-19 21:59 ` [PATCH v4 6/7] KVM: SVM: Move global "avic" variable to avic.c Sean Christopherson
@ 2025-09-19 21:59 ` Sean Christopherson
2025-09-24 18:07 ` [PATCH v4 0/7] KVM: SVM: Enable AVIC for Zen4+ (if x2AVIC) Sean Christopherson
7 siblings, 0 replies; 9+ messages in thread
From: Sean Christopherson @ 2025-09-19 21:59 UTC (permalink / raw)
To: Sean Christopherson, Paolo Bonzini, Vitaly Kuznetsov
Cc: kvm, linux-kernel, Naveen N Rao
From: Naveen N Rao (AMD) <naveen@kernel.org>
AVIC and x2AVIC are fully functional since Zen 4, with no known hardware
errata. Enable AVIC and x2AVIC by default on Zen4+ so long as x2AVIC is
supported (to avoid enabling partial support for APIC virtualization by
default).
Internally, convert "avic" to an integer so that KVM can identify if the
user has asked to explicitly enable or disable AVIC, i.e. so that KVM
doesn't override an explicit 'y' from the user. Arbitrarily use -1 to
denote auto-mode, and accept the string "auto" for the module param in
addition to standard boolean values, i.e. continue to allow the user to
configure the "avic" module parameter to explicitly enable/disable AVIC.
To again maintain backward compatibility with a standard boolean param,
set KERNEL_PARAM_OPS_FL_NOARG, which tells the params infrastructure to
allow empty values for %true, i.e. to interpret a bare "avic" as "avic=y".
Take care to check for a NULL @val when looking for "auto"!
Lastly, always print "avic" as a boolean, since auto-mode is resolved
during module initialization, i.e. the user should never see "auto" in
sysfs.
Signed-off-by: Naveen N Rao (AMD) <naveen@kernel.org>
Tested-by: Naveen N Rao (AMD) <naveen@kernel.org>
Co-developed-by: Sean Christopherson <seanjc@google.com>
Signed-off-by: Sean Christopherson <seanjc@google.com>
---
arch/x86/kvm/svm/avic.c | 40 ++++++++++++++++++++++++++++++++++++----
1 file changed, 36 insertions(+), 4 deletions(-)
diff --git a/arch/x86/kvm/svm/avic.c b/arch/x86/kvm/svm/avic.c
index ec214062d136..f286b5706d7c 100644
--- a/arch/x86/kvm/svm/avic.c
+++ b/arch/x86/kvm/svm/avic.c
@@ -64,12 +64,32 @@
static_assert(__AVIC_GATAG(AVIC_VM_ID_MASK, AVIC_VCPU_IDX_MASK) == -1u);
+#define AVIC_AUTO_MODE -1
+
+static int avic_param_set(const char *val, const struct kernel_param *kp)
+{
+ if (val && sysfs_streq(val, "auto")) {
+ *(int *)kp->arg = AVIC_AUTO_MODE;
+ return 0;
+ }
+
+ return param_set_bint(val, kp);
+}
+
+static const struct kernel_param_ops avic_ops = {
+ .flags = KERNEL_PARAM_OPS_FL_NOARG,
+ .set = avic_param_set,
+ .get = param_get_bool,
+};
+
/*
- * enable / disable AVIC. Because the defaults differ for APICv
- * support between VMX and SVM we cannot use module_param_named.
+ * Enable / disable AVIC. In "auto" mode (default behavior), AVIC is enabled
+ * for Zen4+ CPUs with x2AVIC (and all other criteria for enablement are met).
*/
-static bool avic;
-module_param(avic, bool, 0444);
+static int avic = AVIC_AUTO_MODE;
+module_param_cb(avic, &avic_ops, &avic, 0444);
+__MODULE_PARM_TYPE(avic, "bool");
+
module_param(enable_ipiv, bool, 0444);
static bool force_avic;
@@ -1151,6 +1171,18 @@ void avic_vcpu_unblocking(struct kvm_vcpu *vcpu)
static bool __init avic_want_avic_enabled(void)
{
+ /*
+ * In "auto" mode, enable AVIC by default for Zen4+ if x2AVIC is
+ * supported (to avoid enabling partial support by default, and because
+ * x2AVIC should be supported by all Zen4+ CPUs). Explicitly check for
+ * family 0x19 and later (Zen5+), as the kernel's synthetic ZenX flags
+ * aren't inclusive of previous generations, i.e. the kernel will set
+ * at most one ZenX feature flag.
+ */
+ if (avic == AVIC_AUTO_MODE)
+ avic = boot_cpu_has(X86_FEATURE_X2AVIC) &&
+ (boot_cpu_data.x86 > 0x19 || cpu_feature_enabled(X86_FEATURE_ZEN4));
+
if (!avic || !npt_enabled)
return false;
--
2.51.0.470.ga7dc726c21-goog
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH v4 0/7] KVM: SVM: Enable AVIC for Zen4+ (if x2AVIC)
2025-09-19 21:59 [PATCH v4 0/7] KVM: SVM: Enable AVIC for Zen4+ (if x2AVIC) Sean Christopherson
` (6 preceding siblings ...)
2025-09-19 21:59 ` [PATCH v4 7/7] KVM: SVM: Enable AVIC by default for Zen4+ if x2AVIC is support Sean Christopherson
@ 2025-09-24 18:07 ` Sean Christopherson
7 siblings, 0 replies; 9+ messages in thread
From: Sean Christopherson @ 2025-09-24 18:07 UTC (permalink / raw)
To: Sean Christopherson, Paolo Bonzini, Vitaly Kuznetsov
Cc: kvm, linux-kernel, Naveen N Rao
On Fri, 19 Sep 2025 14:59:27 -0700, Sean Christopherson wrote:
> Enable AVIC by default for Zen4+, so long as x2AVIC is supported (which should
> be the case if AVIC is supported).
>
> v4:
> - Collect tags. [Naveen]
> - Add missing "(AMD)" for Naveen's attribution. [Naveen]
> - Make svm_x86_ops globally visible, to match TDX, instead of passing in
> the struct as parameter to avic_hardware_setup(). [Naveen]
> - s/avic_want_avic_enabled/avic_want_enabled. [Naveen]
> - Print "AVIC enabled" in avic_harware_setup() so that it's close to the
> "x2AVIC enabled" message. [Naveen]
>
> [...]
Applied to kvm-x86 svm, thanks!
[1/7] KVM: SVM: Make svm_x86_ops globally visible, clean up on-HyperV usage
https://github.com/kvm-x86/linux/commit/44bfe1f0490d
[2/7] KVM: SVM: Move x2AVIC MSR interception helper to avic.c
https://github.com/kvm-x86/linux/commit/eb44ea6a7aac
[3/7] KVM: SVM: Update "APICv in x2APIC without x2AVIC" in avic.c, not svm.c
https://github.com/kvm-x86/linux/commit/a9095e4fc436
[4/7] KVM: SVM: Always print "AVIC enabled" separately, even when force enabled
https://github.com/kvm-x86/linux/commit/ce4253e21fa8
[5/7] KVM: SVM: Don't advise the user to do force_avic=y (when x2AVIC is detected)
https://github.com/kvm-x86/linux/commit/ad65dca2ca4c
[6/7] KVM: SVM: Move global "avic" variable to avic.c
https://github.com/kvm-x86/linux/commit/b14665353162
[7/7] KVM: SVM: Enable AVIC by default for Zen4+ if x2AVIC is support
https://github.com/kvm-x86/linux/commit/ca2967de5a5b
--
https://github.com/kvm-x86/linux/tree/next
^ permalink raw reply [flat|nested] 9+ messages in thread
end of thread, other threads:[~2025-09-24 18:45 UTC | newest]
Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2025-09-19 21:59 [PATCH v4 0/7] KVM: SVM: Enable AVIC for Zen4+ (if x2AVIC) Sean Christopherson
2025-09-19 21:59 ` [PATCH v4 1/7] KVM: SVM: Make svm_x86_ops globally visible, clean up on-HyperV usage Sean Christopherson
2025-09-19 21:59 ` [PATCH v4 2/7] KVM: SVM: Move x2AVIC MSR interception helper to avic.c Sean Christopherson
2025-09-19 21:59 ` [PATCH v4 3/7] KVM: SVM: Update "APICv in x2APIC without x2AVIC" in avic.c, not svm.c Sean Christopherson
2025-09-19 21:59 ` [PATCH v4 4/7] KVM: SVM: Always print "AVIC enabled" separately, even when force enabled Sean Christopherson
2025-09-19 21:59 ` [PATCH v4 5/7] KVM: SVM: Don't advise the user to do force_avic=y (when x2AVIC is detected) Sean Christopherson
2025-09-19 21:59 ` [PATCH v4 6/7] KVM: SVM: Move global "avic" variable to avic.c Sean Christopherson
2025-09-19 21:59 ` [PATCH v4 7/7] KVM: SVM: Enable AVIC by default for Zen4+ if x2AVIC is support Sean Christopherson
2025-09-24 18:07 ` [PATCH v4 0/7] KVM: SVM: Enable AVIC for Zen4+ (if x2AVIC) Sean Christopherson
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®