Skip to content

Commit 10ef74c

Browse files
committed
Merge tag 'kvm-x86-ciphertext-6.18' of https://github.com/kvm-x86/linux into HEAD
KVM SEV-SNP CipherText Hiding support for 6.18 Add support for SEV-SNP's CipherText Hiding, an opt-in feature that prevents unauthorized CPU accesses from reading the ciphertext of SNP guest private memory, e.g. to attempt an offline attack. Instead of ciphertext, the CPU will always read back all FFs when CipherText Hiding is enabled. Add new module parameter to the KVM module to enable CipherText Hiding and control the number of ASIDs that can be used for VMs with CipherText Hiding, which is in effect the number of SNP VMs. When CipherText Hiding is enabled, the shared SEV-ES/SEV-SNP ASID space is split into separate ranges for SEV-ES and SEV-SNP guests, i.e. ASIDs that can be used for CipherText Hiding cannot be used to run SEV-ES guests.
2 parents a104e0a + 6c7c620 commit 10ef74c

File tree

6 files changed

+249
-27
lines changed

6 files changed

+249
-27
lines changed

Documentation/admin-guide/kernel-parameters.txt

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2957,6 +2957,27 @@
29572957
(enabled). Disable by KVM if hardware lacks support
29582958
for NPT.
29592959

2960+
kvm-amd.ciphertext_hiding_asids=
2961+
[KVM,AMD] Ciphertext hiding prevents disallowed accesses
2962+
to SNP private memory from reading ciphertext. Instead,
2963+
reads will see constant default values (0xff).
2964+
2965+
If ciphertext hiding is enabled, the joint SEV-ES and
2966+
SEV-SNP ASID space is partitioned into separate SEV-ES
2967+
and SEV-SNP ASID ranges, with the SEV-SNP range being
2968+
[1..max_snp_asid] and the SEV-ES range being
2969+
(max_snp_asid..min_sev_asid), where min_sev_asid is
2970+
enumerated by CPUID.0x.8000_001F[EDX].
2971+
2972+
A non-zero value enables SEV-SNP ciphertext hiding and
2973+
adjusts the ASID ranges for SEV-ES and SEV-SNP guests.
2974+
KVM caps the number of SEV-SNP ASIDs at the maximum
2975+
possible value, e.g. specifying -1u will assign all
2976+
joint SEV-ES and SEV-SNP ASIDs to SEV-SNP. Note,
2977+
assigning all joint ASIDs to SEV-SNP, i.e. configuring
2978+
max_snp_asid == min_sev_asid-1, will effectively make
2979+
SEV-ES unusable.
2980+
29602981
kvm-arm.mode=
29612982
[KVM,ARM,EARLY] Select one of KVM/arm64's modes of
29622983
operation.

arch/x86/kvm/svm/sev.c

Lines changed: 58 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,9 @@ static bool sev_es_debug_swap_enabled = true;
5858
module_param_named(debug_swap, sev_es_debug_swap_enabled, bool, 0444);
5959
static u64 sev_supported_vmsa_features;
6060

61+
static unsigned int nr_ciphertext_hiding_asids;
62+
module_param_named(ciphertext_hiding_asids, nr_ciphertext_hiding_asids, uint, 0444);
63+
6164
#define AP_RESET_HOLD_NONE 0
6265
#define AP_RESET_HOLD_NAE_EVENT 1
6366
#define AP_RESET_HOLD_MSR_PROTO 2
@@ -84,6 +87,10 @@ static DECLARE_RWSEM(sev_deactivate_lock);
8487
static DEFINE_MUTEX(sev_bitmap_lock);
8588
unsigned int max_sev_asid;
8689
static unsigned int min_sev_asid;
90+
static unsigned int max_sev_es_asid;
91+
static unsigned int min_sev_es_asid;
92+
static unsigned int max_snp_asid;
93+
static unsigned int min_snp_asid;
8794
static unsigned long sev_me_mask;
8895
static unsigned int nr_asids;
8996
static unsigned long *sev_asid_bitmap;
@@ -180,20 +187,34 @@ static void sev_misc_cg_uncharge(struct kvm_sev_info *sev)
180187
misc_cg_uncharge(type, sev->misc_cg, 1);
181188
}
182189

