Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 28b47809 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull IOMMU updates from Joerg Roedel:

 - code optimizations for the Intel VT-d driver

 - ability to switch off a previously enabled Intel IOMMU

 - support for 'struct iommu_device' for OMAP, Rockchip and Mediatek
   IOMMUs

 - header optimizations for IOMMU core code headers and a few fixes that
   became necessary in other parts of the kernel because of that

 - ACPI/IORT updates and fixes

 - Exynos IOMMU optimizations

 - updates for the IOMMU dma-api code to bring it closer to use per-cpu
   iova caches

 - new command-line option to set default domain type allocated by the
   iommu core code

 - another command line option to allow the Intel IOMMU switched off in
   a tboot environment

 - ARM/SMMU: TLB sync optimisations for SMMUv2, Support for using an
   IDENTITY domain in conjunction with DMA ops, Support for SMR masking,
   Support for 16-bit ASIDs (was previously broken)

 - various other small fixes and improvements

* tag 'iommu-updates-v4.12' of git://git.kernel.org/pub/scm/linux/kernel/git/joro/iommu: (63 commits)
  soc/qbman: Move dma-mapping.h include to qman_priv.h
  soc/qbman: Fix implicit header dependency now causing build fails
  iommu: Remove trace-events include from iommu.h
  iommu: Remove pci.h include from trace/events/iommu.h
  arm: dma-mapping: Don't override dma_ops in arch_setup_dma_ops()
  ACPI/IORT: Fix CONFIG_IOMMU_API dependency
  iommu/vt-d: Don't print the failure message when booting non-kdump kernel
  iommu: Move report_iommu_fault() to iommu.c
  iommu: Include device.h in iommu.h
  x86, iommu/vt-d: Add an option to disable Intel IOMMU force on
  iommu/arm-smmu: Return IOVA in iova_to_phys when SMMU is bypassed
  iommu/arm-smmu: Correct sid to mask
  iommu/amd: Fix incorrect error handling in amd_iommu_bind_pasid()
  iommu: Make iommu_bus_notifier return NOTIFY_DONE rather than error code
  omap3isp: Remove iommu_group related code
  iommu/omap: Add iommu-group support
  iommu/omap: Make use of 'struct iommu_device'
  iommu/omap: Store iommu_dev pointer in arch_data
  iommu/omap: Move data structures to omap-iommu.h
  iommu/omap: Drop legacy-style device support
  ...
parents 4a1e31c6 2c0248d6
Loading
Loading
Loading
Loading
+15 −0
Original line number Diff line number Diff line
@@ -1578,6 +1578,15 @@
			extended tables themselves, and also PASID support. With
			this option set, extended tables will not be used even
			on hardware which claims to support them.
		tboot_noforce [Default Off]
			Do not force the Intel IOMMU enabled under tboot.
			By default, tboot will force Intel IOMMU on, which
			could harm performance of some high-throughput
			devices like 40GBit network cards, even if identity
			mapping is enabled.
			Note that using this option lowers the security
			provided by tboot because it makes the system
			vulnerable to DMA attacks.

	intel_idle.max_cstate=	[KNL,HW,ACPI,X86]
			0	disables intel_idle and fall back on acpi_idle.
@@ -1644,6 +1653,12 @@
		nobypass	[PPC/POWERNV]
			Disable IOMMU bypass, using IOMMU for PCI devices.

	iommu.passthrough=
			[ARM64] Configure DMA to bypass the IOMMU by default.
			Format: { "0" | "1" }
			0 - Use IOMMU translation for DMA.
			1 - Bypass the IOMMU for DMA.
			unset - Use IOMMU translation for DMA.

	io7=		[HW] IO7 for Marvel based alpha systems
			See comment before marvel_specify_io7 in
+28 −0
Original line number Diff line number Diff line
@@ -60,6 +60,17 @@ conditions.
                  aliases of secure registers have to be used during
                  SMMU configuration.

