Skip to content

Commit 7e5516e

Browse files
ankitvvsonijoergroedel
authored andcommitted
iommu/amd: Add HATDis feature support
Current AMD IOMMU assumes Host Address Translation (HAT) is always supported, and Linux kernel enables this capability by default. However, in case of emulated and virtualized IOMMU, this might not be the case. For example,current QEMU-emulated AMD vIOMMU does not support host translation for VFIO pass-through device, but the interrupt remapping support is required for x2APIC (i.e. kvm-msi-ext-dest-id is also not supported by the guest OS). This would require the guest kernel to boot with guest kernel option iommu=pt to by-pass the initialization of host (v1) table. The AMD I/O Virtualization Technology (IOMMU) Specification Rev 3.10 [1] introduces a new flag 'HATDis' in the IVHD 11h IOMMU attributes to indicate that HAT is not supported on a particular IOMMU instance. Therefore, modifies the AMD IOMMU driver to detect the new HATDis attributes, and disable host translation and switch to use guest translation if it is available. Otherwise, the driver will disable DMA translation. [1] https://www.amd.com/content/dam/amd/en/documents/processor-tech-docs/specifications/48882_IOMMU.pdf Reviewed-by: Suravee Suthikulpanit <suravee.suthikulpanit@amd.com> Signed-off-by: Ankit Soni <Ankit.Soni@amd.com> Link: https://lore.kernel.org/r/8109b208f87b80e400c2abd24a2e44fcbc0763a5.1749016436.git.Ankit.Soni@amd.com Signed-off-by: Joerg Roedel <joerg.roedel@amd.com>
1 parent 86731a2 commit 7e5516e

4 files changed

Lines changed: 48 additions & 3 deletions

File tree

drivers/iommu/amd/amd_iommu.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ extern int amd_iommu_guest_ir;
4343
extern enum protection_domain_mode amd_iommu_pgtable;
4444
extern int amd_iommu_gpt_level;
4545
extern unsigned long amd_iommu_pgsize_bitmap;
46+
extern bool amd_iommu_hatdis;
4647

4748
/* Protection domain ops */
4849
void amd_iommu_init_identity_domain(void);

drivers/iommu/amd/amd_iommu_types.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -460,6 +460,9 @@
460460
/* IOMMU Feature Reporting Field (for IVHD type 10h */
461461
#define IOMMU_FEAT_GASUP_SHIFT 6
462462

463+
/* IOMMU HATDIS for IVHD type 11h and 40h */
464+
#define IOMMU_IVHD_ATTR_HATDIS_SHIFT 0
465+
463466
/* IOMMU Extended Feature Register (EFR) */
464467
#define IOMMU_EFR_XTSUP_SHIFT 2
465468
#define IOMMU_EFR_GASUP_SHIFT 7
@@ -558,7 +561,8 @@ struct amd_io_pgtable {
558561
};
559562

560563
enum protection_domain_mode {
561-
PD_MODE_V1 = 1,
564+
PD_MODE_NONE,
565+
PD_MODE_V1,
562566
PD_MODE_V2,
563567
};
564568

drivers/iommu/amd/init.c

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,9 @@ static int amd_iommu_target_ivhd_type;
168168
u64 amd_iommu_efr;
169169
u64 amd_iommu_efr2;
170170

171+
/* Host (v1) page table is not supported*/
172+
bool amd_iommu_hatdis;
173+
171174
/* SNP is enabled on the system? */
172175
bool amd_iommu_snp_en;
173176
EXPORT_SYMBOL(amd_iommu_snp_en);
@@ -1792,6 +1795,11 @@ static int __init init_iommu_one(struct amd_iommu *iommu, struct ivhd_header *h,
17921795
if (h->efr_reg & BIT(IOMMU_EFR_XTSUP_SHIFT))
17931796
amd_iommu_xt_mode = IRQ_REMAP_X2APIC_MODE;
17941797

1798+
if (h->efr_attr & BIT(IOMMU_IVHD_ATTR_HATDIS_SHIFT)) {
1799+
pr_warn_once("Host Address Translation is not supported.\n");
1800+
amd_iommu_hatdis = true;
1801+
}
1802+
17951803
early_iommu_features_init(iommu, h);
17961804

17971805
break;
@@ -2112,7 +2120,15 @@ static int __init iommu_init_pci(struct amd_iommu *iommu)
21122120
return ret;
21132121
}
21142122

