@@ -1183,6 +1183,50 @@ static int vfio_get_iommu_type(VFIOContainer *container,
return ret;
}
+static int vfio_host_iommu_ctx_pasid_alloc(HostIOMMUContext *iommu_ctx,
+ uint32_t min, uint32_t max,
+ uint32_t *pasid)
+{
+ VFIOContainer *container = container_of(iommu_ctx,
+ VFIOContainer, iommu_ctx);
+ struct vfio_iommu_type1_pasid_request req;
+ int ret = 0;
+
+ req.argsz = sizeof(req);
+ req.flags = VFIO_IOMMU_FLAG_ALLOC_PASID;
+ req.range.min = min;
+ req.range.max = max;
+
+ ret = ioctl(container->fd, VFIO_IOMMU_PASID_REQUEST, &req);
+ if (ret < 0) {
+ error_report("%s: alloc failed (%m)", __func__);
+ return ret;
+ }
+ *pasid = ret;
+ return 0;
+}
+
+static int vfio_host_iommu_ctx_pasid_free(HostIOMMUContext *iommu_ctx,
+ uint32_t pasid)
+{
+ VFIOContainer *container = container_of(iommu_ctx,
+ VFIOContainer, iommu_ctx);
+ struct vfio_iommu_type1_pasid_request req;
+
+ int ret = 0;
+
+ req.argsz = sizeof(req);
+ req.flags = VFIO_IOMMU_FLAG_FREE_PASID;
+ req.range.min = pasid;
+ req.range.max = pasid + 1;
+
+ ret = ioctl(container->fd, VFIO_IOMMU_PASID_REQUEST, &req);
+ if (ret) {
+ error_report("%s: free failed (%m)", __func__);
+ }
+ return ret;
+}
+
static int vfio_init_container(VFIOContainer *container, int group_fd,
bool want_nested, Error **errp)
{
@@ -1802,3 +1846,25 @@ int vfio_eeh_as_op(AddressSpace *as, uint32_t op)
}
return vfio_eeh_container_op(container, op);
}
+
+static void vfio_host_iommu_context_class_init(ObjectClass *klass,
+ void *data)
+{
+ HostIOMMUContextClass *hicxc = HOST_IOMMU_CONTEXT_CLASS(klass);
+
+ hicxc->pasid_alloc = vfio_host_iommu_ctx_pasid_alloc;
+ hicxc->pasid_free = vfio_host_iommu_ctx_pasid_free;
+}
+
+static const TypeInfo vfio_host_iommu_context_info = {
+ .parent = TYPE_HOST_IOMMU_CONTEXT,
+ .name = TYPE_VFIO_HOST_IOMMU_CONTEXT,
+ .class_init = vfio_host_iommu_context_class_init,
+};
+
+static void vfio_register_types(void)
+{
+ type_register_static(&vfio_host_iommu_context_info);
+}
+
+type_init(vfio_register_types)
@@ -33,6 +33,9 @@
#define TYPE_HOST_IOMMU_CONTEXT "qemu:host-iommu-context"
#define HOST_IOMMU_CONTEXT(obj) \
OBJECT_CHECK(HostIOMMUContext, (obj), TYPE_HOST_IOMMU_CONTEXT)
+#define HOST_IOMMU_CONTEXT_CLASS(klass) \
+ OBJECT_CLASS_CHECK(HostIOMMUContextClass, (klass), \
+ TYPE_HOST_IOMMU_CONTEXT)
#define HOST_IOMMU_CONTEXT_GET_CLASS(obj) \
OBJECT_GET_CLASS(HostIOMMUContextClass, (obj), \
TYPE_HOST_IOMMU_CONTEXT)
@@ -26,12 +26,15 @@
#include "qemu/notify.h"
#include "ui/console.h"
#include "hw/display/ramfb.h"
+#include "hw/iommu/host_iommu_context.h"
#ifdef CONFIG_LINUX
#include <linux/vfio.h>
#endif
#define VFIO_MSG_PREFIX "vfio %s: "
+#define TYPE_VFIO_HOST_IOMMU_CONTEXT "qemu:vfio-host-iommu-context"
+
enum {
VFIO_DEVICE_TYPE_PCI = 0,
VFIO_DEVICE_TYPE_PLATFORM = 1,
@@ -71,6 +74,7 @@ typedef struct VFIOContainer {
MemoryListener listener;
MemoryListener prereg_listener;
unsigned iommu_type;
+ HostIOMMUContext iommu_ctx;
Error *error;
bool initialized;
unsigned long pgsizes;
This patch defines vfio_host_iommu_context_info, implements the PASID alloc/free hooks defined in HostIOMMUContextClass. Cc: Kevin Tian <kevin.tian@intel.com> Cc: Jacob Pan <jacob.jun.pan@linux.intel.com> Cc: Peter Xu <peterx@redhat.com> Cc: Eric Auger <eric.auger@redhat.com> Cc: Yi Sun <yi.y.sun@linux.intel.com> Cc: David Gibson <david@gibson.dropbear.id.au> Cc: Alex Williamson <alex.williamson@redhat.com> Signed-off-by: Liu Yi L <yi.l.liu@intel.com> --- hw/vfio/common.c | 66 +++++++++++++++++++++++++++++++++++ include/hw/iommu/host_iommu_context.h | 3 ++ include/hw/vfio/vfio-common.h | 4 +++ 3 files changed, 73 insertions(+)