Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

vfio: Add an option to get migration data size

Add an option to get migration data size by introducing a new migration
feature named VFIO_DEVICE_FEATURE_MIG_DATA_SIZE.

Upon VFIO_DEVICE_FEATURE_GET the estimated data length that will be
required to complete STOP_COPY is returned.

This option may better enable user space to consider before moving to
STOP_COPY whether it can meet the downtime SLA based on the returned
data.

The patch also includes the implementation for mlx5 and hisi for this
new option to make it feature complete for the existing drivers in this
area.

Signed-off-by: Yishai Hadas <yishaih@nvidia.com>
Reviewed-by: Jason Gunthorpe <jgg@nvidia.com>
Reviewed-by: Longfang Liu <liulongfang@huawei.com>
Link: https://lore.kernel.org/r/20221106174630.25909-2-yishaih@nvidia.com
Signed-off-by: Alex Williamson <alex.williamson@redhat.com>

authored by

Yishai Hadas and committed by
Alex Williamson
4e016f96 913447d0

+79 -1
+9
drivers/vfio/pci/hisilicon/hisi_acc_vfio_pci.c
··· 958 958 } 959 959 960 960 static int 961 + hisi_acc_vfio_pci_get_data_size(struct vfio_device *vdev, 962 + unsigned long *stop_copy_length) 963 + { 964 + *stop_copy_length = sizeof(struct acc_vf_data); 965 + return 0; 966 + } 967 + 968 + static int 961 969 hisi_acc_vfio_pci_get_device_state(struct vfio_device *vdev, 962 970 enum vfio_device_mig_state *curr_state) 963 971 { ··· 1221 1213 static const struct vfio_migration_ops hisi_acc_vfio_pci_migrn_state_ops = { 1222 1214 .migration_set_state = hisi_acc_vfio_pci_set_device_state, 1223 1215 .migration_get_state = hisi_acc_vfio_pci_get_device_state, 1216 + .migration_get_data_size = hisi_acc_vfio_pci_get_data_size, 1224 1217 }; 1225 1218 1226 1219 static int hisi_acc_vfio_pci_migrn_init_dev(struct vfio_device *core_vdev)
+18
drivers/vfio/pci/mlx5/main.c
··· 512 512 return res; 513 513 } 514 514 515 + static int mlx5vf_pci_get_data_size(struct vfio_device *vdev, 516 + unsigned long *stop_copy_length) 517 + { 518 + struct mlx5vf_pci_core_device *mvdev = container_of( 519 + vdev, struct mlx5vf_pci_core_device, core_device.vdev); 520 + size_t state_size; 521 + int ret; 522 + 523 + mutex_lock(&mvdev->state_mutex); 524 + ret = mlx5vf_cmd_query_vhca_migration_state(mvdev, 525 + &state_size); 526 + if (!ret) 527 + *stop_copy_length = state_size; 528 + mlx5vf_state_mutex_unlock(mvdev); 529 + return ret; 530 + } 531 + 515 532 static int mlx5vf_pci_get_device_state(struct vfio_device *vdev, 516 533 enum vfio_device_mig_state *curr_state) 517 534 { ··· 594 577 static const struct vfio_migration_ops mlx5vf_pci_mig_ops = { 595 578 .migration_set_state = mlx5vf_pci_set_device_state, 596 579 .migration_get_state = mlx5vf_pci_get_device_state, 580 + .migration_get_data_size = mlx5vf_pci_get_data_size, 597 581 }; 598 582 599 583 static const struct vfio_log_ops mlx5vf_pci_log_ops = {
+2 -1
drivers/vfio/pci/vfio_pci_core.c
··· 2127 2127 2128 2128 if (vdev->vdev.mig_ops) { 2129 2129 if (!(vdev->vdev.mig_ops->migration_get_state && 2130 - vdev->vdev.mig_ops->migration_set_state) || 2130 + vdev->vdev.mig_ops->migration_set_state && 2131 + vdev->vdev.mig_ops->migration_get_data_size) || 2131 2132 !(vdev->vdev.migration_flags & VFIO_MIGRATION_STOP_COPY)) 2132 2133 return -EINVAL; 2133 2134 }
+32
drivers/vfio/vfio_main.c
··· 1242 1242 return 0; 1243 1243 } 1244 1244 1245 + static int 1246 + vfio_ioctl_device_feature_migration_data_size(struct vfio_device *device, 1247 + u32 flags, void __user *arg, 1248 + size_t argsz) 1249 + { 1250 + struct vfio_device_feature_mig_data_size data_size = {}; 1251 + unsigned long stop_copy_length; 1252 + int ret; 1253 + 1254 + if (!device->mig_ops) 1255 + return -ENOTTY; 1256 + 1257 + ret = vfio_check_feature(flags, argsz, VFIO_DEVICE_FEATURE_GET, 1258 + sizeof(data_size)); 1259 + if (ret != 1) 1260 + return ret; 1261 + 1262 + ret = device->mig_ops->migration_get_data_size(device, &stop_copy_length); 1263 + if (ret) 1264 + return ret; 1265 + 1266 + data_size.stop_copy_length = stop_copy_length; 1267 + if (copy_to_user(arg, &data_size, sizeof(data_size))) 1268 + return -EFAULT; 1269 + 1270 + return 0; 1271 + } 1272 + 1245 1273 static int vfio_ioctl_device_feature_migration(struct vfio_device *device, 1246 1274 u32 flags, void __user *arg, 1247 1275 size_t argsz) ··· 1495 1467 feature.argsz - minsz); 1496 1468 case VFIO_DEVICE_FEATURE_DMA_LOGGING_REPORT: 1497 1469 return vfio_ioctl_device_feature_logging_report( 1470 + device, feature.flags, arg->data, 1471 + feature.argsz - minsz); 1472 + case VFIO_DEVICE_FEATURE_MIG_DATA_SIZE: 1473 + return vfio_ioctl_device_feature_migration_data_size( 1498 1474 device, feature.flags, arg->data, 1499 1475 feature.argsz - minsz); 1500 1476 default:
+5
include/linux/vfio.h
··· 107 107 * @migration_get_state: Optional callback to get the migration state for 108 108 * devices that support migration. It's mandatory for 109 109 * VFIO_DEVICE_FEATURE_MIGRATION migration support. 110 + * @migration_get_data_size: Optional callback to get the estimated data 111 + * length that will be required to complete stop copy. It's mandatory for 112 + * VFIO_DEVICE_FEATURE_MIGRATION migration support. 110 113 */ 111 114 struct vfio_migration_ops { 112 115 struct file *(*migration_set_state)( ··· 117 114 enum vfio_device_mig_state new_state); 118 115 int (*migration_get_state)(struct vfio_device *device, 119 116 enum vfio_device_mig_state *curr_state); 117 + int (*migration_get_data_size)(struct vfio_device *device, 118 + unsigned long *stop_copy_length); 120 119 }; 121 120 122 121 /**
+13
include/uapi/linux/vfio.h
··· 1128 1128 1129 1129 #define VFIO_DEVICE_FEATURE_DMA_LOGGING_REPORT 8 1130 1130 1131 + /* 1132 + * Upon VFIO_DEVICE_FEATURE_GET read back the estimated data length that will 1133 + * be required to complete stop copy. 1134 + * 1135 + * Note: Can be called on each device state. 1136 + */ 1137 + 1138 + struct vfio_device_feature_mig_data_size { 1139 + __aligned_u64 stop_copy_length; 1140 + }; 1141 + 1142 + #define VFIO_DEVICE_FEATURE_MIG_DATA_SIZE 9 1143 + 1131 1144 /* -------- API for Type1 VFIO IOMMU -------- */ 1132 1145 1133 1146 /**