From d7ccfb5297261d2781b3e29c2636ac94e9194569 Mon Sep 17 00:00:00 2001 From: James Sewart Date: Thu, 7 Mar 2019 17:57:15 +0000 Subject: [PATCH 3/9] iommu/vt-d: Expose ISA direct mapping region via iommu_get_resv_regions To support mapping ISA region via iommu_group_create_direct_mappings, make sure its exposed by iommu_get_resv_regions. This allows deduplication of reserved region mappings Signed-off-by: James Sewart diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c index 3caa7b6fcdde..1075a7c74507 100644 --- a/drivers/iommu/intel-iommu.c +++ b/drivers/iommu/intel-iommu.c @@ -339,6 +339,8 @@ static LIST_HEAD(dmar_rmrr_units); #define for_each_rmrr_units(rmrr) \ list_for_each_entry(rmrr, &dmar_rmrr_units, list) +static struct iommu_resv_region *isa_resv_region; + /* bitmap for indexing intel_iommus */ static int g_num_of_iommus; @@ -2782,26 +2784,34 @@ static inline int iommu_prepare_rmrr_dev(struct dmar_rmrr_unit *rmrr, rmrr->end_address); } +static inline struct iommu_resv_region *iommu_get_isa_resv_region(void) +{ + if (!isa_resv_region) + isa_resv_region = iommu_alloc_resv_region(0, + 16*1024*1024, + 0, IOMMU_RESV_DIRECT); + + return isa_resv_region; +} + #ifdef CONFIG_INTEL_IOMMU_FLOPPY_WA -static inline void iommu_prepare_isa(void) +static inline void iommu_prepare_isa(struct pci_dev *pdev) { - struct pci_dev *pdev; int ret; + struct iommu_resv_region *reg = iommu_get_isa_resv_region(); - pdev = pci_get_class(PCI_CLASS_BRIDGE_ISA << 8, NULL); - if (!pdev) + if (!reg) return; pr_info("Prepare 0-16MiB unity mapping for LPC\n"); - ret = iommu_prepare_identity_map(&pdev->dev, 0, 16*1024*1024 - 1); + ret = iommu_prepare_identity_map(&pdev->dev, reg->start, + reg->start + reg->length - 1); if (ret) pr_err("Failed to create 0-16MiB identity map - floppy might not work\n"); - - pci_dev_put(pdev); } #else -static inline void iommu_prepare_isa(void) +static inline void iommu_prepare_isa(struct pci_dev *pdev) { return; } @@ -3290,6 +3300,7 @@ static int __init init_dmars(void) struct dmar_rmrr_unit *rmrr; bool copied_tables = false; struct device *dev; + struct pci_dev *pdev; struct intel_iommu *iommu; int i, ret; @@ -3470,7 +3481,11 @@ static int __init init_dmars(void) } } - iommu_prepare_isa(); + pdev = pci_get_class(PCI_CLASS_BRIDGE_ISA << 8, NULL); + if (pdev) { + iommu_prepare_isa(pdev); + pci_dev_put(pdev); + } domains_done: @@ -5274,6 +5289,7 @@ static void intel_iommu_get_resv_regions(struct device *device, struct iommu_resv_region *reg; struct dmar_rmrr_unit *rmrr; struct device *i_dev; + struct pci_dev *pdev; int i; rcu_read_lock(); @@ -5288,6 +5304,14 @@ static void intel_iommu_get_resv_regions(struct device *device, } rcu_read_unlock(); + if (dev_is_pci(device)) { + pdev = to_pci_dev(device); + if ((pdev->class >> 8) == PCI_CLASS_BRIDGE_ISA) { + reg = iommu_get_isa_resv_region(); + list_add_tail(®->list, head); + } + } + reg = iommu_alloc_resv_region(IOAPIC_RANGE_START, IOAPIC_RANGE_END - IOAPIC_RANGE_START + 1, 0, IOMMU_RESV_MSI); -- 2.17.1