Skip to content

Commit 605bbdc

Browse files
committed
KVM: SEV: store VMSA features in kvm_sev_info
Right now, the set of features that are stored in the VMSA upon initialization is fixed and depends on the module parameters for kvm-amd.ko. However, the hypervisor cannot really change it at will because the feature word has to match between the hypervisor and whatever computes a measurement of the VMSA for attestation purposes. Add a field to kvm_sev_info that holds the set of features to be stored in the VMSA; and query it instead of referring to the module parameters. Because KVM_SEV_INIT and KVM_SEV_ES_INIT accept no parameters, this does not yet introduce any functional change, but it paves the way for an API that allows customization of the features per-VM. Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> Message-Id: <20240209183743.22030-6-pbonzini@redhat.com> Reviewed-by: Michael Roth <michael.roth@amd.com> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> Message-ID: <20240404121327.3107131-7-pbonzini@redhat.com> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
1 parent ac5c480 commit 605bbdc

3 files changed

Lines changed: 24 additions & 10 deletions

File tree

arch/x86/kvm/svm/sev.c

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,14 @@ static inline bool is_mirroring_enc_context(struct kvm *kvm)
9999
return !!to_kvm_svm(kvm)->sev_info.enc_context_owner;
100100
}
101101

102+
static bool sev_vcpu_has_debug_swap(struct vcpu_svm *svm)
103+
{
104+
struct kvm_vcpu *vcpu = &svm->vcpu;
105+
struct kvm_sev_info *sev = &to_kvm_svm(vcpu->kvm)->sev_info;
106+
107+
return sev->vmsa_features & SVM_SEV_FEAT_DEBUG_SWAP;
108+
}
109+
102110
/* Must be called with the sev_bitmap_lock held */
103111
static bool __sev_recycle_asids(unsigned int min_asid, unsigned int max_asid)
104112
{
@@ -248,6 +256,11 @@ static int sev_guest_init(struct kvm *kvm, struct kvm_sev_cmd *argp)
248256

249257
sev->active = true;
250258
sev->es_active = argp->id == KVM_SEV_ES_INIT;
259+
sev->vmsa_features = sev_supported_vmsa_features;
260+
if (sev_supported_vmsa_features)
261+
pr_warn_once("Enabling DebugSwap with KVM_SEV_ES_INIT. "
262+
"This will not work starting with Linux 6.10\n");
263+
251264
ret = sev_asid_new(sev);
252265
if (ret)
253266
goto e_no_asid;
@@ -269,6 +282,7 @@ static int sev_guest_init(struct kvm *kvm, struct kvm_sev_cmd *argp)
269282
sev_asid_free(sev);
270283
sev->asid = 0;
271284
e_no_asid:
285+
sev->vmsa_features = 0;
272286
sev->es_active = false;
273287
sev->active = false;
274288
return ret;
@@ -563,6 +577,8 @@ static int sev_launch_update_data(struct kvm *kvm, struct kvm_sev_cmd *argp)
563577

564578
static int sev_es_sync_vmsa(struct vcpu_svm *svm)
565579
{
580+
struct kvm_vcpu *vcpu = &svm->vcpu;
581+
struct kvm_sev_info *sev = &to_kvm_svm(vcpu->kvm)->sev_info;
566582
struct sev_es_save_area *save = svm->sev_es.vmsa;
567583

568584
/* Check some debug related fields before encrypting the VMSA */
@@ -604,11 +620,7 @@ static int sev_es_sync_vmsa(struct vcpu_svm *svm)
604620
save->xss = svm->vcpu.arch.ia32_xss;
605621
save->dr6 = svm->vcpu.arch.dr6;
606622

607-
if (sev_supported_vmsa_features) {
608-
save->sev_features = sev_supported_vmsa_features;
609-
pr_warn_once("Enabling DebugSwap with KVM_SEV_ES_INIT. "
610-
"This will not work starting with Linux 6.10\n");
611-
}
623+
save->sev_features = sev->vmsa_features;
612624

613625
pr_debug("Virtual Machine Save Area (VMSA):\n");
614626
print_hex_dump_debug("", DUMP_PREFIX_NONE, 16, 1, save, sizeof(*save), false);
@@ -1688,6 +1700,7 @@ static void sev_migrate_from(struct kvm *dst_kvm, struct kvm *src_kvm)
16881700
dst->pages_locked = src->pages_locked;
16891701
dst->enc_context_owner = src->enc_context_owner;
16901702
dst->es_active = src->es_active;
1703+
dst->vmsa_features = src->vmsa_features;
16911704

16921705
src->asid = 0;
16931706
src->active = false;
@@ -3063,7 +3076,7 @@ static void sev_es_init_vmcb(struct vcpu_svm *svm)
30633076
svm_set_intercept(svm, TRAP_CR8_WRITE);
30643077

30653078
vmcb->control.intercepts[INTERCEPT_DR] = 0;
3066-
if (!sev_es_debug_swap_enabled) {
3079+
if (!sev_vcpu_has_debug_swap(svm)) {
30673080
vmcb_set_intercept(&vmcb->control, INTERCEPT_DR7_READ);
30683081
vmcb_set_intercept(&vmcb->control, INTERCEPT_DR7_WRITE);
30693082
recalc_intercepts(svm);
@@ -3118,7 +3131,7 @@ void sev_es_vcpu_reset(struct vcpu_svm *svm)
31183131
sev_enc_bit));
31193132
}
31203133

3121-
void sev_es_prepare_switch_to_guest(struct sev_es_save_area *hostsa)
3134+
void sev_es_prepare_switch_to_guest(struct vcpu_svm *svm, struct sev_es_save_area *hostsa)
31223135
{
31233136
/*
31243137
* All host state for SEV-ES guests is categorized into three swap types
@@ -3146,7 +3159,7 @@ void sev_es_prepare_switch_to_guest(struct sev_es_save_area *hostsa)
31463159
* the CPU (Type-B). If DebugSwap is disabled/unsupported, the CPU both
31473160
* saves and loads debug registers (Type-A).
31483161
*/
3149-
if (sev_es_debug_swap_enabled) {
3162+
if (sev_vcpu_has_debug_swap(svm)) {
31503163
hostsa->dr0 = native_get_debugreg(0);
31513164
hostsa->dr1 = native_get_debugreg(1);
31523165
hostsa->dr2 = native_get_debugreg(2);

arch/x86/kvm/svm/svm.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1523,7 +1523,7 @@ static void svm_prepare_switch_to_guest(struct kvm_vcpu *vcpu)
15231523
struct sev_es_save_area *hostsa;
15241524
hostsa = (struct sev_es_save_area *)(page_address(sd->save_area) + 0x400);
15251525

1526-
sev_es_prepare_switch_to_guest(hostsa);
1526+
sev_es_prepare_switch_to_guest(svm, hostsa);
15271527
}
15281528

15291529
if (tsc_scaling)

arch/x86/kvm/svm/svm.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ struct kvm_sev_info {
8585
unsigned long pages_locked; /* Number of pages locked */
8686
struct list_head regions_list; /* List of registered regions */
8787
u64 ap_jump_table; /* SEV-ES AP Jump Table address */
88+
u64 vmsa_features;
8889
struct kvm *enc_context_owner; /* Owner of copied encryption context */
8990
struct list_head mirror_vms; /* List of VMs mirroring */
9091
struct list_head mirror_entry; /* Use as a list entry of mirrors */
@@ -670,7 +671,7 @@ void sev_vcpu_after_set_cpuid(struct vcpu_svm *svm);
670671
int sev_es_string_io(struct vcpu_svm *svm, int size, unsigned int port, int in);
671672
void sev_es_vcpu_reset(struct vcpu_svm *svm);
672673
void sev_vcpu_deliver_sipi_vector(struct kvm_vcpu *vcpu, u8 vector);
673-
void sev_es_prepare_switch_to_guest(struct sev_es_save_area *hostsa);
674+
void sev_es_prepare_switch_to_guest(struct vcpu_svm *svm, struct sev_es_save_area *hostsa);
674675
void sev_es_unmap_ghcb(struct vcpu_svm *svm);
675676

676677
#ifdef CONFIG_KVM_AMD_SEV

0 commit comments

Comments
 (0)