@@ -1575,6 +1575,54 @@ static int vfio_get_iommu_type(VFIOContainer *container,
return ret;
}
+static int vfio_host_iommu_ctx_bind_stage1_pgtbl(HostIOMMUContext *iommu_ctx,
+ struct iommu_gpasid_bind_data *bind)
+{
+ VFIOContainer *container = container_of(iommu_ctx,
+ VFIOContainer, iommu_ctx);
+ struct vfio_iommu_type1_nesting_op *op;
+ unsigned long argsz;
+ int ret = 0;
+
+ argsz = sizeof(*op) + sizeof(*bind);
+ op = g_malloc0(argsz);
+ op->argsz = argsz;
+ op->flags = VFIO_IOMMU_NESTING_OP_BIND_PGTBL;
+ memcpy(&op->data, bind, sizeof(*bind));
+
+ if (ioctl(container->fd, VFIO_IOMMU_NESTING_OP, op)) {
+ ret = -errno;
+ error_report("%s: pasid (%llu) bind failed: %m",
+ __func__, bind->hpasid);
+ }
+ g_free(op);
+ return ret;
+}
+
+static int vfio_host_iommu_ctx_unbind_stage1_pgtbl(HostIOMMUContext *iommu_ctx,
+ struct iommu_gpasid_bind_data *unbind)
+{
+ VFIOContainer *container = container_of(iommu_ctx,
+ VFIOContainer, iommu_ctx);
+ struct vfio_iommu_type1_nesting_op *op;
+ unsigned long argsz;
+ int ret = 0;
+
+ argsz = sizeof(*op) + sizeof(*unbind);
+ op = g_malloc0(argsz);
+ op->argsz = argsz;
+ op->flags = VFIO_IOMMU_NESTING_OP_UNBIND_PGTBL;
+ memcpy(&op->data, unbind, sizeof(*unbind));
+
+ if (ioctl(container->fd, VFIO_IOMMU_NESTING_OP, op)) {
+ ret = -errno;
+ error_report("%s: pasid (%llu) unbind failed: %m",
+ __func__, unbind->hpasid);
+ }
+ g_free(op);
+ return ret;
+}
+
static int vfio_init_container(VFIOContainer *container, int group_fd,
bool want_nested, Error **errp)
{
@@ -2268,3 +2316,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->bind_stage1_pgtbl = vfio_host_iommu_ctx_bind_stage1_pgtbl;
+ hicxc->unbind_stage1_pgtbl = vfio_host_iommu_ctx_unbind_stage1_pgtbl;
+}
+
+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,6 +26,7 @@
#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
@@ -33,6 +34,8 @@
#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,
This patch adds support for HostIOMMUContext, implements bind_stage1_pgtbl() and unbind_stage1_pgtbl() for vIOMMU to setup dual stage DMA translation for passthru devices on hardware. 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 | 70 +++++++++++++++++++++++++++ include/hw/iommu/host_iommu_context.h | 3 ++ include/hw/vfio/vfio-common.h | 3 ++ 3 files changed, 76 insertions(+)