On Fri, Feb 09, 2024 at 01:37:37PM -0500, Paolo Bonzini wrote: > 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_set_info that holds the set of features to be stored s/kvm_set_info_/kvm_sev_info/ Otherwise: Reviewed-by: Michael Roth <michael.roth@xxxxxxx> > 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@xxxxxxxxxx> > --- > arch/x86/kvm/svm/sev.c | 22 ++++++++++++++++++---- > arch/x86/kvm/svm/svm.c | 2 +- > arch/x86/kvm/svm/svm.h | 3 ++- > 3 files changed, 21 insertions(+), 6 deletions(-) > > diff --git a/arch/x86/kvm/svm/sev.c b/arch/x86/kvm/svm/sev.c > index 2e558f7538c2..712bfbc0028a 100644 > --- a/arch/x86/kvm/svm/sev.c > +++ b/arch/x86/kvm/svm/sev.c > @@ -116,6 +116,14 @@ static inline bool is_mirroring_enc_context(struct kvm *kvm) > return !!to_kvm_svm(kvm)->sev_info.enc_context_owner; > } > > +static bool sev_vcpu_has_debug_swap(struct vcpu_svm *svm) > +{ > + struct kvm_vcpu *vcpu = &svm->vcpu; > + struct kvm_sev_info *sev = &to_kvm_svm(vcpu->kvm)->sev_info; > + > + return sev->vmsa_features & SVM_SEV_FEAT_DEBUG_SWAP; > +} > + > /* Must be called with the sev_bitmap_lock held */ > static bool __sev_recycle_asids(int min_asid, int max_asid) > { > @@ -258,6 +266,8 @@ static int sev_guest_init(struct kvm *kvm, struct kvm_sev_cmd *argp) > > sev->active = true; > sev->es_active = argp->id == KVM_SEV_ES_INIT; > + sev->vmsa_features = sev_supported_vmsa_features; > + > asid = sev_asid_new(sev); > if (asid < 0) > goto e_no_asid; > @@ -278,6 +288,7 @@ static int sev_guest_init(struct kvm *kvm, struct kvm_sev_cmd *argp) > sev_asid_free(sev); > sev->asid = 0; > e_no_asid: > + sev->vmsa_features = 0; > sev->es_active = false; > sev->active = false; > return ret; > @@ -572,6 +583,8 @@ static int sev_launch_update_data(struct kvm *kvm, struct kvm_sev_cmd *argp) > > static int sev_es_sync_vmsa(struct vcpu_svm *svm) > { > + struct kvm_vcpu *vcpu = &svm->vcpu; > + struct kvm_sev_info *sev = &to_kvm_svm(vcpu->kvm)->sev_info; > struct sev_es_save_area *save = svm->sev_es.vmsa; > > /* Check some debug related fields before encrypting the VMSA */ > @@ -613,7 +626,7 @@ static int sev_es_sync_vmsa(struct vcpu_svm *svm) > save->xss = svm->vcpu.arch.ia32_xss; > save->dr6 = svm->vcpu.arch.dr6; > > - save->sev_features = sev_supported_vmsa_features; > + save->sev_features = sev->vmsa_features; > > pr_debug("Virtual Machine Save Area (VMSA):\n"); > print_hex_dump_debug("", DUMP_PREFIX_NONE, 16, 1, save, sizeof(*save), false); > @@ -1693,6 +1706,7 @@ static void sev_migrate_from(struct kvm *dst_kvm, struct kvm *src_kvm) > dst->pages_locked = src->pages_locked; > dst->enc_context_owner = src->enc_context_owner; > dst->es_active = src->es_active; > + dst->vmsa_features = src->vmsa_features; > > src->asid = 0; > src->active = false; > @@ -3063,7 +3077,7 @@ static void sev_es_init_vmcb(struct vcpu_svm *svm) > svm_set_intercept(svm, TRAP_CR8_WRITE); > > vmcb->control.intercepts[INTERCEPT_DR] = 0; > - if (!sev_es_debug_swap_enabled) { > + if (!sev_vcpu_has_debug_swap(svm)) { > vmcb_set_intercept(&vmcb->control, INTERCEPT_DR7_READ); > vmcb_set_intercept(&vmcb->control, INTERCEPT_DR7_WRITE); > recalc_intercepts(svm); > @@ -3118,7 +3132,7 @@ void sev_es_vcpu_reset(struct vcpu_svm *svm) > sev_enc_bit)); > } > > -void sev_es_prepare_switch_to_guest(struct sev_es_save_area *hostsa) > +void sev_es_prepare_switch_to_guest(struct vcpu_svm *svm, struct sev_es_save_area *hostsa) > { > /* > * All host state for SEV-ES guests is categorized into three swap types > @@ -3146,7 +3160,7 @@ void sev_es_prepare_switch_to_guest(struct sev_es_save_area *hostsa) > * the CPU (Type-B). If DebugSwap is disabled/unsupported, the CPU both > * saves and loads debug registers (Type-A). > */ > - if (sev_es_debug_swap_enabled) { > + if (sev_vcpu_has_debug_swap(svm)) { > hostsa->dr0 = native_get_debugreg(0); > hostsa->dr1 = native_get_debugreg(1); > hostsa->dr2 = native_get_debugreg(2); > diff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c > index aa1792f402ab..392b9c2e2ce1 100644 > --- a/arch/x86/kvm/svm/svm.c > +++ b/arch/x86/kvm/svm/svm.c > @@ -1523,7 +1523,7 @@ static void svm_prepare_switch_to_guest(struct kvm_vcpu *vcpu) > struct sev_es_save_area *hostsa; > hostsa = (struct sev_es_save_area *)(page_address(sd->save_area) + 0x400); > > - sev_es_prepare_switch_to_guest(hostsa); > + sev_es_prepare_switch_to_guest(svm, hostsa); > } > > if (tsc_scaling) > diff --git a/arch/x86/kvm/svm/svm.h b/arch/x86/kvm/svm/svm.h > index d630026b23b0..864c782eaa58 100644 > --- a/arch/x86/kvm/svm/svm.h > +++ b/arch/x86/kvm/svm/svm.h > @@ -85,6 +85,7 @@ struct kvm_sev_info { > unsigned long pages_locked; /* Number of pages locked */ > struct list_head regions_list; /* List of registered regions */ > u64 ap_jump_table; /* SEV-ES AP Jump Table address */ > + u64 vmsa_features; > struct kvm *enc_context_owner; /* Owner of copied encryption context */ > struct list_head mirror_vms; /* List of VMs mirroring */ > struct list_head mirror_entry; /* Use as a list entry of mirrors */ > @@ -693,7 +694,7 @@ int sev_handle_vmgexit(struct kvm_vcpu *vcpu); > int sev_es_string_io(struct vcpu_svm *svm, int size, unsigned int port, int in); > void sev_es_vcpu_reset(struct vcpu_svm *svm); > void sev_vcpu_deliver_sipi_vector(struct kvm_vcpu *vcpu, u8 vector); > -void sev_es_prepare_switch_to_guest(struct sev_es_save_area *hostsa); > +void sev_es_prepare_switch_to_guest(struct vcpu_svm *svm, struct sev_es_save_area *hostsa); > void sev_es_unmap_ghcb(struct vcpu_svm *svm); > > /* vmenter.S */ > -- > 2.39.0 > > >