Skip to content

Commit 0b020f5

Browse files
pgondabonzini
authored andcommitted
KVM: SEV: Add support for SEV-ES intra host migration
For SEV-ES to work with intra host migration the VMSAs, GHCB metadata, and other SEV-ES info needs to be preserved along with the guest's memory. Signed-off-by: Peter Gonda <[email protected]> Reviewed-by: Marc Orr <[email protected]> Cc: Marc Orr <[email protected]> Cc: Paolo Bonzini <[email protected]> Cc: Sean Christopherson <[email protected]> Cc: David Rientjes <[email protected]> Cc: Dr. David Alan Gilbert <[email protected]> Cc: Brijesh Singh <[email protected]> Cc: Tom Lendacky <[email protected]> Cc: Vitaly Kuznetsov <[email protected]> Cc: Wanpeng Li <[email protected]> Cc: Jim Mattson <[email protected]> Cc: Joerg Roedel <[email protected]> Cc: Thomas Gleixner <[email protected]> Cc: Ingo Molnar <[email protected]> Cc: Borislav Petkov <[email protected]> Cc: "H. Peter Anvin" <[email protected]> Cc: [email protected] Cc: [email protected] Message-Id: <[email protected]> Signed-off-by: Paolo Bonzini <[email protected]>
1 parent b566393 commit 0b020f5

File tree

1 file changed

+47
-1
lines changed

1 file changed

+47
-1
lines changed

arch/x86/kvm/svm/sev.c

Lines changed: 47 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1612,6 +1612,46 @@ static void sev_migrate_from(struct kvm_sev_info *dst,
16121612
list_replace_init(&src->regions_list, &dst->regions_list);
16131613
}
16141614

1615+
static int sev_es_migrate_from(struct kvm *dst, struct kvm *src)
1616+
{
1617+
int i;
1618+
struct kvm_vcpu *dst_vcpu, *src_vcpu;
1619+
struct vcpu_svm *dst_svm, *src_svm;
1620+
1621+
if (atomic_read(&src->online_vcpus) != atomic_read(&dst->online_vcpus))
1622+
return -EINVAL;
1623+
1624+
kvm_for_each_vcpu(i, src_vcpu, src) {
1625+
if (!src_vcpu->arch.guest_state_protected)
1626+
return -EINVAL;
1627+
}
1628+
1629+
kvm_for_each_vcpu(i, src_vcpu, src) {
1630+
src_svm = to_svm(src_vcpu);
1631+
dst_vcpu = kvm_get_vcpu(dst, i);
1632+
dst_svm = to_svm(dst_vcpu);
1633+
1634+
/*
1635+
* Transfer VMSA and GHCB state to the destination. Nullify and
1636+
* clear source fields as appropriate, the state now belongs to
1637+
* the destination.
1638+
*/
1639+
memcpy(&dst_svm->sev_es, &src_svm->sev_es, sizeof(src_svm->sev_es));
1640+
dst_svm->vmcb->control.ghcb_gpa = src_svm->vmcb->control.ghcb_gpa;
1641+
dst_svm->vmcb->control.vmsa_pa = src_svm->vmcb->control.vmsa_pa;
1642+
dst_vcpu->arch.guest_state_protected = true;
1643+
1644+
memset(&src_svm->sev_es, 0, sizeof(src_svm->sev_es));
1645+
src_svm->vmcb->control.ghcb_gpa = INVALID_PAGE;
1646+
src_svm->vmcb->control.vmsa_pa = INVALID_PAGE;
1647+
src_vcpu->arch.guest_state_protected = false;
1648+
}
1649+
to_kvm_svm(src)->sev_info.es_active = false;
1650+
to_kvm_svm(dst)->sev_info.es_active = true;
1651+
1652+
return 0;
1653+
}
1654+
16151655
int svm_vm_migrate_from(struct kvm *kvm, unsigned int source_fd)
16161656
{
16171657
struct kvm_sev_info *dst_sev = &to_kvm_svm(kvm)->sev_info;
@@ -1640,7 +1680,7 @@ int svm_vm_migrate_from(struct kvm *kvm, unsigned int source_fd)
16401680
if (ret)
16411681
goto out_fput;
16421682

1643-
if (!sev_guest(source_kvm) || sev_es_guest(source_kvm)) {
1683+
if (!sev_guest(source_kvm)) {
16441684
ret = -EINVAL;
16451685
goto out_source;
16461686
}
@@ -1660,10 +1700,16 @@ int svm_vm_migrate_from(struct kvm *kvm, unsigned int source_fd)
16601700
if (ret)
16611701
goto out_dst_vcpu;
16621702

1703+
if (sev_es_guest(source_kvm)) {
1704+
ret = sev_es_migrate_from(kvm, source_kvm);
1705+
if (ret)
1706+
goto out_source_vcpu;
1707+
}
16631708
sev_migrate_from(dst_sev, src_sev);
16641709
kvm_vm_dead(source_kvm);
16651710
ret = 0;
16661711

1712+
out_source_vcpu:
16671713
sev_unlock_vcpus_for_migration(source_kvm);
16681714
out_dst_vcpu:
16691715
sev_unlock_vcpus_for_migration(kvm);

0 commit comments

Comments
 (0)