vfio-user: support VFIO_USER_DEVICE_FEATURE
Plumb through vfio_device_get_feature to the vfio-user server. Note that we translate EINVAL into ENOTTY, as the existing generic vfio code is expecting the latter to mean "unsupported". As part of adding a trace point, clean up the trace file. 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/20260410085716.877185-2-john.levon@nutanix.com Signed-off-by: Cédric Le Goater <clg@redhat.com>
This commit is contained in:
committed by
Cédric Le Goater
parent
f2ac20026e
commit
e2358af583
@@ -74,6 +74,47 @@ void vfio_user_device_reset(VFIOUserProxy *proxy)
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
vfio_user_device_io_device_feature(VFIODevice *vbasedev,
|
||||
struct vfio_device_feature *feature)
|
||||
{
|
||||
g_autofree VFIOUserDeviceFeature *msgp = NULL;
|
||||
int size = sizeof(VFIOUserHdr) + feature->argsz;
|
||||
VFIOUserProxy *proxy = vbasedev->proxy;
|
||||
Error *local_err = NULL;
|
||||
|
||||
msgp = g_malloc0(size);
|
||||
|
||||
vfio_user_request_msg(&msgp->hdr, VFIO_USER_DEVICE_FEATURE, size, 0);
|
||||
|
||||
memcpy(&msgp->argsz, &feature->argsz, feature->argsz);
|
||||
|
||||
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) {
|
||||
/*
|
||||
* Client expects ENOTTY for "not supported", but the protocol may
|
||||
* return EINVAL (which should only occur in the case the feature isn't
|
||||
* actually supported on the server).
|
||||
*/
|
||||
if (msgp->hdr.error_reply == EINVAL) {
|
||||
return -ENOTTY;
|
||||
}
|
||||
|
||||
return -msgp->hdr.error_reply;
|
||||
}
|
||||
|
||||
memcpy(feature, &msgp->argsz, feature->argsz);
|
||||
|
||||
trace_vfio_user_device_io_device_feature(msgp->argsz, msgp->flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int vfio_user_get_region_info(VFIOUserProxy *proxy,
|
||||
struct vfio_region_info *info,
|
||||
VFIOUserFDs *fds)
|
||||
@@ -432,6 +473,7 @@ static int vfio_user_device_io_region_write(VFIODevice *vbasedev, uint8_t index,
|
||||
* Socket-based io_ops
|
||||
*/
|
||||
VFIODeviceIOOps vfio_user_device_io_ops_sock = {
|
||||
.device_feature = vfio_user_device_io_device_feature,
|
||||
.get_region_info = vfio_user_device_io_get_region_info,
|
||||
.get_irq_info = vfio_user_device_io_get_irq_info,
|
||||
.set_irqs = vfio_user_device_io_set_irqs,
|
||||
|
||||
@@ -40,6 +40,7 @@ enum vfio_user_command {
|
||||
VFIO_USER_DEVICE_RESET = 13,
|
||||
VFIO_USER_DIRTY_PAGES = 14,
|
||||
VFIO_USER_REGION_WRITE_MULTI = 15,
|
||||
VFIO_USER_DEVICE_FEATURE = 16,
|
||||
VFIO_USER_MAX,
|
||||
};
|
||||
|
||||
@@ -239,4 +240,15 @@ typedef struct {
|
||||
VFIOUserWROne wrs[VFIO_USER_MULTI_MAX];
|
||||
} VFIOUserWRMulti;
|
||||
|
||||
/*
|
||||
* VFIO_USER_DEVICE_FEATURE
|
||||
* imported from struct vfio_device_feature
|
||||
*/
|
||||
typedef struct {
|
||||
VFIOUserHdr hdr;
|
||||
uint32_t argsz;
|
||||
uint32_t flags;
|
||||
char data[];
|
||||
} VFIOUserDeviceFeature;
|
||||
|
||||
#endif /* VFIO_USER_PROTOCOL_H */
|
||||
|
||||
@@ -2,19 +2,22 @@
|
||||
#
|
||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
# common.c
|
||||
# container.c
|
||||
vfio_user_dma_map(uint64_t iova, uint64_t size, uint64_t off, uint32_t flags, bool async_ops) " iova 0x%"PRIx64" size 0x%"PRIx64" off 0x%"PRIx64" flags 0x%x async_ops %d"
|
||||
vfio_user_dma_unmap(uint64_t iova, uint64_t size, uint32_t flags, bool async_ops) " iova 0x%"PRIx64" size 0x%"PRIx64" flags 0x%x async_ops %d"
|
||||
|
||||
# device.c
|
||||
vfio_user_device_io_device_feature(uint32_t argsz, uint32_t flags) " argsz 0x%x flags 0x%x"
|
||||
vfio_user_get_info(uint32_t nregions, uint32_t nirqs) " #regions %d #irqs %d"
|
||||
vfio_user_get_irq_info(uint32_t index, uint32_t flags, uint32_t count) " index %d flags 0x%x count %d"
|
||||
vfio_user_set_irqs(uint32_t index, uint32_t start, uint32_t count, uint32_t flags) " index %d start %d count %d flags 0x%x"
|
||||
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"
|
||||
|
||||
# proxy.c
|
||||
vfio_user_recv_hdr(const char *name, uint16_t id, uint16_t cmd, uint32_t size, uint32_t flags) " (%s) id 0x%x cmd 0x%x size 0x%x flags 0x%x"
|
||||
vfio_user_recv_read(uint16_t id, int read) " id 0x%x read 0x%x"
|
||||
vfio_user_recv_request(uint16_t cmd) " command 0x%x"
|
||||
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"
|
||||
vfio_user_get_irq_info(uint32_t index, uint32_t flags, uint32_t count) " index %d flags 0x%x count %d"
|
||||
vfio_user_set_irqs(uint32_t index, uint32_t start, uint32_t count, uint32_t flags) " index %d start %d count %d flags 0x%x"
|
||||
vfio_user_wrmulti(const char *s, uint64_t wr_cnt) " %s count 0x%"PRIx64
|
||||
|
||||
# container.c
|
||||
vfio_user_dma_map(uint64_t iova, uint64_t size, uint64_t off, uint32_t flags, bool async_ops) " iova 0x%"PRIx64" size 0x%"PRIx64" off 0x%"PRIx64" flags 0x%x async_ops %d"
|
||||
vfio_user_dma_unmap(uint64_t iova, uint64_t size, uint32_t flags, bool async_ops) " iova 0x%"PRIx64" size 0x%"PRIx64" flags 0x%x async_ops %d"
|
||||
|
||||
Reference in New Issue
Block a user