diff options
author | John Levon <john.levon@nutanix.com> | 2025-06-25 20:29:59 +0100 |
---|---|---|
committer | Cédric Le Goater <clg@redhat.com> | 2025-06-26 08:55:38 +0200 |
commit | 1ed50fcb6a8b99312458b9653de2d1d5acfd7506 (patch) | |
tree | d2e6eaffb2c61861c938568fe256fbee9bec3f23 | |
parent | 667866d66620e9f545eb3bd4f065d9ab81bda727 (diff) | |
download | qemu-1ed50fcb6a8b99312458b9653de2d1d5acfd7506.zip qemu-1ed50fcb6a8b99312458b9653de2d1d5acfd7506.tar.gz qemu-1ed50fcb6a8b99312458b9653de2d1d5acfd7506.tar.bz2 |
vfio-user: implement VFIO_USER_REGION_READ/WRITE
Originally-by: John Johnson <john.g.johnson@oracle.com>
Signed-off-by: Elena Ufimtseva <elena.ufimtseva@oracle.com>
Signed-off-by: Jagannathan Raman <jag.raman@oracle.com>
Signed-off-by: John Levon <john.levon@nutanix.com>
Reviewed-by: Cédric Le Goater <clg@redhat.com>
Link: https://lore.kernel.org/qemu-devel/20250625193012.2316242-8-john.levon@nutanix.com
Signed-off-by: Cédric Le Goater <clg@redhat.com>
-rw-r--r-- | hw/vfio-user/device.c | 79 | ||||
-rw-r--r-- | hw/vfio-user/protocol.h | 12 | ||||
-rw-r--r-- | hw/vfio-user/trace-events | 1 |
3 files changed, 92 insertions, 0 deletions
diff --git a/hw/vfio-user/device.c b/hw/vfio-user/device.c index d90232a..4ef6a2d 100644 --- a/hw/vfio-user/device.c +++ b/hw/vfio-user/device.c @@ -121,9 +121,88 @@ static int vfio_user_device_io_get_region_info(VFIODevice *vbasedev, return 0; } +static int vfio_user_device_io_region_read(VFIODevice *vbasedev, uint8_t index, + off_t off, uint32_t count, + void *data) +{ + g_autofree VFIOUserRegionRW *msgp = NULL; + VFIOUserProxy *proxy = vbasedev->proxy; + int size = sizeof(*msgp) + count; + Error *local_err = NULL; + + if (count > proxy->max_xfer_size) { + return -EINVAL; + } + + msgp = g_malloc0(size); + vfio_user_request_msg(&msgp->hdr, VFIO_USER_REGION_READ, sizeof(*msgp), 0); + msgp->offset = off; + msgp->region = index; + msgp->count = count; + trace_vfio_user_region_rw(msgp->region, msgp->offset, msgp->count); + + if (!vfio_user_send_wait(proxy, &msgp->hdr, NULL, size, &local_err)) { + error_prepend(&local_err, "%s: ", __func__); + error_report_err(local_err); + return -EFAULT; + } + + if (msgp->hdr.flags & VFIO_USER_ERROR) { + return -msgp->hdr.error_reply; + } else if (msgp->count > count) { + return -E2BIG; + } else { + memcpy(data, &msgp->data, msgp->count); + } + + return msgp->count; +} + +static int vfio_user_device_io_region_write(VFIODevice *vbasedev, uint8_t index, + off_t off, unsigned count, + void *data, bool post) +{ + g_autofree VFIOUserRegionRW *msgp = NULL; + VFIOUserProxy *proxy = vbasedev->proxy; + int size = sizeof(*msgp) + count; + Error *local_err = NULL; + int ret; + + if (count > proxy->max_xfer_size) { + return -EINVAL; + } + + msgp = g_malloc0(size); + vfio_user_request_msg(&msgp->hdr, VFIO_USER_REGION_WRITE, size, 0); + msgp->offset = off; + msgp->region = index; + msgp->count = count; + memcpy(&msgp->data, data, count); + trace_vfio_user_region_rw(msgp->region, msgp->offset, msgp->count); + + /* Ignore post: all writes are synchronous/non-posted. */ + + if (!vfio_user_send_wait(proxy, &msgp->hdr, NULL, 0, &local_err)) { + error_prepend(&local_err, "%s: ", __func__); + error_report_err(local_err); + return -EFAULT; + } + + if (msgp->hdr.flags & VFIO_USER_ERROR) { + ret = -msgp->hdr.error_reply; + } else { + ret = count; + } + + return ret; +} + /* * Socket-based io_ops */ VFIODeviceIOOps vfio_user_device_io_ops_sock = { .get_region_info = vfio_user_device_io_get_region_info, + .region_read = vfio_user_device_io_region_read, + .region_write = vfio_user_device_io_region_write, + }; diff --git a/hw/vfio-user/protocol.h b/hw/vfio-user/protocol.h index db88f5f..0cd32ad 100644 --- a/hw/vfio-user/protocol.h +++ b/hw/vfio-user/protocol.h @@ -138,4 +138,16 @@ typedef struct { uint64_t offset; } VFIOUserRegionInfo; +/* + * VFIO_USER_REGION_READ + * VFIO_USER_REGION_WRITE + */ +typedef struct { + VFIOUserHdr hdr; + uint64_t offset; + uint32_t region; + uint32_t count; + char data[]; +} VFIOUserRegionRW; + #endif /* VFIO_USER_PROTOCOL_H */ diff --git a/hw/vfio-user/trace-events b/hw/vfio-user/trace-events index ef3f14c..733313c 100644 --- a/hw/vfio-user/trace-events +++ b/hw/vfio-user/trace-events @@ -10,3 +10,4 @@ vfio_user_send_write(uint16_t id, int wrote) " id 0x%x wrote 0x%x" vfio_user_version(uint16_t major, uint16_t minor, const char *caps) " major %d minor %d caps: %s" vfio_user_get_info(uint32_t nregions, uint32_t nirqs) " #regions %d #irqs %d" vfio_user_get_region_info(uint32_t index, uint32_t flags, uint64_t size) " index %d flags 0x%x size 0x%"PRIx64 +vfio_user_region_rw(uint32_t region, uint64_t off, uint32_t count) " region %d offset 0x%"PRIx64" count %d" |