aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWill Deacon <will.deacon@arm.com>2014-09-29 12:06:19 -0400
committerAlex Williamson <alex.williamson@redhat.com>2014-09-29 12:06:19 -0400
commitf5c9ecebaf2a2c9381973798e389cc019dd983e0 (patch)
tree0668589b668a32145609cde83473824fbd4cfe30
parentc02607aad2f9ed478eb288bcec1c00cd9df38b3c (diff)
vfio/iommu_type1: add new VFIO_TYPE1_NESTING_IOMMU IOMMU type
VFIO allows devices to be safely handed off to userspace by putting them behind an IOMMU configured to ensure DMA and interrupt isolation. This enables userspace KVM clients, such as kvmtool and qemu, to further map the device into a virtual machine. With IOMMUs such as the ARM SMMU, it is then possible to provide SMMU translation services to the guest operating system, which are nested with the existing translation installed by VFIO. However, enabling this feature means that the IOMMU driver must be informed that the VFIO domain is being created for the purposes of nested translation. This patch adds a new IOMMU type (VFIO_TYPE1_NESTING_IOMMU) to the VFIO type-1 driver. The new IOMMU type acts identically to the VFIO_TYPE1v2_IOMMU type, but additionally sets the DOMAIN_ATTR_NESTING attribute on its IOMMU domains. Cc: Joerg Roedel <joro@8bytes.org> Signed-off-by: Will Deacon <will.deacon@arm.com> Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
-rw-r--r--drivers/vfio/vfio_iommu_type1.c30
-rw-r--r--include/uapi/linux/vfio.h3
2 files changed, 28 insertions, 5 deletions
diff --git a/drivers/vfio/vfio_iommu_type1.c b/drivers/vfio/vfio_iommu_type1.c
index 0734fbe5b651..583ccdb2c58f 100644
--- a/drivers/vfio/vfio_iommu_type1.c
+++ b/drivers/vfio/vfio_iommu_type1.c
@@ -57,7 +57,8 @@ struct vfio_iommu {
57 struct list_head domain_list; 57 struct list_head domain_list;
58 struct mutex lock; 58 struct mutex lock;
59 struct rb_root dma_list; 59 struct rb_root dma_list;
60 bool v2; 60 bool v2;
61 bool nesting;
61}; 62};
62 63
63struct vfio_domain { 64struct vfio_domain {
@@ -705,6 +706,15 @@ static int vfio_iommu_type1_attach_group(void *iommu_data,
705 goto out_free; 706 goto out_free;
706 } 707 }
707 708
709 if (iommu->nesting) {
710 int attr = 1;
711
712 ret = iommu_domain_set_attr(domain->domain, DOMAIN_ATTR_NESTING,
713 &attr);
714 if (ret)
715 goto out_domain;
716 }
717
708 ret = iommu_attach_group(domain->domain, iommu_group); 718 ret = iommu_attach_group(domain->domain, iommu_group);
709 if (ret) 719 if (ret)
710 goto out_domain; 720 goto out_domain;
@@ -819,17 +829,26 @@ static void *vfio_iommu_type1_open(unsigned long arg)
819{ 829{
820 struct vfio_iommu *iommu; 830 struct vfio_iommu *iommu;
821 831
822 if (arg != VFIO_TYPE1_IOMMU && arg != VFIO_TYPE1v2_IOMMU)
823 return ERR_PTR(-EINVAL);
824
825 iommu = kzalloc(sizeof(*iommu), GFP_KERNEL); 832 iommu = kzalloc(sizeof(*iommu), GFP_KERNEL);
826 if (!iommu) 833 if (!iommu)
827 return ERR_PTR(-ENOMEM); 834 return ERR_PTR(-ENOMEM);
828 835
836 switch (arg) {
837 case VFIO_TYPE1_IOMMU:
838 break;
839 case VFIO_TYPE1_NESTING_IOMMU:
840 iommu->nesting = true;
841 case VFIO_TYPE1v2_IOMMU:
842 iommu->v2 = true;
843 break;
844 default:
845 kfree(iommu);
846 return ERR_PTR(-EINVAL);
847 }
848
829 INIT_LIST_HEAD(&iommu->domain_list); 849 INIT_LIST_HEAD(&iommu->domain_list);
830 iommu->dma_list = RB_ROOT; 850 iommu->dma_list = RB_ROOT;
831 mutex_init(&iommu->lock); 851 mutex_init(&iommu->lock);
832 iommu->v2 = (arg == VFIO_TYPE1v2_IOMMU);
833 852
834 return iommu; 853 return iommu;
835} 854}
@@ -885,6 +904,7 @@ static long vfio_iommu_type1_ioctl(void *iommu_data,
885 switch (arg) { 904 switch (arg) {
886 case VFIO_TYPE1_IOMMU: 905 case VFIO_TYPE1_IOMMU:
887 case VFIO_TYPE1v2_IOMMU: 906 case VFIO_TYPE1v2_IOMMU:
907 case VFIO_TYPE1_NESTING_IOMMU:
888 return 1; 908 return 1;
889 case VFIO_DMA_CC_IOMMU: 909 case VFIO_DMA_CC_IOMMU:
890 if (!iommu) 910 if (!iommu)
diff --git a/include/uapi/linux/vfio.h b/include/uapi/linux/vfio.h
index 6612974c64bf..29715d27548f 100644
--- a/include/uapi/linux/vfio.h
+++ b/include/uapi/linux/vfio.h
@@ -33,6 +33,9 @@
33/* Check if EEH is supported */ 33/* Check if EEH is supported */
34#define VFIO_EEH 5 34#define VFIO_EEH 5
35 35
36/* Two-stage IOMMU */
37#define VFIO_TYPE1_NESTING_IOMMU 6 /* Implies v2 */
38
36/* 39/*
37 * The IOCTL interface is designed for extensibility by embedding the 40 * The IOCTL interface is designed for extensibility by embedding the
38 * structure length (argsz) and flags into structures passed between 41 * structure length (argsz) and flags into structures passed between