Add Variable Page Size and IA64 Support in Intel IOMMU: IA64 Specific Part
Subsystems (4)
PATCH 2/2 Add Variable Page Size and IA64 Support in Intel IOMMU: IA64 Specific Part
---
Kconfig | 17 ++++ Makefile | 1 configs/generic_defconfig | 2 configs/tiger_defconfig | 2 dig/Makefile | 2 dig/dig_vtd_iommu.c | 59 +++++++++++++++++ dig/machvec_vtd.c | 3 include/asm/cacheflush.h | 2 include/asm/device.h | 3 include/asm/dma-mapping.h | 50 ++++++++++++++ include/asm/iommu.h | 11 +++ include/asm/machvec.h | 2 include/asm/machvec_dig_vtd.h | 38 +++++++++++ include/asm/machvec_init.h | 1 include/asm/pci.h | 3 include/asm/swiotlb.h | 56 ++++++++++++++++ kernel/Makefile | 4 + kernel/acpi.c | 17 ++++ kernel/msi_ia64.c | 80 +++++++++++++++++++++++ kernel/pci-dma.c | 143 ++++++++++++++++++++++++++++++++++++++++++ kernel/pci-swiotlb.c | 46 +++++++++++++ kernel/setup.c | 42 ++++++++---- lib/flush.S | 55 ++++++++++++++++ 23 files changed, 626 insertions(+), 13 deletions(-)
arch/ia64/Kconfig +17 -0
@@ -125,6 +125,7 @@ config IA64_GENERIC select NUMA select ACPI_NUMA select SWIOTLB + select PCI_MSI help This selects the system type of your hardware. A "generic" kernel will run on any supported IA-64 system. However, if you configure
@@ -132,6 +133,7 @@ config IA64_GENERIC generic For any supported IA-64 system DIG-compliant For DIG ("Developer's Interface Guide") compliant systems + DIG+Intel+IOMMU For DIG systems with Intel IOMMU HP-zx1/sx1000 For HP systems HP-zx1/sx1000+swiotlb For HP systems with (broken) DMA-constrained devices. SGI-SN2 For SGI Altix systems
@@ -144,6 +146,11 @@ config IA64_DIG bool "DIG-compliant" select SWIOTLB +config IA64_DIG_VTD + bool "DIG+Intel+IOMMU" + select DMAR + select PCI_MSI + config IA64_HP_ZX1 bool "HP-zx1/sx1000" help
@@ -589,6 +596,16 @@ source "drivers/pci/hotplug/Kconfig" source "drivers/pcmcia/Kconfig" +config DMAR + bool "Support for DMA Remapping Devices (EXPERIMENTAL)" + depends on IA64_GENERIC && ACPI && EXPERIMENTAL + help + DMA remapping (DMAR) devices support enables independent address + translations for Direct Memory Access (DMA) from devices. + These DMA remapping devices are reported via ACPI tables + and include PCI device scope covered by these DMA + remapping devices. + endmenu endif
arch/ia64/Makefile +1 -0
@@ -53,6 +53,7 @@ libs-y += arch/ia64/lib/ core-y += arch/ia64/kernel/ arch/ia64/mm/ core-$(CONFIG_IA32_SUPPORT) += arch/ia64/ia32/ core-$(CONFIG_IA64_DIG) += arch/ia64/dig/ +core-$(CONFIG_IA64_DIG_VTD) += arch/ia64/dig/ core-$(CONFIG_IA64_GENERIC) += arch/ia64/dig/ core-$(CONFIG_IA64_HP_ZX1) += arch/ia64/dig/ core-$(CONFIG_IA64_HP_ZX1_SWIOTLB) += arch/ia64/dig/
arch/ia64/configs/generic_defconfig +2 -0
@@ -233,6 +233,8 @@ CONFIG_DMIID=y CONFIG_BINFMT_ELF=y CONFIG_BINFMT_MISC=m +# CONFIG_DMAR is not set + # # Power management and ACPI #
arch/ia64/configs/tiger_defconfig +2 -0
@@ -172,6 +172,8 @@ CONFIG_DMIID=y CONFIG_BINFMT_ELF=y CONFIG_BINFMT_MISC=m +# CONFIG_DMAR is not set + # # Power management and ACPI #
arch/ia64/dig/Makefile +2 -0
@@ -7,3 +7,5 @@ obj-y := setup.o obj-$(CONFIG_IA64_GENERIC) += machvec.o +obj-$(CONFIG_DMAR) += machvec_vtd.o dig_vtd_iommu.o +obj-$(CONFIG_IA64_DIG_VTD) += dig_vtd_iommu.o
arch/ia64/dig/dig_vtd_iommu.c new file +59 -0
59 lines not on this page · raw message
arch/ia64/dig/machvec_vtd.c new file +3 -0
@@ -0,0 +1,3 @@ +#define MACHVEC_PLATFORM_NAME dig_vtd +#define MACHVEC_PLATFORM_HEADER <asm/machvec_dig_vtd.h> +#include <asm/machvec_init.h>
arch/ia64/include/asm/cacheflush.h +2 -0
@@ -34,6 +34,8 @@ do { \#define flush_dcache_mmap_unlock (mapping) do { } while (0)extern void flush_icache_range (unsigned long start,unsigned long end); +extern void clflush_cache_range (void *addr,int size); +#define flush_icache_user_range (vma, page, user_addr, len) \ do { \
arch/ia64/include/asm/device.h +3 -0
@@ -10,6 +10,9 @@ struct dev_archdata {#ifdef CONFIG_ACPI void *acpi_handle;#endif +#ifdef CONFIG_DMAR +void *iommu;/* hook for IOMMU specific extension */ +#endif };#endif /* _ASM_IA64_DEVICE_H */
arch/ia64/include/asm/dma-mapping.h +50 -0
60 lines not on this page · raw message
arch/ia64/include/asm/iommu.h new file +11 -0
@@ -0,0 +1,11 @@ +#ifndef _ASM_IA64_IOMMU_H +#define _ASM_IA64_IOMMU_H 1 + +extern void pci_iommu_shutdown (void ); +extern void no_iommu_init (void ); +extern int force_iommu, no_iommu; +extern int iommu_detected; +extern void iommu_dma_init (void ); +extern void machvec_init (const char *name); + +#endif
arch/ia64/include/asm/machvec.h +2 -0
@@ -120,6 +120,8 @@ extern void machvec_tlb_migrate_finish (struct mm_struct *);# include <asm/machvec_hpsim.h> # elif defined (CONFIG_IA64_DIG )# include <asm/machvec_dig.h> +# elif defined(CONFIG_IA64_DIG_VTD ) +# include <asm/machvec_dig_vtd.h> # elif defined (CONFIG_IA64_HP_ZX1 )# include <asm/machvec_hpzx1.h> # elif defined (CONFIG_IA64_HP_ZX1_SWIOTLB )
arch/ia64/include/asm/machvec_dig_vtd.h new file +38 -0
@@ -0,0 +1,38 @@ +#ifndef _ASM_IA64_MACHVEC_DIG_VTD_h +#define _ASM_IA64_MACHVEC_DIG_VTD_h + +extern ia64_mv_setup_t dig_setup; +extern ia64_mv_dma_alloc_coherent vtd_alloc_coherent; +extern ia64_mv_dma_free_coherent vtd_free_coherent; +extern ia64_mv_dma_map_single_attrs vtd_map_single_attrs; +extern ia64_mv_dma_unmap_single_attrs vtd_unmap_single_attrs; +extern ia64_mv_dma_map_sg_attrs vtd_map_sg_attrs; +extern ia64_mv_dma_unmap_sg_attrs vtd_unmap_sg_attrs; +extern ia64_mv_dma_supported iommu_dma_supported; +extern ia64_mv_dma_mapping_error vtd_dma_mapping_error; +extern ia64_mv_dma_init pci_iommu_alloc; + +/* +* This stuff has dual use! +* +* For a generic kernel, the macros are used to initialize the +* platform's machvec structure. When compiling a non-generic kernel, +* the macros are used directly. +*/ +#define platform_name "dig_vtd" +#define platform_setup dig_setup +#define platform_dma_init pci_iommu_alloc +#define platform_dma_alloc_coherent vtd_alloc_coherent +#define platform_dma_free_coherent vtd_free_coherent +#define platform_dma_map_single_attrs vtd_map_single_attrs +#define platform_dma_unmap_single_attrs vtd_unmap_single_attrs +#define platform_dma_map_sg_attrs vtd_map_sg_attrs +#define platform_dma_unmap_sg_attrs vtd_unmap_sg_attrs +#define platform_dma_sync_single_for_cpu machvec_dma_sync_single +#define platform_dma_sync_sg_for_cpu machvec_dma_sync_sg +#define platform_dma_sync_single_for_device machvec_dma_sync_single +#define platform_dma_sync_sg_for_device machvec_dma_sync_sg +#define platform_dma_supported iommu_dma_supported +#define platform_dma_mapping_error vtd_dma_mapping_error + +#endif /* _ASM_IA64_MACHVEC_DIG_VTD_h */
arch/ia64/include/asm/machvec_init.h +1 -0
@@ -1,3 +1,4 @@ +#include <asm/iommu.h> #include <asm/machvec.h> extern ia64_mv_send_ipi_t ia64_send_ipi;
arch/ia64/include/asm/pci.h +3 -0
@@ -164,4 +164,7 @@ static inline int pci_get_legacy_ide_irq(struct pci_dev *dev, int channel) return channel ? isa_irq_to_vector(15) : isa_irq_to_vector(14); } +#ifdef CONFIG_DMAR +extern void pci_iommu_alloc (void ); +#endif #endif /* _ASM_IA64_PCI_H */
arch/ia64/include/asm/swiotlb.h new file +56 -0
56 lines not on this page · raw message
arch/ia64/kernel/Makefile +4 -0
@@ -42,6 +42,10 @@ obj-$(CONFIG_IA64_ESI) += esi.o ifneq ($(CONFIG_IA64_ESI),) obj-y += esi_stub.o # must be in kernel proper endif +obj-$(CONFIG_DMAR) += pci-dma.o +ifeq ($(CONFIG_DMAR), y) +obj-$(CONFIG_SWIOTLB) += pci-swiotlb.o +endif # The gate DSO image is built using a special linker script. targets += gate.so gate-syms.o
arch/ia64/kernel/acpi.c +17 -0
@@ -91,6 +91,9 @@ acpi_get_sysname(void)struct acpi_table_rsdp *rsdp;struct acpi_table_xsdt *xsdt;struct acpi_table_header *hdr; +#ifdef CONFIG_DMAR +u64 i, nentries; +#endif rsdp_phys =acpi_find_rsdp ();if (!rsdp_phys) {
@@ -123,6 +126,18 @@ acpi_get_sysname(void) return "sn2"; } +#ifdef CONFIG_DMAR +/* Look for Intel IOMMU */ + nentries = (hdr->length -sizeof (*hdr)) / +sizeof (xsdt->table_offset_entry[0 ]); +for (i =0 ; i < nentries; i++) { + hdr =__va (xsdt->table_offset_entry[i]); +if (strncmp (hdr->signature,ACPI_SIG_DMAR , +sizeof (ACPI_SIG_DMAR ) -1 ) =0 ) +return "dig_vtd" ; + } +#endif +return "dig" ;#else # if defined (CONFIG_IA64_HP_SIM )
@@ -137,6 +152,8 @@ acpi_get_sysname(void)return "uv" ;# elif defined (CONFIG_IA64_DIG )return "dig" ; +# elif defined(CONFIG_IA64_DIG_VTD ) +return "dig_vtd" ;# else # error Unknown platform. Fix acpi.c.# endif
arch/ia64/kernel/msi_ia64.c +78 -0
87 lines not on this page · raw message
arch/ia64/kernel/pci-dma.c new file +143 -0
143 lines not on this page · raw message
arch/ia64/kernel/pci-swiotlb.c new file +46 -0
46 lines not on this page · raw message
arch/ia64/kernel/setup.c +29 -13
82 lines not on this page · raw message
arch/ia64/lib/flush.S +54 -0
57 lines not on this page · raw message
arch/ia64/include/asm/cacheflush.h do { \ · line 37
Quoted 7 lines · Fenghua Yu
arch/ia64/include/asm/cacheflush.h +1
-0@@ -34,6 +34,8 @@ do { \#define flush_dcache_mmap_unlock (mapping) do { } while (0)extern void flush_icache_range (unsigned long start,unsigned long end); +extern void clflush_cache_range (void *addr,int size);
This patch adds clflush_cache_range(), but it's not used anywhere.
If you do need it, it'd be nice if the arguments were the same types as for flush_icache_range(), and if there were a comment describing why it is necessary for VT-d. And maybe the name could be more like the other cache flushing functions.
arch/ia64/include/asm/cacheflush.h do { \
Quoted 7 lines
arch/ia64/include/asm/cacheflush.h +7
-0+#ifdef CONFIG_PCI +/* Many VIA bridges seem to corrupt data for DAC. Disable it here */ + +static __devinit void via_no_dac (struct pci_dev *dev) +{ +if ((dev->class >>8 ) =PCI_CLASS_BRIDGE_PCI && forbid_dac =0 ) { +printk (KERN_INFO "PCI: VIA PCI bridge detected. Disabling DAC.\n" );
Please use dev_info() here. I see you just copied this from x86, but we should fix x86, too. Or better, since this doesn't appear to be arch-specific, maybe this should be moved to drivers/pci/quirks.c alongside all the other VIA quirks.
arch/ia64/include/asm/cacheflush.h
Quoted 1 line
arch/ia64/include/asm/cacheflush.h +1
-0+ forbid_dac =1 ;
Shouldn't forbid_dac be a per-device or at least a per-bridge property rather than a global?
Quoted 7 lines
arch/ia64/include/asm/cacheflush.h +7
-0+ } +} +DECLARE_PCI_FIXUP_FINAL (PCI_VENDOR_ID_VIA ,PCI_ANY_ID , via_no_dac); +#endif +/* Must execute after PCI subsystem */ +fs_initcall (pci_iommu_init); +
arch/ia64/include/asm/cacheflush.h
Quoted 10 lines
arch/ia64/include/asm/cacheflush.h +10
-0+struct dma_mapping_ops *dma_ops; +EXPORT_SYMBOL (dma_ops); + +int iommu_dma_supported (struct device *dev,u64 mask) +{ +struct dma_mapping_ops *ops =get_dma_ops (dev); + +#ifdef CONFIG_PCI +if (mask >0xffffffff && forbid_dac >0 ) { +dev_info (dev,"PCI: Disallowing DAC for device\n" );
The "PCI: " should be removed since dev_info() will add the driver name and device ID.
Bjorn
Quoted 9 lines
arch/ia64/include/asm/cacheflush.h do { \ · line 37
Quoted 7 lines
arch/ia64/include/asm/cacheflush.h +1
-0@@ -34,6 +34,8 @@ do { \#define flush_dcache_mmap_unlock (mapping) do { } while (0)extern void flush_icache_range (unsigned long start,unsigned long end); +extern void clflush_cache_range (void *addr,int size);This patch adds
clflush_cache_range(), but it's not used anywhere.
Clflush_cache_range() is used in __iommu_flush_cache() in include/linux/intel-iommu.h.
Quoted 4 lines
If you do need it, it'd be nice if the arguments were the same types as for
flush_icache_range(), and if there were a comment describing why it is necessary for VT-d. And maybe the name could be more like the other cache flushing functions.
Since clflush_cache_range(start, size) is defined in x86, I just want to keep the same definition. So this patch set won't change __iommu_flush_cache(). Otherwise, the patch set will have #ifdef CONFIG_IA64 in __iommu_flush_cache() which is not desired.
Does this make sense?
Quoted 4 lines
Quoted 4 lines
arch/ia64/include/asm/cacheflush.h +4
-0+#ifdef CONFIG_PCI +/* Many VIA bridges seem to corrupt data for DAC. Disable it here */ + +static __devinit void via_no_dac (struct pci_dev *dev)
Quoted 8 lines
arch/ia64/include/asm/cacheflush.h do { \
Quoted 3 lines
arch/ia64/include/asm/cacheflush.h +3
-0+{ +if ((dev->class >>8 ) =PCI_CLASS_BRIDGE_PCI && forbid_dac =0 ) { +printk (KERN_INFO "PCI: VIA PCI bridge detected. Disabling DAC.\n" );Please use
dev_info()here. I see you just copied this from x86, but we should fix x86, too. Or better, since this doesn't appear to be arch-specific, maybe this should be moved todrivers/pci/quirks.calongside all the other VIA quirks.
I'll move this to drivers/pci/quirks.c and use dev_info().
Quoted 4 lines
Quoted 1 line
+
forbid_dac= 1;Shouldn't
forbid_dacbe a per-device or at least a per-bridge property rather than a global?
This patch set is mainly for IA64 porting purpose. I will use the same forbid dac code as x86-64 and will send a follow-up patch to deal with forbid dac.
Quoted 12 lines
Quoted 12 lines
arch/ia64/include/asm/cacheflush.h +12
-0+ } +} +DECLARE_PCI_FIXUP_FINAL (PCI_VENDOR_ID_VIA ,PCI_ANY_ID , via_no_dac); +#endif +/* Must execute after PCI subsystem */ +fs_initcall (pci_iommu_init); + +struct dma_mapping_ops *dma_ops; +EXPORT_SYMBOL (dma_ops); + +int iommu_dma_supported (struct device *dev,u64 mask) +{
Quoted 8 lines
arch/ia64/include/asm/cacheflush.h
Quoted 5 lines
arch/ia64/include/asm/cacheflush.h +5
-0+struct dma_mapping_ops *ops =get_dma_ops (dev); + +#ifdef CONFIG_PCI +if (mask >0xffffffff && forbid_dac >0 ) { +dev_info (dev,"PCI: Disallowing DAC for device\n" );The "PCI: " should be removed since
dev_info()will add the driver name and device ID.
Will change this.
Bjorn
--
To unsubscribe from this list: send the line "unsubscribe linux-ia64" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Quoted 10 lines · Fenghua
Quoted 9 lines
arch/ia64/include/asm/cacheflush.h do { \ · line 37
Quoted 7 lines
arch/ia64/include/asm/cacheflush.h +1
-0@@ -34,6 +34,8 @@ do { \#define flush_dcache_mmap_unlock (mapping) do { } while (0)extern void flush_icache_range (unsigned long start,unsigned long end); +extern void clflush_cache_range (void *addr,int size);This patch adds
clflush_cache_range(), but it's not used anywhere.
Clflush_cache_range()is used in__iommu_flush_cache()ininclude/linux/intel-iommu.h.
Oh, OK. I didn't look hard enough to find __iommu_flush_cache() (currently in drivers/pci/intel-iommu.c).
Architecturally, I'm surprised that ia64 would need to actually do a cache flush. I would think the VT-d hardware would do coherent accesses which would make the cache flush unnecessary.
Bjorn
Quoted 9 lines
Quoted 2 lines
Quoted 1 line
This patch adds
clflush_cache_range(), but it's not used anywhere.
Clflush_cache_range()is used in__iommu_flush_cache()ininclude/linux/intel-iommu.h.Oh, OK. I didn't look hard enough to find
__iommu_flush_cache()(currently indrivers/pci/intel-iommu.c).Architecturally, I'm surprised that ia64 would need to actually do a cache flush. I would think the VT-d hardware would do coherent accesses which would make the cache flush unnecessary.
VT-d hardware supports both non cache coherency and cache coherency by bit Coherency in Extended Capabilities Register.
Could you please point me to the doc that explicitly says that architecturally ia64 doesn't need cache flush?
Thanks.
-Fenghua
Quoted 6 lines · Fenghua
Quoted 2 lines
Architecturally, I'm surprised that ia64 would need to actually do a cache flush. I would think the VT-d hardware would do coherent
accesses which would make the cache flush unnecessary.
VT-d hardware supports both non cache coherency and cache coherency by bit Coherency in Extended Capabilities Register.
But is the version without the cache coherency actually going to be _seen_ on IA64?
Quoted 2 lines
Could you please point me to the doc that explicitly says that architecturally ia64 doesn't need cache flush?
For safety, we can always make the driver just refuse to initialise on IA64 if the cache coherency bit isn't set.
Signature · 2 lines
David Woodhouse Open Source Technology Centre [email protected] Intel Corporation
Quoted 6 lines
Quoted 2 lines
VT-d hardware supports both non cache coherency and cache coherency by bit Coherency in Extended Capabilities Register.
But is the version without the cache coherency actually going to be _seen_ on IA64?
Currently there is only one IA64 platform CraterLake supporting VT-d. Its BIOS sets cache coherency bit. But since there is no architecture spec saying cache coherency is required for all ia64 platforms, non cache coherency could be seen in future platforms having VT-d. And one VT-d architect explicitly tell me that ia64 Linux IOMMU needs to deal with non cache coherency case and flush cache line for non cache coherency case (just like x86-64 is doing).
Quoted 5 lines
Quoted 2 lines
Could you please point me to the doc that explicitly says that architecturally ia64 doesn't need cache flush?
For safety, we can always make the driver just refuse to initialise on IA64 if the cache coherency bit isn't set.
The current patch set works just fine for both cache coherency and non cache coherency. We don't need to abandon non cache coherency support on ia64 unless there is explicit spec claiming that non cache coherency is a requirement on all ia64 platforms.
Thanks.
-Fenghua
Quoted 6 lines · Fenghua
Quoted 5 lines
Quoted 2 lines
Quoted 1 line
This patch adds
clflush_cache_range(), but it's not used anywhere.
Clflush_cache_range()is used in__iommu_flush_cache()ininclude/linux/intel-iommu.h.Oh, OK. I didn't look hard enough to find
__iommu_flush_cache()(currently indrivers/pci/intel-iommu.c).
Quoted 7 lines
Quoted 3 lines
Architecturally, I'm surprised that ia64 would need to actually do a cache flush. I would think the VT-d hardware would do coherent accesses which would make the cache flush unnecessary.
VT-d hardware supports both non cache coherency and cache coherency by bit Coherency in Extended Capabilities Register.
Could you please point me to the doc that explicitly says that architecturally ia64 doesn't need cache flush?
I don't know the details of VT-d, so I'm just asking the question. I do know the HP IOMMU does not require flushing because it participates in the coherency domain, so I was just surprised to see this in Intel chipset support.
The following sections in volume 2 of the SDM mention DMA:
Part 1, Sec 4.4.3, Cacheability and Coherency Attribute:
The processor must ensure that transactions from other I/O agents (such as DMA) are physically coherent with the instruction and data cache.
Part 2, Sec 2.5.4, DMA:
Unlike Programmed I/O, which requires intervention from the CPU to move data from the device to main memory, data movement in DMA occurs without help from the CPU. A processor based on the Itanium architecture expects the platform to maintain coherency for DMA traffic. That is, the platform issues snoop cycles on the bus to invalidate cacheable pages that a DMA access modifies. These snoop cycles invalidate the appropriate lines in both instruction and data caches and thus maintain coherency. This behavior allows an operating system to page code pages without taking explicit actions to ensure coherency.
Software must maintain coherency for DMA traffic through explicit action if the platform does not maintain coherency for this traffic. Software can provide coherency by using the flush cache instruction, fc, to invalidate the instruction and data cache lines that a DMA transfer modifies.
It sounds like the expectation is that DMA will be fully coherent and no flushes would be required, but there is wiggle room in that last paragraph for platforms that don't maintain coherency.
Bjorn
Quoted 9 lines
Quoted 1 line
Could you please point me to the doc that explicitly says that architecturally ia64 doesn't need cache flush?
The following sections in volume 2 of the SDM mention DMA:
Part 1, Sec 4.4.3, Cacheability and Coherency Attribute:
Part 2, Sec 2.5.4, DMA:It sounds like the expectation is that DMA will be fully coherent and no flushes would be required, but there is wiggle room in that last paragraph for platforms that don't maintain coherency.
The cache coherency bit in VT-d is for root, context, and page tables which are for DMA management, not DMA data itself. VT-d DMA data should be cache coherent.The Intel IOMMU code doesn't need to deal with non cache coherency in DMA data traffic. But root, context, and page tables could be non cache coherent and this is handled by Intel IOMMU code.
Thanks.
-Fenghua
PATCH 1/2 Enable Pass Through Feature in Intel IOMMU
In reply to Bjorn HelgaasThe patch set adds kernel parameter intel_iommu=pt to set up pass through mode in context mapping entry. This disables DMAR in linux kernel; but KVM still runs on VT-d. In this mode, kernel uses swiotlb for DMA API functions but other VT-d functionalities are enabled for KVM. KVM always uses multi level translation page table in VT-d. By default, pass though mode is disabled in kernel.
This is useful when people don't want to enable VT-d DMAR in kernel for reasons like kernel iommu performance concern or debug purpose but still want to use KVM.
Thanks.
-Fenghua
---
Documentation/kernel-parameters.txt | 5 +++ arch/ia64/include/asm/iommu.h | 1 arch/ia64/kernel/pci-swiotlb.c | 2 - arch/x86/include/asm/iommu.h | 1 arch/x86/kernel/pci-swiotlb_64.c | 4 ++- drivers/pci/intel-iommu.c | 47 ++++++++++++++++++++++++++---------- include/linux/dma_remapping.h | 3 ++ include/linux/intel-iommu.h | 3 +- 8 files changed, 50 insertions(+), 16 deletions(-)
Documentation/kernel-parameters.txt +5 -0
@@ -931,6 +931,11 @@ and is between 256 and 4096 characters. It is defined in the file With this option on every unmap_single operation will result in a hardware IOTLB flush operation as opposed to batching them for performance. + pt [Default no Pass Through] + This option enables Pass Through in context mapping if + Pass Through is supported in hardware. With this option + DMAR is disabled in kernel and kernel uses swiotlb, but + KVM still uses VT-d hardware. io_delay= [X86-32,X86-64] I/O delay method 0x80
arch/ia64/include/asm/iommu.h +1 -0
@@ -9,6 +9,7 @@ extern void pci_iommu_shutdown(void);extern void no_iommu_init (void );extern int force_iommu, no_iommu;extern int iommu_detected; +extern int iommu_pass_through;extern void iommu_dma_init (void );extern void machvec_init (const char *name);
arch/ia64/kernel/pci-swiotlb.c +1 -1
@@ -32,7 +32,7 @@ struct dma_mapping_ops swiotlb_dma_ops = {void __init pci_swiotlb_init (void ) { -if (!iommu_detected) { +if (!iommu_detected || iommu_pass_through) {#ifdef CONFIG_IA64_GENERIC swiotlb =1 ;printk (KERN_INFO "PCI-DMA: Re-initialize machine vector.\n" );
arch/x86/include/asm/iommu.h +1 -0
@@ -6,6 +6,7 @@ extern void no_iommu_init(void);extern struct dma_mapping_ops nommu_dma_ops;extern int force_iommu, no_iommu;extern int iommu_detected; +extern int iommu_pass_through;extern unsigned long iommu_nr_pages (unsigned long addr,unsigned long len);
arch/x86/kernel/pci-swiotlb_64.c +3 -1
@@ -50,8 +50,10 @@ struct dma_mapping_ops swiotlb_dma_ops = {void __init pci_swiotlb_init (void ) {/* don't initialize swiotlb if iommu=off (no_iommu=1) */ -if (!iommu_detected && !no_iommu && max_pfn >MAX_DMA32_PFN ) +if ((!iommu_detected && !no_iommu && max_pfn >MAX_DMA32_PFN ) || + iommu_pass_through) swiotlb =1 ; +if (swiotlb_force) swiotlb =1 ;if (swiotlb) {
drivers/pci/intel-iommu.c +34 -13
160 lines not on this page · raw message
include/linux/dma_remapping.h +3 -0
@@ -12,6 +12,9 @@#define DMA_PTE_READ (1)#define DMA_PTE_WRITE (2) +#define CONTEXT_TT_MULTI_LEVEL 0 +#define CONTEXT_TT_PASS_THROUGH 2 +struct intel_iommu ;struct dmar_domain ;struct root_entry ;
include/linux/intel-iommu.h +2 -1
@@ -120,6 +120,7 @@ static inline void dmar_writeq(void __iomem *addr, u64 val) (ecap_iotlb_offset(e) + ecap_niotlb_iunits(e) * 16)#define ecap_coherent (e) ((e) & 0x1)#define ecap_qis (e) ((e) & 0x2) +#define ecap_pass_through (e) ((e >> 6) & 0x1)#define ecap_eim_support (e) ((e >> 4) & 0x1)#define ecap_ir_support (e) ((e >> 3) & 0x1)#define ecap_max_handle_mask (e) ((e >> 20) & 0xf)
@@ -332,7 +333,7 @@ extern void qi_submit_sync(struct qi_desc *desc, struct intel_iommu *iommu);void intel_iommu_domain_exit (struct dmar_domain *domain);struct dmar_domain *intel_iommu_domain_alloc (struct pci_dev *pdev);int intel_iommu_context_mapping (struct dmar_domain *domain, -struct pci_dev *pdev); +struct pci_dev *pdev,int translation);int intel_iommu_page_mapping (struct dmar_domain *domain,dma_addr_t iova,u64 hpa,size_t size,int prot);void intel_iommu_detach_dev (struct dmar_domain *domain,u8 bus,u8 devfn);
PATCH v2 2/2 Add Variable Page Size and IA64 Support in Intel IOMMU: IA64 Specific Part
In reply to Fenghua YuThe patch contains Intel IOMMU IA64 specific code. It defines new machvec dig_vtd, hooks for IOMMU, DMAR table detection, cache line flush function, etc.
For a generic kernel with CONFIG_DMAR=y, if Intel IOMMU is detected, dig_vtd is used for machinve vector. Otherwise, kernel falls back to dig machine vector. Kernel parameter "machvec=dig" or "intel_iommu=off" can be used to force kernel to boot dig machine vector.
---
arch/ia64/Kconfig | 17 ++++ arch/ia64/Makefile | 1 arch/ia64/configs/generic_defconfig | 2 arch/ia64/configs/tiger_defconfig | 2 arch/ia64/dig/Makefile | 5 + arch/ia64/dig/dig_vtd_iommu.c | 59 ++++++++++++++ arch/ia64/dig/machvec_vtd.c | 3 arch/ia64/include/asm/cacheflush.h | 2 arch/ia64/include/asm/device.h | 3 arch/ia64/include/asm/dma-mapping.h | 50 ++++++++++++ arch/ia64/include/asm/iommu.h | 16 +++ arch/ia64/include/asm/machvec.h | 2 arch/ia64/include/asm/machvec_dig_vtd.h | 38 +++++++++ arch/ia64/include/asm/machvec_init.h | 1 arch/ia64/include/asm/pci.h | 3 arch/ia64/include/asm/swiotlb.h | 56 +++++++++++++ arch/ia64/kernel/Makefile | 4 arch/ia64/kernel/acpi.c | 17 ++++ arch/ia64/kernel/msi_ia64.c | 80 +++++++++++++++++++ arch/ia64/kernel/pci-dma.c | 129 ++++++++++++++++++++++++++++++++ arch/ia64/kernel/pci-swiotlb.c | 46 +++++++++++ arch/ia64/kernel/setup.c | 42 +++++++--- arch/ia64/lib/flush.S | 55 +++++++++++++ 23 files changed, 620 insertions(+), 13 deletions(-)
arch/ia64/Kconfig +17 -0
@@ -125,6 +125,7 @@ config IA64_GENERIC select NUMA select ACPI_NUMA select SWIOTLB + select PCI_MSI help This selects the system type of your hardware. A "generic" kernel will run on any supported IA-64 system. However, if you configure
@@ -132,6 +133,7 @@ config IA64_GENERIC generic For any supported IA-64 system DIG-compliant For DIG ("Developer's Interface Guide") compliant systems + DIG+Intel+IOMMU For DIG systems with Intel IOMMU HP-zx1/sx1000 For HP systems HP-zx1/sx1000+swiotlb For HP systems with (broken) DMA-constrained devices. SGI-SN2 For SGI Altix systems
@@ -144,6 +146,11 @@ config IA64_DIG bool "DIG-compliant" select SWIOTLB +config IA64_DIG_VTD + bool "DIG+Intel+IOMMU" + select DMAR + select PCI_MSI + config IA64_HP_ZX1 bool "HP-zx1/sx1000" help
@@ -589,6 +596,16 @@ source "drivers/pci/hotplug/Kconfig" source "drivers/pcmcia/Kconfig" +config DMAR + bool "Support for DMA Remapping Devices (EXPERIMENTAL)" + depends on IA64_GENERIC && ACPI && EXPERIMENTAL + help + DMA remapping (DMAR) devices support enables independent address + translations for Direct Memory Access (DMA) from devices. + These DMA remapping devices are reported via ACPI tables + and include PCI device scope covered by these DMA + remapping devices. + endmenu endif
arch/ia64/Makefile +1 -0
@@ -53,6 +53,7 @@ libs-y += arch/ia64/lib/ core-y += arch/ia64/kernel/ arch/ia64/mm/ core-$(CONFIG_IA32_SUPPORT) += arch/ia64/ia32/ core-$(CONFIG_IA64_DIG) += arch/ia64/dig/ +core-$(CONFIG_IA64_DIG_VTD) += arch/ia64/dig/ core-$(CONFIG_IA64_GENERIC) += arch/ia64/dig/ core-$(CONFIG_IA64_HP_ZX1) += arch/ia64/dig/ core-$(CONFIG_IA64_HP_ZX1_SWIOTLB) += arch/ia64/dig/
arch/ia64/configs/generic_defconfig +2 -0
@@ -233,6 +233,8 @@ CONFIG_DMIID=y CONFIG_BINFMT_ELF=y CONFIG_BINFMT_MISC=m +# CONFIG_DMAR is not set + # # Power management and ACPI #
arch/ia64/configs/tiger_defconfig +2 -0
@@ -172,6 +172,8 @@ CONFIG_DMIID=y CONFIG_BINFMT_ELF=y CONFIG_BINFMT_MISC=m +# CONFIG_DMAR is not set + # # Power management and ACPI #
arch/ia64/dig/Makefile +5 -0
@@ -6,4 +6,9 @@ # obj-y := setup.o +ifeq ($(CONFIG_DMAR), y) +obj-$(CONFIG_IA64_GENERIC) += machvec.o machvec_vtd.o dig_vtd_iommu.o +else obj-$(CONFIG_IA64_GENERIC) += machvec.o +endif +obj-$(CONFIG_IA64_DIG_VTD) += dig_vtd_iommu.o
new file mode 100644
index 0000000..289d7e8
arch/ia64/dig/dig_vtd_iommu.c new file +59 -0
59 lines not on this page · raw message
arch/ia64/dig/machvec_vtd.c new file +3 -0
@@ -0,0 +1,3 @@ +#define MACHVEC_PLATFORM_NAME dig_vtd +#define MACHVEC_PLATFORM_HEADER <asm/machvec_dig_vtd.h> +#include <asm/machvec_init.h>
arch/ia64/include/asm/cacheflush.h +2 -0
@@ -34,6 +34,8 @@ do { \#define flush_dcache_mmap_unlock (mapping) do { } while (0)extern void flush_icache_range (unsigned long start,unsigned long end); +extern void clflush_cache_range (void *addr,int size); +#define flush_icache_user_range (vma, page, user_addr, len) \ do { \
arch/ia64/include/asm/device.h +3 -0
@@ -10,6 +10,9 @@ struct dev_archdata {#ifdef CONFIG_ACPI void *acpi_handle;#endif +#ifdef CONFIG_DMAR +void *iommu;/* hook for IOMMU specific extension */ +#endif };#endif /* _ASM_IA64_DEVICE_H */
arch/ia64/include/asm/dma-mapping.h +50 -0
60 lines not on this page · raw message
arch/ia64/include/asm/iommu.h new file +16 -0
@@ -0,0 +1,16 @@ +#ifndef _ASM_IA64_IOMMU_H +#define _ASM_IA64_IOMMU_H 1 + +#define cpu_has_x2apic 0 +/* 10 seconds */ +#define DMAR_OPERATION_TIMEOUT (((cycles_t) local_cpu_data->itc_freq)*10) + +extern void pci_iommu_shutdown (void ); +extern void no_iommu_init (void ); +extern int force_iommu, no_iommu; +extern int iommu_detected; +extern void iommu_dma_init (void ); +extern void machvec_init (const char *name); +extern int forbid_dac; + +#endif
arch/ia64/include/asm/machvec.h +2 -0
@@ -120,6 +120,8 @@ extern void machvec_tlb_migrate_finish (struct mm_struct *);# include <asm/machvec_hpsim.h> # elif defined (CONFIG_IA64_DIG )# include <asm/machvec_dig.h> +# elif defined(CONFIG_IA64_DIG_VTD ) +# include <asm/machvec_dig_vtd.h> # elif defined (CONFIG_IA64_HP_ZX1 )# include <asm/machvec_hpzx1.h> # elif defined (CONFIG_IA64_HP_ZX1_SWIOTLB )
arch/ia64/include/asm/machvec_dig_vtd.h new file +38 -0
@@ -0,0 +1,38 @@ +#ifndef _ASM_IA64_MACHVEC_DIG_VTD_h +#define _ASM_IA64_MACHVEC_DIG_VTD_h + +extern ia64_mv_setup_t dig_setup; +extern ia64_mv_dma_alloc_coherent vtd_alloc_coherent; +extern ia64_mv_dma_free_coherent vtd_free_coherent; +extern ia64_mv_dma_map_single_attrs vtd_map_single_attrs; +extern ia64_mv_dma_unmap_single_attrs vtd_unmap_single_attrs; +extern ia64_mv_dma_map_sg_attrs vtd_map_sg_attrs; +extern ia64_mv_dma_unmap_sg_attrs vtd_unmap_sg_attrs; +extern ia64_mv_dma_supported iommu_dma_supported; +extern ia64_mv_dma_mapping_error vtd_dma_mapping_error; +extern ia64_mv_dma_init pci_iommu_alloc; + +/* +* This stuff has dual use! +* +* For a generic kernel, the macros are used to initialize the +* platform's machvec structure. When compiling a non-generic kernel, +* the macros are used directly. +*/ +#define platform_name "dig_vtd" +#define platform_setup dig_setup +#define platform_dma_init pci_iommu_alloc +#define platform_dma_alloc_coherent vtd_alloc_coherent +#define platform_dma_free_coherent vtd_free_coherent +#define platform_dma_map_single_attrs vtd_map_single_attrs +#define platform_dma_unmap_single_attrs vtd_unmap_single_attrs +#define platform_dma_map_sg_attrs vtd_map_sg_attrs +#define platform_dma_unmap_sg_attrs vtd_unmap_sg_attrs +#define platform_dma_sync_single_for_cpu machvec_dma_sync_single +#define platform_dma_sync_sg_for_cpu machvec_dma_sync_sg +#define platform_dma_sync_single_for_device machvec_dma_sync_single +#define platform_dma_sync_sg_for_device machvec_dma_sync_sg +#define platform_dma_supported iommu_dma_supported +#define platform_dma_mapping_error vtd_dma_mapping_error + +#endif /* _ASM_IA64_MACHVEC_DIG_VTD_h */
arch/ia64/include/asm/machvec_init.h +1 -0
@@ -1,3 +1,4 @@ +#include <asm/iommu.h> #include <asm/machvec.h> extern ia64_mv_send_ipi_t ia64_send_ipi;
arch/ia64/include/asm/pci.h +3 -0
@@ -164,4 +164,7 @@ static inline int pci_get_legacy_ide_irq(struct pci_dev *dev, int channel) return channel ? isa_irq_to_vector(15) : isa_irq_to_vector(14); } +#ifdef CONFIG_DMAR +extern void pci_iommu_alloc (void ); +#endif #endif /* _ASM_IA64_PCI_H */
arch/ia64/include/asm/swiotlb.h new file +56 -0
56 lines not on this page · raw message
arch/ia64/kernel/Makefile +4 -0
@@ -42,6 +42,10 @@ obj-$(CONFIG_IA64_ESI) += esi.o ifneq ($(CONFIG_IA64_ESI),) obj-y += esi_stub.o # must be in kernel proper endif +obj-$(CONFIG_DMAR) += pci-dma.o +ifeq ($(CONFIG_DMAR), y) +obj-$(CONFIG_SWIOTLB) += pci-swiotlb.o +endif # The gate DSO image is built using a special linker script. targets += gate.so gate-syms.o
arch/ia64/kernel/acpi.c +17 -0
@@ -91,6 +91,9 @@ acpi_get_sysname(void)struct acpi_table_rsdp *rsdp;struct acpi_table_xsdt *xsdt;struct acpi_table_header *hdr; +#ifdef CONFIG_DMAR +u64 i, nentries; +#endif rsdp_phys =acpi_find_rsdp ();if (!rsdp_phys) {
@@ -123,6 +126,18 @@ acpi_get_sysname(void) return "sn2"; } +#ifdef CONFIG_DMAR +/* Look for Intel IOMMU */ + nentries = (hdr->length -sizeof (*hdr)) / +sizeof (xsdt->table_offset_entry[0 ]); +for (i =0 ; i < nentries; i++) { + hdr =__va (xsdt->table_offset_entry[i]); +if (strncmp (hdr->signature,ACPI_SIG_DMAR , +sizeof (ACPI_SIG_DMAR ) -1 ) =0 ) +return "dig_vtd" ; + } +#endif +return "dig" ;#else # if defined (CONFIG_IA64_HP_SIM )
@@ -137,6 +152,8 @@ acpi_get_sysname(void)return "uv" ;# elif defined (CONFIG_IA64_DIG )return "dig" ; +# elif defined(CONFIG_IA64_DIG_VTD ) +return "dig_vtd" ;# else # error Unknown platform. Fix acpi.c.# endif
arch/ia64/kernel/msi_ia64.c +78 -0
87 lines not on this page · raw message
arch/ia64/kernel/pci-dma.c new file +129 -0
129 lines not on this page · raw message
arch/ia64/kernel/pci-swiotlb.c new file +46 -0
46 lines not on this page · raw message
arch/ia64/kernel/setup.c +29 -13
82 lines not on this page · raw message
arch/ia64/lib/flush.S +54 -0
57 lines not on this page · raw message