]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
iommu/vt-d: Restore context entry setup order for aliased devices
authorLu Baolu <baolu.lu@linux.intel.com>
Tue, 20 May 2025 07:58:49 +0000 (15:58 +0800)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 27 Jun 2025 10:11:21 +0000 (11:11 +0100)
commit 320302baed05c6456164652541f23d2a96522c06 upstream.

Commit 2031c469f816 ("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: 2031c469f816 ("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: Lu Baolu <baolu.lu@linux.intel.com>
Reviewed-by: Kevin Tian <kevin.tian@intel.com>
Reviewed-by: Yi 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: Joerg Roedel <jroedel@suse.de>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/iommu/intel/iommu.c
drivers/iommu/intel/iommu.h
drivers/iommu/intel/nested.c

index 157542c07aaafa779be82e49427c31378aea2bee..56e9f125cda9a0504edfdd36d9dfe7a7fe3ca83f 100644 (file)
@@ -1970,6 +1970,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);
@@ -3381,6 +3382,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);
 
@@ -3393,6 +3398,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;
 
@@ -4406,6 +4414,9 @@ static int device_set_dirty_tracking(struct list_head *devices, bool enable)
                        break;
        }
 
+       if (!ret)
+               info->domain_attached = true;
+
        return ret;
 }
 
index 1497f3112b12cd69551ff7a6654052d4148a1c2b..6f16eeb2ac6554a8c011fcdccde6f31a66197936 100644 (file)
@@ -776,6 +776,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;
        struct device *dev; /* it's NULL for PCIe-to-PCI bridge */
        struct intel_iommu *iommu; /* IOMMU used by this device */
index 433c58944401f9f4c15ba816d5e2b177a120bb18..3b5251034a871bedd74cd68af03ee53b818b5cf6 100644 (file)
@@ -27,8 +27,7 @@ static int intel_nested_attach_dev(struct iommu_domain *domain,
        unsigned long flags;
        int ret = 0;
 
-       if (info->domain)
-               device_block_translation(dev);
+       device_block_translation(dev);
 
        if (iommu->agaw < dmar_domain->s2_domain->agaw) {
                dev_err_ratelimited(dev, "Adjusted guest address width not compatible\n");
@@ -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);