A platform can choose to disable AVIC by turning off the AVIC CPUID feature bit, while keeping x2AVIC CPUID feature bit enabled to indicate AVIC support for the x2APIC MSR interface. Since this is a valid configuration, stop printing a warning. Signed-off-by: Naveen N Rao (AMD) --- arch/x86/kvm/svm/avic.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/arch/x86/kvm/svm/avic.c b/arch/x86/kvm/svm/avic.c index a34c5c3b164e..346cd23a43a9 100644 --- a/arch/x86/kvm/svm/avic.c +++ b/arch/x86/kvm/svm/avic.c @@ -1101,14 +1101,8 @@ bool avic_hardware_setup(void) if (!npt_enabled) return false; - /* 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_AVIC) && !force_avic) return false; - } if (cc_platform_has(CC_ATTR_HOST_SEV_SNP) && !boot_cpu_has(X86_FEATURE_HV_INUSE_WR_ALLOWED)) { -- 2.50.1 On systems that do not advertise support for AVIC, it can be force-enabled through 'force_avic' module parameter. In that case, a warning is displayed but the customary "AVIC enabled" message isn't. Fix that by printing "AVIC enabled" unconditionally. The warning for 'force_avic' is also needlessly long. Simplify the same. Signed-off-by: Naveen N Rao (AMD) --- arch/x86/kvm/svm/avic.c | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/arch/x86/kvm/svm/avic.c b/arch/x86/kvm/svm/avic.c index 346cd23a43a9..3faed85fcacd 100644 --- a/arch/x86/kvm/svm/avic.c +++ b/arch/x86/kvm/svm/avic.c @@ -1110,16 +1110,8 @@ bool 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"); - } + pr_info("AVIC enabled%s\n", cpu_feature_enabled(X86_FEATURE_AVIC) ? "" : + " (forced, your system may crash and burn)"); /* AVIC is a prerequisite for x2AVIC. */ x2avic_enabled = boot_cpu_has(X86_FEATURE_X2AVIC); -- 2.50.1 Consolidate all AVIC-related setup in avic_hardware_setup() to match other SVM setup functions (sev_hardware_setup() et al). No functional change. Signed-off-by: Naveen N Rao (AMD) --- arch/x86/kvm/svm/svm.h | 3 ++- arch/x86/kvm/svm/avic.c | 17 +++++++++++------ arch/x86/kvm/svm/svm.c | 4 ++-- 3 files changed, 15 insertions(+), 9 deletions(-) diff --git a/arch/x86/kvm/svm/svm.h b/arch/x86/kvm/svm/svm.h index 3c7f208b7935..ec2e275829a6 100644 --- a/arch/x86/kvm/svm/svm.h +++ b/arch/x86/kvm/svm/svm.h @@ -48,6 +48,7 @@ extern bool npt_enabled; extern int nrips; extern int vgif; extern bool intercept_smi; +extern bool avic; extern bool x2avic_enabled; extern bool vnmi; extern int lbrv; @@ -801,7 +802,7 @@ extern struct kvm_x86_nested_ops svm_nested_ops; BIT(APICV_INHIBIT_REASON_PHYSICAL_ID_TOO_BIG) \ ) -bool avic_hardware_setup(void); +void 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); diff --git a/arch/x86/kvm/svm/avic.c b/arch/x86/kvm/svm/avic.c index 3faed85fcacd..620583b2ddd1 100644 --- a/arch/x86/kvm/svm/avic.c +++ b/arch/x86/kvm/svm/avic.c @@ -1096,20 +1096,23 @@ 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) +void avic_hardware_setup(void) { - if (!npt_enabled) - return false; + bool enable = false; + + if (!avic || !npt_enabled) + goto out; if (!boot_cpu_has(X86_FEATURE_AVIC) && !force_avic) - return false; + goto out; if (cc_platform_has(CC_ATTR_HOST_SEV_SNP) && !boot_cpu_has(X86_FEATURE_HV_INUSE_WR_ALLOWED)) { pr_warn("AVIC disabled: missing HvInUseWrAllowed on SNP-enabled system\n"); - return false; + goto out; } + enable = true; pr_info("AVIC enabled%s\n", cpu_feature_enabled(X86_FEATURE_AVIC) ? "" : " (forced, your system may crash and burn)"); @@ -1128,5 +1131,7 @@ bool avic_hardware_setup(void) amd_iommu_register_ga_log_notifier(&avic_ga_log_notifier); - return true; +out: + avic = enable; + enable_apicv = avic; } diff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c index cb4f81be0024..d5854e0bc799 100644 --- a/arch/x86/kvm/svm/svm.c +++ b/arch/x86/kvm/svm/svm.c @@ -162,7 +162,7 @@ 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; +bool avic; module_param(avic, bool, 0444); module_param(enable_ipiv, bool, 0444); @@ -5406,7 +5406,7 @@ static __init int svm_hardware_setup(void) goto err; } - enable_apicv = avic = avic && avic_hardware_setup(); + avic_hardware_setup(); if (!enable_apicv) { enable_ipiv = false; -- 2.50.1 Move 'force_avic' module parameter from avic.c to svm.c so that all SVM module parameters are consolidated in a single place. No functional change. Signed-off-by: Naveen N Rao (AMD) --- arch/x86/kvm/svm/svm.h | 2 +- arch/x86/kvm/svm/avic.c | 5 +---- arch/x86/kvm/svm/svm.c | 5 ++++- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/arch/x86/kvm/svm/svm.h b/arch/x86/kvm/svm/svm.h index ec2e275829a6..d332930b3dae 100644 --- a/arch/x86/kvm/svm/svm.h +++ b/arch/x86/kvm/svm/svm.h @@ -802,7 +802,7 @@ extern struct kvm_x86_nested_ops svm_nested_ops; BIT(APICV_INHIBIT_REASON_PHYSICAL_ID_TOO_BIG) \ ) -void avic_hardware_setup(void); +void avic_hardware_setup(bool force_avic); int avic_ga_log_notifier(u32 ga_tag); void avic_vm_destroy(struct kvm *kvm); int avic_vm_init(struct kvm *kvm); diff --git a/arch/x86/kvm/svm/avic.c b/arch/x86/kvm/svm/avic.c index 620583b2ddd1..9fe1fd709458 100644 --- a/arch/x86/kvm/svm/avic.c +++ b/arch/x86/kvm/svm/avic.c @@ -64,9 +64,6 @@ static_assert(__AVIC_GATAG(AVIC_VM_ID_MASK, AVIC_VCPU_IDX_MASK) == -1u); -static bool force_avic; -module_param_unsafe(force_avic, bool, 0444); - /* Note: * This hash table is used to map VM_ID to a struct kvm_svm, * when handling AMD IOMMU GALOG notification to schedule in @@ -1096,7 +1093,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. */ -void avic_hardware_setup(void) +void avic_hardware_setup(bool force_avic) { bool enable = false; diff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c index d5854e0bc799..b66fbfd47d4c 100644 --- a/arch/x86/kvm/svm/svm.c +++ b/arch/x86/kvm/svm/svm.c @@ -166,6 +166,9 @@ bool avic; module_param(avic, bool, 0444); module_param(enable_ipiv, bool, 0444); +static bool force_avic; +module_param_unsafe(force_avic, bool, 0444); + module_param(enable_device_posted_irqs, bool, 0444); bool __read_mostly dump_invalid_vmcb; @@ -5406,7 +5409,7 @@ static __init int svm_hardware_setup(void) goto err; } - avic_hardware_setup(); + avic_hardware_setup(force_avic); if (!enable_apicv) { enable_ipiv = false; -- 2.50.1 AVIC and x2AVIC are fully functional since Zen 4, with no known hardware errata. Enable it by default on those processors, but allow users to continue passing 'avic' module parameter to explicitly enable/disable AVIC. Convert 'avic' to an integer to be able to identify if the user has asked to explicitly enable or disable AVIC. By default, 'avic' is initialized to -1 and AVIC is enabled if Zen 4+ processor is detected (and other dependencies are satisfied). So as not to break existing usage of 'avic' which was a boolean, switch to using module_param_cb() and use existing callbacks which expose this field as a boolean (so users can still continue to pass 'avic=on' or 'avic=off') but sets an integer value. Finally, stop warning about missing HvInUseWrAllowed on SNP-enabled systems if trying to enable AVIC by default so as not to spam the kernel log. Users who specifically care about AVIC can explicitly pass 'avic=on' in which case the error is still printed. Signed-off-by: Naveen N Rao (AMD) --- arch/x86/kvm/svm/svm.h | 2 +- arch/x86/kvm/svm/avic.c | 8 +++++++- arch/x86/kvm/svm/svm.c | 17 +++++++++++------ 3 files changed, 19 insertions(+), 8 deletions(-) diff --git a/arch/x86/kvm/svm/svm.h b/arch/x86/kvm/svm/svm.h index d332930b3dae..0e87e2768a1f 100644 --- a/arch/x86/kvm/svm/svm.h +++ b/arch/x86/kvm/svm/svm.h @@ -48,7 +48,7 @@ extern bool npt_enabled; extern int nrips; extern int vgif; extern bool intercept_smi; -extern bool avic; +extern int avic; extern bool x2avic_enabled; extern bool vnmi; extern int lbrv; diff --git a/arch/x86/kvm/svm/avic.c b/arch/x86/kvm/svm/avic.c index 9fe1fd709458..6bd5079a01f1 100644 --- a/arch/x86/kvm/svm/avic.c +++ b/arch/x86/kvm/svm/avic.c @@ -1095,8 +1095,13 @@ void avic_vcpu_unblocking(struct kvm_vcpu *vcpu) */ void avic_hardware_setup(bool force_avic) { + bool default_avic = (avic == -1); bool enable = false; + /* Enable AVIC by default from Zen 4 */ + if (default_avic) + avic = boot_cpu_data.x86 > 0x19 || cpu_feature_enabled(X86_FEATURE_ZEN4); + if (!avic || !npt_enabled) goto out; @@ -1105,7 +1110,8 @@ void avic_hardware_setup(bool force_avic) if (cc_platform_has(CC_ATTR_HOST_SEV_SNP) && !boot_cpu_has(X86_FEATURE_HV_INUSE_WR_ALLOWED)) { - pr_warn("AVIC disabled: missing HvInUseWrAllowed on SNP-enabled system\n"); + if (!default_avic) + pr_warn("AVIC disabled: missing HvInUseWrAllowed on SNP-enabled system\n"); goto out; } diff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c index b66fbfd47d4c..3d4f1ef2ff76 100644 --- a/arch/x86/kvm/svm/svm.c +++ b/arch/x86/kvm/svm/svm.c @@ -158,12 +158,17 @@ 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. - */ -bool avic; -module_param(avic, bool, 0444); +static const struct kernel_param_ops avic_ops = { + .flags = KERNEL_PARAM_OPS_FL_NOARG, + .set = param_set_bint, + .get = param_get_bool, +}; + +/* enable/disable AVIC (-1 = auto) */ +int avic = -1; +module_param_cb(avic, &avic_ops, &avic, 0444); +__MODULE_PARM_TYPE(avic, "bool"); + module_param(enable_ipiv, bool, 0444); static bool force_avic; -- 2.50.1