diff options
author | John Levon <john.levon@nutanix.com> | 2021-06-02 15:04:10 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-06-02 15:04:10 +0100 |
commit | b8234a75d9ec2c95cb889c0cef27927f34ad9cbc (patch) | |
tree | a2cd490a958e3b3c08595451c62f7e62108bebe2 | |
parent | 8ac2360a8aefbd2dd11c65f2b2e21565c36c0ee6 (diff) | |
download | libvfio-user-b8234a75d9ec2c95cb889c0cef27927f34ad9cbc.zip libvfio-user-b8234a75d9ec2c95cb889c0cef27927f34ad9cbc.tar.gz libvfio-user-b8234a75d9ec2c95cb889c0cef27927f34ad9cbc.tar.bz2 |
clean up migration register definitions (#550)
We should explicitly define the expected migration register contents for API
users who aren't using the callbacks. Clean up some related lint.
Signed-off-by: John Levon <john.levon@nutanix.com>
Reviewed-by: Thanos Makatos <thanos.makatos@nutanix.com>
-rw-r--r-- | include/libvfio-user.h | 67 | ||||
-rw-r--r-- | include/vfio-user.h | 49 | ||||
-rw-r--r-- | lib/migration.c | 14 | ||||
-rw-r--r-- | lib/migration_priv.h | 2 | ||||
-rw-r--r-- | samples/client.c | 22 | ||||
-rw-r--r-- | test/unit-tests.c | 3 |
6 files changed, 70 insertions, 87 deletions
diff --git a/include/libvfio-user.h b/include/libvfio-user.h index c9e8ca2..9c2628a 100644 --- a/include/libvfio-user.h +++ b/include/libvfio-user.h @@ -263,20 +263,19 @@ typedef ssize_t (vfu_region_access_cb_t)(vfu_ctx_t *vfu_ctx, char *buf, * Regions VFU_PCI_DEV_MIGR_REGION_IDX and VFU_GENERIC_DEV_MIGR_REG_IDX, * corresponding to the migration region, enable live migration support for * the device. The migration region must contain at the beginning the migration - * registers (struct vfio_device_migration_info defined in <linux/vfio.h>) and - * the remaining part of the region can be arbitrarily used by the device - * implementation. The region provided must have at least - * vfu_get_migr_register_area_size() bytes available at the start of the region - * (this size is guaranteed to be page-aligned). If mmap_areas is given, it - * must _not_ include this part of the region. + * registers (struct vfio_user_migration_info) and the remaining part of the + * region can be arbitrarily used by the device implementation. The region + * provided must have at least vfu_get_migr_register_area_size() bytes available + * at the start of the region (this size is guaranteed to be page-aligned). If + * mmap_areas is given, it must _not_ include this part of the region. * * libvfio-user offers two ways for the migration region to be used: * 1. natively: the device implementation must handle accesses to the * migration registers and migration data via the region callbacks. The * semantics of these registers are explained in <linux/vfio.h>. - * 2. via the vfu_migration_t callbacks: the device implementation registers - * a set of callbacks by calling vfu_setup_device_migration. The region's - * read/write callbacks are never called. + * 2. via the vfu_migration_callbacks_t callbacks: the device implementation + * registers a set of callbacks by calling vfu_setup_device_migration. + * The region's read/write callbacks are never called. * * @vfu_ctx: the libvfio-user context * @region_idx: region index @@ -300,13 +299,6 @@ vfu_setup_region(vfu_ctx_t *vfu_ctx, int region_idx, size_t size, struct iovec *mmap_areas, uint32_t nr_mmap_areas, int fd, uint64_t offset); -/* - * Returns the size of the area needed to hold the migration registers at the - * beginning of the migration region; guaranteed to be page aligned. - */ -size_t -vfu_get_migr_register_area_size(void); - typedef enum vfu_reset_type { /* * Client requested a device reset (for example, as part of a guest VM @@ -456,15 +448,6 @@ int vfu_setup_device_nr_irqs(vfu_ctx_t *vfu_ctx, enum vfu_dev_irq_type type, uint32_t count); -/* - * FIXME the names of migration callback functions are probably far too long, - * but for now it helps with the implementation. - */ -/** - * Migration callback function. - * @vfu_ctx: the libvfio-user context - */ -typedef int (vfu_migration_callback_t)(vfu_ctx_t *vfu_ctx); typedef enum { VFU_MIGR_STATE_STOP, @@ -474,7 +457,6 @@ typedef enum { VFU_MIGR_STATE_RESUME } vfu_migr_state_t; - #define VFU_MIGR_CALLBACKS_VERS 1 /* @@ -568,6 +550,39 @@ typedef struct { } vfu_migration_callbacks_t; + +#ifndef VFIO_DEVICE_STATE_STOP + +#define VFIO_DEVICE_STATE_STOP (0) +#define VFIO_DEVICE_STATE_RUNNING (1 << 0) +#define VFIO_DEVICE_STATE_SAVING (1 << 1) +#define VFIO_DEVICE_STATE_RESUMING (1 << 2) +#define VFIO_DEVICE_STATE_MASK ((1 << 3) - 1) + +#endif /* VFIO_DEVICE_STATE_STOP */ + +/* + * The currently defined migration registers; if using migration callbacks, + * these are handled internally by the library. + * + * This is analogous to struct vfio_device_migration_info. + */ +struct vfio_user_migration_info { + /* VFIO_DEVICE_STATE_* */ + uint32_t device_state; + uint32_t reserved; + uint64_t pending_bytes; + uint64_t data_offset; + uint64_t data_size; +}; + +/* + * Returns the size of the area needed to hold the migration registers at the + * beginning of the migration region; guaranteed to be page aligned. + */ +size_t +vfu_get_migr_register_area_size(void); + /** * vfu_setup_device_migration provides an abstraction over the migration * protocol: the user specifies a set of callbacks which are called in response diff --git a/include/vfio-user.h b/include/vfio-user.h index 71112ef..7be7cf7 100644 --- a/include/vfio-user.h +++ b/include/vfio-user.h @@ -159,9 +159,9 @@ struct vfio_user_irq_info { struct vfio_user_dirty_pages { uint32_t argsz; #ifndef VFIO_IOMMU_DIRTY_PAGES_FLAG_START -#define VFIO_IOMMU_DIRTY_PAGES_FLAG_START (1 << 0) -#define VFIO_IOMMU_DIRTY_PAGES_FLAG_STOP (1 << 1) -#define VFIO_IOMMU_DIRTY_PAGES_FLAG_GET_BITMAP (1 << 2) +#define VFIO_IOMMU_DIRTY_PAGES_FLAG_START (1 << 0) +#define VFIO_IOMMU_DIRTY_PAGES_FLAG_STOP (1 << 1) +#define VFIO_IOMMU_DIRTY_PAGES_FLAG_GET_BITMAP (1 << 2) #endif uint32_t flags; } __attribute__((packed)); @@ -173,45 +173,12 @@ struct vfio_user_bitmap_range { struct vfio_user_bitmap bitmap; } __attribute__((packed)); -#if LINUX_VERSION_CODE < KERNEL_VERSION(5,8,0) - -/* copied from <linux/vfio.h> */ - -#define VFIO_DEVICE_STATE_STOP (0) -#define VFIO_DEVICE_STATE_RUNNING (1 << 0) -#define VFIO_DEVICE_STATE_SAVING (1 << 1) -#define VFIO_DEVICE_STATE_RESUMING (1 << 2) -#define VFIO_DEVICE_STATE_MASK (VFIO_DEVICE_STATE_RUNNING | \ - VFIO_DEVICE_STATE_SAVING | \ - VFIO_DEVICE_STATE_RESUMING) - -#define VFIO_DEVICE_STATE_VALID(state) \ - (state & VFIO_DEVICE_STATE_RESUMING ? \ - (state & VFIO_DEVICE_STATE_MASK) == VFIO_DEVICE_STATE_RESUMING : 1) - -#define VFIO_DEVICE_STATE_IS_ERROR(state) \ - ((state & VFIO_DEVICE_STATE_MASK) == (VFIO_DEVICE_STATE_SAVING | \ - VFIO_DEVICE_STATE_RESUMING)) - -#define VFIO_DEVICE_STATE_SET_ERROR(state) \ - ((state & ~VFIO_DEVICE_STATE_MASK) | VFIO_DEVICE_SATE_SAVING | \ - VFIO_DEVICE_STATE_RESUMING) - -/* RHEL kernels have some of it backported */ -#ifndef VFIO_REGION_TYPE_MIGRATION /* not a RHEL kernel */ -#define VFIO_REGION_TYPE_MIGRATION (3) -#define VFIO_REGION_SUBTYPE_MIGRATION (1) - -struct vfio_device_migration_info { - __u32 device_state; /* VFIO device state */ - __u32 reserved; - __u64 pending_bytes; - __u64 data_offset; - __u64 data_size; -}; -#endif /* not a RHEL kernel */ +#ifndef VFIO_REGION_TYPE_MIGRATION + +#define VFIO_REGION_TYPE_MIGRATION (3) +#define VFIO_REGION_SUBTYPE_MIGRATION (1) -#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(5,8,0) */ +#endif /* VFIO_REGION_TYPE_MIGRATION */ #ifdef __cplusplus } diff --git a/lib/migration.c b/lib/migration.c index f690959..c1fe0b5 100644 --- a/lib/migration.c +++ b/lib/migration.c @@ -48,7 +48,7 @@ MOCK_DEFINE(vfio_migr_state_transition_is_valid)(uint32_t from, uint32_t to) EXPORT size_t vfu_get_migr_register_area_size(void) { - return ROUND_UP(sizeof(struct vfio_device_migration_info), + return ROUND_UP(sizeof(struct vfio_user_migration_info), sysconf(_SC_PAGE_SIZE)); } @@ -405,7 +405,7 @@ MOCK_DEFINE(migration_region_access_registers)(vfu_ctx_t *vfu_ctx, char *buf, assert(migr != NULL); switch (pos) { - case offsetof(struct vfio_device_migration_info, device_state): + case offsetof(struct vfio_user_migration_info, device_state): if (count != sizeof(migr->info.device_state)) { vfu_log(vfu_ctx, LOG_ERR, "bad device_state access size %ld", count); @@ -417,7 +417,7 @@ MOCK_DEFINE(migration_region_access_registers)(vfu_ctx_t *vfu_ctx, char *buf, return 0; } old_device_state = migr->info.device_state; - ret = handle_device_state(vfu_ctx, migr, *device_state , true); + ret = handle_device_state(vfu_ctx, migr, *device_state, true); if (ret == 0) { vfu_log(vfu_ctx, LOG_DEBUG, "migration: transition from state %s to state %s", @@ -430,7 +430,7 @@ MOCK_DEFINE(migration_region_access_registers)(vfu_ctx_t *vfu_ctx, char *buf, migr_states[*device_state].name); } break; - case offsetof(struct vfio_device_migration_info, pending_bytes): + case offsetof(struct vfio_user_migration_info, pending_bytes): if (count != sizeof(migr->info.pending_bytes)) { vfu_log(vfu_ctx, LOG_ERR, "bad pending_bytes access size %ld", count); @@ -438,7 +438,7 @@ MOCK_DEFINE(migration_region_access_registers)(vfu_ctx_t *vfu_ctx, char *buf, } ret = handle_pending_bytes(vfu_ctx, migr, (uint64_t *)buf, is_write); break; - case offsetof(struct vfio_device_migration_info, data_offset): + case offsetof(struct vfio_user_migration_info, data_offset): if (count != sizeof(migr->info.data_offset)) { vfu_log(vfu_ctx, LOG_ERR, "bad data_offset access size %ld", count); @@ -446,7 +446,7 @@ MOCK_DEFINE(migration_region_access_registers)(vfu_ctx_t *vfu_ctx, char *buf, } ret = handle_data_offset(vfu_ctx, migr, (uint64_t *)buf, is_write); break; - case offsetof(struct vfio_device_migration_info, data_size): + case offsetof(struct vfio_user_migration_info, data_size): if (count != sizeof(migr->info.data_size)) { vfu_log(vfu_ctx, LOG_ERR, "bad data_size access size %ld", count); @@ -478,7 +478,7 @@ migration_region_access(vfu_ctx_t *vfu_ctx, char *buf, size_t count, * in that case. */ - if (pos + count <= sizeof(struct vfio_device_migration_info)) { + if (pos + count <= sizeof(struct vfio_user_migration_info)) { ret = migration_region_access_registers(vfu_ctx, buf, count, pos, is_write); if (ret != 0) { diff --git a/lib/migration_priv.h b/lib/migration_priv.h index 1a0496f..340d507 100644 --- a/lib/migration_priv.h +++ b/lib/migration_priv.h @@ -48,7 +48,7 @@ struct migration { * TODO if the user provides an FD then should mmap it and use the migration * registers in the file */ - struct vfio_device_migration_info info; + struct vfio_user_migration_info info; size_t pgsize; vfu_migration_callbacks_t callbacks; uint64_t data_offset; diff --git a/samples/client.c b/samples/client.c index 8595f2e..12eee21 100644 --- a/samples/client.c +++ b/samples/client.c @@ -716,7 +716,7 @@ do_migrate(int sock, size_t nr_iters, struct iovec *migr_iter) /* XXX read pending_bytes */ ret = access_region(sock, VFU_PCI_DEV_MIGR_REGION_IDX, false, - offsetof(struct vfio_device_migration_info, pending_bytes), + offsetof(struct vfio_user_migration_info, pending_bytes), &pending_bytes, sizeof(pending_bytes)); if (ret < 0) { err(EXIT_FAILURE, "failed to read pending_bytes"); @@ -726,14 +726,14 @@ do_migrate(int sock, size_t nr_iters, struct iovec *migr_iter) /* XXX read data_offset and data_size */ ret = access_region(sock, VFU_PCI_DEV_MIGR_REGION_IDX, false, - offsetof(struct vfio_device_migration_info, data_offset), + offsetof(struct vfio_user_migration_info, data_offset), &data_offset, sizeof(data_offset)); if (ret < 0) { err(EXIT_FAILURE, "failed to read data_offset"); } ret = access_region(sock, VFU_PCI_DEV_MIGR_REGION_IDX, false, - offsetof(struct vfio_device_migration_info, data_size), + offsetof(struct vfio_user_migration_info, data_size), &data_size, sizeof(data_size)); if (ret < 0) { err(EXIT_FAILURE, "failed to read data_size"); @@ -760,7 +760,7 @@ do_migrate(int sock, size_t nr_iters, struct iovec *migr_iter) * migration data have been consumed. */ ret = access_region(sock, VFU_PCI_DEV_MIGR_REGION_IDX, false, - offsetof(struct vfio_device_migration_info, pending_bytes), + offsetof(struct vfio_user_migration_info, pending_bytes), &pending_bytes, sizeof(pending_bytes)); if (ret < 0) { err(EXIT_FAILURE, "failed to read pending_bytes"); @@ -843,7 +843,7 @@ migrate_from(int sock, size_t *nr_iters, struct iovec **migr_iters, */ device_state = VFIO_DEVICE_STATE_SAVING | VFIO_DEVICE_STATE_RUNNING; ret = access_region(sock, VFU_PCI_DEV_MIGR_REGION_IDX, true, - offsetof(struct vfio_device_migration_info, device_state), + offsetof(struct vfio_user_migration_info, device_state), &device_state, sizeof(device_state)); if (ret < 0) { err(EXIT_FAILURE, "failed to write to device state"); @@ -864,7 +864,7 @@ migrate_from(int sock, size_t *nr_iters, struct iovec **migr_iters, device_state = VFIO_DEVICE_STATE_SAVING; ret = access_region(sock, VFU_PCI_DEV_MIGR_REGION_IDX, true, - offsetof(struct vfio_device_migration_info, device_state), + offsetof(struct vfio_user_migration_info, device_state), &device_state, sizeof(device_state)); if (ret < 0) { err(EXIT_FAILURE, "failed to write to device state"); @@ -880,7 +880,7 @@ migrate_from(int sock, size_t *nr_iters, struct iovec **migr_iters, /* XXX read device state, migration must have finished now */ device_state = VFIO_DEVICE_STATE_STOP; ret = access_region(sock, VFU_PCI_DEV_MIGR_REGION_IDX, true, - offsetof(struct vfio_device_migration_info, device_state), + offsetof(struct vfio_user_migration_info, device_state), &device_state, sizeof(device_state)); if (ret < 0) { err(EXIT_FAILURE, "failed to write to device state"); @@ -951,7 +951,7 @@ migrate_to(char *old_sock_path, int *server_max_fds, /* XXX set device state to resuming */ ret = access_region(sock, VFU_PCI_DEV_MIGR_REGION_IDX, true, - offsetof(struct vfio_device_migration_info, device_state), + offsetof(struct vfio_user_migration_info, device_state), &device_state, sizeof(device_state)); if (ret < 0) { err(EXIT_FAILURE, "failed to set device state to resuming"); @@ -961,7 +961,7 @@ migrate_to(char *old_sock_path, int *server_max_fds, /* XXX read data offset */ ret = access_region(sock, VFU_PCI_DEV_MIGR_REGION_IDX, false, - offsetof(struct vfio_device_migration_info, data_offset), + offsetof(struct vfio_user_migration_info, data_offset), &data_offset, sizeof(data_offset)); if (ret < 0) { err(EXIT_FAILURE, "failed to read migration data offset"); @@ -985,7 +985,7 @@ migrate_to(char *old_sock_path, int *server_max_fds, /* XXX write data_size */ data_len = migr_iters[i].iov_len; ret = access_region(sock, VFU_PCI_DEV_MIGR_REGION_IDX, true, - offsetof(struct vfio_device_migration_info, data_size), + offsetof(struct vfio_user_migration_info, data_size), &data_len, sizeof(data_len)); if (ret < 0) { err(EXIT_FAILURE, "failed to write migration data size"); @@ -995,7 +995,7 @@ migrate_to(char *old_sock_path, int *server_max_fds, /* XXX set device state to running */ device_state = VFIO_DEVICE_STATE_RUNNING; ret = access_region(sock, VFU_PCI_DEV_MIGR_REGION_IDX, true, - offsetof(struct vfio_device_migration_info, device_state), + offsetof(struct vfio_user_migration_info, device_state), &device_state, sizeof(device_state)); if (ret < 0) { err(EXIT_FAILURE, "failed to set device state to running"); diff --git a/test/unit-tests.c b/test/unit-tests.c index d334244..9e3fe00 100644 --- a/test/unit-tests.c +++ b/test/unit-tests.c @@ -541,7 +541,8 @@ setup_test_setup_migration_region(void **state) if (p->v == NULL) { return -1; } - p->rs = ROUND_UP(sizeof(struct vfio_device_migration_info), sysconf(_SC_PAGE_SIZE)); + p->rs = ROUND_UP(sizeof(struct vfio_user_migration_info), + sysconf(_SC_PAGE_SIZE)); p->ds = sysconf(_SC_PAGE_SIZE); p->s = p->rs + p->ds; *state = p; |