aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/migration.c6
-rw-r--r--lib/migration.h2
-rw-r--r--lib/muser.h18
-rw-r--r--lib/muser_ctx.c128
-rw-r--r--lib/muser_priv.h4
-rw-r--r--samples/client.c70
-rw-r--r--samples/server.c28
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
+ }
}
};