From: Jagannathan Raman <jag.ra...@oracle.com> Originally-by: John Johnson <john.g.john...@oracle.com> Signed-off-by: Elena Ufimtseva <elena.ufimts...@oracle.com> Signed-off-by: Jagannathan Raman <jag.ra...@oracle.com> Signed-off-by: John Levon <john.le...@nutanix.com> --- hw/vfio/container.c | 4 ++- hw/vfio/user-container.c | 52 ++++++++++++++++++++++++++++------- hw/vfio/user-protocol.h | 2 ++ hw/vfio/user.c | 4 +++ hw/vfio/user.h | 10 +++++++ include/hw/vfio/vfio-common.h | 1 + 6 files changed, 62 insertions(+), 11 deletions(-)
diff --git a/hw/vfio/container.c b/hw/vfio/container.c index 7e1a1a010a..e60e92066d 100644 --- a/hw/vfio/container.c +++ b/hw/vfio/container.c @@ -914,7 +914,9 @@ void vfio_put_base_device(VFIODevice *vbasedev) QLIST_REMOVE(vbasedev, next); vbasedev->group = NULL; trace_vfio_put_base_device(vbasedev->fd); - close(vbasedev->fd); + if (vbasedev->fd != -1) { + close(vbasedev->fd); + } } static int vfio_device_groupid(VFIODevice *vbasedev, Error **errp) diff --git a/hw/vfio/user-container.c b/hw/vfio/user-container.c index f1218560a4..f0414509d5 100644 --- a/hw/vfio/user-container.c +++ b/hw/vfio/user-container.c @@ -56,34 +56,62 @@ static int vfio_user_query_dirty_bitmap(const VFIOContainerBase *bcontainer, static bool vfio_user_setup(VFIOContainerBase *bcontainer, Error **errp) { - error_setg_errno(errp, ENOTSUP, "Not supported"); - return -ENOTSUP; + VFIOUserContainer *container = container_of(bcontainer, VFIOUserContainer, + bcontainer); + + assert(container->proxy->dma_pgsizes != 0); + bcontainer->pgsizes = container->proxy->dma_pgsizes; + bcontainer->dma_max_mappings = container->proxy->max_dma; + + /* No live migration support yet. */ + bcontainer->dirty_pages_supported = false; + bcontainer->max_dirty_bitmap_size = container->proxy->max_bitmap; + bcontainer->dirty_pgsizes = container->proxy->migr_pgsize; + + return true; } /* * Try to mirror vfio_connect_container() as much as possible. */ static VFIOUserContainer * -vfio_connect_user_container(AddressSpace *as, Error **errp) +vfio_connect_user_container(AddressSpace *as, VFIODevice *vbasedev, + Error **errp) { - VFIOAddressSpace *space; - VFIOUserContainer *container; VFIOContainerBase *bcontainer; + VFIOUserContainer *container; + const VFIOIOMMUClass *ops; + VFIOAddressSpace *space; + int ret; space = vfio_get_address_space(as); container = g_malloc0(sizeof(*container)); - + container->proxy = vbasedev->proxy; bcontainer = &container->bcontainer; + ops = VFIO_IOMMU_CLASS(object_class_by_name(TYPE_VFIO_IOMMU_USER)); + + vfio_container_init(&container->bcontainer, space, ops); + if (!vfio_cpr_register_container(bcontainer, errp)) { goto free_container_exit; } + /* + * VFIO user allows the device server to map guest memory so it has the same + * issue with discards as a local IOMMU has. + */ + ret = ram_block_uncoordinated_discard_disable(true); + if (ret) { + error_setg_errno(errp, -ret, "Cannot set discarding of RAM broken"); + goto unregister_container_exit; + } + assert(bcontainer->ops->setup); if (!bcontainer->ops->setup(bcontainer, errp)) { - goto unregister_container_exit; + goto enable_discards_exit; } QLIST_INSERT_HEAD(&space->containers, bcontainer, next); @@ -109,6 +137,9 @@ listener_release_exit: bcontainer->ops->release(bcontainer); } +enable_discards_exit: + ram_block_uncoordinated_discard_disable(false); + unregister_container_exit: vfio_cpr_unregister_container(bcontainer); @@ -123,14 +154,15 @@ free_container_exit: static void vfio_disconnect_user_container(VFIOUserContainer *container) { VFIOContainerBase *bcontainer = &container->bcontainer; + VFIOAddressSpace *space = bcontainer->space; + + ram_block_uncoordinated_discard_disable(false); memory_listener_unregister(&bcontainer->listener); if (bcontainer->ops->release) { bcontainer->ops->release(bcontainer); } - VFIOAddressSpace *space = bcontainer->space; - vfio_container_destroy(bcontainer); vfio_cpr_unregister_container(bcontainer); @@ -166,7 +198,7 @@ static bool vfio_user_attach_device(const char *name, VFIODevice *vbasedev, { VFIOUserContainer *container; - container = vfio_connect_user_container(as, errp); + container = vfio_connect_user_container(as, vbasedev, errp); if (container == NULL) { error_prepend(errp, "failed to connect proxy"); return false; diff --git a/hw/vfio/user-protocol.h b/hw/vfio/user-protocol.h index 48dd475ab3..87e43ddc72 100644 --- a/hw/vfio/user-protocol.h +++ b/hw/vfio/user-protocol.h @@ -16,6 +16,8 @@ * region and offset info for read and write commands. */ +#include <stdint.h> + typedef struct { uint16_t id; uint16_t command; diff --git a/hw/vfio/user.c b/hw/vfio/user.c index 352c10d37b..224b5febd8 100644 --- a/hw/vfio/user.c +++ b/hw/vfio/user.c @@ -18,10 +18,14 @@ #include "qemu/lockable.h" #include "hw/hw.h" #include "hw/vfio/vfio-common.h" +#include "exec/address-spaces.h" +#include "exec/memory.h" +#include "exec/ram_addr.h" #include "qemu/sockets.h" #include "io/channel.h" #include "io/channel-socket.h" #include "io/channel-util.h" +#include "sysemu/reset.h" #include "sysemu/iothread.h" #include "qapi/qmp/qdict.h" #include "qapi/qmp/qjson.h" diff --git a/hw/vfio/user.h b/hw/vfio/user.h index 1f99a976d6..9039e96069 100644 --- a/hw/vfio/user.h +++ b/hw/vfio/user.h @@ -11,7 +11,17 @@ * */ +#include <stdbool.h> + +#include "glib-compat.h" #include "user-protocol.h" +#include "qemu/osdep.h" +#include "qemu/typedefs.h" +#include "qemu/queue.h" +#include "qemu/sockets.h" +#include "qemu/thread.h" + +typedef struct VFIODevice VFIODevice; typedef struct { int send_fds; diff --git a/include/hw/vfio/vfio-common.h b/include/hw/vfio/vfio-common.h index 747b343596..c06099edce 100644 --- a/include/hw/vfio/vfio-common.h +++ b/include/hw/vfio/vfio-common.h @@ -90,6 +90,7 @@ typedef struct VFIOContainer { /* MMU container sub-class for vfio-user. */ typedef struct VFIOUserContainer { VFIOContainerBase bcontainer; + VFIOUserProxy *proxy; } VFIOUserContainer; typedef struct VFIOHostDMAWindow { -- 2.34.1