@@ -1612,6 +1612,46 @@ static void sev_migrate_from(struct kvm_sev_info *dst,
1612
1612
list_replace_init (& src -> regions_list , & dst -> regions_list );
1613
1613
}
1614
1614
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
+
1615
1655
int svm_vm_migrate_from (struct kvm * kvm , unsigned int source_fd )
1616
1656
{
1617
1657
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)
1640
1680
if (ret )
1641
1681
goto out_fput ;
1642
1682
1643
- if (!sev_guest (source_kvm ) || sev_es_guest ( source_kvm ) ) {
1683
+ if (!sev_guest (source_kvm )) {
1644
1684
ret = - EINVAL ;
1645
1685
goto out_source ;
1646
1686
}
@@ -1660,10 +1700,16 @@ int svm_vm_migrate_from(struct kvm *kvm, unsigned int source_fd)
1660
1700
if (ret )
1661
1701
goto out_dst_vcpu ;
1662
1702
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
+ }
1663
1708
sev_migrate_from (dst_sev , src_sev );
1664
1709
kvm_vm_dead (source_kvm );
1665
1710
ret = 0 ;
1666
1711
1712
+ out_source_vcpu :
1667
1713
sev_unlock_vcpus_for_migration (source_kvm );
1668
1714
out_dst_vcpu :
1669
1715
sev_unlock_vcpus_for_migration (kvm );
0 commit comments