[git pull] IOMMU Updates for Linux v4.2

From: Joerg Roedel
Date: Tue Jun 23 2015 - 05:24:30 EST


Hi Linus,

The IOMMU changes have conflicts this time with IRQ related patches
coming from the tip tree. Some of the IRQ patches there also touch the
Intel and AMD interrupt remapping code in drivers/iommu, which conflicts
with the Intel VT-d kdump fixes.

I attached my resolution of the conflicts to this pull-request and
compiled and run-time tested my resolution on an Intel VT-d and an
AMD IOMMU machine.

If you want me to send you another pull-request with the conflicts
already solved, please let me know. So with that notice in front, here
comes the pull-request:

The following changes since commit 0f57d86787d8b1076ea8f9cbdddda2a46d534a27:

Linux 4.1-rc8 (2015-06-14 15:51:10 -1000)

are available in the git repository at:

git://git.kernel.org/pub/scm/linux/kernel/git/joro/iommu.git tags/iommu-updates-v4.2

for you to fetch changes up to 5ffde2f67181195d457b95df44b8f88e8d969d89:

Merge branches 'arm/rockchip', 'arm/exynos', 'arm/smmu', 'x86/vt-d', 'x86/amd', 'default-domains' and 'core' into next (2015-06-19 17:17:47 +0200)

----------------------------------------------------------------

IOMMU Updates for Linux v4.2

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.

----------------------------------------------------------------
Colin Cross (1):
iommu/exynos: Tell kmemleak to ignore 2nd level page tables

Dan Carpenter (1):
iommu: Checking for NULL instead of IS_ERR

Heiko Stuebner (1):
iommu/rockchip: Silence attaching and detaching of devices

Joerg Roedel (45):
iommu/amd: Handle integer overflow in dma_ops_area_alloc
iommu: Remove function name from pr_fmt()
iommu: Add a few printk messages to group handling code
iommu: Propagate error in add_iommu_group
iommu: Clean up after a failed bus initialization
iommu: Call remove_device call-back after driver release
iommu: Allocate a default domain for iommu groups
iommu: Limit iommu_attach/detach_device to devices with their own group
iommu: Make sure a device is always attached to a domain
iommu: Add iommu_get_domain_for_dev function
iommu: Introduce direct mapped region handling
iommu: Create direct mappings in default domains
iommu: Add function to query the default domain of a group
iommu: Introduce iommu_request_dm_for_dev()
iommu/amd: Implement dm_region call-backs
iommu/amd: Use default domain if available for DMA-API
iommu/amd: Implement add_device and remove_device
iommu/amd: Support IOMMU_DOMAIN_DMA type allocation
iommu/amd: Support IOMMU_DOMAIN_IDENTITY type allocation
iommu/amd: Put IOMMUv2 devices in a direct mapped domain
iommu/amd: Get rid of device_dma_ops_init()
iommu/amd: Remove unused fields from struct dma_ops_domain
iommu/amd: Propagate errors from amd_iommu_init_api
iommu/amd: Handle errors returned from iommu_init_device
iommu/vt-d: Cleanup log messages
iommu/vt-d: Init QI before root entry is allocated
iommu/vt-d: Make root entry visible for hardware right after allocation
iommu/vt-d: Detect pre enabled translation
iommu/vt-d: Copy translation tables from old kernel
iommu/vt-d: Do not re-use domain-ids from the old kernel
iommu/vt-d: Mark copied context entries
iommu/vt-d: Allocate si_domain in init_dmars()
iommu/vt-d: Don't do early domain assignment if kdump kernel
iommu/vt-d: Don't copy translation tables if RTT bit needs to be changed
iommu/vt-d: Don't disable translation prior to OS handover
iommu/vt-d: Enable Translation only if it was previously disabled
iommu/vt-d: Move EIM detection to intel_prepare_irq_remapping
iommu/vt-d: Move QI initializationt to intel_setup_irq_remapping
iommu/vt-d: Disable IRQ remapping in intel_prepare_irq_remapping
iommu/vt-d: Set IRTA in intel_setup_irq_remapping
iommu/vt-d: Copy IR table from old kernel when in kdump mode
iommu/vt-d: Make sure copied over IR entries are not reused
iommu/vt-d: Don't disable IR when it was previously enabled
iommu/amd: Handle large pages correctly in free_pagetable
Merge branches 'arm/rockchip', 'arm/exynos', 'arm/smmu', 'x86/vt-d', 'x86/amd', 'default-domains' and 'core' into next