2115-
iommu_device_register(&iommu->iommu, &amd_iommu_ops, NULL);
2123+
ret = iommu_device_register(&iommu->iommu, &amd_iommu_ops, NULL);
2124+
if (ret || amd_iommu_pgtable == PD_MODE_NONE) {
2125+
/*
2126+
* Remove sysfs if DMA translation is not supported by the
2127+
* IOMMU. Do not return an error to enable IRQ remapping
2128+
* in state_next(), DTE[V, TV] must eventually be set to 0.
2129+
*/
2130+
iommu_device_sysfs_remove(&iommu->iommu);
2131+
}
21162132

21172133
return pci_enable_device(iommu->dev);
21182134
}
@@ -2573,7 +2589,7 @@ static void init_device_table_dma(struct amd_iommu_pci_seg *pci_seg)
25732589
u32 devid;
25742590
struct dev_table_entry *dev_table = pci_seg->dev_table;
25752591

2576-
if (dev_table == NULL)
2592+
if (!dev_table || amd_iommu_pgtable == PD_MODE_NONE)
25772593
return;
25782594

25792595
for (devid = 0; devid <= pci_seg->last_bdf; ++devid) {
@@ -3084,6 +3100,17 @@ static int __init early_amd_iommu_init(void)
30843100
}
30853101
}
30863102

3103+
if (amd_iommu_hatdis) {
3104+
/*
3105+
* Host (v1) page table is not available. Attempt to use
3106+
* Guest (v2) page table.
3107+
*/
3108+
if (amd_iommu_v2_pgtbl_supported())
3109+
amd_iommu_pgtable = PD_MODE_V2;
3110+
else
3111+
amd_iommu_pgtable = PD_MODE_NONE;
3112+
}
3113+
30873114
/* Disable any previously enabled IOMMUs */
30883115
if (!is_kdump_kernel() || amd_iommu_disabled)
30893116
disable_iommus();

drivers/iommu/amd/iommu.c

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2424,6 +2424,13 @@ static struct iommu_device *amd_iommu_probe_device(struct device *dev)
24242424
pci_max_pasids(to_pci_dev(dev)));
24252425
}
24262426

2427+
if (amd_iommu_pgtable == PD_MODE_NONE) {
2428+
pr_warn_once("%s: DMA translation not supported by iommu.\n",
2429+
__func__);
2430+
iommu_dev = ERR_PTR(-ENODEV);
2431+
goto out_err;
2432+
}
2433+
24272434
out_err:
24282435

24292436
iommu_completion_wait(iommu);
@@ -2511,6 +2518,9 @@ static int pdom_setup_pgtable(struct protection_domain *domain,
25112518
case PD_MODE_V2:
25122519
fmt = AMD_IOMMU_V2;
25132520
break;
2521+
case PD_MODE_NONE:
2522+
WARN_ON_ONCE(1);
2523+
return -EPERM;
25142524
}
25152525

25162526
domain->iop.pgtbl.cfg.amd.nid = dev_to_node(dev);
@@ -2532,6 +2542,9 @@ static inline u64 dma_max_address(enum protection_domain_mode pgtable)
25322542

25332543
static bool amd_iommu_hd_support(struct amd_iommu *iommu)
25342544
{
2545+
if (amd_iommu_hatdis)
2546+
return false;
2547+
25352548
return iommu && (iommu->features & FEATURE_HDSUP);
25362549
}
25372550

0 commit comments

Comments
 (0)