[PATCH] KVM: SEV: Init target VMCBs in sev_migrate_from
From: Peter Gonda
Date: Fri Jun 17 2022 - 15:52:18 EST
The target VMCBs during an intra-host migration need to correctly setup
for running SEV and SEV-ES guests. Use the sev_es_init_vmcb() to setup
the sev-es VMCBs and refactor out a new sev_init_vmcb() function to
handle SEV only migrations.
Fixes: 0b020f5af092 ("KVM: SEV: Add support for SEV-ES intra host migration")
Fixes: b56639318bb2 ("KVM: SEV: Add support for SEV intra host migration")
Signed-off-by: Peter Gonda <pgonda@xxxxxxxxxx>
Cc: Marc Orr <marcorr@xxxxxxxxxx>
Cc: Paolo Bonzini <pbonzini@xxxxxxxxxx>
Cc: Sean Christopherson <seanjc@xxxxxxxxxx>
Cc: Tom Lendacky <thomas.lendacky@xxxxxxx>
Cc: kvm@xxxxxxxxxxxxxxx
Cc: linux-kernel@xxxxxxxxxxxxxxx
---
I had tested this with the selftests and by backporting patches to our
kernel fork and running on our Vanadium VMM internally. Doing that however
I dropped the requirement that SEV_INIT not be done on the target for
minimal changes to our VMM for testing. This lead to me missing this bug.
Tested by backporting back to our kernel fork and running our intra-host
migration test suite without SEV_INITing the target VM.
---
arch/x86/kvm/svm/sev.c | 14 ++++++++++++++
arch/x86/kvm/svm/svm.c | 3 +--
arch/x86/kvm/svm/svm.h | 1 +
3 files changed, 16 insertions(+), 2 deletions(-)
diff --git a/arch/x86/kvm/svm/sev.c b/arch/x86/kvm/svm/sev.c
index 655770522471..d483f253fcf5 100644
--- a/arch/x86/kvm/svm/sev.c
+++ b/arch/x86/kvm/svm/sev.c
@@ -1666,6 +1666,8 @@ static void sev_migrate_from(struct kvm *dst_kvm, struct kvm *src_kvm)
struct kvm_sev_info *dst = &to_kvm_svm(dst_kvm)->sev_info;
struct kvm_sev_info *src = &to_kvm_svm(src_kvm)->sev_info;
struct kvm_sev_info *mirror;
+ struct kvm_vcpu *vcpu;
+ unsigned long i;
dst->active = true;
dst->asid = src->asid;
@@ -1681,6 +1683,10 @@ static void sev_migrate_from(struct kvm *dst_kvm, struct kvm *src_kvm)
list_cut_before(&dst->regions_list, &src->regions_list, &src->regions_list);
+ kvm_for_each_vcpu(i, vcpu, dst_kvm) {
+ sev_init_vmcb(to_svm(vcpu));
+ }
+
/*
* If this VM has mirrors, "transfer" each mirror's refcount of the
* source to the destination (this KVM). The caller holds a reference
@@ -1739,6 +1745,8 @@ static int sev_es_migrate_from(struct kvm *dst, struct kvm *src)
src_svm->vmcb->control.ghcb_gpa = INVALID_PAGE;
src_svm->vmcb->control.vmsa_pa = INVALID_PAGE;
src_vcpu->arch.guest_state_protected = false;
+
+ sev_es_init_vmcb(dst_svm);
}
to_kvm_svm(src)->sev_info.es_active = false;
to_kvm_svm(dst)->sev_info.es_active = true;
@@ -2914,6 +2922,12 @@ int sev_es_string_io(struct vcpu_svm *svm, int size, unsigned int port, int in)
count, in);
}
+void sev_init_vmcb(struct vcpu_svm *svm)
+{
+ svm->vmcb->control.nested_ctl |= SVM_NESTED_CTL_SEV_ENABLE;
+ clr_exception_intercept(svm, UD_VECTOR);
+}
+
void sev_es_init_vmcb(struct vcpu_svm *svm)
{
struct kvm_vcpu *vcpu = &svm->vcpu;
diff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c
index 12e792389e8b..9b9bbc228a69 100644
--- a/arch/x86/kvm/svm/svm.c
+++ b/arch/x86/kvm/svm/svm.c
@@ -1247,8 +1247,7 @@ static void init_vmcb(struct kvm_vcpu *vcpu)
}
if (sev_guest(vcpu->kvm)) {
- svm->vmcb->control.nested_ctl |= SVM_NESTED_CTL_SEV_ENABLE;
- clr_exception_intercept(svm, UD_VECTOR);
+ sev_init_vmcb(svm);
if (sev_es_guest(vcpu->kvm)) {
/* Perform SEV-ES specific VMCB updates */
diff --git a/arch/x86/kvm/svm/svm.h b/arch/x86/kvm/svm/svm.h
index cd92f4343753..33b6c6dd1a10 100644
--- a/arch/x86/kvm/svm/svm.h
+++ b/arch/x86/kvm/svm/svm.h
@@ -656,6 +656,7 @@ int sev_cpu_init(struct svm_cpu_data *sd);
void sev_free_vcpu(struct kvm_vcpu *vcpu);
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_init_vmcb(struct vcpu_svm *svm);
void sev_es_init_vmcb(struct vcpu_svm *svm);
void sev_es_vcpu_reset(struct vcpu_svm *svm);
void sev_vcpu_deliver_sipi_vector(struct kvm_vcpu *vcpu, u8 vector);
--
2.36.1.476.g0c4daa206d-goog