183-
static int sev_asid_new(struct kvm_sev_info *sev)
190+
static int sev_asid_new(struct kvm_sev_info *sev, unsigned long vm_type)
184191
{
185192
/*
186193
* SEV-enabled guests must use asid from min_sev_asid to max_sev_asid.
187194
* SEV-ES-enabled guest can use from 1 to min_sev_asid - 1.
188-
* Note: min ASID can end up larger than the max if basic SEV support is
189-
* effectively disabled by disallowing use of ASIDs for SEV guests.
190195
*/
191-
unsigned int min_asid = sev->es_active ? 1 : min_sev_asid;
192-
unsigned int max_asid = sev->es_active ? min_sev_asid - 1 : max_sev_asid;
193-
unsigned int asid;
196+
unsigned int min_asid, max_asid, asid;
194197
bool retry = true;
195198
int ret;
196199

200+
if (vm_type == KVM_X86_SNP_VM) {
201+
min_asid = min_snp_asid;
202+
max_asid = max_snp_asid;
203+
} else if (sev->es_active) {
204+
min_asid = min_sev_es_asid;
205+
max_asid = max_sev_es_asid;
206+
} else {
207+
min_asid = min_sev_asid;
208+
max_asid = max_sev_asid;
209+
}
210+
211+
/*
212+
* The min ASID can end up larger than the max if basic SEV support is
213+
* effectively disabled by disallowing use of ASIDs for SEV guests.
214+
* Similarly for SEV-ES guests the min ASID can end up larger than the
215+
* max when ciphertext hiding is enabled, effectively disabling SEV-ES
216+
* support.
217+
*/
197218
if (min_asid > max_asid)
198219
return -ENOTTY;
199220

@@ -454,7 +475,7 @@ static int __sev_guest_init(struct kvm *kvm, struct kvm_sev_cmd *argp,
454475
if (snp_active)
455476
sev->vmsa_features |= SVM_SEV_FEAT_SNP_ACTIVE;
456477

457-
ret = sev_asid_new(sev);
478+
ret = sev_asid_new(sev, vm_type);
458479
if (ret)
459480
goto e_no_asid;
460481

@@ -3058,6 +3079,9 @@ void __init sev_hardware_setup(void)
30583079
if (min_sev_asid == 1)
30593080
goto out;
30603081

3082+
min_sev_es_asid = min_snp_asid = 1;
3083+
max_sev_es_asid = max_snp_asid = min_sev_asid - 1;
3084+
30613085
sev_es_asid_count = min_sev_asid - 1;
30623086
WARN_ON_ONCE(misc_cg_set_capacity(MISC_CG_RES_SEV_ES, sev_es_asid_count));
30633087
sev_es_supported = true;
@@ -3066,10 +3090,32 @@ void __init sev_hardware_setup(void)
30663090
out:
30673091
if (sev_enabled) {
30683092
init_args.probe = true;
3093+
3094+
if (sev_is_snp_ciphertext_hiding_supported())
3095+
init_args.max_snp_asid = min(nr_ciphertext_hiding_asids,
3096+
min_sev_asid - 1);
3097+
30693098
if (sev_platform_init(&init_args))
30703099
sev_supported = sev_es_supported = sev_snp_supported = false;
30713100
else if (sev_snp_supported)
30723101
sev_snp_supported = is_sev_snp_initialized();
3102+
3103+
if (sev_snp_supported)
3104+
nr_ciphertext_hiding_asids = init_args.max_snp_asid;
3105+
3106+
/*
3107+
* If ciphertext hiding is enabled, the joint SEV-ES/SEV-SNP
3108+
* ASID range is partitioned into separate SEV-ES and SEV-SNP
3109+
* ASID ranges, with the SEV-SNP range being [1..max_snp_asid]
3110+
* and the SEV-ES range being (max_snp_asid..max_sev_es_asid].
3111+
* Note, SEV-ES may effectively be disabled if all ASIDs from
3112+
* the joint range are assigned to SEV-SNP.
3113+
*/
3114+
if (nr_ciphertext_hiding_asids) {
3115+
max_snp_asid = nr_ciphertext_hiding_asids;
3116+
min_sev_es_asid = max_snp_asid + 1;
3117+
pr_info("SEV-SNP ciphertext hiding enabled\n");
3118+
}
30733119
}
30743120

30753121
if (boot_cpu_has(X86_FEATURE_SEV))
@@ -3080,12 +3126,14 @@ void __init sev_hardware_setup(void)
30803126
min_sev_asid, max_sev_asid);
30813127
if (boot_cpu_has(X86_FEATURE_SEV_ES))
30823128
pr_info("SEV-ES %s (ASIDs %u - %u)\n",
3083-
str_enabled_disabled(sev_es_supported),
3084-
min_sev_asid > 1 ? 1 : 0, min_sev_asid - 1);
3129+
sev_es_supported ? min_sev_es_asid <= max_sev_es_asid ? "enabled" :
3130+
"unusable" :
3131+
"disabled",
3132+
min_sev_es_asid, max_sev_es_asid);
30853133
if (boot_cpu_has(X86_FEATURE_SEV_SNP))
30863134
pr_info("SEV-SNP %s (ASIDs %u - %u)\n",
30873135
str_enabled_disabled(sev_snp_supported),
3088-
min_sev_asid > 1 ? 1 : 0, min_sev_asid - 1);
3136+
min_snp_asid, max_snp_asid);
30893137

30903138
sev_enabled = sev_supported;
30913139
sev_es_enabled = sev_es_supported;

0 commit comments

Comments
 (0)