[PATCH 20/22] iommufd: Introduce vIOMMU option via IOMMU_OPTION ioctl

Suravee Suthikulpanit posted 22 patches 3 days, 2 hours ago
[PATCH 20/22] iommufd: Introduce vIOMMU option via IOMMU_OPTION ioctl
Posted by Suravee Suthikulpanit 3 days, 2 hours ago
Introduce a new iommufd_option enum value, IOMMU_OPTION_VIOMMU, to
support vIOMMU-specific options. Extend the existing IOMMU_OPTION
ioctl to accept key-value style input, enabling access to data arrays
such as hardware registers.

Additionally, introduce struct iommufd_viommu_ops with set_option
and get_option callbacks to support IOMMUFD vIOMMU options.

Signed-off-by: Suravee Suthikulpanit <suravee.suthikulpanit@amd.com>
---
 drivers/iommu/iommufd/ioas.c            |  2 +-
 drivers/iommu/iommufd/iommufd_private.h |  1 +
 drivers/iommu/iommufd/main.c            |  6 +++---
 drivers/iommu/iommufd/viommu.c          | 18 ++++++++++++++++++
 include/linux/iommufd.h                 |  5 +++++
 include/uapi/linux/iommufd.h            |  8 ++++++--
 6 files changed, 34 insertions(+), 6 deletions(-)

diff --git a/drivers/iommu/iommufd/ioas.c b/drivers/iommu/iommufd/ioas.c
index f4721afedadc..95547630fd3a 100644
--- a/drivers/iommu/iommufd/ioas.c
+++ b/drivers/iommu/iommufd/ioas.c
@@ -643,7 +643,7 @@ int iommufd_ioas_option(struct iommufd_ucmd *ucmd)
 	struct iommufd_ioas *ioas;
 	int rc = 0;
 
-	if (cmd->__reserved)
+	if (cmd->key)
 		return -EOPNOTSUPP;
 
 	ioas = iommufd_get_ioas(ucmd->ictx, cmd->object_id);
diff --git a/drivers/iommu/iommufd/iommufd_private.h b/drivers/iommu/iommufd/iommufd_private.h
index eb6d1a70f673..0306f2b8236f 100644
--- a/drivers/iommu/iommufd/iommufd_private.h
+++ b/drivers/iommu/iommufd/iommufd_private.h
@@ -698,6 +698,7 @@ void iommufd_vdevice_destroy(struct iommufd_object *obj);
 void iommufd_vdevice_abort(struct iommufd_object *obj);
 int iommufd_hw_queue_alloc_ioctl(struct iommufd_ucmd *ucmd);
 void iommufd_hw_queue_destroy(struct iommufd_object *obj);
+int iommufd_viommu_option(struct iommufd_ucmd *ucmd);
 
 static inline struct iommufd_vdevice *
 iommufd_get_vdevice(struct iommufd_ctx *ictx, u32 id)
diff --git a/drivers/iommu/iommufd/main.c b/drivers/iommu/iommufd/main.c
index 5cc4b08c25f5..ae36a6e8042d 100644
--- a/drivers/iommu/iommufd/main.c
+++ b/drivers/iommu/iommufd/main.c
@@ -391,9 +391,6 @@ static int iommufd_option(struct iommufd_ucmd *ucmd)
 	struct iommu_option *cmd = ucmd->cmd;
 	int rc;
 
-	if (cmd->__reserved)
-		return -EOPNOTSUPP;
-
 	switch (cmd->option_id) {
 	case IOMMU_OPTION_RLIMIT_MODE:
 		rc = iommufd_option_rlimit_mode(cmd, ucmd->ictx);
@@ -401,6 +398,9 @@ static int iommufd_option(struct iommufd_ucmd *ucmd)
 	case IOMMU_OPTION_HUGE_PAGES:
 		rc = iommufd_ioas_option(ucmd);
 		break;
+	case IOMMU_OPTION_VIOMMU:
+		rc = iommufd_viommu_option(ucmd);
+		break;
 	default:
 		return -EOPNOTSUPP;
 	}
diff --git a/drivers/iommu/iommufd/viommu.c b/drivers/iommu/iommufd/viommu.c
index 59b31b3e36be..51585337b8e4 100644
--- a/drivers/iommu/iommufd/viommu.c
+++ b/drivers/iommu/iommufd/viommu.c
@@ -477,3 +477,21 @@ int iommufd_hw_queue_alloc_ioctl(struct iommufd_ucmd *ucmd)
 	iommufd_put_object(ucmd->ictx, &viommu->obj);
 	return rc;
 }
