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".
Signed-off-by: John Levon <john.levon@nutanix.com>
---
hw/vfio-user/protocol.h | 12 ++++++++++++
hw/vfio-user/device.c | 39 +++++++++++++++++++++++++++++++++++++++
2 files changed, 51 insertions(+)
diff --git a/hw/vfio-user/protocol.h b/hw/vfio-user/protocol.h
index 3249a4a6b6..2a0c31e7c5 100644
--- a/hw/vfio-user/protocol.h
+++ b/hw/vfio-user/protocol.h
@@ -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 */
diff --git a/hw/vfio-user/device.c b/hw/vfio-user/device.c
index 64ef35b320..6910d183d7 100644
--- a/hw/vfio-user/device.c
+++ b/hw/vfio-user/device.c
@@ -74,6 +74,44 @@ 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.
+ */
+ if (msgp->hdr.error_reply == EINVAL) {
+ return -ENOTTY;
+ }
+
+ return -msgp->hdr.error_reply;
+ }
+
+ memcpy(feature, &msgp->argsz, feature->argsz);
+
+ return 0;
+}
+
static int vfio_user_get_region_info(VFIOUserProxy *proxy,
struct vfio_region_info *info,
VFIOUserFDs *fds)
@@ -432,6 +470,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,
--
2.43.0