From: John G Johnson <john.g.john...@oracle.com> Send VFIO_USER_DEVICE_GET_INFO and VFIO_USER_DEVICE_GET_IRQ_INFO commands.
Signed-off-by: Elena Ufimtseva <elena.ufimts...@oracle.com> Signed-off-by: John G Johnson <john.g.john...@oracle.com> Signed-off-by: Jagannathan Raman <jag.ra...@oracle.com> --- hw/vfio/user.h | 27 +++++++++++++++++++++++++++ hw/vfio/pci.c | 32 +++++++++++++++++++++++++++++--- hw/vfio/user.c | 40 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 96 insertions(+), 3 deletions(-) diff --git a/hw/vfio/user.h b/hw/vfio/user.h index 844496ef82..9f51e14c7c 100644 --- a/hw/vfio/user.h +++ b/hw/vfio/user.h @@ -122,9 +122,36 @@ typedef struct VFIOProxy { #define VFIO_PROXY_CLIENT 0x1 +/* + * VFIO_USER_DEVICE_GET_INFO + * imported from struct_device_info + */ +struct vfio_user_device_info { + vfio_user_hdr_t hdr; + uint32_t argsz; + uint32_t flags; + uint32_t num_regions; + uint32_t num_irqs; + uint32_t cap_offset; +}; + +/* + * VFIO_USER_DEVICE_GET_IRQ_INFO + * imported from struct vfio_irq_info + */ +struct vfio_user_irq_info { + vfio_user_hdr_t hdr; + uint32_t argsz; + uint32_t flags; + uint32_t index; + uint32_t count; +}; + void vfio_user_recv(void *opaque); void vfio_user_send_reply(VFIOProxy *proxy, char *buf, int ret); VFIOProxy *vfio_user_connect_dev(char *sockname, Error **errp); void vfio_user_disconnect(VFIOProxy *proxy); int vfio_user_validate_version(VFIODevice *vbasedev, Error **errp); +int vfio_user_get_info(VFIODevice *vbasedev); +int vfio_user_get_irq_info(VFIODevice *vbasedev, struct vfio_irq_info *info); #endif /* VFIO_USER_H */ diff --git a/hw/vfio/pci.c b/hw/vfio/pci.c index 5ed42ad858..029a191bcb 100644 --- a/hw/vfio/pci.c +++ b/hw/vfio/pci.c @@ -2620,7 +2620,12 @@ static void vfio_populate_device(VFIOPCIDevice *vdev, Error **errp) irq_info.index = VFIO_PCI_ERR_IRQ_INDEX; - ret = ioctl(vdev->vbasedev.fd, VFIO_DEVICE_GET_IRQ_INFO, &irq_info); + if (vbasedev->proxy != NULL) { + ret = vfio_user_get_irq_info(vbasedev, &irq_info); + } else { + ret = ioctl(vdev->vbasedev.fd, VFIO_DEVICE_GET_IRQ_INFO, &irq_info); + } + if (ret) { /* This can fail for an old kernel or legacy PCI dev */ trace_vfio_populate_device_get_irq_info_failure(strerror(errno)); @@ -2739,8 +2744,16 @@ static void vfio_register_req_notifier(VFIOPCIDevice *vdev) return; } - if (ioctl(vdev->vbasedev.fd, - VFIO_DEVICE_GET_IRQ_INFO, &irq_info) < 0 || irq_info.count < 1) { + if (vdev->vbasedev.proxy != NULL) { + if (vfio_user_get_irq_info(&vdev->vbasedev, &irq_info) < 0) { + return; + } + } else { + if (ioctl(vdev->vbasedev.fd, VFIO_DEVICE_GET_IRQ_INFO, &irq_info) < 0) { + return; + } + } + if (irq_info.count < 1) { return; } @@ -3359,6 +3372,7 @@ static void vfio_user_pci_realize(PCIDevice *pdev, Error **errp) VFIODevice *vbasedev = &vdev->vbasedev; VFIOProxy *proxy; VFIOGroup *group = NULL; + int ret; Error *err = NULL; if (!udev->sock_name) { @@ -3399,6 +3413,18 @@ static void vfio_user_pci_realize(PCIDevice *pdev, Error **errp) vfio_connect_proxy(proxy, group, pci_device_iommu_address_space(pdev)); + ret = vfio_user_get_info(&vdev->vbasedev); + if (ret) { + error_setg_errno(errp, -ret, "get info failure"); + goto error; + } + + vfio_populate_device(vdev, &err); + if (err) { + error_propagate(errp, err); + goto error; + } + return; error: diff --git a/hw/vfio/user.c b/hw/vfio/user.c index 24dd45b55d..a282b7b7b8 100644 --- a/hw/vfio/user.c +++ b/hw/vfio/user.c @@ -508,6 +508,27 @@ int vfio_user_validate_version(VFIODevice *vbasedev, Error **errp) return 0; } +int vfio_user_get_info(VFIODevice *vbasedev) +{ + struct vfio_user_device_info msg; + + memset(&msg, 0, sizeof(msg)); + vfio_user_request_msg(&msg.hdr, VFIO_USER_DEVICE_GET_INFO, sizeof(msg), 0); + msg.argsz = sizeof(struct vfio_device_info); + + vfio_user_send_recv(vbasedev->proxy, &msg.hdr, NULL, 0); + if (msg.hdr.flags & VFIO_USER_ERROR) { + return -msg.hdr.error_reply; + } + + vbasedev->num_irqs = msg.num_irqs; + vbasedev->num_regions = msg.num_regions; + vbasedev->flags = msg.flags; + vbasedev->reset_works = !!(msg.flags & VFIO_DEVICE_FLAGS_RESET); + return 0; + +} + static QLIST_HEAD(, VFIOProxy) vfio_user_sockets = QLIST_HEAD_INITIALIZER(vfio_user_sockets); @@ -594,3 +615,22 @@ void vfio_user_disconnect(VFIOProxy *proxy) g_free(proxy); } + +int vfio_user_get_irq_info(VFIODevice *vbasedev, struct vfio_irq_info *info) +{ + struct vfio_user_irq_info msg; + + memset(&msg, 0, sizeof(msg)); + vfio_user_request_msg(&msg.hdr, VFIO_USER_DEVICE_GET_IRQ_INFO, + sizeof(msg), 0); + msg.argsz = info->argsz; + msg.index = info->index; + + vfio_user_send_recv(vbasedev->proxy, &msg.hdr, NULL, 0); + if (msg.hdr.flags & VFIO_USER_ERROR) { + return -msg.hdr.error_reply; + } + + memcpy(info, &msg.argsz, sizeof(*info)); + return 0; +} -- 2.25.1