From 104a1c13ac66e40cf8c6ae74d76ff14ff24b9b01 Mon Sep 17 00:00:00 2001 From: Alex Williamson Date: Thu, 3 Jul 2014 09:51:18 -0600 Subject: iommu/core: Create central IOMMU group lookup/creation interface Currently each IOMMU driver that supports IOMMU groups has its own code for discovering the base device used in grouping. This code is generally not specific to the IOMMU hardware, but to the bus of the devices managed by the IOMMU. We can therefore create a common interface for supporting devices on different buses. Signed-off-by: Alex Williamson Signed-off-by: Joerg Roedel --- include/linux/iommu.h | 1 + 1 file changed, 1 insertion(+) (limited to 'include/linux') diff --git a/include/linux/iommu.h b/include/linux/iommu.h index b96a5b2136e4..a2e5843b0a22 100644 --- a/include/linux/iommu.h +++ b/include/linux/iommu.h @@ -181,6 +181,7 @@ extern int iommu_group_register_notifier(struct iommu_group *group, extern int iommu_group_unregister_notifier(struct iommu_group *group, struct notifier_block *nb); extern int iommu_group_id(struct iommu_group *group); +extern struct iommu_group *iommu_group_get_for_dev(struct device *dev); extern int iommu_domain_get_attr(struct iommu_domain *domain, enum iommu_attr, void *data); -- cgit From c61959ecbbc6bf9034e65c8e8ef03fa9d1066f05 Mon Sep 17 00:00:00 2001 From: Alex Williamson Date: Thu, 12 Jun 2014 16:12:24 -0600 Subject: iommu: Add sysfs support for IOMMUs IOMMUs currently have no common representation to userspace, most seem to have no representation at all aside from a few printks on bootup. There are however features of IOMMUs that are useful to know about. For instance the IOMMU might support superpages, making use of processor large/huge pages more important in a device assignment scenario. It's also useful to create cross links between devices and IOMMU hardware units, so that users might be able to load balance their devices to avoid thrashing a single hardware unit. This patch adds a device create and destroy interface as well as device linking, making it very lightweight for an IOMMU driver to add basic support. IOMMU drivers can provide additional attributes automatically by using an attribute_group. The attributes exposed are expected to be relatively device specific, the means to retrieve them certainly are, so there are currently no common attributes for the new class created here. Signed-off-by: Alex Williamson Signed-off-by: Joerg Roedel --- include/linux/iommu.h | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) (limited to 'include/linux') diff --git a/include/linux/iommu.h b/include/linux/iommu.h index a2e5843b0a22..7fd16e3d1f25 100644 --- a/include/linux/iommu.h +++ b/include/linux/iommu.h @@ -187,6 +187,12 @@ extern int iommu_domain_get_attr(struct iommu_domain *domain, enum iommu_attr, void *data); extern int iommu_domain_set_attr(struct iommu_domain *domain, enum iommu_attr, void *data); +struct device *iommu_device_create(struct device *parent, void *drvdata, + const struct attribute_group **groups, + const char *fmt, ...); +void iommu_device_destroy(struct device *dev); +int iommu_device_link(struct device *dev, struct device *link); +void iommu_device_unlink(struct device *dev, struct device *link); /* Window handling function prototypes */ extern int iommu_domain_window_enable(struct iommu_domain *domain, u32 wnd_nr, @@ -397,6 +403,26 @@ static inline int iommu_domain_set_attr(struct iommu_domain *domain, return -EINVAL; } +struct device *iommu_device_create(struct device *parent, void *drvdata, + const struct attribute_group **groups, + const char *fmt, ...) +{ + return ERR_PTR(-ENODEV); +} + +void iommu_device_destroy(struct device *dev) +{ +} + +int iommu_device_link(struct device *dev, struct device *link) +{ + return -EINVAL; +} + +void iommu_device_unlink(struct device *dev, struct device *link) +{ +} + #endif /* CONFIG_IOMMU_API */ #endif /* __LINUX_IOMMU_H */ -- cgit From a5459cfece880e82778a60e6290ad6c0dd688a06 Mon Sep 17 00:00:00 2001 From: Alex Williamson Date: Thu, 12 Jun 2014 16:12:31 -0600 Subject: iommu/vt-d: Make use of IOMMU sysfs support Register our DRHD IOMMUs, cross link devices, and provide a base set of attributes for the IOMMU. Note that IRQ remapping support parses the DMAR table very early in boot, well before the iommu_class can reasonably be setup, so our registration is split between intel_iommu_init(), which occurs later, and alloc_iommu(), which typically occurs much earlier, but may happen at any time later with IOMMU hot-add support. On a typical desktop system, this provides the following (pruned): $ find /sys | grep dmar /sys/devices/virtual/iommu/dmar0 /sys/devices/virtual/iommu/dmar0/devices /sys/devices/virtual/iommu/dmar0/devices/0000:00:02.0 /sys/devices/virtual/iommu/dmar0/intel-iommu /sys/devices/virtual/iommu/dmar0/intel-iommu/cap /sys/devices/virtual/iommu/dmar0/intel-iommu/ecap /sys/devices/virtual/iommu/dmar0/intel-iommu/address /sys/devices/virtual/iommu/dmar0/intel-iommu/version /sys/devices/virtual/iommu/dmar1 /sys/devices/virtual/iommu/dmar1/devices /sys/devices/virtual/iommu/dmar1/devices/0000:00:00.0 /sys/devices/virtual/iommu/dmar1/devices/0000:00:01.0 /sys/devices/virtual/iommu/dmar1/devices/0000:00:16.0 /sys/devices/virtual/iommu/dmar1/devices/0000:00:1a.0 /sys/devices/virtual/iommu/dmar1/devices/0000:00:1b.0 /sys/devices/virtual/iommu/dmar1/devices/0000:00:1c.0 ... /sys/devices/virtual/iommu/dmar1/intel-iommu /sys/devices/virtual/iommu/dmar1/intel-iommu/cap /sys/devices/virtual/iommu/dmar1/intel-iommu/ecap /sys/devices/virtual/iommu/dmar1/intel-iommu/address /sys/devices/virtual/iommu/dmar1/intel-iommu/version /sys/class/iommu/dmar0 /sys/class/iommu/dmar1 (devices also link back to the dmar units) This makes address, version, capabilities, and extended capabilities available, just like printed on boot. I've tried not to duplicate data that can be found in the DMAR table, with the exception of the address, which provides an easy way to associate the sysfs device with a DRHD entry in the DMAR. It's tempting to add scopes and RMRR data here, but the full DMAR table is already exposed under /sys/firmware/ and therefore already provides a way for userspace to learn such details. Signed-off-by: Alex Williamson Signed-off-by: Joerg Roedel --- include/linux/intel-iommu.h | 3 +++ 1 file changed, 3 insertions(+) (limited to 'include/linux') diff --git a/include/linux/intel-iommu.h b/include/linux/intel-iommu.h index 0a2da5188217..a65208a8fe18 100644 --- a/include/linux/intel-iommu.h +++ b/include/linux/intel-iommu.h @@ -336,6 +336,7 @@ struct intel_iommu { #ifdef CONFIG_IRQ_REMAP struct ir_table *ir_table; /* Interrupt remapping info */ #endif + struct device *iommu_dev; /* IOMMU-sysfs device */ int node; }; @@ -365,4 +366,6 @@ extern int qi_submit_sync(struct qi_desc *desc, struct intel_iommu *iommu); extern int dmar_ir_support(void); +extern const struct attribute_group *intel_iommu_groups[]; + #endif -- cgit From b22f6434cf48af001330e370e9d781aeb668f98c Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Fri, 27 Jun 2014 09:03:12 +0200 Subject: iommu: Constify struct iommu_ops This structure is read-only data and should never be modified. Signed-off-by: Thierry Reding Signed-off-by: Greg Kroah-Hartman Signed-off-by: Joerg Roedel --- include/linux/device.h | 2 +- include/linux/iommu.h | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'include/linux') diff --git a/include/linux/device.h b/include/linux/device.h index af424acd393d..75f5bcb8930b 100644 --- a/include/linux/device.h +++ b/include/linux/device.h @@ -124,7 +124,7 @@ struct bus_type { const struct dev_pm_ops *pm; - struct iommu_ops *iommu_ops; + const struct iommu_ops *iommu_ops; struct subsys_private *p; struct lock_class_key lock_key; diff --git a/include/linux/iommu.h b/include/linux/iommu.h index 7fd16e3d1f25..c7097d7f024c 100644 --- a/include/linux/iommu.h +++ b/include/linux/iommu.h @@ -50,7 +50,7 @@ struct iommu_domain_geometry { }; struct iommu_domain { - struct iommu_ops *ops; + const struct iommu_ops *ops; void *priv; iommu_fault_handler_t handler; void *handler_token; @@ -140,7 +140,7 @@ struct iommu_ops { #define IOMMU_GROUP_NOTIFY_UNBIND_DRIVER 5 /* Pre Driver unbind */ #define IOMMU_GROUP_NOTIFY_UNBOUND_DRIVER 6 /* Post Driver unbind */ -extern int bus_set_iommu(struct bus_type *bus, struct iommu_ops *ops); +extern int bus_set_iommu(struct bus_type *bus, const struct iommu_ops *ops); extern bool iommu_present(struct bus_type *bus); extern struct iommu_domain *iommu_domain_alloc(struct bus_type *bus); extern struct iommu_group *iommu_group_get_by_id(int id); -- cgit From e09f8ea560490e941139d23b4c278d3e6e2c871a Mon Sep 17 00:00:00 2001 From: Alex Williamson Date: Mon, 7 Jul 2014 14:31:36 -0600 Subject: iommu: Fix IOMMU sysfs stubs 0-day kernel build testing reports: arch/x86/kvm/x86.o: In function `iommu_device_destroy': >> (.text+0x7a0a): multiple definition of `iommu_device_destroy' arch/x86/kvm/../../../virt/kvm/vfio.o:vfio.c:(.text+0x490): first defined here arch/x86/kvm/x86.o: In function `iommu_device_link': >> (.text+0x7a15): multiple definition of `iommu_device_link' arch/x86/kvm/../../../virt/kvm/vfio.o:vfio.c:(.text+0x49b): first defined here arch/x86/kvm/x86.o: In function `iommu_device_unlink': >> (.text+0x7a25): multiple definition of `iommu_device_unlink' arch/x86/kvm/../../../virt/kvm/vfio.o:vfio.c:(.text+0x4ab): first defined here arch/x86/kvm/x86.o: In function `iommu_device_create': >> (.text+0x79f8): multiple definition of `iommu_device_create' arch/x86/kvm/../../../virt/kvm/vfio.o:vfio.c:(.text+0x47e): first defined here These are due to failing to define the stubs as static inline. Fix. Signed-off-by: Alex Williamson Signed-off-by: Joerg Roedel --- include/linux/iommu.h | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) (limited to 'include/linux') diff --git a/include/linux/iommu.h b/include/linux/iommu.h index c7097d7f024c..20f9a527922a 100644 --- a/include/linux/iommu.h +++ b/include/linux/iommu.h @@ -403,23 +403,24 @@ static inline int iommu_domain_set_attr(struct iommu_domain *domain, return -EINVAL; } -struct device *iommu_device_create(struct device *parent, void *drvdata, - const struct attribute_group **groups, - const char *fmt, ...) +static inline struct device *iommu_device_create(struct device *parent, + void *drvdata, + const struct attribute_group **groups, + const char *fmt, ...) { return ERR_PTR(-ENODEV); } -void iommu_device_destroy(struct device *dev) +static inline void iommu_device_destroy(struct device *dev) { } -int iommu_device_link(struct device *dev, struct device *link) +static inline int iommu_device_link(struct device *dev, struct device *link) { return -EINVAL; } -void iommu_device_unlink(struct device *dev, struct device *link) +static inline void iommu_device_unlink(struct device *dev, struct device *link) { } -- cgit From 51499aa912e0d6f5b3497e2b1121309f579e78ed Mon Sep 17 00:00:00 2001 From: Alexey Skidanov Date: Tue, 8 Jul 2014 17:30:17 +0300 Subject: iommu/amd: Moving PPR fault flags macros definitions Any kernel source registering the invalid PPR calback may include the header file with PPR fault flags macros definitions. Thus we move them to include/linux/amd-iommu.h Signed-off-by: Alexey Skidanov Signed-off-by: Oded Gabbay Signed-off-by: Joerg Roedel --- include/linux/amd-iommu.h | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'include/linux') diff --git a/include/linux/amd-iommu.h b/include/linux/amd-iommu.h index 15f6b9edd0b1..2b08e79f5100 100644 --- a/include/linux/amd-iommu.h +++ b/include/linux/amd-iommu.h @@ -119,6 +119,13 @@ typedef int (*amd_iommu_invalid_ppr_cb)(struct pci_dev *pdev, extern int amd_iommu_set_invalid_ppr_cb(struct pci_dev *pdev, amd_iommu_invalid_ppr_cb cb); +#define PPR_FAULT_EXEC (1 << 1) +#define PPR_FAULT_READ (1 << 2) +#define PPR_FAULT_WRITE (1 << 5) +#define PPR_FAULT_USER (1 << 6) +#define PPR_FAULT_RSVD (1 << 7) +#define PPR_FAULT_GN (1 << 8) + /** * amd_iommu_device_info() - Get information about IOMMUv2 support of a * PCI device -- cgit From 8594d83261d14754288ef00993f0971131ff08eb Mon Sep 17 00:00:00 2001 From: Jiang Liu Date: Fri, 11 Jul 2014 14:19:32 +0800 Subject: iommu/vt-d: Simplify include/linux/dmar.h Simplify include/linux/dmar.h a bit based on the fact that both CONFIG_INTEL_IOMMU and CONFIG_IRQ_REMAP select CONFIG_DMAR_TABLE. Signed-off-by: Jiang Liu Signed-off-by: Joerg Roedel --- include/linux/dmar.h | 50 ++++++++++++++++++-------------------------------- 1 file changed, 18 insertions(+), 32 deletions(-) (limited to 'include/linux') diff --git a/include/linux/dmar.h b/include/linux/dmar.h index 23c8db129560..1deece46a0ca 100644 --- a/include/linux/dmar.h +++ b/include/linux/dmar.h @@ -114,22 +114,30 @@ extern int dmar_remove_dev_scope(struct dmar_pci_notify_info *info, /* Intel IOMMU detection */ extern int detect_intel_iommu(void); extern int enable_drhd_fault_handling(void); -#else -struct dmar_pci_notify_info; -static inline int detect_intel_iommu(void) + +#ifdef CONFIG_INTEL_IOMMU +extern int iommu_detected, no_iommu; +extern int intel_iommu_init(void); +extern int dmar_parse_one_rmrr(struct acpi_dmar_header *header); +extern int dmar_parse_one_atsr(struct acpi_dmar_header *header); +extern int dmar_iommu_notify_scope_dev(struct dmar_pci_notify_info *info); +#else /* !CONFIG_INTEL_IOMMU: */ +static inline int intel_iommu_init(void) { return -ENODEV; } +static inline int dmar_parse_one_rmrr(struct acpi_dmar_header *header) { - return -ENODEV; + return 0; } - -static inline int dmar_table_init(void) +static inline int dmar_parse_one_atsr(struct acpi_dmar_header *header) { - return -ENODEV; + return 0; } -static inline int enable_drhd_fault_handling(void) +static inline int dmar_iommu_notify_scope_dev(struct dmar_pci_notify_info *info) { - return -1; + return 0; } -#endif /* !CONFIG_DMAR_TABLE */ +#endif /* CONFIG_INTEL_IOMMU */ + +#endif /* CONFIG_DMAR_TABLE */ struct irte { union { @@ -177,26 +185,4 @@ extern int dmar_set_interrupt(struct intel_iommu *iommu); extern irqreturn_t dmar_fault(int irq, void *dev_id); extern int arch_setup_dmar_msi(unsigned int irq); -#ifdef CONFIG_INTEL_IOMMU -extern int iommu_detected, no_iommu; -extern int dmar_parse_one_rmrr(struct acpi_dmar_header *header); -extern int dmar_parse_one_atsr(struct acpi_dmar_header *header); -extern int dmar_iommu_notify_scope_dev(struct dmar_pci_notify_info *info); -extern int intel_iommu_init(void); -#else /* !CONFIG_INTEL_IOMMU: */ -static inline int intel_iommu_init(void) { return -ENODEV; } -static inline int dmar_parse_one_rmrr(struct acpi_dmar_header *header) -{ - return 0; -} -static inline int dmar_parse_one_atsr(struct acpi_dmar_header *header) -{ - return 0; -} -static inline int dmar_iommu_notify_scope_dev(struct dmar_pci_notify_info *info) -{ - return 0; -} -#endif /* CONFIG_INTEL_IOMMU */ - #endif /* __DMAR_H__ */ -- cgit From a156ef99e874f3701367cc192aa604bcf8c0a236 Mon Sep 17 00:00:00 2001 From: Jiang Liu Date: Fri, 11 Jul 2014 14:19:36 +0800 Subject: iommu/vt-d: Introduce helper function iova_size() to improve code readability Signed-off-by: Jiang Liu Signed-off-by: Joerg Roedel --- include/linux/iova.h | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'include/linux') diff --git a/include/linux/iova.h b/include/linux/iova.h index 3277f4711349..19e81d5ccb6d 100644 --- a/include/linux/iova.h +++ b/include/linux/iova.h @@ -34,6 +34,11 @@ struct iova_domain { unsigned long dma_32bit_pfn; }; +static inline unsigned long iova_size(struct iova *iova) +{ + return iova->pfn_hi - iova->pfn_lo + 1; +} + struct iova *alloc_iova_mem(void); void free_iova_mem(struct iova *iova); void free_iova(struct iova_domain *iovad, unsigned long pfn); -- cgit From baaa7b5d4f1e515a39f1eebd5fb16b67e00b22fb Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Fri, 18 Jul 2014 12:49:55 +0200 Subject: iommu/omap: Remove virtual memory manager The OMAP3 ISP driver was the only user of the OMAP IOVMM API. Now that is has been ported to the DMA API, remove the unused virtual memory manager. Signed-off-by: Laurent Pinchart Signed-off-by: Joerg Roedel --- include/linux/omap-iommu.h | 37 ++----------------------------------- 1 file changed, 2 insertions(+), 35 deletions(-) (limited to 'include/linux') diff --git a/include/linux/omap-iommu.h b/include/linux/omap-iommu.h index cac78de09c07..c1aede46718b 100644 --- a/include/linux/omap-iommu.h +++ b/include/linux/omap-iommu.h @@ -10,41 +10,8 @@ * published by the Free Software Foundation. */ -#ifndef _INTEL_IOMMU_H_ -#define _INTEL_IOMMU_H_ - -struct iovm_struct { - struct omap_iommu *iommu; /* iommu object which this belongs to */ - u32 da_start; /* area definition */ - u32 da_end; - u32 flags; /* IOVMF_: see below */ - struct list_head list; /* linked in ascending order */ - const struct sg_table *sgt; /* keep 'page' <-> 'da' mapping */ - void *va; /* mpu side mapped address */ -}; - -#define MMU_RAM_ENDIAN_SHIFT 9 -#define MMU_RAM_ENDIAN_LITTLE (0 << MMU_RAM_ENDIAN_SHIFT) -#define MMU_RAM_ELSZ_8 (0 << MMU_RAM_ELSZ_SHIFT) -#define IOVMF_ENDIAN_LITTLE MMU_RAM_ENDIAN_LITTLE -#define MMU_RAM_ELSZ_SHIFT 7 -#define IOVMF_ELSZ_8 MMU_RAM_ELSZ_8 - -struct iommu_domain; - -extern struct iovm_struct *omap_find_iovm_area(struct device *dev, u32 da); -extern u32 -omap_iommu_vmap(struct iommu_domain *domain, struct device *dev, u32 da, - const struct sg_table *sgt, u32 flags); -extern struct sg_table *omap_iommu_vunmap(struct iommu_domain *domain, - struct device *dev, u32 da); -extern u32 -omap_iommu_vmalloc(struct iommu_domain *domain, struct device *dev, - u32 da, size_t bytes, u32 flags); -extern void -omap_iommu_vfree(struct iommu_domain *domain, struct device *dev, - const u32 da); -extern void *omap_da_to_va(struct device *dev, u32 da); +#ifndef _OMAP_IOMMU_H_ +#define _OMAP_IOMMU_H_ extern void omap_iommu_save_ctx(struct device *dev); extern void omap_iommu_restore_ctx(struct device *dev); -- cgit From e8a6ebc71e40ec02cd0113c803e919c8329b411b Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Fri, 18 Jul 2014 12:49:57 +0200 Subject: iommu/omap: Remove platform data da_start and da_end fields The fields were used by the now gone omap-iovmm driver. They're not used anymore, remove them. Signed-off-by: Laurent Pinchart Acked-by: Tony Lindgren Signed-off-by: Joerg Roedel --- include/linux/platform_data/iommu-omap.h | 6 ------ 1 file changed, 6 deletions(-) (limited to 'include/linux') diff --git a/include/linux/platform_data/iommu-omap.h b/include/linux/platform_data/iommu-omap.h index 5b429c43a297..54a0a9582fad 100644 --- a/include/linux/platform_data/iommu-omap.h +++ b/include/linux/platform_data/iommu-omap.h @@ -31,14 +31,10 @@ struct omap_iommu_arch_data { /** * struct omap_mmu_dev_attr - OMAP mmu device attributes for omap_hwmod - * @da_start: device address where the va space starts. - * @da_end: device address where the va space ends. * @nr_tlb_entries: number of entries supported by the translation * look-aside buffer (TLB). */ struct omap_mmu_dev_attr { - u32 da_start; - u32 da_end; int nr_tlb_entries; }; @@ -46,8 +42,6 @@ struct iommu_platform_data { const char *name; const char *reset_name; int nr_tlb_entries; - u32 da_start; - u32 da_end; int (*assert_reset)(struct platform_device *pdev, const char *name); int (*deassert_reset)(struct platform_device *pdev, const char *name); -- cgit