aboutsummaryrefslogtreecommitdiffstats
path: root/include
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2015-06-23 18:27:19 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2015-06-23 18:27:19 -0700
commit6eae81a5e2d6646a61146501fd3032a340863c1d (patch)
treec1c8a5fd7930f756d4d124870e0076903e3b4ba0 /include
parentMerge tag 'for-linus-20150623' of git://git.infradead.org/linux-mtd (diff)
parentMerge branches 'arm/rockchip', 'arm/exynos', 'arm/smmu', 'x86/vt-d', 'x86/amd', 'default-domains' and 'core' into next (diff)
downloadlinux-dev-6eae81a5e2d6646a61146501fd3032a340863c1d.tar.xz
linux-dev-6eae81a5e2d6646a61146501fd3032a340863c1d.zip
Merge tag 'iommu-updates-v4.2' of git://git.kernel.org/pub/scm/linux/kernel/git/joro/iommu
Pull IOMMU updates from Joerg Roedel: "This time with bigger changes than usual: - A new IOMMU driver for the ARM SMMUv3. This IOMMU is pretty different from SMMUv1 and v2 in that it is configured through in-memory structures and not through the MMIO register region. The ARM SMMUv3 also supports IO demand paging for PCI devices with PRI/PASID capabilities, but this is not implemented in the driver yet. - Lots of cleanups and device-tree support for the Exynos IOMMU driver. This is part of the effort to bring Exynos DRM support upstream. - Introduction of default domains into the IOMMU core code. The rationale behind this is to move functionalily out of the IOMMU drivers to common code to get to a unified behavior between different drivers. The patches here introduce a default domain for iommu-groups (isolation groups). A device will now always be attached to a domain, either the default domain or another domain handled by the device driver. The IOMMU drivers have to be modified to make use of that feature. So long the AMD IOMMU driver is converted, with others to follow. - Patches for the Intel VT-d drvier to fix DMAR faults that happen when a kdump kernel boots. When the kdump kernel boots it re-initializes the IOMMU hardware, which destroys all mappings from the crashed kernel. As this happens before the endpoint devices are re-initialized, any in-flight DMA causes a DMAR fault. These faults cause PCI master aborts, which some devices can't handle properly and go into an undefined state, so that the device driver in the kdump kernel fails to initialize them and the dump fails. This is now fixed by copying over the mapping structures (only context tables and interrupt remapping tables) from the old kernel and keep the old mappings in place until the device driver of the new kernel takes over. This emulates the the behavior without an IOMMU to the best degree possible. - A couple of other small fixes and cleanups" * tag 'iommu-updates-v4.2' of git://git.kernel.org/pub/scm/linux/kernel/git/joro/iommu: (69 commits) iommu/amd: Handle large pages correctly in free_pagetable iommu/vt-d: Don't disable IR when it was previously enabled iommu/vt-d: Make sure copied over IR entries are not reused iommu/vt-d: Copy IR table from old kernel when in kdump mode iommu/vt-d: Set IRTA in intel_setup_irq_remapping iommu/vt-d: Disable IRQ remapping in intel_prepare_irq_remapping iommu/vt-d: Move QI initializationt to intel_setup_irq_remapping iommu/vt-d: Move EIM detection to intel_prepare_irq_remapping iommu/vt-d: Enable Translation only if it was previously disabled iommu/vt-d: Don't disable translation prior to OS handover iommu/vt-d: Don't copy translation tables if RTT bit needs to be changed iommu/vt-d: Don't do early domain assignment if kdump kernel iommu/vt-d: Allocate si_domain in init_dmars() iommu/vt-d: Mark copied context entries iommu/vt-d: Do not re-use domain-ids from the old kernel iommu/vt-d: Copy translation tables from old kernel iommu/vt-d: Detect pre enabled translation iommu/vt-d: Make root entry visible for hardware right after allocation iommu/vt-d: Init QI before root entry is allocated iommu/vt-d: Cleanup log messages ...
Diffstat (limited to 'include')
-rw-r--r--include/linux/intel-iommu.h5
-rw-r--r--include/linux/iommu.h44
2 files changed, 49 insertions, 0 deletions
diff --git a/include/linux/intel-iommu.h b/include/linux/intel-iommu.h
index 3665cb331ca1..d9a366d24e3b 100644
--- a/include/linux/intel-iommu.h
+++ b/include/linux/intel-iommu.h
@@ -297,6 +297,7 @@ struct q_inval {
/* 1MB - maximum possible interrupt remapping table size */
#define INTR_REMAP_PAGE_ORDER 8
#define INTR_REMAP_TABLE_REG_SIZE 0xf
+#define INTR_REMAP_TABLE_REG_SIZE_MASK 0xf
#define INTR_REMAP_TABLE_ENTRIES 65536
@@ -323,6 +324,9 @@ enum {
MAX_SR_DMAR_REGS
};
+#define VTD_FLAG_TRANS_PRE_ENABLED (1 << 0)
+#define VTD_FLAG_IRQ_REMAP_PRE_ENABLED (1 << 1)
+
struct intel_iommu {
void __iomem *reg; /* Pointer to hardware regs, virtual addr */
u64 reg_phys; /* physical address of hw register set */
@@ -356,6 +360,7 @@ struct intel_iommu {
#endif
struct device *iommu_dev; /* IOMMU-sysfs device */
int node;
+ u32 flags; /* Software defined flags */
};
static inline void __iommu_flush_cache(
diff --git a/include/linux/iommu.h b/include/linux/iommu.h
index 0546b8710ce3..dc767f7c3704 100644
--- a/include/linux/iommu.h
+++ b/include/linux/iommu.h
@@ -114,6 +114,20 @@ enum iommu_attr {
DOMAIN_ATTR_MAX,
};
+/**
+ * struct iommu_dm_region - descriptor for a direct mapped memory region
+ * @list: Linked list pointers
+ * @start: System physical start address of the region
+ * @length: Length of the region in bytes
+ * @prot: IOMMU Protection flags (READ/WRITE/...)
+ */
+struct iommu_dm_region {
+ struct list_head list;
+ phys_addr_t start;
+ size_t length;
+ int prot;
+};
+
#ifdef CONFIG_IOMMU_API
/**
@@ -159,6 +173,10 @@ struct iommu_ops {
int (*domain_set_attr)(struct iommu_domain *domain,
enum iommu_attr attr, void *data);
+ /* Request/Free a list of direct mapping requirements for a device */
+ void (*get_dm_regions)(struct device *dev, struct list_head *list);
+ void (*put_dm_regions)(struct device *dev, struct list_head *list);
+
/* Window handling functions */
int (*domain_window_enable)(struct iommu_domain *domain, u32 wnd_nr,
phys_addr_t paddr, u64 size, int prot);
@@ -193,6 +211,7 @@ extern int iommu_attach_device(struct iommu_domain *domain,
struct device *dev);
extern void iommu_detach_device(struct iommu_domain *domain,
struct device *dev);
+extern struct iommu_domain *iommu_get_domain_for_dev(struct device *dev);
extern int iommu_map(struct iommu_domain *domain, unsigned long iova,
phys_addr_t paddr, size_t size, int prot);
extern size_t iommu_unmap(struct iommu_domain *domain, unsigned long iova,
@@ -204,6 +223,10 @@ extern phys_addr_t iommu_iova_to_phys(struct iommu_domain *domain, dma_addr_t io
extern void iommu_set_fault_handler(struct iommu_domain *domain,
iommu_fault_handler_t handler, void *token);
+extern void iommu_get_dm_regions(struct device *dev, struct list_head *list);
+extern void iommu_put_dm_regions(struct device *dev, struct list_head *list);
+extern int iommu_request_dm_for_dev(struct device *dev);
+
extern int iommu_attach_group(struct iommu_domain *domain,
struct iommu_group *group);
extern void iommu_detach_group(struct iommu_domain *domain,
@@ -227,6 +250,7 @@ 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 struct iommu_domain *iommu_group_default_domain(struct iommu_group *);
extern int iommu_domain_get_attr(struct iommu_domain *domain, enum iommu_attr,
void *data);
@@ -332,6 +356,11 @@ static inline void iommu_detach_device(struct iommu_domain *domain,
{
}
+static inline struct iommu_domain *iommu_get_domain_for_dev(struct device *dev)
+{
+ return NULL;
+}
+
static inline int iommu_map(struct iommu_domain *domain, unsigned long iova,
phys_addr_t paddr, int gfp_order, int prot)
{
@@ -373,6 +402,21 @@ static inline void iommu_set_fault_handler(struct iommu_domain *domain,
{
}
+static inline void iommu_get_dm_regions(struct device *dev,
+ struct list_head *list)
+{
+}
+
+static inline void iommu_put_dm_regions(struct device *dev,
+ struct list_head *list)
+{
+}
+
+static inline int iommu_request_dm_for_dev(struct device *dev)
+{
+ return -ENODEV;
+}
+
static inline int iommu_attach_group(struct iommu_domain *domain,
struct iommu_group *group)
{