@@ -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+
16151655int 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 );
16681714out_dst_vcpu :
16691715 sev_unlock_vcpus_for_migration (kvm );
0 commit comments