Skip to contentSkip to conversation

iommu/amd: Force identity mode for selected GPUs only

PATCH Applied Vasant Hegde 6 participants 8 messages Aug 24 – Nov 5

Subsystems (3)
lore
Share & tools
lore

Vasant Hegde

author maintainer
#0 lore raw

PATCH v2 1/1 iommu/amd: Force identity mode for selected GPUs only

Certain AMD GPUs must always operate in IOMMU identity mode. This was previously enforced using a PASID check, which happened to work because these specific GPUs are PASID-capable. However, this approach incorrectly applies identity mode enforcement to all PASID-capable devices, not just the GPUs that require it.

This made sense in the past because the domain allocation API (iommu_ops->domain_alloc()) only received the domain type, so the driver had no way to inspect device capabilities and pick the most suitable page table format (v1 or v2). With the recent driver enhancement to use domain_alloc_paging_flags() for all paging domain allocations, the driver can now inspect the device and flags directly and choose the appropriate page table type per device.

Update amd_iommu_def_domain_type() to force identity mapping only for the specific GPUs that require it, via a new quirks_force_identity_mapping().

With this change, a system booting in DMA translation mode will now select:
* Guest (v2) page table for PASID-capable devices
* Host (v1) page table for non-PASID-capable devices

Also drop the amd_iommu_snp_en check, as SNP enforces paging domain, which doesn't work with the identity requirement of these GPUs.

---
Changes in v2:
- Dropped disabling ATS for "Radeon Pro WX 4100"
- Addressed review comments

@Jason,
Once this patch settles, I will send separate patch to drop 'untrusted' check inside amd_iommu_def_domain_type().

Regarding SME check, I have retained SME chek inside quirks_force_identity_mapping(). If everyone is fine to drop then I will do follow up patch later.

-Vasant

 drivers/iommu/amd/iommu.c | 45 +++++++++++++++++++++++++++++----------
 1 file changed, 34 insertions(+), 11 deletions(-)
drivers/iommu/amd/iommu.c +34 -11
index 29dc18d3d22e..fc7819f57521 100644
@@ -3122,6 +3122,26 @@ static bool amd_iommu_is_attach_deferred(struct device *dev)
 	return dev_data->defer_attach;
 }
 
