summaryrefslogtreecommitdiff
path: root/drivers/iommu/apple-dart.c
diff options
context:
space:
mode:
authorMarc Zyngier <maz@kernel.org>2021-09-29 19:38:41 +0300
committerBjorn Helgaas <bhelgaas@google.com>2021-11-05 00:29:30 +0300
commit946d619fa25f55483206befb035fed6a99fbe7b5 (patch)
tree808c519bd2557ea4061f34426800d59d94d8875d /drivers/iommu/apple-dart.c
parent476c41ed4597512f9da334be8ddf2fb2262d3057 (diff)
downloadlinux-946d619fa25f55483206befb035fed6a99fbe7b5.tar.xz
iommu/dart: Exclude MSI doorbell from PCIe device IOVA range
The MSI doorbell on Apple HW can be any address in the low 4GB range. However, the MSI write is matched by the PCIe block before hitting the iommu. It must thus be excluded from the IOVA range that is assigned to any PCIe device. Link: https://lore.kernel.org/r/20210929163847.2807812-9-maz@kernel.org Tested-by: Alyssa Rosenzweig <alyssa@rosenzweig.io> Signed-off-by: Marc Zyngier <maz@kernel.org> Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com> Signed-off-by: Bjorn Helgaas <bhelgaas@google.com> Reviewed-by: Sven Peter <sven@svenpeter.dev>
Diffstat (limited to 'drivers/iommu/apple-dart.c')
-rw-r--r--drivers/iommu/apple-dart.c27
1 files changed, 27 insertions, 0 deletions
diff --git a/drivers/iommu/apple-dart.c b/drivers/iommu/apple-dart.c
index 559db9259e65..f1f1f024c604 100644
--- a/drivers/iommu/apple-dart.c
+++ b/drivers/iommu/apple-dart.c
@@ -721,6 +721,31 @@ static int apple_dart_def_domain_type(struct device *dev)
return 0;
}
+#ifndef CONFIG_PCIE_APPLE_MSI_DOORBELL_ADDR
+/* Keep things compiling when CONFIG_PCI_APPLE isn't selected */
+#define CONFIG_PCIE_APPLE_MSI_DOORBELL_ADDR 0
+#endif
+#define DOORBELL_ADDR (CONFIG_PCIE_APPLE_MSI_DOORBELL_ADDR & PAGE_MASK)
+
+static void apple_dart_get_resv_regions(struct device *dev,
+ struct list_head *head)
+{
+ if (IS_ENABLED(CONFIG_PCIE_APPLE) && dev_is_pci(dev)) {
+ struct iommu_resv_region *region;
+ int prot = IOMMU_WRITE | IOMMU_NOEXEC | IOMMU_MMIO;
+
+ region = iommu_alloc_resv_region(DOORBELL_ADDR,
+ PAGE_SIZE, prot,
+ IOMMU_RESV_MSI);
+ if (!region)
+ return;
+
+ list_add_tail(&region->list, head);
+ }
+
+ iommu_dma_get_resv_regions(dev, head);
+}
+
static const struct iommu_ops apple_dart_iommu_ops = {
.domain_alloc = apple_dart_domain_alloc,
.domain_free = apple_dart_domain_free,
@@ -737,6 +762,8 @@ static const struct iommu_ops apple_dart_iommu_ops = {
.device_group = apple_dart_device_group,
.of_xlate = apple_dart_of_xlate,
.def_domain_type = apple_dart_def_domain_type,
+ .get_resv_regions = apple_dart_get_resv_regions,
+ .put_resv_regions = generic_iommu_put_resv_regions,
.pgsize_bitmap = -1UL, /* Restricted during dart probe */
};