- stream-match-mask : For SMMUs supporting stream matching and using
                  #iommu-cells = <1>, specifies a mask of bits to ignore
		  when matching stream IDs (e.g. this may be programmed
		  into the SMRn.MASK field of every stream match register
		  used). For cases where it is desirable to ignore some
                  portion of every Stream ID (e.g. for certain MMU-500
                  configurations given globally unique input IDs). This
                  property is not valid for SMMUs using stream indexing,
                  or using stream matching with #iommu-cells = <2>, and
                  may be ignored if present in such cases.

** Deprecated properties:

- mmu-masters (deprecated in favour of the generic "iommus" binding) :
@@ -109,3 +120,20 @@ conditions.
        master3 {
                iommus = <&smmu2 1 0x30>;
        };


        /* ARM MMU-500 with 10-bit stream ID input configuration */
        smmu3: iommu {
                compatible = "arm,mmu-500", "arm,smmu-v2";
                ...
                #iommu-cells = <1>;
                /* always ignore appended 5-bit TBU number */
                stream-match-mask = 0x7c00;
        };

        bus {
                /* bus whose child devices emit one unique 10-bit stream
                   ID each, but may master through multiple SMMU TBUs */
                iommu-map = <0 &smmu3 0 0x400>;
                ...
        };
+9 −0
Original line number Diff line number Diff line
@@ -2408,6 +2408,15 @@ void arch_setup_dma_ops(struct device *dev, u64 dma_base, u64 size,
	const struct dma_map_ops *dma_ops;

	dev->archdata.dma_coherent = coherent;

	/*
	 * Don't override the dma_ops if they have already been set. Ideally
	 * this should be the only location where dma_ops are set, remove this
	 * check when all other callers of set_dma_ops will have disappeared.
	 */
	if (dev->dma_ops)
		return;

	if (arm_setup_iommu_dma_ops(dev, dma_base, size, iommu))
		dma_ops = arm_get_iommu_dma_map_ops(coherent);
	else
+19 −124
Original line number Diff line number Diff line
@@ -28,6 +28,7 @@
#include <linux/dma-contiguous.h>
#include <linux/vmalloc.h>
#include <linux/swiotlb.h>
#include <linux/pci.h>

#include <asm/cacheflush.h>

@@ -879,34 +880,26 @@ static const struct dma_map_ops iommu_dma_ops = {
	.mapping_error = iommu_dma_mapping_error,
};

/*
 * TODO: Right now __iommu_setup_dma_ops() gets called too early to do
 * everything it needs to - the device is only partially created and the
 * IOMMU driver hasn't seen it yet, so it can't have a group. Thus we
 * need this delayed attachment dance. Once IOMMU probe ordering is sorted
 * to move the arch_setup_dma_ops() call later, all the notifier bits below
 * become unnecessary, and will go away.
 */
struct iommu_dma_notifier_data {
	struct list_head list;
	struct device *dev;
	const struct iommu_ops *ops;
	u64 dma_base;
	u64 size;
};
static LIST_HEAD(iommu_dma_masters);
static DEFINE_MUTEX(iommu_dma_notifier_lock);
static int __init __iommu_dma_init(void)
{
	return iommu_dma_init();
}
arch_initcall(__iommu_dma_init);

static bool do_iommu_attach(struct device *dev, const struct iommu_ops *ops,
			   u64 dma_base, u64 size)
static void __iommu_setup_dma_ops(struct device *dev, u64 dma_base, u64 size,
				  const struct iommu_ops *ops)
{
	struct iommu_domain *domain = iommu_get_domain_for_dev(dev);
	struct iommu_domain *domain;

	if (!ops)
		return;

	/*
	 * If the IOMMU driver has the DMA domain support that we require,
	 * then the IOMMU core will have already configured a group for this
	 * device, and allocated the default domain for that group.
	 * The IOMMU core code allocates the default DMA domain, which the
	 * underlying IOMMU driver needs to support via the dma-iommu layer.
	 */
	domain = iommu_get_domain_for_dev(dev);

	if (!domain)
		goto out_err;

@@ -917,109 +910,11 @@ static bool do_iommu_attach(struct device *dev, const struct iommu_ops *ops,
		dev->dma_ops = &iommu_dma_ops;
	}

	return true;
	return;

out_err:
	 pr_warn("Failed to set up IOMMU for device %s; retaining platform DMA ops\n",
		 dev_name(dev));
	return false;
}

static void queue_iommu_attach(struct device *dev, const struct iommu_ops *ops,
			      u64 dma_base, u64 size)
{
	struct iommu_dma_notifier_data *iommudata;

	iommudata = kzalloc(sizeof(*iommudata), GFP_KERNEL);
	if (!iommudata)
		return;

	iommudata->dev = dev;
	iommudata->ops = ops;
	iommudata->dma_base = dma_base;
	iommudata->size = size;

	mutex_lock(&iommu_dma_notifier_lock);
	list_add(&iommudata->list, &iommu_dma_masters);
	mutex_unlock(&iommu_dma_notifier_lock);
}

static int __iommu_attach_notifier(struct notifier_block *nb,
				   unsigned long action, void *data)
{
	struct iommu_dma_notifier_data *master, *tmp;

	if (action != BUS_NOTIFY_BIND_DRIVER)
		return 0;

	mutex_lock(&iommu_dma_notifier_lock);
	list_for_each_entry_safe(master, tmp, &iommu_dma_masters, list) {
		if (data == master->dev && do_iommu_attach(master->dev,
				master->ops, master->dma_base, master->size)) {
			list_del(&master->list);
			kfree(master);
			break;
		}
	}
	mutex_unlock(&iommu_dma_notifier_lock);
	return 0;
}

static int __init register_iommu_dma_ops_notifier(struct bus_type *bus)
{
	struct notifier_block *nb = kzalloc(sizeof(*nb), GFP_KERNEL);
	int ret;

	if (!nb)
		return -ENOMEM;

	nb->notifier_call = __iommu_attach_notifier;

	ret = bus_register_notifier(bus, nb);
	if (ret) {
		pr_warn("Failed to register DMA domain notifier; IOMMU DMA ops unavailable on bus '%s'\n",
			bus->name);
		kfree(nb);
	}
	return ret;
}

static int __init __iommu_dma_init(void)
{
	int ret;

	ret = iommu_dma_init();
	if (!ret)
		ret = register_iommu_dma_ops_notifier(&platform_bus_type);
	if (!ret)
		ret = register_iommu_dma_ops_notifier(&amba_bustype);
#ifdef CONFIG_PCI
	if (!ret)
		ret = register_iommu_dma_ops_notifier(&pci_bus_type);
#endif
	return ret;
}
arch_initcall(__iommu_dma_init);

static void __iommu_setup_dma_ops(struct device *dev, u64 dma_base, u64 size,
				  const struct iommu_ops *ops)
{
	struct iommu_group *group;

	if (!ops)
		return;
	/*
	 * TODO: As a concession to the future, we're ready to handle being
	 * called both early and late (i.e. after bus_add_device). Once all
	 * the platform bus code is reworked to call us late and the notifier
	 * junk above goes away, move the body of do_iommu_attach here.
	 */
	group = iommu_group_get(dev);
	if (group) {
		do_iommu_attach(dev, ops, dma_base, size);
		iommu_group_put(group);
	} else {
		queue_iommu_attach(dev, ops, dma_base, size);
	}
}

void arch_teardown_dma_ops(struct device *dev)
+3 −0
Original line number Diff line number Diff line
@@ -514,6 +514,9 @@ int tboot_force_iommu(void)
	if (!tboot_enabled())
		return 0;

	if (!intel_iommu_tboot_noforce)
		return 1;

	if (no_iommu || swiotlb || dmar_disabled)
		pr_warning("Forcing Intel-IOMMU to enabled\n");

Loading