+
+int iommufd_viommu_option(struct iommufd_ucmd *ucmd)
+{
+	int ret = -EOPNOTSUPP;
+	struct iommu_option *cmd = ucmd->cmd;
+	struct iommufd_viommu *viommu = iommufd_get_viommu(ucmd, cmd->object_id);
+
+	if (cmd->op == IOMMU_OPTION_OP_SET) {
+		if (!viommu->ops->set_option)
+			return ret;
+		ret = viommu->ops->set_option(viommu, cmd->key, cmd->val64);
+	} else if (cmd->op == IOMMU_OPTION_OP_GET) {
+		if (!viommu->ops->get_option)
+			return ret;
+		ret = viommu->ops->get_option(viommu, cmd->key, &cmd->val64);
+	}
+	return ret;
+}
diff --git a/include/linux/iommufd.h b/include/linux/iommufd.h
index c0030677e13c..8096b7e59088 100644
--- a/include/linux/iommufd.h
+++ b/include/linux/iommufd.h
@@ -183,6 +183,9 @@ struct iommufd_hw_queue {
  * @hw_queue_init: Similar to hw_queue_init_phys, but driver providing this op
  *                 indicates that HW accesses the guest queue memory via
  *                 @hw_queue->baseaddr.
+ * @set_option: Set the key-value option for the specified vIOMMU.
+ * @get_option: Get the key-value option for the specified vIOMMU.
+ *              On success, the value is returned via the provided value.
  */
 struct iommufd_viommu_ops {
 	void (*destroy)(struct iommufd_viommu *viommu);
@@ -198,6 +201,8 @@ struct iommufd_viommu_ops {
 	int (*hw_queue_init_phys)(struct iommufd_hw_queue *hw_queue, u32 index,
 				  phys_addr_t base_addr_pa);
 	int (*hw_queue_init)(struct iommufd_hw_queue *hw_queue, u32 index);
+	int (*set_option)(struct iommufd_viommu *viommu, u16 key, u64 value);
+	int (*get_option)(struct iommufd_viommu *viommu, u16 key, u64 *value);
 };
 
 #if IS_ENABLED(CONFIG_IOMMUFD)
diff --git a/include/uapi/linux/iommufd.h b/include/uapi/linux/iommufd.h
index f71a4b979d52..922bb7511045 100644
--- a/include/uapi/linux/iommufd.h
+++ b/include/uapi/linux/iommufd.h
@@ -306,10 +306,14 @@ struct iommu_ioas_unmap {
  *    iommu mappings. Value 0 disables combining, everything is mapped to
  *    PAGE_SIZE. This can be useful for benchmarking.  This is a per-IOAS
  *    option, the object_id must be the IOAS ID.
+ * @IOMMU_KEY_VAL_OPTION_VIOMMU:
+ *    Specifies key-value option for vIOMMU object. The caller must specify
+ *    vIOMMU ID for object_id. The allowed ops are set and get.
  */
 enum iommufd_option {
 	IOMMU_OPTION_RLIMIT_MODE = 0,
 	IOMMU_OPTION_HUGE_PAGES = 1,
+	IOMMU_OPTION_VIOMMU = 2,
 };
 
 /**
@@ -328,7 +332,7 @@ enum iommufd_option_ops {
  * @size: sizeof(struct iommu_option)
  * @option_id: One of enum iommufd_option
  * @op: One of enum iommufd_option_ops
- * @__reserved: Must be 0
+ * @key: Option key to match with the value
  * @object_id: ID of the object if required
  * @val64: Option value to set or value returned on get
  *
@@ -340,7 +344,7 @@ struct iommu_option {
 	__u32 size;
 	__u32 option_id;
 	__u16 op;
-	__u16 __reserved;
+	__u16 key;
 	__u32 object_id;
 	__aligned_u64 val64;
 };
-- 
2.34.1
Re: [PATCH 20/22] iommufd: Introduce vIOMMU option via IOMMU_OPTION ioctl
Posted by Jason Gunthorpe 2 days, 22 hours ago
On Mon, Mar 30, 2026 at 08:42:04AM +0000, Suravee Suthikulpanit wrote:
> Introduce a new iommufd_option enum value, IOMMU_OPTION_VIOMMU, to
> support vIOMMU-specific options. Extend the existing IOMMU_OPTION
> ioctl to accept key-value style input, enabling access to data arrays
> such as hardware registers.
> 
> Additionally, introduce struct iommufd_viommu_ops with set_option
> and get_option callbacks to support IOMMUFD vIOMMU options.

This doesn't seem like the right API to use use for this. You should
probably add a new ioctl for viommu "commands" or something like that
which is better structured..

Jason