Skip to content

Commit

Permalink
support VFIO_USER_REGION_WRITE_MULTI
Browse files Browse the repository at this point in the history
FIXME: needs work

Signed-off-by: John Levon <[email protected]>
  • Loading branch information
jlevon committed Nov 2, 2022
1 parent 4953810 commit 9d3619e
Show file tree
Hide file tree
Showing 4 changed files with 111 additions and 5 deletions.
16 changes: 16 additions & 0 deletions include/vfio-user.h
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ enum vfio_user_command {
VFIO_USER_DMA_WRITE = 12,
VFIO_USER_DEVICE_RESET = 13,
VFIO_USER_DIRTY_PAGES = 14,
VFIO_USER_REGION_WRITE_MULTI = 15,
VFIO_USER_MAX,
};

Expand Down Expand Up @@ -227,6 +228,21 @@ struct vfio_user_bitmap_range {

#endif /* VFIO_REGION_TYPE_MIGRATION */

#define VFIO_USER_MULTI_DATA 8
#define VFIO_USER_MULTI_MAX 200

struct vfio_user_write_multi_data {
uint64_t offset;
uint32_t region;
uint32_t count;
char data[VFIO_USER_MULTI_DATA];
} __attribute__((packed));

struct vfio_user_write_multi {
uint64_t wr_cnt;
struct vfio_user_write_multi_data wrs[VFIO_USER_MULTI_MAX];
} __attribute__((packed));

#ifdef __cplusplus
}
#endif
Expand Down
95 changes: 91 additions & 4 deletions lib/libvfio-user.c
Original file line number Diff line number Diff line change
Expand Up @@ -264,10 +264,27 @@ is_valid_region_access(vfu_ctx_t *vfu_ctx, size_t size, uint16_t cmd,
return false;
}

if (cmd == VFIO_USER_REGION_WRITE && size - sizeof(*ra) != ra->count) {
vfu_log(vfu_ctx, LOG_ERR, "region write count too small: "
"expected %lu, got %u", size - sizeof(*ra), ra->count);
return false;
switch (cmd) {
case VFIO_USER_REGION_WRITE:
if (size - sizeof(*ra) != ra->count) {
vfu_log(vfu_ctx, LOG_ERR, "region write count too small: "
"expected %lu, got %u", size - sizeof(*ra), ra->count);
return false;
}

break;

case VFIO_USER_REGION_WRITE_MULTI:
if (ra->count > VFIO_USER_MULTI_DATA) {
vfu_log(vfu_ctx, LOG_ERR, "region write count too large: "
"expected %lu, got %u", size - sizeof(*ra), ra->count);
return false;
}

break;

default:
break;
}

index = ra->region;
Expand Down Expand Up @@ -350,6 +367,67 @@ handle_region_access(vfu_ctx_t *vfu_ctx, vfu_msg_t *msg)
return 0;
}

static int
handle_region_write_multi(vfu_ctx_t *vfu_ctx, vfu_msg_t *msg)
{
struct vfio_user_write_multi *wm = msg->in.iov.iov_base;
ssize_t ret;
char *buf;

assert(vfu_ctx != NULL);
assert(msg != NULL);

// FIXME: validate properly (?) - need tests

if (msg->in.iov.iov_len < sizeof(wm->wr_cnt)) {
return ERROR_INT(EINVAL);
}

if (wm->wr_cnt > VFIO_USER_MULTI_MAX) {
return ERROR_INT(EINVAL);
}

if (msg->in.iov.iov_len !=
(offsetof(struct vfio_user_write_multi, wrs) +
wm->wr_cnt * sizeof(struct vfio_user_write_multi_data))) {
return ERROR_INT(EINVAL);
}

for (size_t i = 0; i < wm->wr_cnt; i++) {
struct vfio_user_region_access *in_ra;

/* Re-use the very similar type. */
in_ra = (struct vfio_user_region_access *)&wm->wrs[i];

/*
* We already checked total length so can be sure each entry is at least
* big enough.
*/
if (!is_valid_region_access(vfu_ctx, sizeof(wm->wrs[i]),
msg->hdr.cmd, in_ra)) {
return ERROR_INT(EINVAL);
}

if (in_ra->count == 0) {
continue;
}

buf = (char *)(&in_ra->data);

ret = region_access(vfu_ctx, in_ra->region, buf, in_ra->count,
in_ra->offset, true);
if (ret != in_ra->count) {
/* FIXME we should return whatever has been accessed, not an error */
if (ret >= 0) {
ret = ERROR_INT(EINVAL);
}
return ret;
}
}

return 0;
}

static int
handle_device_get_info(vfu_ctx_t *vfu_ctx, vfu_msg_t *msg)
{
Expand Down Expand Up @@ -1164,6 +1242,11 @@ handle_request(vfu_ctx_t *vfu_ctx, vfu_msg_t *msg)
ret = handle_region_access(vfu_ctx, msg);
break;

case VFIO_USER_REGION_WRITE_MULTI:
ret = handle_region_write_multi(vfu_ctx, msg);
break;


case VFIO_USER_DEVICE_RESET:
vfu_log(vfu_ctx, LOG_INFO, "device reset by client");
ret = handle_device_reset(vfu_ctx, VFU_RESET_DEVICE);
Expand Down Expand Up @@ -1352,6 +1435,10 @@ command_needs_quiesce(vfu_ctx_t *vfu_ctx, const vfu_msg_t *msg)
return true;
}
break;

case VFIO_USER_REGION_WRITE_MULTI:
/* FIXME */
return false;
}

return false;
Expand Down
1 change: 1 addition & 0 deletions samples/client.c
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@ send_version(int sock)
slen = snprintf(client_caps, sizeof(client_caps),
"{"
"\"capabilities\":{"
"\"write_multiple\": true,"
"\"max_msg_fds\":%u,"
"\"max_data_xfer_size\":%u,"
"\"migration\":{"
Expand Down
4 changes: 3 additions & 1 deletion test/py/libvfio_user.py
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,9 @@
VFIO_USER_DMA_WRITE = 12
VFIO_USER_DEVICE_RESET = 13
VFIO_USER_DIRTY_PAGES = 14
VFIO_USER_MAX = 15
# FIXME: need tests
VFIO_USER_REGION_WRITE_MULTI = 15
VFIO_USER_MAX = 16

VFIO_USER_F_TYPE_COMMAND = 0
VFIO_USER_F_TYPE_REPLY = 1
Expand Down

0 comments on commit 9d3619e

Please sign in to comment.