@@ -29,6 +29,7 @@
#include <linux/of_platform.h>
#include <linux/percpu.h>
#include <linux/slab.h>
+#include <linux/vfio.h>
#include <linux/irqchip.h>
#include <linux/irqchip/arm-gic-v3.h>
@@ -1257,8 +1258,38 @@ out:
return 0;
}
+#if IS_ENABLED(CONFIG_VFIO)
+
+static int its_vfio_map(struct irq_domain *domain,
+ const struct vfio_iommu_driver_ops *ops,
+ void *iommu_data)
+{
+ struct msi_domain_info *msi_info = msi_get_domain_info(domain);
+ struct its_node *its = msi_info->data;
+ u64 addr = its->phys_base + GIC_V3_ITS_CONTROL_SIZE;
+
+ return ops->map(iommu_data, addr, addr, 1, IOMMU_READ|IOMMU_WRITE);
+}
+
+static void its_vfio_unmap(struct irq_domain *domain,
+ const struct vfio_iommu_driver_ops *ops,
+ void *iommu_data)
+{
+ struct msi_domain_info *msi_info = msi_get_domain_info(domain);
+ struct its_node *its = msi_info->data;
+ u64 addr = its->phys_base + GIC_V3_ITS_CONTROL_SIZE;
+
+ ops->unmap(iommu_data, addr, 1);
+}
+
+#endif
+
static struct msi_domain_ops its_msi_domain_ops = {
.msi_prepare = its_msi_prepare,
+#if IS_ENABLED(CONFIG_VFIO)
+ .vfio_map = its_vfio_map,
+ .vfio_unmap = its_vfio_unmap,
+#endif
};
static int its_irq_gic_domain_alloc(struct irq_domain *domain,
@@ -241,6 +241,8 @@
#define GITS_BASER_TYPE_RESERVED6 6
#define GITS_BASER_TYPE_RESERVED7 7
+#define GIC_V3_ITS_CONTROL_SIZE 0x10000
+
/*
* ITS commands
*/
@@ -155,6 +155,8 @@ void arch_restore_msi_irqs(struct pci_dev *dev);
void default_teardown_msi_irqs(struct pci_dev *dev);
void default_restore_msi_irqs(struct pci_dev *dev);
+struct vfio_iommu_driver_ops;
+
struct msi_controller {
struct module *owner;
struct device *dev;
@@ -189,6 +191,8 @@ struct msi_domain_info;
* @msi_finish: Optional callbacl to finalize the allocation
* @set_desc: Set the msi descriptor for an interrupt
* @handle_error: Optional error handler if the allocation fails
+ * @vfio_map: Map the MSI hardware for VFIO
+ * @vfio_unmap: Unmap the MSI hardware for VFIO
*
* @get_hwirq, @msi_init and @msi_free are callbacks used by
* msi_create_irq_domain() and related interfaces
@@ -218,6 +222,14 @@ struct msi_domain_ops {
struct msi_desc *desc);
int (*handle_error)(struct irq_domain *domain,
struct msi_desc *desc, int error);
+#if IS_ENABLED(CONFIG_VFIO)
+ int (*vfio_map)(struct irq_domain *domain,
+ const struct vfio_iommu_driver_ops *ops,
+ void *iommu_data);
+ void (*vfio_unmap)(struct irq_domain *domain,
+ const struct vfio_iommu_driver_ops *ops,
+ void *iommu_data);
+#endif
};
/**
These new functions use the supplied IOMMU in order to map and unmap MSI translation register(s). Signed-off-by: Pavel Fedin <p.fedin@samsung.com> --- drivers/irqchip/irq-gic-v3-its.c | 31 +++++++++++++++++++++++++++++++ include/linux/irqchip/arm-gic-v3.h | 2 ++ include/linux/msi.h | 12 ++++++++++++ 3 files changed, 45 insertions(+)