]>
Commit | Line | Data |
---|---|---|
7e19d03b SL |
1 | From 0202c1d64303b5c4f85e0358008fc049d3df5bb0 Mon Sep 17 00:00:00 2001 |
2 | From: Sasha Levin <sashal@kernel.org> | |
3 | Date: Wed, 31 Jan 2024 15:56:08 -0800 | |
4 | Subject: KVM: SVM: Add support for allowing zero SEV ASIDs | |
5 | ||
6 | From: Ashish Kalra <ashish.kalra@amd.com> | |
7 | ||
8 | [ Upstream commit 0aa6b90ef9d75b4bd7b6d106d85f2a3437697f91 ] | |
9 | ||
10 | Some BIOSes allow the end user to set the minimum SEV ASID value | |
11 | (CPUID 0x8000001F_EDX) to be greater than the maximum number of | |
12 | encrypted guests, or maximum SEV ASID value (CPUID 0x8000001F_ECX) | |
13 | in order to dedicate all the SEV ASIDs to SEV-ES or SEV-SNP. | |
14 | ||
15 | The SEV support, as coded, does not handle the case where the minimum | |
16 | SEV ASID value can be greater than the maximum SEV ASID value. | |
17 | As a result, the following confusing message is issued: | |
18 | ||
19 | [ 30.715724] kvm_amd: SEV enabled (ASIDs 1007 - 1006) | |
20 | ||
21 | Fix the support to properly handle this case. | |
22 | ||
23 | Fixes: 916391a2d1dc ("KVM: SVM: Add support for SEV-ES capability in KVM") | |
24 | Suggested-by: Sean Christopherson <seanjc@google.com> | |
25 | Signed-off-by: Ashish Kalra <ashish.kalra@amd.com> | |
26 | Cc: stable@vger.kernel.org | |
27 | Acked-by: Tom Lendacky <thomas.lendacky@amd.com> | |
28 | Link: https://lore.kernel.org/r/20240104190520.62510-1-Ashish.Kalra@amd.com | |
29 | Link: https://lore.kernel.org/r/20240131235609.4161407-4-seanjc@google.com | |
30 | Signed-off-by: Sean Christopherson <seanjc@google.com> | |
31 | Signed-off-by: Sasha Levin <sashal@kernel.org> | |
32 | --- | |
33 | arch/x86/kvm/svm/sev.c | 29 +++++++++++++++++++---------- | |
34 | 1 file changed, 19 insertions(+), 10 deletions(-) | |
35 | ||
36 | diff --git a/arch/x86/kvm/svm/sev.c b/arch/x86/kvm/svm/sev.c | |
37 | index ea68a08cc89c2..c5845f31c34dc 100644 | |
38 | --- a/arch/x86/kvm/svm/sev.c | |
39 | +++ b/arch/x86/kvm/svm/sev.c | |
40 | @@ -144,10 +144,21 @@ static void sev_misc_cg_uncharge(struct kvm_sev_info *sev) | |
41 | ||
42 | static int sev_asid_new(struct kvm_sev_info *sev) | |
43 | { | |
44 | - unsigned int asid, min_asid, max_asid; | |
45 | + /* | |
46 | + * SEV-enabled guests must use asid from min_sev_asid to max_sev_asid. | |
47 | + * SEV-ES-enabled guest can use from 1 to min_sev_asid - 1. | |
48 | + * Note: min ASID can end up larger than the max if basic SEV support is | |
49 | + * effectively disabled by disallowing use of ASIDs for SEV guests. | |
50 | + */ | |
51 | + unsigned int min_asid = sev->es_active ? 1 : min_sev_asid; | |
52 | + unsigned int max_asid = sev->es_active ? min_sev_asid - 1 : max_sev_asid; | |
53 | + unsigned int asid; | |
54 | bool retry = true; | |
55 | int ret; | |
56 | ||
57 | + if (min_asid > max_asid) | |
58 | + return -ENOTTY; | |
59 | + | |
60 | WARN_ON(sev->misc_cg); | |
61 | sev->misc_cg = get_current_misc_cg(); | |
62 | ret = sev_misc_cg_try_charge(sev); | |
63 | @@ -159,12 +170,6 @@ static int sev_asid_new(struct kvm_sev_info *sev) | |
64 | ||
65 | mutex_lock(&sev_bitmap_lock); | |
66 | ||
67 | - /* | |
68 | - * SEV-enabled guests must use asid from min_sev_asid to max_sev_asid. | |
69 | - * SEV-ES-enabled guest can use from 1 to min_sev_asid - 1. | |
70 | - */ | |
71 | - min_asid = sev->es_active ? 1 : min_sev_asid; | |
72 | - max_asid = sev->es_active ? min_sev_asid - 1 : max_sev_asid; | |
73 | again: | |
74 | asid = find_next_zero_bit(sev_asid_bitmap, max_asid + 1, min_asid); | |
75 | if (asid > max_asid) { | |
76 | @@ -2236,8 +2241,10 @@ void __init sev_hardware_setup(void) | |
77 | goto out; | |
78 | } | |
79 | ||
80 | - sev_asid_count = max_sev_asid - min_sev_asid + 1; | |
81 | - WARN_ON_ONCE(misc_cg_set_capacity(MISC_CG_RES_SEV, sev_asid_count)); | |
82 | + if (min_sev_asid <= max_sev_asid) { | |
83 | + sev_asid_count = max_sev_asid - min_sev_asid + 1; | |
84 | + WARN_ON_ONCE(misc_cg_set_capacity(MISC_CG_RES_SEV, sev_asid_count)); | |
85 | + } | |
86 | sev_supported = true; | |
87 | ||
88 | /* SEV-ES support requested? */ | |
89 | @@ -2268,7 +2275,9 @@ void __init sev_hardware_setup(void) | |
90 | out: | |
91 | if (boot_cpu_has(X86_FEATURE_SEV)) | |
92 | pr_info("SEV %s (ASIDs %u - %u)\n", | |
93 | - sev_supported ? "enabled" : "disabled", | |
94 | + sev_supported ? min_sev_asid <= max_sev_asid ? "enabled" : | |
95 | + "unusable" : | |
96 | + "disabled", | |
97 | min_sev_asid, max_sev_asid); | |
98 | if (boot_cpu_has(X86_FEATURE_SEV_ES)) | |
99 | pr_info("SEV-ES %s (ASIDs %u - %u)\n", | |
100 | -- | |
101 | 2.43.0 | |
102 |