drivers/iommu/amd/Makefile | 2 +- drivers/iommu/amd/iommu.c | 2 ++ drivers/iommu/amd/iommufd.c | 34 ++++++++++++++++++++++++++++++++++ drivers/iommu/amd/iommufd.h | 11 +++++++++++ include/uapi/linux/iommufd.h | 20 ++++++++++++++++++++ 5 files changed, 68 insertions(+), 1 deletion(-) create mode 100644 drivers/iommu/amd/iommufd.c create mode 100644 drivers/iommu/amd/iommufd.h
AMD IOMMU Extended Feature (EFR) and Extended Feature 2 (EFR2) registers
specify features supported by each IOMMU hardware instance.
The IOMMU driver checks each feature-specific bits before enabling
each feature at run time.
For IOMMUFD, the hypervisor passes the raw value of amd_iommu_efr and
amd_iommu_efr2 to VMM via iommufd IOMMU_DEVICE_GET_HW_INFO ioctl.
Reviewed-by: Nicolin Chen <nicolinc@nvidia.com>
Signed-off-by: Suravee Suthikulpanit <suravee.suthikulpanit@amd.com>
---
Change in v3:
* Remove extern
* Fix link to IOMMU spec
* Update kdoc
Change in v2:
* Do not mask the EFR/EFR2 and simply return the value reported by hardware
* Move amd_iommufd_hw_info() to drivers/iommu/amd/iommufd.c
* Also support IOMMU_HW_INFO_TYPE_DEFAULT
drivers/iommu/amd/Makefile | 2 +-
drivers/iommu/amd/iommu.c | 2 ++
drivers/iommu/amd/iommufd.c | 34 ++++++++++++++++++++++++++++++++++
drivers/iommu/amd/iommufd.h | 11 +++++++++++
include/uapi/linux/iommufd.h | 20 ++++++++++++++++++++
5 files changed, 68 insertions(+), 1 deletion(-)
create mode 100644 drivers/iommu/amd/iommufd.c
create mode 100644 drivers/iommu/amd/iommufd.h
diff --git a/drivers/iommu/amd/Makefile b/drivers/iommu/amd/Makefile
index 59c04a67f398..b74384465594 100644
--- a/drivers/iommu/amd/Makefile
+++ b/drivers/iommu/amd/Makefile
@@ -1,3 +1,3 @@
# SPDX-License-Identifier: GPL-2.0-only
-obj-y += iommu.o init.o quirks.o io_pgtable.o io_pgtable_v2.o ppr.o pasid.o
+obj-y += iommu.o init.o quirks.o io_pgtable.o io_pgtable_v2.o ppr.o pasid.o iommufd.o
obj-$(CONFIG_AMD_IOMMU_DEBUGFS) += debugfs.o
diff --git a/drivers/iommu/amd/iommu.c b/drivers/iommu/amd/iommu.c
index eb348c63a8d0..344364ef94f8 100644
--- a/drivers/iommu/amd/iommu.c
+++ b/drivers/iommu/amd/iommu.c
@@ -42,6 +42,7 @@
#include <uapi/linux/iommufd.h>
#include "amd_iommu.h"
+#include "iommufd.h"
#include "../dma-iommu.h"
#include "../irq_remapping.h"
#include "../iommu-pages.h"
@@ -3040,6 +3041,7 @@ static const struct iommu_dirty_ops amd_dirty_ops = {
const struct iommu_ops amd_iommu_ops = {
.capable = amd_iommu_capable,
+ .hw_info = amd_iommufd_hw_info,
.blocked_domain = &blocked_domain,
.release_domain = &release_domain,
.identity_domain = &identity_domain.domain,
diff --git a/drivers/iommu/amd/iommufd.c b/drivers/iommu/amd/iommufd.c
new file mode 100644
index 000000000000..08deccf9d35a
--- /dev/null
+++ b/drivers/iommu/amd/iommufd.c
@@ -0,0 +1,34 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (C) 2025 Advanced Micro Devices, Inc.
+ */
+
+#include <linux/iommu.h>
+
+#include "iommufd.h"
+#include "amd_iommu.h"
+#include "amd_iommu_types.h"
+
+void *amd_iommufd_hw_info(struct device *dev, u32 *length, u32 *type)
+{
+ struct iommu_hw_info_amd *hwinfo;
+
+ if (*type != IOMMU_HW_INFO_TYPE_DEFAULT &&
+ *type != IOMMU_HW_INFO_TYPE_AMD)
+ return ERR_PTR(-EOPNOTSUPP);
+
+ hwinfo = kzalloc(sizeof(*hwinfo), GFP_KERNEL);
+ if (!hwinfo)
+ return ERR_PTR(-ENOMEM);
+
+ *length = sizeof(*hwinfo);
+ *type = IOMMU_HW_INFO_TYPE_AMD;
+
+ hwinfo->efr = amd_iommu_efr;
+ hwinfo->efr2 = amd_iommu_efr2;
+
+ pr_debug("%s: efr=%#llx, efr2=%#llx\n", __func__,
+ hwinfo->efr, hwinfo->efr2);
+
+ return hwinfo;
+}
diff --git a/drivers/iommu/amd/iommufd.h b/drivers/iommu/amd/iommufd.h
new file mode 100644
index 000000000000..992fc5cba21b
--- /dev/null
+++ b/drivers/iommu/amd/iommufd.h
@@ -0,0 +1,11 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (C) 2025 Advanced Micro Devices, Inc.
+ */
+
+#ifndef AMD_IOMMUFD_H
+#define AMD_IOMMUFD_H
+
+void *amd_iommufd_hw_info(struct device *dev, u32 *length, u32 *type);
+
+#endif /* AMD_IOMMUFD_H */
diff --git a/include/uapi/linux/iommufd.h b/include/uapi/linux/iommufd.h
index c218c89e0e2e..6ec6b82674ac 100644
--- a/include/uapi/linux/iommufd.h
+++ b/include/uapi/linux/iommufd.h
@@ -613,6 +613,24 @@ struct iommu_hw_info_tegra241_cmdqv {
__u8 __reserved;
};
+/**
+ * struct iommu_hw_info_amd - AMD IOMMU device info
+ *
+ * @efr : Value of AMD IOMMU Extended Feature Register (EFR) reported by hardware
+ * @efr2: Value of AMD IOMMU Extended Feature 2 Register (EFR2) reported by hardware
+ *
+ * Please See description of these registers in the following sections of
+ * the AMD I/O Virtualization Technology (IOMMU) Specification.
+ * (https://docs.amd.com/v/u/en-US/48882_3.10_PUB)
+ *
+ * - MMIO Offset 0030h IOMMU Extended Feature Register
+ * - MMIO Offset 01A0h IOMMU Extended Feature 2 Register
+ */
+struct iommu_hw_info_amd {
+ __aligned_u64 efr;
+ __aligned_u64 efr2;
+};
+
/**
* enum iommu_hw_info_type - IOMMU Hardware Info Types
* @IOMMU_HW_INFO_TYPE_NONE: Output by the drivers that do not report hardware
@@ -622,6 +640,7 @@ struct iommu_hw_info_tegra241_cmdqv {
* @IOMMU_HW_INFO_TYPE_ARM_SMMUV3: ARM SMMUv3 iommu info type
* @IOMMU_HW_INFO_TYPE_TEGRA241_CMDQV: NVIDIA Tegra241 CMDQV (extension for ARM
* SMMUv3) info type
+ * @IOMMU_HW_INFO_TYPE_AMD: AMD IOMMU info type
*/
enum iommu_hw_info_type {
IOMMU_HW_INFO_TYPE_NONE = 0,
@@ -629,6 +648,7 @@ enum iommu_hw_info_type {
IOMMU_HW_INFO_TYPE_INTEL_VTD = 1,
IOMMU_HW_INFO_TYPE_ARM_SMMUV3 = 2,
IOMMU_HW_INFO_TYPE_TEGRA241_CMDQV = 3,
+ IOMMU_HW_INFO_TYPE_AMD = 4,
};
/**
--
2.34.1
On Wed, Aug 27, 2025 at 04:23:09PM +0000, Suravee Suthikulpanit wrote: > AMD IOMMU Extended Feature (EFR) and Extended Feature 2 (EFR2) registers > specify features supported by each IOMMU hardware instance. > The IOMMU driver checks each feature-specific bits before enabling > each feature at run time. > > For IOMMUFD, the hypervisor passes the raw value of amd_iommu_efr and > amd_iommu_efr2 to VMM via iommufd IOMMU_DEVICE_GET_HW_INFO ioctl. > > Reviewed-by: Nicolin Chen <nicolinc@nvidia.com> > Signed-off-by: Suravee Suthikulpanit <suravee.suthikulpanit@amd.com> Was there a reason this is not part of the other series? > +obj-y += iommu.o init.o quirks.o io_pgtable.o io_pgtable_v2.o ppr.o pasid.o iommufd.o Part of the point of another file is to not compile it when !CONFIG_IOMMUFD So you should change the makefile and add some header magic: #if IS_ENABLED(CONFIG_IOMMUFD) void *amd_iommufd_hw_info(struct device *dev, u32 *length, u32 *type); #else #define amd_iommufd_hw_info NULL #endif > +/** > + * struct iommu_hw_info_amd - AMD IOMMU device info > + * > + * @efr : Value of AMD IOMMU Extended Feature Register (EFR) reported by hardware > + * @efr2: Value of AMD IOMMU Extended Feature 2 Register (EFR2) reported by hardware > + * > + * Please See description of these registers in the following sections of > + * the AMD I/O Virtualization Technology (IOMMU) Specification. > + * (https://docs.amd.com/v/u/en-US/48882_3.10_PUB) > + * > + * - MMIO Offset 0030h IOMMU Extended Feature Register > + * - MMIO Offset 01A0h IOMMU Extended Feature 2 Register > + */ It would be good to elaborate on the bits like ARM does for iommu_hw_info_arm_smmuv3 and where some of the bits should come from in other places in the API. Jason
On 9/2/2025 6:57 AM, Jason Gunthorpe wrote: > On Wed, Aug 27, 2025 at 04:23:09PM +0000, Suravee Suthikulpanit wrote: >> AMD IOMMU Extended Feature (EFR) and Extended Feature 2 (EFR2) registers >> specify features supported by each IOMMU hardware instance. >> The IOMMU driver checks each feature-specific bits before enabling >> each feature at run time. >> >> For IOMMUFD, the hypervisor passes the raw value of amd_iommu_efr and >> amd_iommu_efr2 to VMM via iommufd IOMMU_DEVICE_GET_HW_INFO ioctl. >> >> Reviewed-by: Nicolin Chen <nicolinc@nvidia.com> >> Signed-off-by: Suravee Suthikulpanit <suravee.suthikulpanit@amd.com> > > Was there a reason this is not part of the other series? Since this can be a standalone patch, I think it might be best to just focus on this in a separate submission. > >> +obj-y += iommu.o init.o quirks.o io_pgtable.o io_pgtable_v2.o ppr.o pasid.o iommufd.o > > Part of the point of another file is to not compile it when !CONFIG_IOMMUFD > > So you should change the makefile and add some header magic: > > #if IS_ENABLED(CONFIG_IOMMUFD) > void *amd_iommufd_hw_info(struct device *dev, u32 *length, u32 *type); > #else > #define amd_iommufd_hw_info NULL > #endif Ok. Good point. >> +/** >> + * struct iommu_hw_info_amd - AMD IOMMU device info >> + * >> + * @efr : Value of AMD IOMMU Extended Feature Register (EFR) reported by hardware >> + * @efr2: Value of AMD IOMMU Extended Feature 2 Register (EFR2) reported by hardware >> + * >> + * Please See description of these registers in the following sections of >> + * the AMD I/O Virtualization Technology (IOMMU) Specification. >> + * (https://docs.amd.com/v/u/en-US/48882_3.10_PUB) >> + * >> + * - MMIO Offset 0030h IOMMU Extended Feature Register >> + * - MMIO Offset 01A0h IOMMU Extended Feature 2 Register >> + */ > > It would be good to elaborate on the bits like ARM does for > iommu_hw_info_arm_smmuv3 and where some of the bits should come from > in other places in the API. > > Jason Got it. I am sending out v4. Thanks, Suravee
© 2016 - 2025 Red Hat, Inc.