+static bool quirks_force_identity_mapping(struct pci_dev *pdev)
+{
+	int class = pdev->class >> 8;
+
+	/* AMD GPU vendor ID */
+	if (pdev->vendor != PCI_VENDOR_ID_ATI)
+		return false;
+
+	/* GPU class */
+	if (class != PCI_CLASS_DISPLAY_VGA &&
+	    class != PCI_CLASS_DISPLAY_OTHER)
+		return false;
+
+	if (pci_upstream_bridge(pdev)->vendor == PCI_VENDOR_ID_ATI)
+		return false;
+
+	/* It is the GPU in an APU, force identity domain */
+	return true;
+}
+
 static int amd_iommu_def_domain_type(struct device *dev)
 {
 	struct iommu_dev_data *dev_data;
@@ -3130,20 +3150,23 @@ static int amd_iommu_def_domain_type(struct device *dev)
 	if (!dev_data)
 		return 0;
 
+	if (!dev_is_pci(dev))
+		return 0;
+
 	/* Always use DMA domain for untrusted device */
-	if (dev_is_pci(dev) && to_pci_dev(dev)->untrusted)
+	if (to_pci_dev(dev)->untrusted)
 		return IOMMU_DOMAIN_DMA;
 
-	/*
-	 * Do not identity map IOMMUv2 capable devices when:
-	 *  - memory encryption is active, because some of those devices
-	 *    (AMD GPUs) don't have the encryption bit in their DMA-mask
-	 *    and require remapping.
-	 *  - SNP is enabled, because it prohibits DTE[Mode]=0.
-	 */
-	if (pdev_pasid_supported(dev_data) &&
-	    !cc_platform_has(CC_ATTR_MEM_ENCRYPT) &&
-	    !amd_iommu_snp_en) {
+	/* Apply device specific quirks */
+	if (quirks_force_identity_mapping(to_pci_dev(dev))) {
+		/*
+		 * When memory encryption is active, some of these devices
+		 * don't have the encryption bit in their DMA-mask and
+		 * require remapping.
+		 */
+		if (cc_platform_has(CC_ATTR_MEM_ENCRYPT))
+			return 0;
+
 		return IOMMU_DOMAIN_IDENTITY;
 	}
 
Signature · 1 line
2.31.1
#1 lore raw
Thank you for your contribution! Sashiko AI review found 3 potential issue(s) to consider: - [Critical] Missing NULL pointer check for `pci_upstream_bridge()` causes a kernel panic during boot on…

Thank you for your contribution! Sashiko AI review found 3 potential issue(s) to consider:
- [Critical] Missing NULL pointer check for pci_upstream_bridge() causes a kernel panic during boot on systems where the GPU is on the root bus.
- [High] The heuristic used to distinguish discrete GPUs (dGPUs) from APU GPUs is flawed and will incorrectly force identity mapping on many dGPUs.
- [High] Discrete GPUs break on SNP-enabled systems due to the removal of the SNP check combined with flawed GPU identification. --

--- Patch [1]: [PATCH v2] iommu/amd: Force identity mode for selected GPUs only --- commit 8994b69ea108b9e83363d3bf65d86e8798e45ba5
Author: Vasant Hegde <[email protected]>

iommu/amd: Force identity mode for selected GPUs only

This commit updates AMD IOMMU domain allocation to force identity mapping only for specific APU GPUs, rather than all PASID-capable devices. It introduces quirks_force_identity_mapping() to apply this targeted enforcement and drops the previous SNP check.

Quoted 12 lines
drivers/iommu/amd/iommu.c +4 -0
index 4dc306a4b5c62..eef585918e607 100644
@@ -3165,6 +3165,26 @@ static bool amd_iommu_is_attach_deferred(struct device *dev)
 	return dev_data->defer_attach;
 }
 
+static bool quirks_force_identity_mapping(struct pci_dev *pdev)
+{
+	int class = pdev->class >> 8;
+

drivers/iommu/amd/iommu.c static bool amd_iommu_is_attach_deferred(struct device *dev) · line 3181

Quoted 10 lines
drivers/iommu/amd/iommu.c +10 -0
+	/* AMD GPU vendor ID */
+	if (pdev->vendor != PCI_VENDOR_ID_ATI)
+		return false;
+
+	/* GPU class */
+	if (class != PCI_CLASS_DISPLAY_VGA &&
+	    class != PCI_CLASS_DISPLAY_OTHER)
+		return false;
+
+	if (pci_upstream_bridge(pdev)->vendor == PCI_VENDOR_ID_ATI)

[Severity: Critical]
Is it possible for pci_upstream_bridge() to return NULL here?

If the GPU is located on the PCIe root bus (such as in an integrated SoC design, or when passed through to a VM via VFIO), pci_upstream_bridge(pdev) would return NULL. This would lead to a kernel panic when dereferencing ->vendor during boot.

drivers/iommu/amd/iommu.c static bool amd_iommu_is_attach_deferred(struct device *dev) · line 3143

Quoted 5 lines
drivers/iommu/amd/iommu.c +5 -0
+		return false;
+
+	/* It is the GPU in an APU, force identity domain */
+	return true;
+}

[Severity: High]
Does this heuristic accurately distinguish APUs from standard discrete GPUs?

Standard discrete GPUs are typically plugged directly into motherboard PCIe slots, which means their upstream bridge is the motherboard's root port (e.g., an Intel or AMD root port, not an ATI switch). Since the root port vendor is not ATI, this check would fall through and erroneously return true, forcing standard discrete GPUs into the identity domain.

[ ... ]

Quoted 12 lines
drivers/iommu/amd/iommu.c +2 -10
-	/*
-	 * Do not identity map IOMMUv2 capable devices when:
-	 *  - memory encryption is active, because some of those devices
-	 *    (AMD GPUs) don't have the encryption bit in their DMA-mask
-	 *    and require remapping.
-	 *  - SNP is enabled, because it prohibits DTE[Mode]=0.
-	 */
-	if (pdev_pasid_supported(dev_data) &&
-	    !cc_platform_has(CC_ATTR_MEM_ENCRYPT) &&
-	    !amd_iommu_snp_en) {
+	/* Apply device specific quirks */
+	if (quirks_force_identity_mapping(to_pci_dev(dev))) {

drivers/iommu/amd/iommu.c static int amd_iommu_def_domain_type(struct device *dev) · line 3171

Quoted 10 lines
drivers/iommu/amd/iommu.c +9 -0
+		/*
+		 * When memory encryption is active, some of these devices
+		 * don't have the encryption bit in their DMA-mask and
+		 * require remapping.
+		 */
+		if (cc_platform_has(CC_ATTR_MEM_ENCRYPT))
+			return 0;
+
+		return IOMMU_DOMAIN_IDENTITY;
 	}

[Severity: High]
Since the amd_iommu_snp_en check was dropped, how does this affect discrete GPUs on SNP-enabled systems?

If standard discrete GPUs are incorrectly identified as APUs by quirks_force_identity_mapping(), they will be unconditionally forced into IOMMU_DOMAIN_IDENTITY here when SME is disabled.

On systems with SNP enabled, amd_iommu_identity_attach() will reject the identity domain if Mode0 isn't supported, returning -EINVAL. Could this leave the discrete GPU without a valid domain and break DMA entirely?

Signature · 1 line
Sashiko AI review · https://sashiko.dev/#/patchset/[email protected]?part=1
Reviewed-by on v2 1/1
#2 lore raw
In reply to Vasant Hegde
Quoted 22 lines · Vasant Hegde

Certain AMD GPUs must always operate in IOMMU identity mode. This was previously enforced using a PASID check, which happened to work because these specific GPUs are PASID-capable. However, this approach incorrectly applies identity mode enforcement to all PASID-capable devices, not just the GPUs that require it.

This made sense in the past because the domain allocation API (iommu_ops->domain_alloc()) only received the domain type, so the driver had no way to inspect device capabilities and pick the most suitable page table format (v1 or v2). With the recent driver enhancement to use domain_alloc_paging_flags() for all paging domain allocations, the driver can now inspect the device and flags directly and choose the appropriate page table type per device.

Update amd_iommu_def_domain_type() to force identity mapping only for the specific GPUs that require it, via a new quirks_force_identity_mapping().

With this change, a system booting in DMA translation mode will now select:
* Guest (v2) page table for PASID-capable devices
* Host (v1) page table for non-PASID-capable devices

Quoted 8 lines

Also drop the amd_iommu_snp_en check, as SNP enforces paging domain, which doesn't work with the identity requirement of these GPUs.

Quoted 83 lines

Changes in v2:
- Dropped disabling ATS for "Radeon Pro WX 4100"
- Addressed review comments

@Jason,
Once this patch settles, I will send separate patch to drop 'untrusted' check inside amd_iommu_def_domain_type().

Regarding SME check, I have retained SME chek inside quirks_force_identity_mapping(). If everyone is fine to drop then I will do follow up patch later.

(quoted diff) +0 -1
-Vasant
 
  drivers/iommu/amd/iommu.c | 45 +++++++++++++++++++++++++++++----------
  1 file changed, 34 insertions(+), 11 deletions(-)
drivers/iommu/amd/iommu.c +34 -11
index 29dc18d3d22e..fc7819f57521 100644
@@ -3122,6 +3122,26 @@ static bool amd_iommu_is_attach_deferred(struct device *dev)
  	return dev_data->defer_attach;
  }
 
+static bool quirks_force_identity_mapping(struct pci_dev *pdev)
+{
+	int class = pdev->class >> 8;
+
+	/* AMD GPU vendor ID */
+	if (pdev->vendor != PCI_VENDOR_ID_ATI)
+		return false;
+
+	/* GPU class */
+	if (class != PCI_CLASS_DISPLAY_VGA &&
+	    class != PCI_CLASS_DISPLAY_OTHER)
+		return false;
+
+	if (pci_upstream_bridge(pdev)->vendor == PCI_VENDOR_ID_ATI)
+		return false;
+
+	/* It is the GPU in an APU, force identity domain */
+	return true;
+}
+
  static int amd_iommu_def_domain_type(struct device *dev)
  {
  	struct iommu_dev_data *dev_data;
@@ -3130,20 +3150,23 @@ static int amd_iommu_def_domain_type(struct device *dev)
  	if (!dev_data)
  		return 0;
 
+	if (!dev_is_pci(dev))
+		return 0;
+
  	/* Always use DMA domain for untrusted device */
-	if (dev_is_pci(dev) && to_pci_dev(dev)->untrusted)
+	if (to_pci_dev(dev)->untrusted)
  		return IOMMU_DOMAIN_DMA;
 
-	/*
-	 * Do not identity map IOMMUv2 capable devices when:
-	 *  - memory encryption is active, because some of those devices
-	 *    (AMD GPUs) don't have the encryption bit in their DMA-mask
-	 *    and require remapping.
-	 *  - SNP is enabled, because it prohibits DTE[Mode]=0.
-	 */
-	if (pdev_pasid_supported(dev_data) &&
-	    !cc_platform_has(CC_ATTR_MEM_ENCRYPT) &&
-	    !amd_iommu_snp_en) {
+	/* Apply device specific quirks */
+	if (quirks_force_identity_mapping(to_pci_dev(dev))) {
+		/*
+		 * When memory encryption is active, some of these devices
+		 * don't have the encryption bit in their DMA-mask and
+		 * require remapping.
+		 */
+		if (cc_platform_has(CC_ATTR_MEM_ENCRYPT))
+			return 0;
+
  		return IOMMU_DOMAIN_IDENTITY;
  	}
 
Reviewed-by on v2 1/1
#3 lore raw
In reply to Vasant Hegde
Quoted 35 lines · Vasant Hegde

Certain AMD GPUs must always operate in IOMMU identity mode. This was previously enforced using a PASID check, which happened to work because these specific GPUs are PASID-capable. However, this approach incorrectly applies identity mode enforcement to all PASID-capable devices, not just the GPUs that require it.

This made sense in the past because the domain allocation API (iommu_ops->domain_alloc()) only received the domain type, so the driver had no way to inspect device capabilities and pick the most suitable page table format (v1 or v2). With the recent driver enhancement to use domain_alloc_paging_flags() for all paging domain allocations, the driver can now inspect the device and flags directly and choose the appropriate page table type per device.

Update amd_iommu_def_domain_type() to force identity mapping only for the specific GPUs that require it, via a new quirks_force_identity_mapping().

With this change, a system booting in DMA translation mode will now select:
* Guest (v2) page table for PASID-capable devices
* Host (v1) page table for non-PASID-capable devices

Also drop the amd_iommu_snp_en check, as SNP enforces paging domain, which doesn't work with the identity requirement of these GPUs.

---
Changes in v2:
- Dropped disabling ATS for "Radeon Pro WX 4100"
- Addressed review comments

Quoted 7 lines

@Jason,
Once this patch settles, I will send separate patch to drop 'untrusted' check inside amd_iommu_def_domain_type().

Regarding SME check, I have retained SME chek inside quirks_force_identity_mapping(). If everyone is fine to drop then I will do follow up patch later.

Sure

drivers/iommu/amd/iommu.c static int amd_iommu_def_domain_type(struct device *dev) · line 3168

Quoted 9 lines
drivers/iommu/amd/iommu.c +9 -0
+	/* Apply device specific quirks */
+	if (quirks_force_identity_mapping(to_pci_dev(dev))) {
+		/*
+		 * When memory encryption is active, some of these devices
+		 * don't have the encryption bit in their DMA-mask and
+		 * require remapping.
+		 */
+		if (cc_platform_has(CC_ATTR_MEM_ENCRYPT))
+			return 0;

I still haven't seen an explanation why this make sense. This patch says two conflicting things:

1) We need identity for the APU cases because they can't handle translation
2) We can't have identity for the SME case because it can't handle the high address bit, so use paging.

Surely #2 is also a per-GPU version thing and this address width issue was fixed in newer chips?

But even so, if paging doesn't work why is it OK to use it for SME? If paging does work then why do we quirk it away?

Jason

maintainer Applied
#4 lore raw
In reply to Vasant Hegde
Quoted 2 lines · Vasant Hegde
 drivers/iommu/amd/iommu.c | 45 +++++++++++++++++++++++++++++----------
 1 file changed, 34 insertions(+), 11 deletions(-)

Applied, thanks.

#5 lore raw

PATCH v2 1/1 iommu/amd: Force identity mode for selected GPUs only

In reply to Vasant Hegde

On a system using an APU (no discrete graphics card):

model name : AMD A10-6800K APU with Radeon(tm) HD Graphics
stepping : 1
microcode : 0x6001119

I was getting the following, git-bisected back to:

commit bf5bdfd1f8d4ad5c6020468d09b68b09c2adc5c2 (HEAD)

Author: Vasant Hegde <[email protected]>
Date:   Mon Aug 24 08:58:21 2026 +0000

iommu/amd: Force identity mode for selected GPUs only

I could only photograph and OCR the screen, so not a lot of data could be captured:

1.295232] </TASK>

1.295233] Modules linked in:

