Commit 320302ba authored by Lu Baolu's avatar Lu Baolu Committed by Joerg Roedel
Browse files

iommu/vt-d: Restore context entry setup order for aliased devices

Commit 2031c469 ("iommu/vt-d: Add support for static identity domain")
changed the context entry setup during domain attachment from a
set-and-check policy to a clear-and-reset approach. This inadvertently
introduced a regression affecting PCI aliased devices behind PCIe-to-PCI
bridges.

Specifically, keyboard and touchpad stopped working on several Apple
Macbooks with below messages:

 kernel: platform pxa2xx-spi.3: Adding to iommu group 20
 kernel: input: Apple SPI Keyboard as
 /devices/pci0000:00/0000:00:1e.3/pxa2xx-spi.3/spi_master/spi2/spi-APP000D:00/input/input0
 kernel: DMAR: DRHD: handling fault status reg 3
 kernel: DMAR: [DMA Read NO_PASID] Request device [00:1e.3] fault addr
 0xffffa000 [fault reason 0x06] PTE Read access is not set
 kernel: DMAR: DRHD: handling fault status reg 3
 kernel: DMAR: [DMA Read NO_PASID] Request device [00:1e.3] fault addr
 0xffffa000 [fault reason 0x06] PTE Read access is not set
 kernel: applespi spi-APP000D:00: Error writing to device: 01 0e 00 00
 kernel: DMAR: DRHD: handling fault status reg 3
 kernel: DMAR: [DMA Read NO_PASID] Request device [00:1e.3] fault addr
 0xffffa000 [fault reason 0x06] PTE Read access is not set
 kernel: DMAR: DRHD: handling fault status reg 3
 kernel: applespi spi-APP000D:00: Error writing to device: 01 0e 00 00

Fix this by restoring the previous context setup order.

Fixes: 2031c469 ("iommu/vt-d: Add support for static identity domain")
Closes: https://lore.kernel.org/all/4dada48a-c5dd-4c30-9c85-5b03b0aa01f0@bfh.ch/


Cc: stable@vger.kernel.org
Signed-off-by: default avatarLu Baolu <baolu.lu@linux.intel.com>
Reviewed-by: default avatarKevin Tian <kevin.tian@intel.com>
Reviewed-by: default avatarYi Liu <yi.l.liu@intel.com>
Link: https://lore.kernel.org/r/20250514060523.2862195-1-baolu.lu@linux.intel.com
Link: https://lore.kernel.org/r/20250520075849.755012-2-baolu.lu@linux.intel.com


Signed-off-by: default avatarJoerg Roedel <jroedel@suse.de>
parent f3fe7e18
Loading
Loading
Loading
Loading
+11 −0
Original line number Diff line number Diff line
@@ -1808,6 +1808,7 @@ static int dmar_domain_attach_device(struct dmar_domain *domain,
		return ret;

	info->domain = domain;
	info->domain_attached = true;
	spin_lock_irqsave(&domain->lock, flags);
	list_add(&info->link, &domain->devices);
	spin_unlock_irqrestore(&domain->lock, flags);
@@ -3204,6 +3205,10 @@ void device_block_translation(struct device *dev)
	struct intel_iommu *iommu = info->iommu;
	unsigned long flags;

	/* Device in DMA blocking state. Noting to do. */
	if (!info->domain_attached)
		return;

	if (info->domain)
		cache_tag_unassign_domain(info->domain, dev, IOMMU_NO_PASID);

@@ -3215,6 +3220,9 @@ void device_block_translation(struct device *dev)
			domain_context_clear(info);
	}

	/* Device now in DMA blocking state. */
	info->domain_attached = false;

	if (!info->domain)
		return;

@@ -4298,6 +4306,9 @@ static int identity_domain_attach_dev(struct iommu_domain *domain, struct device
	else
		ret = device_setup_pass_through(dev);

	if (!ret)
		info->domain_attached = true;

	return ret;
}

+1 −0
Original line number Diff line number Diff line
@@ -775,6 +775,7 @@ struct device_domain_info {
	u8 ats_supported:1;
	u8 ats_enabled:1;
	u8 dtlb_extra_inval:1;	/* Quirk for devices need extra flush */
	u8 domain_attached:1;	/* Device has domain attached */
	u8 ats_qdep;
	unsigned int iopf_refcount;
	struct device *dev; /* it's NULL for PCIe-to-PCI bridge */
+2 −2
Original line number Diff line number Diff line
@@ -27,7 +27,6 @@ static int intel_nested_attach_dev(struct iommu_domain *domain,
	unsigned long flags;
	int ret = 0;

	if (info->domain)
	device_block_translation(dev);

	if (iommu->agaw < dmar_domain->s2_domain->agaw) {
@@ -62,6 +61,7 @@ static int intel_nested_attach_dev(struct iommu_domain *domain,
		goto unassign_tag;

	info->domain = dmar_domain;
	info->domain_attached = true;
	spin_lock_irqsave(&dmar_domain->lock, flags);
	list_add(&info->link, &dmar_domain->devices);
	spin_unlock_irqrestore(&dmar_domain->lock, flags);