From: Ashish Kalra <ashish.kalra@xxxxxxx> Some BIOSes allow the end user to set the minimum SEV ASID value (CPUID 0x8000001F_EDX) to be greater than the maximum number of encrypted guests, or maximum SEV ASID value (CPUID 0x8000001F_ECX) in order to dedicate all the SEV ASIDs to SEV-ES or SEV-SNP. The SEV support, as coded, does not handle the case where the minimum SEV ASID value can be greater than the maximum SEV ASID value. As a result, the following confusing message is issued: [ 30.715724] kvm_amd: SEV enabled (ASIDs 1007 - 1006) Fix the support to properly handle this case. Fixes: 916391a2d1dc ("KVM: SVM: Add support for SEV-ES capability in KVM") Signed-off-by: Ashish Kalra <ashish.kalra@xxxxxxx> Cc: stable@xxxxxxxxxxxxxxx --- arch/x86/kvm/svm/sev.c | 26 ++++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/arch/x86/kvm/svm/sev.c b/arch/x86/kvm/svm/sev.c index 4900c078045a..ad41008ca0d9 100644 --- a/arch/x86/kvm/svm/sev.c +++ b/arch/x86/kvm/svm/sev.c @@ -59,10 +59,14 @@ module_param_named(sev_es, sev_es_enabled, bool, 0444); /* enable/disable SEV-ES DebugSwap support */ static bool sev_es_debug_swap_enabled = true; module_param_named(debug_swap, sev_es_debug_swap_enabled, bool, 0444); + +/* When true, at least one type of SEV guest is enabled to run */ +static bool sev_guests_enabled; #else #define sev_enabled false #define sev_es_enabled false #define sev_es_debug_swap_enabled false +#define sev_guests_enabled false #endif /* CONFIG_KVM_AMD_SEV */ static u8 sev_enc_bit; @@ -1854,7 +1858,7 @@ int sev_mem_enc_ioctl(struct kvm *kvm, void __user *argp) struct kvm_sev_cmd sev_cmd; int r; - if (!sev_enabled) + if (!sev_guests_enabled) return -ENOTTY; if (!argp) @@ -2172,8 +2176,10 @@ void sev_vm_destroy(struct kvm *kvm) void __init sev_set_cpu_caps(void) { - if (!sev_enabled) + if (!sev_guests_enabled) { kvm_cpu_cap_clear(X86_FEATURE_SEV); + return; + } if (!sev_es_enabled) kvm_cpu_cap_clear(X86_FEATURE_SEV_ES); } @@ -2229,9 +2235,11 @@ void __init sev_hardware_setup(void) goto out; } - sev_asid_count = max_sev_asid - min_sev_asid + 1; - WARN_ON_ONCE(misc_cg_set_capacity(MISC_CG_RES_SEV, sev_asid_count)); - sev_supported = true; + if (min_sev_asid <= max_sev_asid) { + sev_asid_count = max_sev_asid - min_sev_asid + 1; + WARN_ON_ONCE(misc_cg_set_capacity(MISC_CG_RES_SEV, sev_asid_count)); + sev_supported = true; + } /* SEV-ES support requested? */ if (!sev_es_enabled) @@ -2262,7 +2270,8 @@ void __init sev_hardware_setup(void) if (boot_cpu_has(X86_FEATURE_SEV)) pr_info("SEV %s (ASIDs %u - %u)\n", sev_supported ? "enabled" : "disabled", - min_sev_asid, max_sev_asid); + sev_supported ? min_sev_asid : 0, + sev_supported ? max_sev_asid : 0); if (boot_cpu_has(X86_FEATURE_SEV_ES)) pr_info("SEV-ES %s (ASIDs %u - %u)\n", sev_es_supported ? "enabled" : "disabled", @@ -2270,6 +2279,7 @@ void __init sev_hardware_setup(void) sev_enabled = sev_supported; sev_es_enabled = sev_es_supported; + sev_guests_enabled = sev_enabled || sev_es_enabled; if (!sev_es_enabled || !cpu_feature_enabled(X86_FEATURE_DEBUG_SWAP) || !cpu_feature_enabled(X86_FEATURE_NO_NESTED_DATA_BP)) sev_es_debug_swap_enabled = false; @@ -2278,7 +2288,7 @@ void __init sev_hardware_setup(void) void sev_hardware_unsetup(void) { - if (!sev_enabled) + if (!sev_guests_enabled) return; /* No need to take sev_bitmap_lock, all VMs have been destroyed. */ @@ -2293,7 +2303,7 @@ void sev_hardware_unsetup(void) int sev_cpu_init(struct svm_cpu_data *sd) { - if (!sev_enabled) + if (!sev_guests_enabled) return 0; sd->sev_vmcbs = kcalloc(nr_asids, sizeof(void *), GFP_KERNEL); -- 2.34.1