1.295237] CR2: 000000000000003c

1.295242] ---[ end trace 0000000000000000 1---

1.295245] RIP: 0010:amd_iommu_def_domain_type+0x76/0xb0

1.295250] Code: ff 25 00 7f ff ff 3d 00 00 03 00 75 cb 83 02 01 75 3f 48 81

ef do 00 00 00 48 8b 57 10 48 8b 42 10 48 85 со 74 04 48 8b 42 38 <66> 81 78 3c

32 10 74 a6 55 31 ff 48 89 e5 e8 d7 ee 3c 00 5d 83 fo

1.295253] RSP: 0018: ffffc90000027c20 EFLACS: 00010246

1.295256] RAX: 000000 RBX: ffff888100f0d5c0

RCX: 00000000ffffffff

1.295258] RDX: ffff888100dd8000 RSI: ffffffff82437607

RDI: ffff888100fc7000

1.295260) RBP: ffffc90000027c60 R08: 0000000000000001

R09: 0000000000000000

1.295262] R10: 0000000003 R11: 0000000000000001

R12: ffff888100fc70d0

1.295264] R13: 0000000000000000 R14: ffff888100aedc48

R15: 0000000000000000

1.295266] FS: 000000000000(0000) CS:ffff8884acefe000(0000) knICS: 00000

