[PATCH v2 26/26] iommu/amd: Introduce logic to check and enable vIOMMU feature

From: Suravee Suthikulpanit

Date: Thu May 28 2026 - 01:21:42 EST


Also switch to enable vIOMMU by default.

Signed-off-by: Suravee Suthikulpanit <suravee.suthikulpanit@xxxxxxx>
---
drivers/iommu/amd/amd_iommu.h | 1 +
drivers/iommu/amd/amd_iommu_types.h | 3 +++
drivers/iommu/amd/init.c | 12 +++++++++++-
drivers/iommu/amd/viommu.c | 24 +++++++++++++++++++++++-
4 files changed, 38 insertions(+), 2 deletions(-)

diff --git a/drivers/iommu/amd/amd_iommu.h b/drivers/iommu/amd/amd_iommu.h
index cf2b051948a3..e505c5420255 100644
--- a/drivers/iommu/amd/amd_iommu.h
+++ b/drivers/iommu/amd/amd_iommu.h
@@ -27,6 +27,7 @@ void amd_iommu_restart_ga_log(struct amd_iommu *iommu);
void amd_iommu_restart_ppr_log(struct amd_iommu *iommu);
void amd_iommu_set_rlookup_table(struct amd_iommu *iommu, u16 devid);
void iommu_feature_enable(struct amd_iommu *iommu, u8 bit);
+bool iommu_feature_enable_and_check(struct amd_iommu *iommu, u8 bit);
void *__init iommu_alloc_4k_pages(struct amd_iommu *iommu,
gfp_t gfp, size_t size);
u8 __iomem * __init iommu_map_mmio_space(u64 address, u64 end);
diff --git a/drivers/iommu/amd/amd_iommu_types.h b/drivers/iommu/amd/amd_iommu_types.h
index 44a185bfa39e..7ff714ce79b8 100644
--- a/drivers/iommu/amd/amd_iommu_types.h
+++ b/drivers/iommu/amd/amd_iommu_types.h
@@ -201,9 +201,12 @@
#define CONTROL_EPH_EN 45
#define CONTROL_PPR_AUTO_RSP_AON 48
#define CONTROL_XT_EN 50
+#define CONTROL_VCMD_EN 52
+#define CONTROL_VIOMMU_EN 53
#define CONTROL_INTCAPXT_EN 51
#define CONTROL_GCR3TRPMODE 58
#define CONTROL_IRTCACHEDIS 59
+#define CONTROL_GSTBUFFERTRPMODE 60
#define CONTROL_SNPAVIC_EN 61

#define CTRL_INV_TO_MASK 7
diff --git a/drivers/iommu/amd/init.c b/drivers/iommu/amd/init.c
index 622bc0337eda..a66a5089bf91 100644
--- a/drivers/iommu/amd/init.c
+++ b/drivers/iommu/amd/init.c
@@ -198,7 +198,7 @@ bool amdr_ivrs_remap_support __read_mostly;
bool amd_iommu_force_isolation __read_mostly;

/* VIOMMU enabling flag */
-bool amd_iommu_viommu;
+bool amd_iommu_viommu = true;

unsigned long amd_iommu_pgsize_bitmap __ro_after_init = AMD_IOMMU_PGSIZES;

@@ -417,6 +417,16 @@ void iommu_feature_enable(struct amd_iommu *iommu, u8 bit)
iommu_feature_set(iommu, 1ULL, 1ULL, bit);
}

+bool iommu_feature_enable_and_check(struct amd_iommu *iommu, u8 bit)
+{
+ u64 ctrl;
+
+ iommu_feature_enable(iommu, bit);
+
+ ctrl = readq(iommu->mmio_base + MMIO_CONTROL_OFFSET);
+ return (ctrl & (1ULL << bit));
+}
+
static void iommu_feature_disable(struct amd_iommu *iommu, u8 bit)
{
iommu_feature_set(iommu, 0ULL, 1ULL, bit);
diff --git a/drivers/iommu/amd/viommu.c b/drivers/iommu/amd/viommu.c
index d2c883e314f8..4dcd781bc35a 100644
--- a/drivers/iommu/amd/viommu.c
+++ b/drivers/iommu/amd/viommu.c
@@ -45,6 +45,18 @@

LIST_HEAD(viommu_devid_map);

+static int viommu_enable(struct amd_iommu *iommu)
+{
+ /* The GstBufferTRPMode feature is checked by set and test */
+ if (!iommu_feature_enable_and_check(iommu, CONTROL_GSTBUFFERTRPMODE))
+ return -EINVAL;
+
+ iommu_feature_enable(iommu, CONTROL_VCMD_EN);
+ iommu_feature_enable(iommu, CONTROL_VIOMMU_EN);
+
+ return 0;
+}
+
static int viommu_init_pci_vsc(struct amd_iommu *iommu)
{
iommu->vsc_offset = pci_find_capability(iommu->dev, PCI_CAP_ID_VNDR);
@@ -308,11 +320,21 @@ int __init amd_viommu_init(struct amd_iommu *iommu)

ret = viommu_private_space_init(iommu);
if (ret)
- return ret;
+ goto err_unmap_vf;

set_iommu_dte(iommu);

+ ret = viommu_enable(iommu);
+ if (ret)
+ goto err_private_space;
+
return 0;
+
+err_private_space:
+ viommu_private_space_uninit(iommu);
+err_unmap_vf:
+ amd_viommu_uninit(iommu);
+ return ret;
}

static int __maybe_unused alloc_private_vm_region(struct amd_iommu *iommu, u64 **entry,
--
2.34.1