@@ -1532,6 +1532,158 @@ static bool cmd_allowed_from_miror(u32 cmd_id)
15321532 return false;
15331533}
15341534
1535+ static int sev_lock_for_migration (struct kvm * kvm )
1536+ {
1537+ struct kvm_sev_info * sev = & to_kvm_svm (kvm )-> sev_info ;
1538+
1539+ /*
1540+ * Bail if this VM is already involved in a migration to avoid deadlock
1541+ * between two VMs trying to migrate to/from each other.
1542+ */
1543+ if (atomic_cmpxchg_acquire (& sev -> migration_in_progress , 0 , 1 ))
1544+ return - EBUSY ;
1545+
1546+ mutex_lock (& kvm -> lock );
1547+
1548+ return 0 ;
1549+ }
1550+
1551+ static void sev_unlock_after_migration (struct kvm * kvm )
1552+ {
1553+ struct kvm_sev_info * sev = & to_kvm_svm (kvm )-> sev_info ;
1554+
1555+ mutex_unlock (& kvm -> lock );
1556+ atomic_set_release (& sev -> migration_in_progress , 0 );
1557+ }
1558+
1559+
1560+ static int sev_lock_vcpus_for_migration (struct kvm * kvm )
1561+ {
1562+ struct kvm_vcpu * vcpu ;
1563+ int i , j ;
1564+
1565+ kvm_for_each_vcpu (i , vcpu , kvm ) {
1566+ if (mutex_lock_killable (& vcpu -> mutex ))
1567+ goto out_unlock ;
1568+ }
1569+
1570+ return 0 ;
1571+
1572+ out_unlock :
1573+ kvm_for_each_vcpu (j , vcpu , kvm ) {
1574+ if (i == j )
1575+ break ;
1576+
1577+ mutex_unlock (& vcpu -> mutex );
1578+ }
1579+ return - EINTR ;
1580+ }
1581+
1582+ static void sev_unlock_vcpus_for_migration (struct kvm * kvm )
1583+ {
1584+ struct kvm_vcpu * vcpu ;
1585+ int i ;
1586+
1587+ kvm_for_each_vcpu (i , vcpu , kvm ) {
1588+ mutex_unlock (& vcpu -> mutex );
1589+ }
1590+ }
1591+
1592+ static void sev_migrate_from (struct kvm_sev_info * dst ,
1593+ struct kvm_sev_info * src )
1594+ {
1595+ dst -> active = true;
1596+ dst -> asid = src -> asid ;
1597+ dst -> handle = src -> handle ;
1598+ dst -> pages_locked = src -> pages_locked ;
1599+
1600+ src -> asid = 0 ;
1601+ src -> active = false;
1602+ src -> handle = 0 ;
1603+ src -> pages_locked = 0 ;
1604+
1605+ if (dst -> misc_cg != src -> misc_cg )
1606+ sev_misc_cg_uncharge (src );
1607+
1608+ put_misc_cg (src -> misc_cg );
1609+ src -> misc_cg = NULL ;
1610+
1611+ INIT_LIST_HEAD (& dst -> regions_list );
1612+ list_replace_init (& src -> regions_list , & dst -> regions_list );
1613+ }
1614+
1615+ int svm_vm_migrate_from (struct kvm * kvm , unsigned int source_fd )
1616+ {
1617+ struct kvm_sev_info * dst_sev = & to_kvm_svm (kvm )-> sev_info ;
1618+ struct kvm_sev_info * src_sev ;
1619+ struct file * source_kvm_file ;
1620+ struct kvm * source_kvm ;
1621+ int ret ;
1622+
1623+ ret = sev_lock_for_migration (kvm );
1624+ if (ret )
1625+ return ret ;
1626+
1627+ if (sev_guest (kvm )) {
1628+ ret = - EINVAL ;
1629+ goto out_unlock ;
1630+ }
1631+
1632+ source_kvm_file = fget (source_fd );
1633+ if (!file_is_kvm (source_kvm_file )) {
1634+ ret = - EBADF ;
1635+ goto out_fput ;
1636+ }
1637+
1638+ source_kvm = source_kvm_file -> private_data ;
1639+ ret = sev_lock_for_migration (source_kvm );
1640+ if (ret )
1641+ goto out_fput ;
1642+
1643+ if (!sev_guest (source_kvm ) || sev_es_guest (source_kvm )) {
1644+ ret = - EINVAL ;
1645+ goto out_source ;
1646+ }
1647+
1648+ src_sev = & to_kvm_svm (source_kvm )-> sev_info ;
1649+ dst_sev -> misc_cg = get_current_misc_cg ();
1650+ if (dst_sev -> misc_cg != src_sev -> misc_cg ) {
1651+ ret = sev_misc_cg_try_charge (dst_sev );
1652+ if (ret )
1653+ goto out_dst_put_cgroup ;
1654+ }
1655+
1656+ ret = sev_lock_vcpus_for_migration (kvm );
1657+ if (ret )
1658+ goto out_dst_cgroup ;
1659+ ret = sev_lock_vcpus_for_migration (source_kvm );
1660+ if (ret )
1661+ goto out_dst_vcpu ;
1662+
1663+ sev_migrate_from (dst_sev , src_sev );
1664+ kvm_vm_dead (source_kvm );
1665+ ret = 0 ;
1666+
1667+ sev_unlock_vcpus_for_migration (source_kvm );
1668+ out_dst_vcpu :
1669+ sev_unlock_vcpus_for_migration (kvm );
1670+ out_dst_cgroup :
1671+ if (ret < 0 ) {
1672+ sev_misc_cg_uncharge (dst_sev );
1673+ out_dst_put_cgroup :
1674+ put_misc_cg (dst_sev -> misc_cg );
1675+ dst_sev -> misc_cg = NULL ;
1676+ }
1677+ out_source :
1678+ sev_unlock_after_migration (source_kvm );
1679+ out_fput :
1680+ if (source_kvm_file )
1681+ fput (source_kvm_file );
1682+ out_unlock :
1683+ sev_unlock_after_migration (kvm );
1684+ return ret ;
1685+ }
1686+
15351687int svm_mem_enc_op (struct kvm * kvm , void __user * argp )
15361688{
15371689 struct kvm_sev_cmd sev_cmd ;
0 commit comments