3000000000

1.295269] CS: 0010 DS: 0000 ES: 0000 CRO: 0000000080050033

1.295271] CR2: 000000000000003c CR3: 0000000002646000 CR4: 00000000000406f0

1.295274] note: swapper/0[1] exited with irqs disabled

1.295280) Kernel panic not syncing: Attempted to kill init! exitcode=0x00

30009

1.297262] ---[ end Kernel panic not syncing: Attempted to kill init! exit

ode=0x00000009 1---

I am happy to provide more details and test any patches.

Arthur.

author maintainer
#6 lore raw

Arthur,

Quoted 7 lines · Arthur Marsh

On a system using an APU (no discrete graphics card):

model name : AMD A10-6800K APU with Radeon(tm) HD Graphics
stepping : 1
microcode : 0x6001119

I was getting the following, git-bisected back to:

Yeah. Unfortunately this patch introduced a regression. Can you please try below patch?

https://lore.kernel.org/linux-iommu/[email protected]/

-Vasant

#7 lore raw
Quoted 6 lines · Vasant Hegde

Yeah. Unfortunately this patch introduced a regression. Can you please try below patch?

https://lore.kernel.org/linux-iommu/[email protected]/

-Vasant

Thanks, booted OK with the patch applied.

FYI

lspci -nnttv

-[0000:00]-+-00.0  Advanced Micro Devices, Inc. [AMD] Family 15h (Models 10h-1fh) Processor Root Complex [1022:1410]

          +-00.2  Advanced Micro Devices, Inc. [AMD] Family 15h (Models 10h-1fh) I/O Memory Management Unit [1022:1419]
          +-01.0  Advanced Micro Devices, Inc. [AMD/ATI] Richland [Radeon HD 8670D] [1002:990c]
          +-01.1  Advanced Micro Devices, Inc. [AMD/ATI] Trinity HDMI Audio Controller [1002:9902]
          +-04.0-[01]----00.0  Realtek Semiconductor Co., Ltd. RTL8111/8168/8211/8411 PCI Express Gigabit Ethernet Controller [10ec:8168]
          +-10.0  Advanced Micro Devices, Inc. [AMD] FCH USB XHCI Controller [1022:7814]
          +-10.1  Advanced Micro Devices, Inc. [AMD] FCH USB XHCI Controller [1022:7814]
          +-11.0  Advanced Micro Devices, Inc. [AMD] FCH SATA Controller [AHCI mode] [1022:7801]
          +-12.0  Advanced Micro Devices, Inc. [AMD] FCH USB OHCI Controller [1022:7807]
          +-12.2  Advanced Micro Devices, Inc. [AMD] FCH USB EHCI Controller [1022:7808]
          +-13.0  Advanced Micro Devices, Inc. [AMD] FCH USB OHCI Controller [1022:7807]
          +-13.2  Advanced Micro Devices, Inc. [AMD] FCH USB EHCI Controller [1022:7808]
          +-14.0  Advanced Micro Devices, Inc. [AMD] FCH SMBus Controller [1022:780b]
          +-14.1  Advanced Micro Devices, Inc. [AMD] FCH IDE Controller [1022:780c]
          +-14.3  Advanced Micro Devices, Inc. [AMD] FCH LPC Bridge [1022:780e]
          +-14.4-[02]--+-06.0  Creative Labs EMU10k2/CA0100/CA0102/CA10200 [Sound Blaster Audigy Series] [1102:0004]
          |            +-06.1  Creative Labs SB Audigy Game Port [1102:7003]
          |            \-06.2  Creative Labs SB Audigy FireWire Port [1102:4001]
          +-14.5  Advanced Micro Devices, Inc. [AMD] FCH USB OHCI Controller [1022:7809]
          +-18.0  Advanced Micro Devices, Inc. [AMD] Family 15h (Models 10h-1fh) Processor Function 0 [1022:1400]
          +-18.1  Advanced Micro Devices, Inc. [AMD] Family 15h (Models 10h-1fh) Processor Function 1 [1022:1401]
          +-18.2  Advanced Micro Devices, Inc. [AMD] Family 15h (Models 10h-1fh) Processor Function 2 [1022:1402]
          +-18.3  Advanced Micro Devices, Inc. [AMD] Family 15h (Models 10h-1fh) Processor Function 3 [1022:1403]
          +-18.4  Advanced Micro Devices, Inc. [AMD] Family 15h (Models 10h-1fh) Processor Function 4 [1022:1404]

          \-18.5  Advanced Micro Devices, Inc. [AMD] Family 15h (Models 10h-1fh) Processor Function 5 [1022:1405]

Regards,

Arthur.