linux/drivers/iommu/intel
Jinhui Guo e70d5feb10 iommu/vt-d: Skip dev-iotlb flush for inaccessible PCIe device without scalable mode
[ Upstream commit 42662d1983 ]

PCIe endpoints with ATS enabled and passed through to userspace
(e.g., QEMU, DPDK) can hard-lock the host when their link drops,
either by surprise removal or by a link fault.

Commit 4fc82cd907 ("iommu/vt-d: Don't issue ATS Invalidation
request when device is disconnected") adds pci_dev_is_disconnected()
to devtlb_invalidation_with_pasid() so ATS invalidation is skipped
only when the device is being safely removed, but it applies only
when Intel IOMMU scalable mode is enabled.

With scalable mode disabled or unsupported, a system hard-lock
occurs when a PCIe endpoint's link drops because the Intel IOMMU
waits indefinitely for an ATS invalidation that cannot complete.

Call Trace:
 qi_submit_sync
 qi_flush_dev_iotlb
 __context_flush_dev_iotlb.part.0
 domain_context_clear_one_cb
 pci_for_each_dma_alias
 device_block_translation
 blocking_domain_attach_dev
 iommu_deinit_device
 __iommu_group_remove_device
 iommu_release_device
 iommu_bus_notifier
 blocking_notifier_call_chain
 bus_notify
 device_del
 pci_remove_bus_device
 pci_stop_and_remove_bus_device
 pciehp_unconfigure_device
 pciehp_disable_slot
 pciehp_handle_presence_or_link_change
 pciehp_ist

Commit 81e921fd32 ("iommu/vt-d: Fix NULL domain on device release")
adds intel_pasid_teardown_sm_context() to intel_iommu_release_device(),
which calls qi_flush_dev_iotlb() and can also hard-lock the system
when a PCIe endpoint's link drops.

Call Trace:
 qi_submit_sync
 qi_flush_dev_iotlb
 __context_flush_dev_iotlb.part.0
 intel_context_flush_no_pasid
 device_pasid_table_teardown
 pci_pasid_table_teardown
 pci_for_each_dma_alias
 intel_pasid_teardown_sm_context
 intel_iommu_release_device
 iommu_deinit_device
 __iommu_group_remove_device
 iommu_release_device
 iommu_bus_notifier
 blocking_notifier_call_chain
 bus_notify
 device_del
 pci_remove_bus_device
 pci_stop_and_remove_bus_device
 pciehp_unconfigure_device
 pciehp_disable_slot
 pciehp_handle_presence_or_link_change
 pciehp_ist

Sometimes the endpoint loses connection without a link-down event
(e.g., due to a link fault); killing the process (virsh destroy)
then hard-locks the host.

Call Trace:
 qi_submit_sync
 qi_flush_dev_iotlb
 __context_flush_dev_iotlb.part.0
 domain_context_clear_one_cb
 pci_for_each_dma_alias
 device_block_translation
 blocking_domain_attach_dev
 __iommu_attach_device
 __iommu_device_set_domain
 __iommu_group_set_domain_internal
 iommu_detach_group
 vfio_iommu_type1_detach_group
 vfio_group_detach_container
 vfio_group_fops_release
 __fput

pci_dev_is_disconnected() only covers safe-removal paths;
pci_device_is_present() tests accessibility by reading
vendor/device IDs and internally calls pci_dev_is_disconnected().
On a ConnectX-5 (8 GT/s, x2) this costs ~70 µs.

Since __context_flush_dev_iotlb() is only called on
{attach,release}_dev paths (not hot), add pci_device_is_present()
there to skip inaccessible devices and avoid the hard-lock.

Fixes: 37764b952e ("iommu/vt-d: Global devTLB flush when present context entry changed")
Fixes: 81e921fd32 ("iommu/vt-d: Fix NULL domain on device release")
Cc: stable@vger.kernel.org
Signed-off-by: Jinhui Guo <guojinhui.liam@bytedance.com>
Link: https://lore.kernel.org/r/20251211035946.2071-2-guojinhui.liam@bytedance.com
Signed-off-by: Lu Baolu <baolu.lu@linux.intel.com>
Signed-off-by: Joerg Roedel <joerg.roedel@amd.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
History 2026-03-12 07:09:29 -04:00
..
cache.c iommu/vt-d: Flush piotlb for SVM and Nested domain 2026-03-04 07:21:12 -05:00
debugfs.c iommu/vt-d: debugfs: Avoid dumping context command register 2025-09-19 09:43:21 +02:00
dmar.c iommu/vt-d: Remove the CONFIG_X86 wrapping from iommu init hook 2025-07-14 11:18:03 +01:00
iommu.c iommu/vt-d: Clear Present bit before tearing down context entry 2026-02-26 14:59:18 -08:00
iommu.h iommu/vt-d: Clear Present bit before tearing down context entry 2026-02-26 14:59:18 -08:00
irq_remapping.c x86/msi: Make irq_retrigger() functional for posted MSI 2026-01-02 12:56:57 +01:00
Kconfig iommu/vt-d: Set INTEL_IOMMU_FLOPPY_WA depend on BLK_DEV_FD 2025-12-18 14:03:06 +01:00
Makefile iommu: make inclusion of intel directory conditional 2025-05-16 08:46:46 +02:00
nested.c iommu/vt-d: Create unique domain ops for each stage 2025-07-14 11:18:03 +01:00
pasid.c iommu/vt-d: Skip dev-iotlb flush for inaccessible PCIe device without scalable mode 2026-03-12 07:09:29 -04:00
pasid.h iommu/vt-d: Clear Present bit before tearing down PASID entry 2026-02-26 14:59:18 -08:00
perf.c iommu/vt-d: Replace snprintf with scnprintf in dmar_latency_snapshot() 2025-09-19 09:43:19 +02:00
perf.h iommu/vt-d: Replace snprintf with scnprintf in dmar_latency_snapshot() 2025-09-19 09:43:19 +02:00
perfmon.c iommu/vt-d: Clean up cpumask and hotplug for perfmon 2024-09-10 11:44:13 +02:00
perfmon.h iommu/vt-d: Add IOMMU perfmon support 2023-02-03 11:06:06 +01:00
prq.c iommu/vt-d: Remove LPIG from page group response descriptor 2025-09-19 09:43:20 +02:00
svm.c iommu/vt-d: Create unique domain ops for each stage 2025-07-14 11:18:03 +01:00
trace.c iommu/vt-d: Move trace/events/intel_iommu.h under iommu 2022-07-15 10:21:28 +02:00
trace.h iommu/vt-d: Deduplicate cache_tag_flush_all by reusing flush_range 2025-07-14 11:18:04 +01:00