Marek Szyprowski (15):
iommu: Init iommu-groups support earlier, in core_initcall
iommu/exynos: Don't read version register on every tlb operation
iommu/exynos: Remove unused functions
iommu/exynos: Remove useless members from exynos_iommu_owner structure
iommu/exynos: Refactor function parameters to simplify code
iommu/exynos: Rename variables to reflect their purpose
iommu/exynos: Use struct exynos_iommu_domain in internal structures
iommu/exynos: Remove excessive includes and sort others alphabetically
iommu/exynos: Document internal structures
iommu/exynos: Add/remove callbacks should fail if no iommu is available
iommu/exynos: Add support for binding more than one sysmmu to master device
iommu/exynos: Add support for runtime_pm
iommu/exynos: Add system suspend/resume support
iommu/exynos: Init from dt-specific callback instead of initcall
iommu/exynos: Add callback for initializing devices from device tree

Robert Callicotte (1):
iommu: Fix checkpatch warnings for Missing a blank line after declarations

Robin Murphy (1):
iommu/arm-smmu: Fix ATS1* register writes

Tomasz Figa (1):
iommu/rockchip: Make sure that page table state is coherent

Will Deacon (4):
iommu/arm-smmu: Make force_stage module param read-only in sysfs
Documentation: dt-bindings: Add device-tree binding for ARM SMMUv3 IOMMU
iommu/arm-smmu: Add initial driver support for ARM SMMUv3 devices
drivers/vfio: Allow type-1 IOMMU instantiation on top of an ARM SMMUv3

.../devicetree/bindings/iommu/arm,smmu-v3.txt | 37 +
MAINTAINERS | 3 +-
drivers/iommu/Kconfig | 13 +
drivers/iommu/Makefile | 1 +
drivers/iommu/amd_iommu.c | 589 ++---
drivers/iommu/amd_iommu_init.c | 34 +-
drivers/iommu/amd_iommu_proto.h | 2 +-
drivers/iommu/amd_iommu_types.h | 11 -
drivers/iommu/arm-smmu-v3.c | 2670 ++++++++++++++++++++
drivers/iommu/arm-smmu.c | 23 +-
drivers/iommu/dmar.c | 28 +-
drivers/iommu/exynos-iommu.c | 527 ++--
drivers/iommu/intel-iommu.c | 495 +++-
drivers/iommu/intel_irq_remapping.c | 255 +-
drivers/iommu/iommu.c | 373 ++-
drivers/iommu/iova.c | 4 +
drivers/iommu/rockchip-iommu.c | 27 +-
drivers/vfio/Kconfig | 2 +-
include/linux/intel-iommu.h | 5 +
include/linux/iommu.h | 44 +
20 files changed, 4186 insertions(+), 957 deletions(-)
create mode 100644 Documentation/devicetree/bindings/iommu/arm,smmu-v3.txt
create mode 100644 drivers/iommu/arm-smmu-v3.c

Please pull.

Thanks,

Joerg

