aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThanos Makatos <thanos.makatos@nutanix.com>2022-11-22 09:10:27 +0000
committerGitHub <noreply@github.com>2022-11-22 09:10:27 +0000
commit14c0bc58e7278271ba22e6d31480da550db69a0c (patch)
tree3c71a37a030e0ece5dfa81f92041d6327032f53a
parentb975ee6e184884b63c654d2414f013c645c8a92e (diff)
downloadlibvfio-user-14c0bc58e7278271ba22e6d31480da550db69a0c.zip
libvfio-user-14c0bc58e7278271ba22e6d31480da550db69a0c.tar.gz
libvfio-user-14c0bc58e7278271ba22e6d31480da550db69a0c.tar.bz2
allow shadow memory offset per shadow ioeventfd (#703)
Signed-off-by: Thanos Makatos <thanos.makatos@nutanix.com> Reviewed-by: John Levon <john.levon@nutanix.com>
-rw-r--r--include/libvfio-user.h7
-rw-r--r--include/vfio-user.h5
-rw-r--r--lib/libvfio-user.c15
-rw-r--r--lib/private.h3
-rw-r--r--test/py/libvfio_user.py17
-rw-r--r--test/py/test_device_get_region_io_fds.py6
-rw-r--r--test/py/test_shadow_ioeventfd.py9
7 files changed, 34 insertions, 28 deletions
diff --git a/include/libvfio-user.h b/include/libvfio-user.h
index d12d89f..0a8af2b 100644
--- a/include/libvfio-user.h
+++ b/include/libvfio-user.h
@@ -1065,7 +1065,7 @@ vfu_sg_is_mappable(vfu_ctx_t *vfu_ctx, dma_sg_t *sg);
* @vfu_ctx: the libvfio-user context
* @region_idx: The index of the memory region to set up the ioeventfd
* @fd: the value of the file descriptor
- * @offset: The offset into the memory region
+ * @gpa_offset: The offset into the memory region
* @size: size of the ioeventfd
* @flags: Any flags to set up the ioeventfd
* @datamatch: sets the datamatch value
@@ -1076,11 +1076,12 @@ vfu_sg_is_mappable(vfu_ctx_t *vfu_ctx, dma_sg_t *sg);
* Requires a kernel with shadow ioeventfd support.
* Experimental, must be compiled with SHADOW_IOEVENTFD defined, otherwise
* must be -1.
+ * @shadow_offset: offset in shadow memory where value is written to.
*/
int
vfu_create_ioeventfd(vfu_ctx_t *vfu_ctx, uint32_t region_idx, int fd,
- size_t offset, uint32_t size, uint32_t flags,
- uint64_t datamatch, int shadow_fd);
+ size_t gpa_offset, uint32_t size, uint32_t flags,
+ uint64_t datamatch, int shadow_fd, size_t shadow_offset);
#ifdef __cplusplus
}
#endif
diff --git a/include/vfio-user.h b/include/vfio-user.h
index dc6fafa..52f0870 100644
--- a/include/vfio-user.h
+++ b/include/vfio-user.h
@@ -171,12 +171,13 @@ typedef struct vfio_user_region_io_fds_request {
#define VFIO_USER_IO_FD_TYPE_IOEVENTFD_SHADOW 2
typedef struct vfio_user_sub_region_ioeventfd {
- uint64_t offset;
+ uint64_t gpa_offset;
uint64_t size;
uint32_t fd_index;
uint32_t type;
uint32_t flags;
- uint32_t padding;
+ uint32_t shadow_mem_fd_index;
+ uint64_t shadow_offset;
uint64_t datamatch;
} __attribute__((packed)) vfio_user_sub_region_ioeventfd_t;
diff --git a/lib/libvfio-user.c b/lib/libvfio-user.c
index 93dca6d..219b527 100644
--- a/lib/libvfio-user.c
+++ b/lib/libvfio-user.c
@@ -477,8 +477,8 @@ handle_device_get_region_info(vfu_ctx_t *vfu_ctx, vfu_msg_t *msg)
EXPORT int
vfu_create_ioeventfd(vfu_ctx_t *vfu_ctx, uint32_t region_idx, int fd,
- size_t offset, uint32_t size, uint32_t flags,
- uint64_t datamatch, int shadow_fd)
+ size_t gpa_offset, uint32_t size, uint32_t flags,
+ uint64_t datamatch, int shadow_fd, size_t shadow_offset)
{
vfu_reg_info_t *vfu_reg;
@@ -498,7 +498,7 @@ vfu_create_ioeventfd(vfu_ctx_t *vfu_ctx, uint32_t region_idx, int fd,
vfu_reg = &vfu_ctx->reg_info[region_idx];
- if (offset + size > vfu_reg->size) {
+ if (gpa_offset + size > vfu_reg->size) {
return ERROR_INT(EINVAL);
}
@@ -508,11 +508,12 @@ vfu_create_ioeventfd(vfu_ctx_t *vfu_ctx, uint32_t region_idx, int fd,
}
elem->fd = fd;
- elem->offset = offset;
+ elem->gpa_offset = gpa_offset;
elem->size = size;
elem->flags = flags;
elem->datamatch = datamatch;
elem->shadow_fd = shadow_fd;
+ elem->shadow_offset = shadow_offset;
LIST_INSERT_HEAD(&vfu_reg->subregions, elem, entry);
return 0;
@@ -647,7 +648,7 @@ handle_device_get_region_io_fds(vfu_ctx_t *vfu_ctx, vfu_msg_t *msg)
for (i = 0; i < max_sent_sub_regions; i++) {
ioefd = &reply->sub_regions[i].ioeventfd;
- ioefd->offset = sub_reg->offset;
+ ioefd->gpa_offset = sub_reg->gpa_offset;
ioefd->size = sub_reg->size;
ioefd->fd_index = add_fd_index(msg->out.fds, &msg->out.nr_fds,
sub_reg->fd);
@@ -655,11 +656,11 @@ handle_device_get_region_io_fds(vfu_ctx_t *vfu_ctx, vfu_msg_t *msg)
ioefd->type = VFIO_USER_IO_FD_TYPE_IOEVENTFD;
} else {
ioefd->type = VFIO_USER_IO_FD_TYPE_IOEVENTFD_SHADOW;
- int ret = add_fd_index(msg->out.fds, &msg->out.nr_fds, sub_reg->shadow_fd);
- assert(ret == 1);
+ ioefd->shadow_mem_fd_index = add_fd_index(msg->out.fds, &msg->out.nr_fds, sub_reg->shadow_fd);
}
ioefd->flags = sub_reg->flags;
ioefd->datamatch = sub_reg->datamatch;
+ ioefd->shadow_offset = sub_reg->shadow_offset;
sub_reg = LIST_NEXT(sub_reg, entry);
}
diff --git a/lib/private.h b/lib/private.h
index 60adfc9..346cfed 100644
--- a/lib/private.h
+++ b/lib/private.h
@@ -185,12 +185,13 @@ struct vfu_ctx {
};
typedef struct ioeventfd {
- uint64_t offset;
+ uint64_t gpa_offset;
uint64_t size;
int32_t fd;
uint32_t flags;
uint64_t datamatch;
int32_t shadow_fd;
+ size_t shadow_offset;
LIST_ENTRY(ioeventfd) entry;
} ioeventfd_t;
diff --git a/test/py/libvfio_user.py b/test/py/libvfio_user.py
index 2bcd1bc..fd09fa8 100644
--- a/test/py/libvfio_user.py
+++ b/test/py/libvfio_user.py
@@ -410,13 +410,14 @@ class vfio_user_region_io_fds_request(Structure):
class vfio_user_sub_region_ioeventfd(Structure):
_pack_ = 1
_fields_ = [
- ("offset", c.c_uint64),
+ ("gpa_offset", c.c_uint64),
("size", c.c_uint64),
("fd_index", c.c_uint32),
("type", c.c_uint32),
("flags", c.c_uint32),
- ("padding", c.c_uint32),
- ("datamatch", c.c_uint64)
+ ("shadow_mem_fd_index", c.c_uint32),
+ ("datamatch", c.c_uint64),
+ ("shadow_offset", c.c_uint64)
]
@@ -633,7 +634,7 @@ lib.vfu_sgl_put.argtypes = (c.c_void_p, c.POINTER(dma_sg_t),
lib.vfu_create_ioeventfd.argtypes = (c.c_void_p, c.c_uint32, c.c_int,
c.c_size_t, c.c_uint32, c.c_uint32,
- c.c_uint64, c.c_int32)
+ c.c_uint64, c.c_int32, c.c_uint64)
lib.vfu_device_quiesced.argtypes = (c.c_void_p, c.c_int)
@@ -1207,12 +1208,12 @@ def vfu_sgl_put(ctx, sg, iovec, cnt=1):
return lib.vfu_sgl_put(ctx, sg, iovec, cnt)
-def vfu_create_ioeventfd(ctx, region_idx, fd, offset, size, flags, datamatch,
- shadow_fd=-1):
+def vfu_create_ioeventfd(ctx, region_idx, fd, gpa_offset, size, flags,
+ datamatch, shadow_fd=-1, shadow_offset=0):
assert ctx is not None
- return lib.vfu_create_ioeventfd(ctx, region_idx, fd, offset, size,
- flags, datamatch, shadow_fd)
+ return lib.vfu_create_ioeventfd(ctx, region_idx, fd, gpa_offset, size,
+ flags, datamatch, shadow_fd, shadow_offset)
def vfu_device_quiesced(ctx, err):
diff --git a/test/py/test_device_get_region_io_fds.py b/test/py/test_device_get_region_io_fds.py
index 924f462..b9c8d93 100644
--- a/test/py/test_device_get_region_io_fds.py
+++ b/test/py/test_device_get_region_io_fds.py
@@ -225,7 +225,7 @@ def test_device_get_region_io_fds_full():
[out] = struct.unpack("@Q", out)
assert out == 1
assert ioevents[i].size == IOEVENT_SIZE
- assert ioevents[i].offset == 40 - (IOEVENT_SIZE * i)
+ assert ioevents[i].gpa_offset == 40 - (IOEVENT_SIZE * i)
assert ioevents[i].type == VFIO_USER_IO_FD_TYPE_IOEVENTFD
for i in newfds:
@@ -284,11 +284,11 @@ def test_device_get_region_io_fds_fds_read_write_dupe_fd():
[out] = struct.unpack("@Q", out)
assert out == 1
assert ioevents[i].size == IOEVENT_SIZE
- assert ioevents[i].offset == 56 - (IOEVENT_SIZE * i)
+ assert ioevents[i].gpa_offset == 56 - (IOEVENT_SIZE * i)
assert ioevents[i].type == VFIO_USER_IO_FD_TYPE_IOEVENTFD
assert ioevents[0].fd_index == ioevents[1].fd_index
- assert ioevents[0].offset != ioevents[1].offset
+ assert ioevents[0].gpa_offset != ioevents[1].gpa_offset
os.write(newfds[ioevents[0].fd_index], c.c_ulonglong(1))
diff --git a/test/py/test_shadow_ioeventfd.py b/test/py/test_shadow_ioeventfd.py
index 642ad0e..c7cc4e5 100644
--- a/test/py/test_shadow_ioeventfd.py
+++ b/test/py/test_shadow_ioeventfd.py
@@ -54,7 +54,7 @@ def test_shadow_ioeventfd():
efd = eventfd(flags=EFD_NONBLOCK)
ret = vfu_create_ioeventfd(ctx, VFU_PCI_DEV_BAR0_REGION_IDX, efd, 0x8,
- 0x16, 0, 0, shadow_fd=fo.fileno())
+ 0x16, 0, 0, shadow_fd=fo.fileno(), 0x10)
assert ret == 0
ret = vfu_realize_ctx(ctx)
assert ret == 0
@@ -70,12 +70,13 @@ def test_shadow_ioeventfd():
reply, ret = vfio_user_region_io_fds_reply.pop_from_buffer(ret)
assert reply.count == 1 # 1 eventfd
ioevent, _ = vfio_user_sub_region_ioeventfd.pop_from_buffer(ret)
- assert ioevent.offset == 0x8
+ assert ioevent.gpa_offset == 0x8
assert ioevent.size == 0x16
assert ioevent.fd_index == 0
assert ioevent.type == VFIO_USER_IO_FD_TYPE_IOEVENTFD_SHADOW
assert ioevent.flags == 0
assert ioevent.datamatch == 0
+ assert ioevent.shadow_offset = 0x10
assert len(newfds) == 2 # 2 FDs: eventfd plus shadow FD
cefd = newfds[0]
@@ -93,13 +94,13 @@ def test_shadow_ioeventfd():
# Client writes to the I/O region. The write to the eventfd would be done
# by KVM and the value would be the same in both cases.
- cmem.seek(0x8)
+ cmem.seek(ioevent.shadow_offset)
cmem.write(c.c_ulonglong(0xdeadbeef))
os.write(cefd, c.c_ulonglong(0xcafebabe))
# vfio-user app reads eventfd
assert os.read(efd, IOEVENT_SIZE) == to_bytes_le(0xcafebabe, 8)
- fo.seek(0x8)
+ fo.seek(ioevent.shadow_offset)
assert fo.read(0x8) == to_bytes_le(0xdeadbeef, 8)
vfu_destroy_ctx(ctx)