IA64 Compilation error fix for Intel IOMMU identity mapping The Intel IOMMU identity mapping uses e820 to walk the memory map. This causes compilation error on IA64 when IOMMU is configured: drivers/pci/intel-iommu.c:42:22: error: asm/e820.h: No such file or directory This patch fixes this compilation error on IA64. It defines architecture dependent memory map walk functions on x86 and ia64 seperately to set up identity mapping for all devices. Signed-off-by: Fenghua Yu <fenghua.yu@xxxxxxxxx> Acked-by: Tony Luck <tony.luck@xxxxxxxxx> --- This patch is against the latest upstream tree. arch/ia64/kernel/pci-dma.c | 27 +++++++++++++++++++++++++++ arch/x86/kernel/pci-dma.c | 22 ++++++++++++++++++++++ drivers/pci/intel-iommu.c | 38 ++++++++++++++++++++++---------------- include/linux/intel-iommu.h | 4 ++++ 4 files changed, 75 insertions(+), 16 deletions(-) diff --git a/arch/ia64/kernel/pci-dma.c b/arch/ia64/kernel/pci-dma.c index 0569596..9cb3700 100644 --- a/arch/ia64/kernel/pci-dma.c +++ b/arch/ia64/kernel/pci-dma.c @@ -10,7 +10,9 @@ #include <linux/dmar.h> #include <asm/iommu.h> #include <asm/machvec.h> +#include <linux/efi.h> #include <linux/dma-mapping.h> +#include <linux/intel-iommu.h> #include <asm/system.h> @@ -122,4 +124,29 @@ void __init pci_iommu_alloc(void) #endif } +static int __initdata identity_mapped = 1; + +static int __init __iommu_prepare_identity_map(u64 start, u64 end, void *pdev) +{ + int ret; + + ret = iommu_prepare_identity_map((struct pci_dev *)pdev, start, end); + if (ret) { + printk(KERN_INFO "1:1 mapping to one domain failed.\n"); + identity_mapped = 0; + return -EFAULT; + } + + return 0; +} + +int __init iommu_setup_identity_map(struct pci_dev *pdev) +{ + efi_memmap_walk(__iommu_prepare_identity_map, pdev); + if (!identity_mapped) + return -EFAULT; + + return 0; +} + #endif diff --git a/arch/x86/kernel/pci-dma.c b/arch/x86/kernel/pci-dma.c index 4763047..775ece5 100644 --- a/arch/x86/kernel/pci-dma.c +++ b/arch/x86/kernel/pci-dma.c @@ -10,6 +10,7 @@ #include <asm/gart.h> #include <asm/calgary.h> #include <asm/amd_iommu.h> +#include <linux/intel-iommu.h> static int forbid_dac __read_mostly; @@ -314,3 +315,24 @@ static __devinit void via_no_dac(struct pci_dev *dev) } DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA, PCI_ANY_ID, via_no_dac); #endif + +int iommu_setup_identity_map(struct pci_dev *pdev) +{ + int i; + int ret; + + for (i = 0; i < e820.nr_map; i++) { + struct e820entry *ei = &e820.map[i]; + + if (ei->type == E820_RAM) { + ret = iommu_prepare_identity_map(pdev, + ei->addr, ei->addr + ei->size); + if (ret) { + printk(KERN_INFO "1:1 mapping to one domain failed.\n"); + return -EFAULT; + } + } + } + + return 0; +} diff --git a/drivers/pci/intel-iommu.c b/drivers/pci/intel-iommu.c index e53eacd..009a79a 100644 --- a/drivers/pci/intel-iommu.c +++ b/drivers/pci/intel-iommu.c @@ -39,7 +39,6 @@ #include <linux/sysdev.h> #include <asm/cacheflush.h> #include <asm/iommu.h> -#include <asm/e820.h> #include "pci.h" #define ROOT_SIZE VTD_PAGE_SIZE @@ -1845,9 +1844,8 @@ error: static int iommu_identity_mapping; -static int iommu_prepare_identity_map(struct pci_dev *pdev, - unsigned long long start, - unsigned long long end) +int iommu_prepare_identity_map(struct pci_dev *pdev, unsigned long long start, + unsigned long long end) { struct dmar_domain *domain; unsigned long size; @@ -2081,8 +2079,8 @@ static int domain_add_dev_info(struct dmar_domain *domain, static int iommu_prepare_static_identity_mapping(void) { - int i; struct pci_dev *pdev = NULL; + int first_pdev = 1; int ret; ret = si_domain_init(); @@ -2091,17 +2089,25 @@ static int iommu_prepare_static_identity_mapping(void) printk(KERN_INFO "IOMMU: Setting identity map:\n"); for_each_pci_dev(pdev) { - for (i = 0; i < e820.nr_map; i++) { - struct e820entry *ei = &e820.map[i]; - - if (ei->type == E820_RAM) { - ret = iommu_prepare_identity_map(pdev, - ei->addr, ei->addr + ei->size); - if (ret) { - printk(KERN_INFO "1:1 mapping to one domain failed.\n"); - return -EFAULT; - } - } + if (first_pdev) { + /* + * first pdev sets up the whole page table for + * si_domain. + */ + first_pdev = 0; + ret = iommu_setup_identity_map(pdev); + if (ret) + return ret; + } else { + /* + * following pdev's just use the page table. + */ + printk(KERN_INFO "IOMMU: identity mapping for device %s\n", + pci_name(pdev)); + ret = domain_context_mapping(si_domain, pdev, + CONTEXT_TT_MULTI_LEVEL); + if (ret) + return ret; } ret = domain_add_dev_info(si_domain, pdev); if (ret) diff --git a/include/linux/intel-iommu.h b/include/linux/intel-iommu.h index 482dc91..5d470cf 100644 --- a/include/linux/intel-iommu.h +++ b/include/linux/intel-iommu.h @@ -359,5 +359,9 @@ extern void qi_flush_dev_iotlb(struct intel_iommu *iommu, u16 sid, u16 qdep, u64 addr, unsigned mask); extern int qi_submit_sync(struct qi_desc *desc, struct intel_iommu *iommu); +extern int iommu_prepare_identity_map(struct pci_dev *pdev, + unsigned long long start, + unsigned long long end); +extern int iommu_setup_identity_map(struct pci_dev *pdev); #endif -- To unsubscribe from this list: send the line "unsubscribe linux-ia64" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html
![]() |