diff options
-rw-r--r-- | lib/migration.c | 6 | ||||
-rw-r--r-- | lib/migration.h | 2 | ||||
-rw-r--r-- | lib/muser.h | 18 | ||||
-rw-r--r-- | lib/muser_ctx.c | 128 | ||||
-rw-r--r-- | lib/muser_priv.h | 4 | ||||
-rw-r--r-- | samples/client.c | 70 | ||||
-rw-r--r-- | samples/server.c | 28 |
7 files changed, 145 insertions, 111 deletions
diff --git a/lib/migration.c b/lib/migration.c index a43a483..f513938 100644 --- a/lib/migration.c +++ b/lib/migration.c @@ -75,11 +75,11 @@ static const __u32 migr_states[VFIO_DEVICE_STATE_MASK] = { }; struct migration* -init_migration(size_t size, const lm_migration_callbacks_t * const migr_callbacks) +init_migration(const lm_migration_t * const lm_migr) { struct migration *migr; - if (size < sizeof(struct vfio_device_migration_info)) { + if (lm_migr->size < sizeof(struct vfio_device_migration_info)) { errno = EINVAL; return NULL; } @@ -99,7 +99,7 @@ init_migration(size_t size, const lm_migration_callbacks_t * const migr_callback /* FIXME this should be done in lm_ctx_run or poll */ migr->info.device_state = VFIO_DEVICE_STATE_RUNNING; - migr->callbacks = *migr_callbacks; + migr->callbacks = lm_migr->callbacks; if (migr->callbacks.transition == NULL || migr->callbacks.get_pending_bytes == NULL || migr->callbacks.prepare_data == NULL || diff --git a/lib/migration.h b/lib/migration.h index 5407d47..2ef22eb 100644 --- a/lib/migration.h +++ b/lib/migration.h @@ -33,7 +33,7 @@ #include "muser.h" struct migration* -init_migration(size_t size, const lm_migration_callbacks_t * const migr_callbacks); +init_migration(const lm_migration_t * const lm_migr); ssize_t handle_migration_region_access(lm_ctx_t *lm_ctx, void *pvt, diff --git a/lib/muser.h b/lib/muser.h index b9a8d08..a71337d 100644 --- a/lib/muser.h +++ b/lib/muser.h @@ -165,15 +165,7 @@ enum { LM_DEV_ROM_REG_IDX, LM_DEV_CFG_REG_IDX, LM_DEV_VGA_REG_IDX, - /* - * FIXME this really belong here, but simplifies implementation for now. A - * migration region can exist for non-PCI devices (can its index be - * anything?). In any case, we should allow the user to define custom regions - * at will, by fixing the migration region in that position we don't allow - * this. - */ - LM_DEV_MIGRATION_REG_IDX, - LM_DEV_NUM_REGS = 10, /* TODO rename to LM_DEV_NUM_PCI_REGS */ + LM_DEV_NUM_REGS, /* TODO rename to LM_DEV_NUM_PCI_REGS */ }; typedef struct { @@ -316,6 +308,12 @@ typedef struct { } lm_migration_callbacks_t; +typedef struct { + size_t size; + lm_migration_callbacks_t callbacks; + struct lm_sparse_mmap_areas *mmap_areas; +} lm_migration_t; + /** * Device information structure, used to create the lm_ctx. * To be filled and passed to lm_ctx_create() @@ -382,7 +380,7 @@ typedef struct { int nr_caps; lm_cap_t **caps; - lm_migration_callbacks_t migration_callbacks; + lm_migration_t migration; } lm_dev_info_t; diff --git a/lib/muser_ctx.c b/lib/muser_ctx.c index 7b19a4b..bf5dbb5 100644 --- a/lib/muser_ctx.c +++ b/lib/muser_ctx.c @@ -356,12 +356,12 @@ dev_get_irqinfo(lm_ctx_t *lm_ctx, struct vfio_irq_info *irq_info_in, } static size_t -get_vfio_caps_size(uint32_t reg_index, struct lm_sparse_mmap_areas *m) +get_vfio_caps_size(bool is_migr_reg, struct lm_sparse_mmap_areas *m) { size_t type_size = 0; size_t sparse_size = 0; - if (reg_index == LM_DEV_MIGRATION_REG_IDX) { + if (is_migr_reg) { type_size = sizeof(struct vfio_region_info_cap_type); } @@ -379,7 +379,7 @@ get_vfio_caps_size(uint32_t reg_index, struct lm_sparse_mmap_areas *m) * points accordingly. */ static void -dev_get_caps(lm_ctx_t *lm_ctx, lm_reg_info_t *lm_reg, int reg_index, +dev_get_caps(lm_ctx_t *lm_ctx, lm_reg_info_t *lm_reg, bool is_migr_reg, struct vfio_region_info *vfio_reg) { struct vfio_info_cap_header *header; @@ -392,7 +392,7 @@ dev_get_caps(lm_ctx_t *lm_ctx, lm_reg_info_t *lm_reg, int reg_index, header = (struct vfio_info_cap_header*)(vfio_reg + 1); - if (reg_index == LM_DEV_MIGRATION_REG_IDX) { + if (is_migr_reg) { type = (struct vfio_region_info_cap_type*)header; type->header.id = VFIO_REGION_INFO_CAP_TYPE; type->header.version = 1; @@ -475,6 +475,12 @@ dump_buffer(const char *prefix, const char *buf, uint32_t count) #define dump_buffer(prefix, buf, count) #endif +static bool +is_migr_reg(lm_ctx_t *lm_ctx, int index) +{ + return &lm_ctx->reg_info[index] == lm_ctx->migr_reg; +} + static long dev_get_reginfo(lm_ctx_t *lm_ctx, uint32_t index, struct vfio_region_info **vfio_reg) @@ -488,12 +494,12 @@ dev_get_reginfo(lm_ctx_t *lm_ctx, uint32_t index, lm_reg = &lm_ctx->reg_info[index]; - if (index >= LM_DEV_NUM_REGS) { + if (index >= lm_ctx->nr_regions) { lm_log(lm_ctx, LM_DBG, "bad region index %d", index); return -EINVAL; } - caps_size = get_vfio_caps_size(index, lm_reg->mmap_areas); + caps_size = get_vfio_caps_size(is_migr_reg(lm_ctx, index), lm_reg->mmap_areas); argsz = caps_size + sizeof(struct vfio_region_info); *vfio_reg = calloc(1, argsz); if (!*vfio_reg) { @@ -507,7 +513,7 @@ dev_get_reginfo(lm_ctx_t *lm_ctx, uint32_t index, (*vfio_reg)->size = lm_reg->size; if (caps_size > 0) { - dev_get_caps(lm_ctx, lm_reg, index, *vfio_reg); + dev_get_caps(lm_ctx, lm_reg, is_migr_reg(lm_ctx, index), *vfio_reg); } lm_log(lm_ctx, LM_DBG, "region_info[%d] offset %#lx flags %#x size %llu " @@ -579,12 +585,12 @@ do_access(lm_ctx_t *lm_ctx, char *buf, uint8_t count, uint64_t pos, bool is_writ idx = lm_get_region(pos, count, &offset); if (idx < 0) { - lm_log(lm_ctx, LM_ERR, "invalid region %d\n", idx); + lm_log(lm_ctx, LM_ERR, "invalid region %d", idx); return idx; } - if (idx < 0 || idx >= LM_DEV_NUM_REGS) { - lm_log(lm_ctx, LM_ERR, "bad region %d\n", idx); + if (idx < 0 || idx >= (int)lm_ctx->nr_regions) { + lm_log(lm_ctx, LM_ERR, "bad region %d", idx); return -EINVAL; } @@ -593,11 +599,11 @@ do_access(lm_ctx_t *lm_ctx, char *buf, uint8_t count, uint64_t pos, bool is_writ is_write); } - if (idx == LM_DEV_MIGRATION_REG_IDX) { - if (offset + count > lm_ctx->reg_info[LM_DEV_MIGRATION_REG_IDX].size) { + if (is_migr_reg(lm_ctx, idx)) { + if (offset + count > lm_ctx->reg_info[idx].size) { lm_log(lm_ctx, LM_ERR, "read %#x-%#x past end of migration region (%#lx)", offset, offset + count - 1, - lm_ctx->reg_info[LM_DEV_MIGRATION_REG_IDX].size); + lm_ctx->reg_info[idx].size); return -EINVAL; } return handle_migration_region_access(lm_ctx, lm_ctx->pvt, @@ -616,7 +622,7 @@ do_access(lm_ctx_t *lm_ctx, char *buf, uint8_t count, uint64_t pos, bool is_writ is_write); } - lm_log(lm_ctx, LM_ERR, "no callback for region %d\n", idx); + lm_log(lm_ctx, LM_ERR, "no callback for region %d", idx); return -EINVAL; } @@ -754,7 +760,7 @@ handle_device_get_info(lm_ctx_t *lm_ctx, uint32_t size, dev_info->argsz = sizeof *dev_info; dev_info->flags = VFIO_DEVICE_FLAGS_PCI | VFIO_DEVICE_FLAGS_RESET; - dev_info->num_regions = LM_DEV_NUM_REGS; + dev_info->num_regions = lm_ctx->nr_regions; dev_info->num_irqs = LM_DEV_NUM_IRQS; lm_log(lm_ctx, LM_DBG, "sent devinfo flags %#x, num_regions %d, num_irqs" @@ -914,14 +920,14 @@ validate_region_access(lm_ctx_t *lm_ctx, uint32_t size, uint16_t cmd, return -EINVAL; } - if (region_access->region >= LM_DEV_NUM_REGS || region_access->count <= 0 ) { + if (region_access->region > lm_ctx->nr_regions || region_access->count <= 0) { lm_log(lm_ctx, LM_ERR, "bad region %d and/or count %d", region_access->region, region_access->count); return -EINVAL; } if (device_is_stopped_and_copying(lm_ctx->migration) && - region_access->region != LM_DEV_MIGRATION_REG_IDX) { + !is_migr_reg(lm_ctx, region_access->region)) { lm_log(lm_ctx, LM_ERR, "cannot access region %d while device in stop-and-copy state", region_access->region); @@ -1423,12 +1429,14 @@ lm_irq_message(lm_ctx_t *lm_ctx, uint32_t subindex) } static void -free_sparse_mmap_areas(lm_reg_info_t *reg_info) +free_sparse_mmap_areas(lm_ctx_t *lm_ctx) { int i; - for (i = 0; i < LM_DEV_NUM_REGS; i++) - free(reg_info[i].mmap_areas); + assert(lm_ctx != NULL); + + for (i = 0; i < (int)lm_ctx->nr_regions; i++) + free(lm_ctx->reg_info[i].mmap_areas); } void @@ -1445,44 +1453,55 @@ lm_ctx_destroy(lm_ctx_t *lm_ctx) if (lm_ctx->dma != NULL) { dma_controller_destroy(lm_ctx->dma); } - free_sparse_mmap_areas(lm_ctx->reg_info); + free_sparse_mmap_areas(lm_ctx); free(lm_ctx->caps); free(lm_ctx->migration); free(lm_ctx); // FIXME: Maybe close any open irq efds? Unmap stuff? } +struct lm_sparse_mmap_areas* +copy_sparse_mmap_area(struct lm_sparse_mmap_areas *src) +{ + struct lm_sparse_mmap_areas *dest; + size_t size; + + assert(src != NULL); + + size = sizeof(*dest) + (src->nr_mmap_areas * sizeof(struct lm_mmap_area)); + dest = calloc(1, size); + if (dest != NULL) { + memcpy(dest, src, size); + } + return dest; +} + static int copy_sparse_mmap_areas(lm_reg_info_t *dst, const lm_reg_info_t *src) { - struct lm_sparse_mmap_areas *mmap_areas; - int nr_mmap_areas; - size_t size; int i; + assert(dst != NULL); + assert(src != NULL); + for (i = 0; i < LM_DEV_NUM_REGS; i++) { if (!src[i].mmap_areas) continue; - - nr_mmap_areas = src[i].mmap_areas->nr_mmap_areas; - size = sizeof(*mmap_areas) + (nr_mmap_areas * sizeof(struct lm_mmap_area)); - mmap_areas = calloc(1, size); - if (!mmap_areas) + dst[i].mmap_areas = copy_sparse_mmap_area(src[i].mmap_areas); + if (dst[i].mmap_areas == NULL) { return -ENOMEM; - - memcpy(mmap_areas, src[i].mmap_areas, size); - dst[i].mmap_areas = mmap_areas; + } } return 0; } static int -pci_config_setup(lm_ctx_t *lm_ctx, const lm_dev_info_t *dev_info) +pci_config_setup(lm_ctx_t *lm_ctx, const lm_dev_info_t *dev_info, + const lm_migration_t *migr) { lm_reg_info_t *cfg_reg; const lm_reg_info_t zero_reg = { 0 }; - lm_reg_info_t *migr_reg; int i; assert(lm_ctx != NULL); @@ -1528,7 +1547,20 @@ pci_config_setup(lm_ctx_t *lm_ctx, const lm_dev_info_t *dev_info) } } - // Initialise capabilities. + if (migr != NULL) { + /* FIXME hacky, find a more robust way to allocate a region index */ + lm_ctx->migr_reg = &lm_ctx->reg_info[(lm_ctx->nr_regions - 1)]; + lm_ctx->migr_reg->flags = LM_REG_FLAG_RW; + lm_ctx->migr_reg->size = sizeof(struct vfio_device_migration_info) + dev_info->migration.size; + /* FIXME is there are sparse areas need to setup flags accordingly */ + lm_ctx->migr_reg->mmap_areas = copy_sparse_mmap_area(migr->mmap_areas); + lm_ctx->migration = init_migration(&dev_info->migration); + if (lm_ctx->migration == NULL) { + goto err; + } + } + + // Initialise PCI capabilities. if (dev_info->nr_caps > 0) { lm_ctx->caps = caps_create(lm_ctx, dev_info->caps, dev_info->nr_caps); if (lm_ctx->caps == NULL) { @@ -1541,18 +1573,6 @@ pci_config_setup(lm_ctx_t *lm_ctx, const lm_dev_info_t *dev_info) lm_ctx->pci_config_space->hdr.cap = PCI_STD_HEADER_SIZEOF; } - /* - * Check the migration region. - */ - migr_reg = &lm_ctx->reg_info[LM_DEV_MIGRATION_REG_IDX]; - if (migr_reg->size > 0) { - lm_ctx->migration = init_migration(migr_reg->size, - &dev_info->migration_callbacks); - if (lm_ctx->migration == NULL) { - goto err; - } - } - return 0; err: @@ -1656,6 +1676,16 @@ lm_ctx_create(const lm_dev_info_t *dev_info) goto out; } + lm_ctx->nr_regions = LM_DEV_NUM_REGS; + if (dev_info->migration.size > 0) { + lm_ctx->nr_regions += 1; + } + lm_ctx->reg_info = calloc(lm_ctx->nr_regions, sizeof *lm_ctx->reg_info); + if (lm_ctx->reg_info == NULL) { + err = -ENOMEM; + goto out; + } + // Bounce the provided pci_info into the context. pci_info_bounce(lm_ctx, &dev_info->pci_info); @@ -1664,12 +1694,12 @@ lm_ctx_create(const lm_dev_info_t *dev_info) * fails then we try to free reg_info->mmap_areas, which is wrong because * this is a user pointer. */ - for (i = 0; i < ARRAY_SIZE(lm_ctx->reg_info); i++) { + for (i = 0; i < lm_ctx->nr_regions; i++) { lm_ctx->reg_info[i].mmap_areas = NULL; } // Setup the PCI config space for this context. - err = pci_config_setup(lm_ctx, dev_info); + err = pci_config_setup(lm_ctx, dev_info, &dev_info->migration); if (err != 0) { goto out; } diff --git a/lib/muser_priv.h b/lib/muser_priv.h index aa528a7..e469895 100644 --- a/lib/muser_priv.h +++ b/lib/muser_priv.h @@ -75,7 +75,8 @@ struct lm_ctx { lm_log_lvl_t log_lvl; lm_log_fn_t *log; uint32_t irq_count[LM_DEV_NUM_IRQS]; - lm_reg_info_t reg_info[LM_DEV_NUM_REGS]; + size_t nr_regions; + lm_reg_info_t *reg_info; lm_pci_config_space_t *pci_config_space; struct transport_ops *trans; struct caps *caps; @@ -90,6 +91,7 @@ struct lm_ctx { int client_max_fds; + lm_reg_info_t *migr_reg; struct migration *migration; lm_irqs_t irqs; /* XXX must be last */ diff --git a/samples/client.c b/samples/client.c index 1c3a491..21630ff 100644 --- a/samples/client.c +++ b/samples/client.c @@ -198,7 +198,8 @@ send_device_reset(int sock) } } -static void +/* returns whether a VFIO migration capability is found */ +static bool get_region_vfio_caps(int sock, size_t cap_sz) { struct vfio_info_cap_header *header, *_header; @@ -206,6 +207,7 @@ get_region_vfio_caps(int sock, size_t cap_sz) struct vfio_region_info_cap_sparse_mmap *sparse; unsigned int i; ssize_t ret; + bool migr = false; header = _header = calloc(cap_sz, 1); if (header == NULL) { @@ -236,6 +238,7 @@ get_region_vfio_caps(int sock, size_t cap_sz) errx(EXIT_FAILURE, "bad region type %d/%d", type->type, type->subtype); } + migr = true; printf("migration region\n"); break; default: @@ -247,15 +250,19 @@ get_region_vfio_caps(int sock, size_t cap_sz) header = (struct vfio_info_cap_header*)((char*)header + header->next - sizeof(struct vfio_region_info)); } free(_header); + return migr; } -static void +/* + * Returns the index of the migration region if found, -1 otherwise. + */ +static int get_device_region_info(int sock, struct vfio_device_info *client_dev_info) { struct vfio_region_info region_info; uint16_t msg_id = 0; size_t cap_sz; - int ret; + int ret, migr_reg_index = -1; unsigned int i; msg_id = 1; @@ -279,9 +286,13 @@ get_device_region_info(int sock, struct vfio_device_info *client_dev_info) "cap_sz %lu\n", __func__, i, region_info.offset, region_info.flags, region_info.size, cap_sz); if (cap_sz) { - get_region_vfio_caps(sock, cap_sz); + if (get_region_vfio_caps(sock, cap_sz)) { + assert(migr_reg_index == -1); + migr_reg_index = i; + } } } + return migr_reg_index; } static void @@ -299,11 +310,6 @@ get_device_info(int sock, struct vfio_device_info *dev_info) errx(EXIT_FAILURE, "failed to get device info: %s", strerror(-ret)); } - if (dev_info->num_regions != 10) { - errx(EXIT_FAILURE, "bad number of device regions %d", - dev_info->num_regions); - } - printf("devinfo: flags %#x, num_regions %d, num_irqs %d\n", dev_info->flags, dev_info->num_regions, dev_info->num_irqs); } @@ -649,13 +655,13 @@ usage(char *path) { } static void -migrate_from(int sock, void **data, __u64 *len) +migrate_from(int sock, int migr_reg_index, void **data, __u64 *len) { __u32 device_state = VFIO_DEVICE_STATE_SAVING; __u64 pending_bytes, data_offset, data_size; /* XXX set device state to stop-and-copy */ - int ret = access_region(sock, LM_DEV_MIGRATION_REG_IDX, true, + int ret = access_region(sock, migr_reg_index, true, offsetof(struct vfio_device_migration_info, device_state), &device_state, sizeof(device_state)); if (ret < 0) { @@ -664,7 +670,7 @@ migrate_from(int sock, void **data, __u64 *len) } /* XXX read pending_bytes */ - ret = access_region(sock, LM_DEV_MIGRATION_REG_IDX, false, + ret = access_region(sock, migr_reg_index, false, offsetof(struct vfio_device_migration_info, pending_bytes), &pending_bytes, sizeof pending_bytes); if (ret < 0) { @@ -690,7 +696,7 @@ migrate_from(int sock, void **data, __u64 *len) while (pending_bytes > 0) { /* XXX read data_offset and data_size */ - ret = access_region(sock, LM_DEV_MIGRATION_REG_IDX, false, + ret = access_region(sock, migr_reg_index, false, offsetof(struct vfio_device_migration_info, data_offset), &data_offset, sizeof data_offset); if (ret < 0) { @@ -698,7 +704,7 @@ migrate_from(int sock, void **data, __u64 *len) strerror(-ret)); } - ret = access_region(sock, LM_DEV_MIGRATION_REG_IDX, false, + ret = access_region(sock, migr_reg_index, false, offsetof(struct vfio_device_migration_info, data_size), &data_size, sizeof data_size); if (ret < 0) { @@ -709,7 +715,7 @@ migrate_from(int sock, void **data, __u64 *len) assert(data_offset - sizeof(struct vfio_device_migration_info) + data_size <= *len); /* XXX read migration data */ - ret = access_region(sock, LM_DEV_MIGRATION_REG_IDX, false, data_offset, + ret = access_region(sock, migr_reg_index, false, data_offset, (char*)*data + data_offset - sizeof(struct vfio_device_migration_info), data_size); if (ret < 0) { @@ -723,7 +729,7 @@ migrate_from(int sock, void **data, __u64 *len) * XXX read pending_bytes again to indicate to the sever that the * migration data have been consumed. */ - ret = access_region(sock, LM_DEV_MIGRATION_REG_IDX, false, + ret = access_region(sock, migr_reg_index, false, offsetof(struct vfio_device_migration_info, pending_bytes), &pending_bytes, sizeof pending_bytes); if (ret < 0) { @@ -734,7 +740,7 @@ migrate_from(int sock, void **data, __u64 *len) /* XXX read device state, migration must have finished now */ device_state = VFIO_DEVICE_STATE_STOP; - ret = access_region(sock, LM_DEV_MIGRATION_REG_IDX, true, + ret = access_region(sock, migr_reg_index, true, offsetof(struct vfio_device_migration_info, device_state), &device_state, sizeof(device_state)); if (ret < 0) { @@ -746,7 +752,7 @@ migrate_from(int sock, void **data, __u64 *len) static int migrate_to(char *old_sock_path, int client_max_fds, int *server_max_fds, size_t *pgsize, void *migr_data, __u64 migr_data_len, - char *path_to_server) + char *path_to_server, int migr_reg_index) { int ret, sock; char *sock_path; @@ -797,18 +803,18 @@ migrate_to(char *old_sock_path, int client_max_fds, int *server_max_fds, negotiate(sock, client_max_fds, server_max_fds, pgsize); /* XXX set device state to resuming */ - ret = access_region(sock, LM_DEV_MIGRATION_REG_IDX, true, - offsetof(struct vfio_device_migration_info, device_state), - &device_state, sizeof(device_state)); + ret = access_region(sock, migr_reg_index, true, + offsetof(struct vfio_device_migration_info, device_state), + &device_state, sizeof(device_state)); if (ret < 0) { errx(EXIT_FAILURE, "failed to set device state to resuming: %s", strerror(-ret)); } /* XXX read data offset */ - ret = access_region(sock, LM_DEV_MIGRATION_REG_IDX, false, - offsetof(struct vfio_device_migration_info, data_offset), - &data_offset, sizeof(data_offset)); + ret = access_region(sock, migr_reg_index, false, + offsetof(struct vfio_device_migration_info, data_offset), + &data_offset, sizeof(data_offset)); if (ret < 0) { errx(EXIT_FAILURE, "failed to read data offset: %s", strerror(-ret)); } @@ -819,7 +825,7 @@ migrate_to(char *old_sock_path, int client_max_fds, int *server_max_fds, * TODO write half of migration data via regular write and other half via * memopy map. */ - ret = access_region(sock, LM_DEV_MIGRATION_REG_IDX, true, + ret = access_region(sock, migr_reg_index, true, data_offset, migr_data, migr_data_len); if (ret < 0) { errx(EXIT_FAILURE, "failed to write migration data: %s", @@ -827,7 +833,7 @@ migrate_to(char *old_sock_path, int client_max_fds, int *server_max_fds, } /* XXX write data_size */ - ret = access_region(sock, LM_DEV_MIGRATION_REG_IDX, true, + ret = access_region(sock, migr_reg_index, true, offsetof(struct vfio_device_migration_info, data_size), &migr_data_len, sizeof migr_data_len); if (ret < 0) { @@ -836,7 +842,7 @@ migrate_to(char *old_sock_path, int client_max_fds, int *server_max_fds, /* XXX set device state to running */ device_state = VFIO_DEVICE_STATE_RUNNING; - ret = access_region(sock, LM_DEV_MIGRATION_REG_IDX, true, + ret = access_region(sock, migr_reg_index, true, offsetof(struct vfio_device_migration_info, device_state), &device_state, sizeof(device_state)); if (ret < 0) { @@ -885,6 +891,7 @@ int main(int argc, char *argv[]) __u64 migr_data_len; char *path_to_server = NULL; lm_pci_hdr_t config_space; + int migr_reg_index; while ((opt = getopt(argc, argv, "h")) != -1) { switch (opt) { @@ -923,7 +930,10 @@ int main(int argc, char *argv[]) get_device_info(sock, &client_dev_info); /* XXX VFIO_USER_DEVICE_GET_REGION_INFO */ - get_device_region_info(sock, &client_dev_info); + migr_reg_index = get_device_region_info(sock, &client_dev_info); + if (migr_reg_index == -1) { + errx(EXIT_FAILURE, "could not find migration region"); + } ret = access_region(sock, LM_DEV_CFG_REG_IDX, false, 0, &config_space, sizeof config_space); @@ -1046,7 +1056,7 @@ int main(int argc, char *argv[]) */ sleep(1); - migrate_from(sock, &migr_data, &migr_data_len); + migrate_from(sock, migr_reg_index, &migr_data, &migr_data_len); /* * Normally the client would now send the device state to the destination @@ -1059,7 +1069,7 @@ int main(int argc, char *argv[]) } sock = migrate_to(argv[optind], client_max_fds, &server_max_fds, &pgsize, - migr_data, migr_data_len, path_to_server); + migr_data, migr_data_len, path_to_server, migr_reg_index); /* * Now we must reconfigure the destination server. diff --git a/samples/server.c b/samples/server.c index 1b11eaa..70733cd 100644 --- a/samples/server.c +++ b/samples/server.c @@ -433,16 +433,6 @@ int main(int argc, char *argv[]) .mmap_areas = sparse_areas, .map = map_area }, - .reg_info[LM_DEV_MIGRATION_REG_IDX] = { /* migration region */ - .flags = LM_REG_FLAG_RW, - /* - * FIXME don't declare support for migration via a region, this - * is a VFIO artifact, make it something different. We still - * have to make the migration data memory mappable. - */ - .size = sizeof(struct vfio_device_migration_info) + server_data.migration.migr_data_len, - .mmap_areas = sparse_areas, - }, .irq_count[LM_DEV_INTX_IRQ_IDX] = 1, }, .uuid = argv[optind], @@ -450,13 +440,17 @@ int main(int argc, char *argv[]) .map_dma = map_dma, .unmap_dma = unmap_dma, .pvt = &server_data, - .migration_callbacks = { - .transition = &migration_device_state_transition, - .get_pending_bytes = &migration_get_pending_bytes, - .prepare_data = &migration_prepare_data, - .read_data = &migration_read_data, - .data_written = &migration_data_written, - .write_data = &migration_write_data + .migration = { + .size = server_data.migration.migr_data_len, + .mmap_areas = sparse_areas, + .callbacks = { + .transition = &migration_device_state_transition, + .get_pending_bytes = &migration_get_pending_bytes, + .prepare_data = &migration_prepare_data, + .read_data = &migration_read_data, + .data_written = &migration_data_written, + .write_data = &migration_write_data + } } }; |