[PATCH v3 06/15] s390/vfio-ap: Transition guest migration state from STOP to STOP_COPY
From: Anthony Krowiak
Date: Tue Jun 30 2026 - 06:51:45 EST
The transition of the guest migration state from VFIO_DEVICE_STATE_STOP to
VFIO_DEVICE_STATE_STOP_COPY begins the process of saving the
vfio device state. The vfio device state is comprised of the guest's
AP configuration which specifies the adapters, domains and control
domains to which the guest will be given access.
To begin the process of saving the vfio device state, the VFIO AP device
driver opens a file stream that will be used to read the source guest's
AP configuration.
Note:
This commit introduces the file operations structure for migration state
files with a stub implementation of the read operation. The complete
implementation is provided in the subsequent commit.
This incremental approach allows for easier review of the migration
infrastructure setup separate from the actual implementation logic.
Signed-off-by: Anthony Krowiak <akrowiak@xxxxxxxxxxxxx>
---
drivers/s390/crypto/vfio_ap_migration.c | 68 ++++++++++++++++++++++++-
1 file changed, 66 insertions(+), 2 deletions(-)
diff --git a/drivers/s390/crypto/vfio_ap_migration.c b/drivers/s390/crypto/vfio_ap_migration.c
index 8274e7b65eea..76e06abe5a9e 100644
--- a/drivers/s390/crypto/vfio_ap_migration.c
+++ b/drivers/s390/crypto/vfio_ap_migration.c
@@ -4,6 +4,7 @@
*
* Copyright IBM Corp. 2025
*/
+#include <linux/anon_inodes.h>
#include <linux/file.h>
#include "ap_bus.h"
#include "vfio_ap_private.h"
@@ -57,6 +58,57 @@ struct vfio_ap_config {
struct vfio_ap_queue_info qinfo[] __counted_by(num_queues);
};
+static void
+vfio_ap_release_stop_copy_file(struct vfio_ap_migration_data *mig_data)
+{
+ if (mig_data->stop_copy_mig_file)
+ mig_data->stop_copy_mig_file = NULL;
+}
+
+static ssize_t
+vfio_ap_stop_copy_read(struct file *, char __user *, size_t, loff_t *)
+{
+ /* TODO */
+ return -EOPNOTSUPP;
+}
+
+static int vfio_ap_release_mig_file(struct inode *file_inode, struct file *filp)
+{
+ struct ap_matrix_mdev *matrix_mdev = filp->private_data;
+
+ if (!matrix_mdev || !matrix_mdev->mig_data)
+ return -ENODEV;
+
+ if (filp == matrix_mdev->mig_data->stop_copy_mig_file)
+ vfio_ap_release_stop_copy_file(matrix_mdev->mig_data);
+ else
+ return -ENOENT;
+
+ return 0;
+}
+
+static const struct file_operations vfio_ap_stop_copy_fops = {
+ .owner = THIS_MODULE,
+ .read = vfio_ap_stop_copy_read,
+ .compat_ioctl = compat_ptr_ioctl,
+ .release = vfio_ap_release_mig_file,
+};
+
+static struct file *vfio_ap_open_file_stream(struct ap_matrix_mdev *matrix_mdev,
+ const struct file_operations *fops,
+ int flags)
+{
+ struct file *filp;
+
+ lockdep_assert_held(&matrix_dev->mdevs_lock);
+
+ filp = anon_inode_getfile("vfio_ap_mig_file", fops, matrix_mdev, flags);
+ if (!IS_ERR(filp))
+ stream_open(filp->f_inode, filp);
+
+ return filp;
+}
+
static struct file *
vfio_ap_transition_to_state(struct ap_matrix_mdev *matrix_mdev,
enum vfio_device_mig_state new_state)
@@ -70,10 +122,22 @@ vfio_ap_transition_to_state(struct ap_matrix_mdev *matrix_mdev,
dev_dbg(matrix_mdev->vdev.dev, "%s: %d -> %d\n", __func__, cur_state,
new_state);
+ /*
+ * Begins the process of saving the vfio device state by creating and
+ * returning a streaming data_fd to be used to read out the internal
+ * state of the vfio-ap device on the source host.
+ */
if (cur_state == VFIO_DEVICE_STATE_STOP &&
new_state == VFIO_DEVICE_STATE_STOP_COPY) {
- /* TODO */
- return ERR_PTR(-EOPNOTSUPP);
+ struct file *filp = vfio_ap_open_file_stream(matrix_mdev,
+ &vfio_ap_stop_copy_fops,
+ O_RDONLY);
+ if (IS_ERR(filp))
+ return ERR_CAST(filp);
+
+ mig_data->stop_copy_mig_file = filp;
+
+ return filp;
}
if (cur_state == VFIO_DEVICE_STATE_STOP &&
--
2.53.0