diff --cc drivers/iommu/dmar.c
index 536f2d8,c588658..c9db04d
--- a/drivers/iommu/dmar.c
+++ b/drivers/iommu/dmar.c
@@@ -1642,17 -1642,26 +1642,17 @@@ int dmar_set_interrupt(struct intel_iom
if (iommu->irq)
return 0;

- irq = dmar_alloc_hwirq();
- if (irq <= 0) {
+ irq = dmar_alloc_hwirq(iommu->seq_id, iommu->node, iommu);
+ if (irq > 0) {
+ iommu->irq = irq;
+ } else {
- pr_err("IOMMU: no free vectors\n");
+ pr_err("No free IRQ vectors\n");
return -EINVAL;
}

- irq_set_handler_data(irq, iommu);
- iommu->irq = irq;
-
- ret = arch_setup_dmar_msi(irq);
- if (ret) {
- irq_set_handler_data(irq, NULL);
- iommu->irq = 0;
- dmar_free_hwirq(irq);
- return ret;
- }
-
ret = request_irq(irq, dmar_fault, IRQF_NO_THREAD, iommu->name, iommu);
if (ret)
- pr_err("IOMMU: can't request irq\n");
+ pr_err("Can't request irq\n");
return ret;
}

diff --cc drivers/iommu/intel_irq_remapping.c
index 80f1d14,47fcebf..6f75ab7
--- a/drivers/iommu/intel_irq_remapping.c
+++ b/drivers/iommu/intel_irq_remapping.c
@@@ -8,7 -11,7 +11,8 @@@
#include <linux/irq.h>
#include <linux/intel-iommu.h>
#include <linux/acpi.h>
+#include <linux/irqdomain.h>
+ #include <linux/crash_dump.h>
#include <asm/io_apic.h>
#include <asm/smp.h>
#include <asm/cpu.h>
@@@ -72,14 -54,63 +76,34 @@@ static struct hpet_scope ir_hpet[MAX_HP
* the dmar_global_lock.
*/
static DEFINE_RAW_SPINLOCK(irq_2_ir_lock);
+static struct irq_domain_ops intel_ir_domain_ops;

+ static void iommu_disable_irq_remapping(struct intel_iommu *iommu);
static int __init parse_ioapics_under_ir(void);

+ static bool ir_pre_enabled(struct intel_iommu *iommu)
+ {
+ return (iommu->flags & VTD_FLAG_IRQ_REMAP_PRE_ENABLED);
+ }
+
+ static void clear_ir_pre_enabled(struct intel_iommu *iommu)
+ {
+ iommu->flags &= ~VTD_FLAG_IRQ_REMAP_PRE_ENABLED;
+ }
+
+ static void init_ir_status(struct intel_iommu *iommu)
+ {
+ u32 gsts;
+
+ gsts = readl(iommu->reg + DMAR_GSTS_REG);
+ if (gsts & DMA_GSTS_IRES)
+ iommu->flags |= VTD_FLAG_IRQ_REMAP_PRE_ENABLED;
+ }
+
-static struct irq_2_iommu *irq_2_iommu(unsigned int irq)
-{
- struct irq_cfg *cfg = irq_cfg(irq);
- return cfg ? &cfg->irq_2_iommu : NULL;
-}
-
-static int get_irte(int irq, struct irte *entry)
-{
- struct irq_2_iommu *irq_iommu = irq_2_iommu(irq);
- unsigned long flags;
- int index;
-
- if (!entry || !irq_iommu)
- return -1;
-
- raw_spin_lock_irqsave(&irq_2_ir_lock, flags);
-
- if (unlikely(!irq_iommu->iommu)) {
- raw_spin_unlock_irqrestore(&irq_2_ir_lock, flags);
- return -1;
- }
-
- index = irq_iommu->irte_index + irq_iommu->sub_handle;
- *entry = *(irq_iommu->iommu->ir_table->base + index);
-
- raw_spin_unlock_irqrestore(&irq_2_ir_lock, flags);
- return 0;
-}
-
-static int alloc_irte(struct intel_iommu *iommu, int irq, u16 count)
+static int alloc_irte(struct intel_iommu *iommu, int irq,
+ struct irq_2_iommu *irq_iommu, u16 count)
{
struct ir_table *table = iommu->ir_table;
- struct irq_2_iommu *irq_iommu = irq_2_iommu(irq);
- struct irq_cfg *cfg = irq_cfg(irq);
unsigned int mask = 0;
unsigned long flags;
int index;
@@@ -534,9 -693,9 +645,29 @@@ static void __init intel_cleanup_irq_re
}

if (x2apic_supported())
- pr_warn("Failed to enable irq remapping. You are vulnerable to irq-injection attacks.\n");
+ pr_warn("Failed to enable irq remapping. You are vulnerable to irq-injection attacks.\n");
+ }
+
++/*
++ * Set Posted-Interrupts capability.
++ */
++static inline void set_irq_posting_cap(void)
++{
++ struct dmar_drhd_unit *drhd;
++ struct intel_iommu *iommu;
++
++ if (!disable_irq_post) {
++ intel_irq_remap_ops.capability |= 1 << IRQ_POSTING_CAP;
++
++ for_each_iommu(iommu, drhd)
++ if (!cap_pi_support(iommu->cap)) {
++ intel_irq_remap_ops.capability &=
++ ~(1 << IRQ_POSTING_CAP);
++ break;
++ }
++ }
+}
+
static int __init intel_prepare_irq_remapping(void)
{
struct dmar_drhd_unit *drhd;
@@@ -676,11 -784,16 +756,11 @@@ static int __init intel_enable_irq_rema

irq_remapping_enabled = 1;

- /*
- * VT-d has a different layout for IO-APIC entries when
- * interrupt remapping is enabled. So it needs a special routine
- * to print IO-APIC entries for debugging purposes too.
- */
- x86_io_apic_ops.print_entries = intel_ir_io_apic_print_entries;
+ set_irq_posting_cap();

- pr_info("Enabled IRQ remapping in %s mode\n", eim ? "x2apic" : "xapic");
+ pr_info("Enabled IRQ remapping in %s mode\n", eim_mode ? "x2apic" : "xapic");

- return eim ? IRQ_REMAP_X2APIC_MODE : IRQ_REMAP_XAPIC_MODE;
+ return eim_mode ? IRQ_REMAP_X2APIC_MODE : IRQ_REMAP_XAPIC_MODE;

error:
intel_cleanup_irq_remapping();

Attachment: signature.asc
Description: Digital signature