linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v6 0/4] iommufd: Add iommu hardware info reporting
@ 2023-08-08 15:35 Yi Liu
  2023-08-08 15:35 ` [PATCH v6 1/4] iommu: Move dev_iommu_ops() to private header Yi Liu
                   ` (3 more replies)
  0 siblings, 4 replies; 13+ messages in thread
From: Yi Liu @ 2023-08-08 15:35 UTC (permalink / raw)
  To: joro, alex.williamson, jgg, kevin.tian, robin.murphy, baolu.lu
  Cc: cohuck, eric.auger, nicolinc, kvm, mjrosato, chao.p.peng,
	yi.l.liu, yi.y.sun, peterx, jasowang, shameerali.kolothum.thodi,
	lulu, suravee.suthikulpanit, iommu, linux-kernel,
	linux-kselftest, zhenzhong.duan

iommufd gives userspace the capability to manipulate iommu subsytem.
e.g. DMA map/unmap etc. In the near future, it will support iommu nested
translation. Different platform vendors have different implementation for
the nested translation. For example, Intel VT-d supports using guest I/O
page table as the stage-1 translation table. This requires guest I/O page
table be compatible with hardware IOMMU. So before set up nested translation,
userspace needs to know the hardware iommu information to understand the
nested translation requirements.

This series reports the iommu hardware information for a given device
which has been bound to iommufd. It is preparation work for userspace to
allocate hwpt for given device. Like the nested translation support[1].

This series introduces an iommu op to report the iommu hardware info,
and an ioctl IOMMU_GET_HW_INFO is added to report such hardware info to
user. enum iommu_hw_info_type is defined to differentiate the iommu hardware
info reported to user hence user can decode them. This series only adds the
framework for iommu hw info reporting, the complete reporting path needs vendor
specific definition and driver support. The full code is available in [1]
as well.

[1] https://github.com/yiliu1765/iommufd/tree/wip/iommufd_nesting_08082023-yi
(only the hw_info report path is the latest, other parts is wip)

Change log:

v6:
 - Add Jingqi's comment on patch 02
 - Add Baolu's r-b to patch 03
 - Address Jason's comment on patch 03

v5: https://lore.kernel.org/linux-iommu/20230803143144.200945-1-yi.l.liu@intel.com/
 - Return hw_info_type in the .hw_info op, hence drop hw_info_type field in iommu_ops (Kevin)
 - Add Jason's r-b for patch 01
 - Address coding style comments from Jason and Kevin w.r.t. patch 02, 03 and 04

v4: https://lore.kernel.org/linux-iommu/20230724105936.107042-1-yi.l.liu@intel.com/
 - Rename ioctl to IOMMU_GET_HW_INFO and structure to iommu_hw_info
 - Move the iommufd_get_hw_info handler to main.c
 - Place iommu_hw_info prior to iommu_hwpt_alloc
 - Update the function namings accordingly
 - Update uapi kdocs

v3: https://lore.kernel.org/linux-iommu/20230511143024.19542-1-yi.l.liu@intel.com/#t
 - Add r-b from Baolu
 - Rename IOMMU_HW_INFO_TYPE_DEFAULT to be IOMMU_HW_INFO_TYPE_NONE to
   better suit what it means
 - Let IOMMU_DEVICE_GET_HW_INFO succeed even the underlying iommu driver
   does not have driver-specific data to report per below remark.
   https://lore.kernel.org/kvm/ZAcwJSK%2F9UVI9LXu@nvidia.com/

v2: https://lore.kernel.org/linux-iommu/20230309075358.571567-1-yi.l.liu@intel.com/
 - Drop patch 05 of v1 as it is already covered by other series
 - Rename the capability info to be iommu hardware info

v1: https://lore.kernel.org/linux-iommu/20230209041642.9346-1-yi.l.liu@intel.com/

Regards,
	Yi Liu

Lu Baolu (1):
  iommu: Add new iommu op to get iommu hardware information

Nicolin Chen (1):
  iommufd/selftest: Add coverage for IOMMU_GET_HW_INFO ioctl

Yi Liu (2):
  iommu: Move dev_iommu_ops() to private header
  iommufd: Add IOMMU_GET_HW_INFO

 drivers/iommu/iommu-priv.h                    | 11 +++
 drivers/iommu/iommufd/iommufd_test.h          |  9 ++
 drivers/iommu/iommufd/main.c                  | 97 +++++++++++++++++++
 drivers/iommu/iommufd/selftest.c              | 16 +++
 include/linux/iommu.h                         | 20 ++--
 include/uapi/linux/iommufd.h                  | 45 +++++++++
 tools/testing/selftests/iommu/iommufd.c       | 17 +++-
 tools/testing/selftests/iommu/iommufd_utils.h | 26 +++++
 8 files changed, 229 insertions(+), 12 deletions(-)

-- 
2.34.1


^ permalink raw reply	[flat|nested] 13+ messages in thread

* [PATCH v6 1/4] iommu: Move dev_iommu_ops() to private header
  2023-08-08 15:35 [PATCH v6 0/4] iommufd: Add iommu hardware info reporting Yi Liu
@ 2023-08-08 15:35 ` Yi Liu
  2023-08-08 15:35 ` [PATCH v6 2/4] iommu: Add new iommu op to get iommu hardware information Yi Liu
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 13+ messages in thread
From: Yi Liu @ 2023-08-08 15:35 UTC (permalink / raw)
  To: joro, alex.williamson, jgg, kevin.tian, robin.murphy, baolu.lu
  Cc: cohuck, eric.auger, nicolinc, kvm, mjrosato, chao.p.peng,
	yi.l.liu, yi.y.sun, peterx, jasowang, shameerali.kolothum.thodi,
	lulu, suravee.suthikulpanit, iommu, linux-kernel,
	linux-kselftest, zhenzhong.duan

dev_iommu_ops() is essentially only used in iommu subsystem, so
move to a private header to avoid being abused by other drivers.

Suggested-by: Jason Gunthorpe <jgg@nvidia.com>
Reviewed-by: Kevin Tian <kevin.tian@intel.com>
Reviewed-by: Lu Baolu <baolu.lu@linux.intel.com>
Reviewed-by: Jason Gunthorpe <jgg@nvidia.com>
Signed-off-by: Yi Liu <yi.l.liu@intel.com>
---
 drivers/iommu/iommu-priv.h | 11 +++++++++++
 include/linux/iommu.h      | 11 -----------
 2 files changed, 11 insertions(+), 11 deletions(-)

diff --git a/drivers/iommu/iommu-priv.h b/drivers/iommu/iommu-priv.h
index 7c8011bfd153..a6e694f59f64 100644
--- a/drivers/iommu/iommu-priv.h
+++ b/drivers/iommu/iommu-priv.h
@@ -4,6 +4,17 @@
 
 #include <linux/iommu.h>
 
+static inline const struct iommu_ops *dev_iommu_ops(struct device *dev)
+{
+	/*
+	 * Assume that valid ops must be installed if iommu_probe_device()
+	 * has succeeded. The device ops are essentially for internal use
+	 * within the IOMMU subsystem itself, so we should be able to trust
+	 * ourselves not to misuse the helper.
+	 */
+	return dev->iommu->iommu_dev->ops;
+}
+
 int iommu_group_replace_domain(struct iommu_group *group,
 			       struct iommu_domain *new_domain);
 
diff --git a/include/linux/iommu.h b/include/linux/iommu.h
index d31642596675..e0245aa82b75 100644
--- a/include/linux/iommu.h
+++ b/include/linux/iommu.h
@@ -450,17 +450,6 @@ static inline void iommu_iotlb_gather_init(struct iommu_iotlb_gather *gather)
 	};
 }
 
-static inline const struct iommu_ops *dev_iommu_ops(struct device *dev)
-{
-	/*
-	 * Assume that valid ops must be installed if iommu_probe_device()
-	 * has succeeded. The device ops are essentially for internal use
-	 * within the IOMMU subsystem itself, so we should be able to trust
-	 * ourselves not to misuse the helper.
-	 */
-	return dev->iommu->iommu_dev->ops;
-}
-
 extern int bus_iommu_probe(const struct bus_type *bus);
 extern bool iommu_present(const struct bus_type *bus);
 extern bool device_iommu_capable(struct device *dev, enum iommu_cap cap);
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH v6 2/4] iommu: Add new iommu op to get iommu hardware information
  2023-08-08 15:35 [PATCH v6 0/4] iommufd: Add iommu hardware info reporting Yi Liu
  2023-08-08 15:35 ` [PATCH v6 1/4] iommu: Move dev_iommu_ops() to private header Yi Liu
@ 2023-08-08 15:35 ` Yi Liu
  2023-08-08 15:35 ` [PATCH v6 3/4] iommufd: Add IOMMU_GET_HW_INFO Yi Liu
  2023-08-08 15:35 ` [PATCH v6 4/4] iommufd/selftest: Add coverage for IOMMU_GET_HW_INFO ioctl Yi Liu
  3 siblings, 0 replies; 13+ messages in thread
From: Yi Liu @ 2023-08-08 15:35 UTC (permalink / raw)
  To: joro, alex.williamson, jgg, kevin.tian, robin.murphy, baolu.lu
  Cc: cohuck, eric.auger, nicolinc, kvm, mjrosato, chao.p.peng,
	yi.l.liu, yi.y.sun, peterx, jasowang, shameerali.kolothum.thodi,
	lulu, suravee.suthikulpanit, iommu, linux-kernel,
	linux-kselftest, zhenzhong.duan

From: Lu Baolu <baolu.lu@linux.intel.com>

Introduce a new iommu op to get the IOMMU hardware capabilities for
iommufd. This information will be used by any vIOMMU driver which is
owned by userspace.

This op chooses to make the special parameters opaque to the core. This
suits the current usage model where accessing any of the IOMMU device
special parameters does require a userspace driver that matches the kernel
driver. If a need for common parameters, implemented similarly by several
drivers, arises then there's room in the design to grow a generic parameter
set as well. No wrapper API is added as it is supposed to be used by
iommufd only.

Different IOMMU hardware would have different hardware information. So the
information reported differs as well. To let the external user understand
the difference. enum iommu_hw_info_type is defined. For the iommu drivers
that are capable to report hardware information, it should have a unique
iommu_hw_info_type and return to caller. For the driver doesn't report
hardware information, caller just uses IOMMU_HW_INFO_TYPE_NONE if a type
is required.

Signed-off-by: Lu Baolu <baolu.lu@linux.intel.com>
Co-developed-by: Nicolin Chen <nicolinc@nvidia.com>
Signed-off-by: Nicolin Chen <nicolinc@nvidia.com>
Signed-off-by: Yi Liu <yi.l.liu@intel.com>
---
 include/linux/iommu.h        | 9 +++++++++
 include/uapi/linux/iommufd.h | 9 +++++++++
 2 files changed, 18 insertions(+)

diff --git a/include/linux/iommu.h b/include/linux/iommu.h
index e0245aa82b75..f2d6a3989713 100644
--- a/include/linux/iommu.h
+++ b/include/linux/iommu.h
@@ -228,6 +228,14 @@ struct iommu_iotlb_gather {
 /**
  * struct iommu_ops - iommu ops and capabilities
  * @capable: check capability
+ * @hw_info: IOMMU hardware information. The type of the returned data is
+ *           marked by the output type of this op. Type is one of
+ *           enum iommu_hw_info_type defined in include/uapi/linux/iommufd.h.
+ *           The drivers that support this op should define a unique type
+ *           in include/uapi/linux/iommufd.h. The data buffer returned by this
+ *           op is allocated in the IOMMU driver and the caller should free it
+ *           after use. Return the data buffer if success, or ERR_PTR on
+ *           failure.
  * @domain_alloc: allocate iommu domain
  * @probe_device: Add device to iommu driver handling
  * @release_device: Remove device from iommu driver handling
@@ -257,6 +265,7 @@ struct iommu_iotlb_gather {
  */
 struct iommu_ops {
 	bool (*capable)(struct device *dev, enum iommu_cap);
+	void *(*hw_info)(struct device *dev, u32 *length, u32 *type);
 
 	/* Domain allocation and freeing by the iommu driver */
 	struct iommu_domain *(*domain_alloc)(unsigned iommu_domain_type);
diff --git a/include/uapi/linux/iommufd.h b/include/uapi/linux/iommufd.h
index 8245c01adca6..ac11ace21edb 100644
--- a/include/uapi/linux/iommufd.h
+++ b/include/uapi/linux/iommufd.h
@@ -370,4 +370,13 @@ struct iommu_hwpt_alloc {
 	__u32 __reserved;
 };
 #define IOMMU_HWPT_ALLOC _IO(IOMMUFD_TYPE, IOMMUFD_CMD_HWPT_ALLOC)
+
+/**
+ * enum iommu_hw_info_type - IOMMU Hardware Info Types
+ * @IOMMU_HW_INFO_TYPE_NONE: Used by the drivers that do not report hardware
+ *                           info
+ */
+enum iommu_hw_info_type {
+	IOMMU_HW_INFO_TYPE_NONE,
+};
 #endif
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH v6 3/4] iommufd: Add IOMMU_GET_HW_INFO
  2023-08-08 15:35 [PATCH v6 0/4] iommufd: Add iommu hardware info reporting Yi Liu
  2023-08-08 15:35 ` [PATCH v6 1/4] iommu: Move dev_iommu_ops() to private header Yi Liu
  2023-08-08 15:35 ` [PATCH v6 2/4] iommu: Add new iommu op to get iommu hardware information Yi Liu
@ 2023-08-08 15:35 ` Yi Liu
  2023-08-09 10:16   ` Baolu Lu
  2023-08-09 16:43   ` Jason Gunthorpe
  2023-08-08 15:35 ` [PATCH v6 4/4] iommufd/selftest: Add coverage for IOMMU_GET_HW_INFO ioctl Yi Liu
  3 siblings, 2 replies; 13+ messages in thread
From: Yi Liu @ 2023-08-08 15:35 UTC (permalink / raw)
  To: joro, alex.williamson, jgg, kevin.tian, robin.murphy, baolu.lu
  Cc: cohuck, eric.auger, nicolinc, kvm, mjrosato, chao.p.peng,
	yi.l.liu, yi.y.sun, peterx, jasowang, shameerali.kolothum.thodi,
	lulu, suravee.suthikulpanit, iommu, linux-kernel,
	linux-kselftest, zhenzhong.duan

Under nested IOMMU translation, userspace owns the stage-1 translation
table (e.g. the stage-1 page table of Intel VT-d or the context table
of ARM SMMUv3, and etc.). Stage-1 translation tables are vendor specific,
and need to be compatible with the underlying IOMMU hardware. Hence,
userspace should know the IOMMU hardware capability before creating and
configuring the stage-1 translation table to kernel.

This adds IOMMU_GET_HW_INFO ioctl to query the IOMMU hardware information
(a.k.a capability) for a given device. The returned data is vendor specific,
userspace needs to decode it with the structure mapped by the @out_data_type
field.

As only physical devices have IOMMU hardware, so this will return error
if the given device is not a physical device.

Reviewed-by: Lu Baolu <baolu.lu@linux.intel.com>
Co-developed-by: Nicolin Chen <nicolinc@nvidia.com>
Signed-off-by: Nicolin Chen <nicolinc@nvidia.com>
Signed-off-by: Yi Liu <yi.l.liu@intel.com>
---
 drivers/iommu/iommufd/main.c | 97 ++++++++++++++++++++++++++++++++++++
 include/uapi/linux/iommufd.h | 36 +++++++++++++
 2 files changed, 133 insertions(+)

diff --git a/drivers/iommu/iommufd/main.c b/drivers/iommu/iommufd/main.c
index 94c498b8fdf6..54e61fbf56f8 100644
--- a/drivers/iommu/iommufd/main.c
+++ b/drivers/iommu/iommufd/main.c
@@ -17,6 +17,7 @@
 #include <linux/bug.h>
 #include <uapi/linux/iommufd.h>
 #include <linux/iommufd.h>
+#include "../iommu-priv.h"
 
 #include "io_pagetable.h"
 #include "iommufd_private.h"
@@ -177,6 +178,99 @@ static int iommufd_destroy(struct iommufd_ucmd *ucmd)
 	return 0;
 }
 
+static int iommufd_zero_fill_user(void __user *ptr, size_t bytes)
+{
+	int index = 0;
+
+	for (; index < bytes; index++) {
+		if (put_user(0, (uint8_t __user *)(ptr + index)))
+			return -EFAULT;
+	}
+	return 0;
+}
+
+static int iommufd_fill_hw_info(struct device *dev, void __user *user_ptr,
+				unsigned int *length, u32 *type)
+{
+	const struct iommu_ops *ops;
+	unsigned int data_len;
+	void *data;
+	int rc = 0;
+
+	ops = dev_iommu_ops(dev);
+	if (!ops->hw_info) {
+		*length = 0;
+		*type = IOMMU_HW_INFO_TYPE_NONE;
+		return 0;
+	}
+
+	data = ops->hw_info(dev, &data_len, type);
+	if (IS_ERR(data))
+		return PTR_ERR(data);
+
+	/*
+	 * drivers that have hw_info callback should have a unique
+	 * iommu_hw_info_type.
+	 */
+	if (WARN_ON_ONCE(*type == IOMMU_HW_INFO_TYPE_NONE)) {
+		rc = -ENODEV;
+		goto err_free;
+	}
+
+	*length = min(*length, data_len);
+	if (copy_to_user(user_ptr, data, *length)) {
+		rc = -EFAULT;
+		goto err_free;
+	}
+
+err_free:
+	kfree(data);
+	return rc;
+}
+
+static int iommufd_get_hw_info(struct iommufd_ucmd *ucmd)
+{
+	struct iommu_hw_info *cmd = ucmd->cmd;
+	unsigned int length = cmd->data_len;
+	struct iommufd_device *idev;
+	void __user *user_ptr;
+	u32 hw_info_type;
+	int rc = 0;
+
+	if (cmd->flags || cmd->__reserved || !cmd->data_len)
+		return -EOPNOTSUPP;
+
+	idev = iommufd_get_device(ucmd, cmd->dev_id);
+	if (IS_ERR(idev))
+		return PTR_ERR(idev);
+
+	user_ptr = u64_to_user_ptr(cmd->data_ptr);
+
+	rc = iommufd_fill_hw_info(idev->dev, user_ptr,
+				  &length, &hw_info_type);
+	if (rc)
+		goto err_put;
+
+	/*
+	 * Zero the trailing bytes if the user buffer is bigger than the
+	 * data size kernel actually has.
+	 */
+	if (length < cmd->data_len) {
+		rc = iommufd_zero_fill_user(user_ptr + length,
+					    cmd->data_len - length);
+		if (rc)
+			goto err_put;
+	}
+
+	cmd->data_len = length;
+	cmd->out_data_type = hw_info_type;
+	rc = iommufd_ucmd_respond(ucmd, sizeof(*cmd));
+
+err_put:
+	iommufd_put_object(&idev->obj);
+	return rc;
+}
+
 static int iommufd_fops_open(struct inode *inode, struct file *filp)
 {
 	struct iommufd_ctx *ictx;
@@ -265,6 +359,7 @@ static int iommufd_option(struct iommufd_ucmd *ucmd)
 
 union ucmd_buffer {
 	struct iommu_destroy destroy;
+	struct iommu_hw_info info;
 	struct iommu_hwpt_alloc hwpt;
 	struct iommu_ioas_alloc alloc;
 	struct iommu_ioas_allow_iovas allow_iovas;
@@ -297,6 +392,8 @@ struct iommufd_ioctl_op {
 	}
 static const struct iommufd_ioctl_op iommufd_ioctl_ops[] = {
 	IOCTL_OP(IOMMU_DESTROY, iommufd_destroy, struct iommu_destroy, id),
+	IOCTL_OP(IOMMU_GET_HW_INFO, iommufd_get_hw_info, struct iommu_hw_info,
+		 __reserved),
 	IOCTL_OP(IOMMU_HWPT_ALLOC, iommufd_hwpt_alloc, struct iommu_hwpt_alloc,
 		 __reserved),
 	IOCTL_OP(IOMMU_IOAS_ALLOC, iommufd_ioas_alloc_ioctl,
diff --git a/include/uapi/linux/iommufd.h b/include/uapi/linux/iommufd.h
index ac11ace21edb..4a00f8fb2d54 100644
--- a/include/uapi/linux/iommufd.h
+++ b/include/uapi/linux/iommufd.h
@@ -46,6 +46,7 @@ enum {
 	IOMMUFD_CMD_OPTION,
 	IOMMUFD_CMD_VFIO_IOAS,
 	IOMMUFD_CMD_HWPT_ALLOC,
+	IOMMUFD_CMD_GET_HW_INFO,
 };
 
 /**
@@ -379,4 +380,39 @@ struct iommu_hwpt_alloc {
 enum iommu_hw_info_type {
 	IOMMU_HW_INFO_TYPE_NONE,
 };
+
+/**
+ * struct iommu_hw_info - ioctl(IOMMU_GET_HW_INFO)
+ * @size: sizeof(struct iommu_hw_info)
+ * @flags: Must be 0
+ * @dev_id: The device bound to the iommufd
+ * @data_len: Input the length of the user buffer in bytes. Output the length
+ *            of data filled in the user buffer.
+ * @data_ptr: Pointer to the user buffer
+ * @out_data_type: Output the iommu hardware info type as defined in the enum
+ *                 iommu_hw_info_type.
+ * @__reserved: Must be 0
+ *
+ * Query the hardware information from an iommu behind a given device that has
+ * been bound to iommufd. @data_len is the size of the buffer, which captures an
+ * iommu type specific input data and a filled output data. Trailing bytes will
+ * be zeroed if the user buffer is larger than the data kernel has.
+ *
+ * The type specific data would be used to sync capabilities between the virtual
+ * IOMMU and the hardware IOMMU, e.g. a nested translation setup needs to check
+ * the hardware information, so the guest stage-1 page table will be compatible.
+ *
+ * The @out_data_type will be filled if the ioctl succeeds. It would be used to
+ * decode the data filled in the buffer pointed by @data_ptr.
+ */
+struct iommu_hw_info {
+	__u32 size;
+	__u32 flags;
+	__u32 dev_id;
+	__u32 data_len;
+	__aligned_u64 data_ptr;
+	__u32 out_data_type;
+	__u32 __reserved;
+};
+#define IOMMU_GET_HW_INFO _IO(IOMMUFD_TYPE, IOMMUFD_CMD_GET_HW_INFO)
 #endif
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH v6 4/4] iommufd/selftest: Add coverage for IOMMU_GET_HW_INFO ioctl
  2023-08-08 15:35 [PATCH v6 0/4] iommufd: Add iommu hardware info reporting Yi Liu
                   ` (2 preceding siblings ...)
  2023-08-08 15:35 ` [PATCH v6 3/4] iommufd: Add IOMMU_GET_HW_INFO Yi Liu
@ 2023-08-08 15:35 ` Yi Liu
  2023-08-09 16:45   ` Jason Gunthorpe
  3 siblings, 1 reply; 13+ messages in thread
From: Yi Liu @ 2023-08-08 15:35 UTC (permalink / raw)
  To: joro, alex.williamson, jgg, kevin.tian, robin.murphy, baolu.lu
  Cc: cohuck, eric.auger, nicolinc, kvm, mjrosato, chao.p.peng,
	yi.l.liu, yi.y.sun, peterx, jasowang, shameerali.kolothum.thodi,
	lulu, suravee.suthikulpanit, iommu, linux-kernel,
	linux-kselftest, zhenzhong.duan

From: Nicolin Chen <nicolinc@nvidia.com>

Add a mock_domain_hw_info function and an iommu_test_hw_info data
structure. This allows to test the IOMMU_GET_HW_INFO ioctl passing
the test_reg value for the mock_dev.

Signed-off-by: Nicolin Chen <nicolinc@nvidia.com>
Signed-off-by: Yi Liu <yi.l.liu@intel.com>
---
 drivers/iommu/iommufd/iommufd_test.h          |  9 +++++++
 drivers/iommu/iommufd/selftest.c              | 16 ++++++++++++
 tools/testing/selftests/iommu/iommufd.c       | 17 +++++++++++-
 tools/testing/selftests/iommu/iommufd_utils.h | 26 +++++++++++++++++++
 4 files changed, 67 insertions(+), 1 deletion(-)

diff --git a/drivers/iommu/iommufd/iommufd_test.h b/drivers/iommu/iommufd/iommufd_test.h
index 258de2253b61..3f3644375bf1 100644
--- a/drivers/iommu/iommufd/iommufd_test.h
+++ b/drivers/iommu/iommufd/iommufd_test.h
@@ -100,4 +100,13 @@ struct iommu_test_cmd {
 };
 #define IOMMU_TEST_CMD _IO(IOMMUFD_TYPE, IOMMUFD_CMD_BASE + 32)
 
+/* Mock structs for IOMMU_DEVICE_GET_HW_INFO ioctl */
+#define IOMMU_HW_INFO_TYPE_SELFTEST	0xfeedbeef
+#define IOMMU_HW_INFO_SELFTEST_REGVAL	0xdeadbeef
+
+struct iommu_test_hw_info {
+	__u32 flags;
+	__u32 test_reg;
+};
+
 #endif
diff --git a/drivers/iommu/iommufd/selftest.c b/drivers/iommu/iommufd/selftest.c
index bb2cd54ca7b6..ab4011e3a7c6 100644
--- a/drivers/iommu/iommufd/selftest.c
+++ b/drivers/iommu/iommufd/selftest.c
@@ -128,6 +128,21 @@ static struct iommu_domain mock_blocking_domain = {
 	.ops = &mock_blocking_ops,
 };
 
+static void *mock_domain_hw_info(struct device *dev, u32 *length, u32 *type)
+{
+	struct iommu_test_hw_info *info;
+
+	info = kzalloc(sizeof(*info), GFP_KERNEL);
+	if (!info)
+		return ERR_PTR(-ENOMEM);
+
+	info->test_reg = IOMMU_HW_INFO_SELFTEST_REGVAL;
+	*length = sizeof(*info);
+	*type = IOMMU_HW_INFO_TYPE_SELFTEST;
+
+	return info;
+}
+
 static struct iommu_domain *mock_domain_alloc(unsigned int iommu_domain_type)
 {
 	struct mock_iommu_domain *mock;
@@ -279,6 +294,7 @@ static void mock_domain_set_plaform_dma_ops(struct device *dev)
 static const struct iommu_ops mock_ops = {
 	.owner = THIS_MODULE,
 	.pgsize_bitmap = MOCK_IO_PAGE_SIZE,
+	.hw_info = mock_domain_hw_info,
 	.domain_alloc = mock_domain_alloc,
 	.capable = mock_domain_capable,
 	.set_platform_dma_ops = mock_domain_set_plaform_dma_ops,
diff --git a/tools/testing/selftests/iommu/iommufd.c b/tools/testing/selftests/iommu/iommufd.c
index 8acd0af37aa5..6b075a68b928 100644
--- a/tools/testing/selftests/iommu/iommufd.c
+++ b/tools/testing/selftests/iommu/iommufd.c
@@ -113,6 +113,7 @@ TEST_F(iommufd, cmd_length)
 	}
 
 	TEST_LENGTH(iommu_destroy, IOMMU_DESTROY);
+	TEST_LENGTH(iommu_hw_info, IOMMU_GET_HW_INFO);
 	TEST_LENGTH(iommu_ioas_alloc, IOMMU_IOAS_ALLOC);
 	TEST_LENGTH(iommu_ioas_iova_ranges, IOMMU_IOAS_IOVA_RANGES);
 	TEST_LENGTH(iommu_ioas_allow_iovas, IOMMU_IOAS_ALLOW_IOVAS);
@@ -185,6 +186,7 @@ FIXTURE(iommufd_ioas)
 	uint32_t ioas_id;
 	uint32_t stdev_id;
 	uint32_t hwpt_id;
+	uint32_t device_id;
 	uint64_t base_iova;
 };
 
@@ -211,7 +213,7 @@ FIXTURE_SETUP(iommufd_ioas)
 
 	for (i = 0; i != variant->mock_domains; i++) {
 		test_cmd_mock_domain(self->ioas_id, &self->stdev_id,
-				     &self->hwpt_id, NULL);
+				     &self->hwpt_id, &self->device_id);
 		self->base_iova = MOCK_APERTURE_START;
 	}
 }
@@ -290,6 +292,19 @@ TEST_F(iommufd_ioas, ioas_area_auto_destroy)
 	}
 }
 
+TEST_F(iommufd_ioas, get_hw_info)
+{
+	struct iommu_test_hw_info info;
+
+	if (self->device_id) {
+		test_cmd_get_hw_info(self->device_id, sizeof(info), &info);
+		assert(info.test_reg == IOMMU_HW_INFO_SELFTEST_REGVAL);
+	} else {
+		test_err_get_hw_info(ENOENT, self->device_id,
+				     sizeof(info), &info);
+	}
+}
+
 TEST_F(iommufd_ioas, area)
 {
 	int i;
diff --git a/tools/testing/selftests/iommu/iommufd_utils.h b/tools/testing/selftests/iommu/iommufd_utils.h
index 70353e68e599..d6d223435881 100644
--- a/tools/testing/selftests/iommu/iommufd_utils.h
+++ b/tools/testing/selftests/iommu/iommufd_utils.h
@@ -348,3 +348,29 @@ static void teardown_iommufd(int fd, struct __test_metadata *_metadata)
 	})
 
 #endif
+
+static int _test_cmd_get_hw_info(int fd, __u32 device_id,
+				 void *data, size_t data_len)
+{
+	struct iommu_hw_info cmd = {
+		.size = sizeof(cmd),
+		.dev_id = device_id,
+		.data_len = data_len,
+		.data_ptr = (uint64_t)data,
+	};
+	int ret;
+
+	ret = ioctl(fd, IOMMU_GET_HW_INFO, &cmd);
+	if (ret)
+		return ret;
+	return 0;
+}
+
+#define test_cmd_get_hw_info(device_id, data_len, data)         \
+	ASSERT_EQ(0, _test_cmd_get_hw_info(self->fd, device_id, \
+					   data, data_len))
+
+#define test_err_get_hw_info(_errno, device_id, data_len, data) \
+	EXPECT_ERRNO(_errno,                                    \
+		     _test_cmd_get_hw_info(self->fd, device_id, \
+					   data, data_len))
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* Re: [PATCH v6 3/4] iommufd: Add IOMMU_GET_HW_INFO
  2023-08-08 15:35 ` [PATCH v6 3/4] iommufd: Add IOMMU_GET_HW_INFO Yi Liu
@ 2023-08-09 10:16   ` Baolu Lu
  2023-08-09 16:16     ` Jason Gunthorpe
  2023-08-09 16:43   ` Jason Gunthorpe
  1 sibling, 1 reply; 13+ messages in thread
From: Baolu Lu @ 2023-08-09 10:16 UTC (permalink / raw)
  To: Yi Liu, joro, alex.williamson, jgg, kevin.tian, robin.murphy
  Cc: baolu.lu, cohuck, eric.auger, nicolinc, kvm, mjrosato,
	chao.p.peng, yi.y.sun, peterx, jasowang,
	shameerali.kolothum.thodi, lulu, suravee.suthikulpanit, iommu,
	linux-kernel, linux-kselftest, zhenzhong.duan

On 2023/8/8 23:35, Yi Liu wrote:
> +static int iommufd_fill_hw_info(struct device *dev, void __user *user_ptr,
> +				unsigned int *length, u32 *type)
> +{
> +	const struct iommu_ops *ops;
> +	unsigned int data_len;
> +	void *data;
> +	int rc = 0;
> +
> +	ops = dev_iommu_ops(dev);
> +	if (!ops->hw_info) {
> +		*length = 0;
> +		*type = IOMMU_HW_INFO_TYPE_NONE;
> +		return 0;
> +	}
> +
> +	data = ops->hw_info(dev, &data_len, type);
> +	if (IS_ERR(data))
> +		return PTR_ERR(data);
> +
> +	/*
> +	 * drivers that have hw_info callback should have a unique
> +	 * iommu_hw_info_type.
> +	 */
> +	if (WARN_ON_ONCE(*type == IOMMU_HW_INFO_TYPE_NONE)) {
> +		rc = -ENODEV;
> +		goto err_free;
> +	}
> +
> +	*length = min(*length, data_len);
> +	if (copy_to_user(user_ptr, data, *length)) {

copy_to_user() returns the number of bytes that were successfully
copied, right?

If so, isn't it always failure case? Or I missed anything?

> +		rc = -EFAULT;
> +		goto err_free;

nit: this goto is unnecessary.

> +	}
> +
> +err_free:
> +	kfree(data);
> +	return rc;
> +}

Best regards,
baolu

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH v6 3/4] iommufd: Add IOMMU_GET_HW_INFO
  2023-08-09 10:16   ` Baolu Lu
@ 2023-08-09 16:16     ` Jason Gunthorpe
  2023-08-10  2:05       ` Baolu Lu
  0 siblings, 1 reply; 13+ messages in thread
From: Jason Gunthorpe @ 2023-08-09 16:16 UTC (permalink / raw)
  To: Baolu Lu
  Cc: Yi Liu, joro, alex.williamson, kevin.tian, robin.murphy, cohuck,
	eric.auger, nicolinc, kvm, mjrosato, chao.p.peng, yi.y.sun,
	peterx, jasowang, shameerali.kolothum.thodi, lulu,
	suravee.suthikulpanit, iommu, linux-kernel, linux-kselftest,
	zhenzhong.duan

On Wed, Aug 09, 2023 at 06:16:19PM +0800, Baolu Lu wrote:
> On 2023/8/8 23:35, Yi Liu wrote:
> > +static int iommufd_fill_hw_info(struct device *dev, void __user *user_ptr,
> > +				unsigned int *length, u32 *type)
> > +{
> > +	const struct iommu_ops *ops;
> > +	unsigned int data_len;
> > +	void *data;
> > +	int rc = 0;
> > +
> > +	ops = dev_iommu_ops(dev);
> > +	if (!ops->hw_info) {
> > +		*length = 0;
> > +		*type = IOMMU_HW_INFO_TYPE_NONE;
> > +		return 0;
> > +	}
> > +
> > +	data = ops->hw_info(dev, &data_len, type);
> > +	if (IS_ERR(data))
> > +		return PTR_ERR(data);
> > +
> > +	/*
> > +	 * drivers that have hw_info callback should have a unique
> > +	 * iommu_hw_info_type.
> > +	 */
> > +	if (WARN_ON_ONCE(*type == IOMMU_HW_INFO_TYPE_NONE)) {
> > +		rc = -ENODEV;
> > +		goto err_free;
> > +	}
> > +
> > +	*length = min(*length, data_len);
> > +	if (copy_to_user(user_ptr, data, *length)) {
> 
> copy_to_user() returns the number of bytes that were successfully
> copied, right?

It returns length on failure and 0 on success

Jason

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH v6 3/4] iommufd: Add IOMMU_GET_HW_INFO
  2023-08-08 15:35 ` [PATCH v6 3/4] iommufd: Add IOMMU_GET_HW_INFO Yi Liu
  2023-08-09 10:16   ` Baolu Lu
@ 2023-08-09 16:43   ` Jason Gunthorpe
  2023-08-10  3:35     ` Liu, Yi L
  1 sibling, 1 reply; 13+ messages in thread
From: Jason Gunthorpe @ 2023-08-09 16:43 UTC (permalink / raw)
  To: Yi Liu
  Cc: joro, alex.williamson, kevin.tian, robin.murphy, baolu.lu,
	cohuck, eric.auger, nicolinc, kvm, mjrosato, chao.p.peng,
	yi.y.sun, peterx, jasowang, shameerali.kolothum.thodi, lulu,
	suravee.suthikulpanit, iommu, linux-kernel, linux-kselftest,
	zhenzhong.duan

On Tue, Aug 08, 2023 at 08:35:09AM -0700, Yi Liu wrote:
> +static int iommufd_zero_fill_user(void __user *ptr, size_t bytes)
> +{
> +	int index = 0;
> +
> +	for (; index < bytes; index++) {
> +		if (put_user(0, (uint8_t __user *)(ptr + index)))
> +			return -EFAULT;
> +	}

I've recently learned this routine is spelled 'clear_user()'

Jason

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH v6 4/4] iommufd/selftest: Add coverage for IOMMU_GET_HW_INFO ioctl
  2023-08-08 15:35 ` [PATCH v6 4/4] iommufd/selftest: Add coverage for IOMMU_GET_HW_INFO ioctl Yi Liu
@ 2023-08-09 16:45   ` Jason Gunthorpe
  2023-08-11  6:57     ` Liu, Yi L
  0 siblings, 1 reply; 13+ messages in thread
From: Jason Gunthorpe @ 2023-08-09 16:45 UTC (permalink / raw)
  To: Yi Liu
  Cc: joro, alex.williamson, kevin.tian, robin.murphy, baolu.lu,
	cohuck, eric.auger, nicolinc, kvm, mjrosato, chao.p.peng,
	yi.y.sun, peterx, jasowang, shameerali.kolothum.thodi, lulu,
	suravee.suthikulpanit, iommu, linux-kernel, linux-kselftest,
	zhenzhong.duan

On Tue, Aug 08, 2023 at 08:35:10AM -0700, Yi Liu wrote:
> From: Nicolin Chen <nicolinc@nvidia.com>
> 
> Add a mock_domain_hw_info function and an iommu_test_hw_info data
> structure. This allows to test the IOMMU_GET_HW_INFO ioctl passing
> the test_reg value for the mock_dev.
> 
> Signed-off-by: Nicolin Chen <nicolinc@nvidia.com>
> Signed-off-by: Yi Liu <yi.l.liu@intel.com>
> ---
>  drivers/iommu/iommufd/iommufd_test.h          |  9 +++++++
>  drivers/iommu/iommufd/selftest.c              | 16 ++++++++++++
>  tools/testing/selftests/iommu/iommufd.c       | 17 +++++++++++-
>  tools/testing/selftests/iommu/iommufd_utils.h | 26 +++++++++++++++++++
>  4 files changed, 67 insertions(+), 1 deletion(-)

Don't forget to add it to fail_nth

Jason

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH v6 3/4] iommufd: Add IOMMU_GET_HW_INFO
  2023-08-09 16:16     ` Jason Gunthorpe
@ 2023-08-10  2:05       ` Baolu Lu
  0 siblings, 0 replies; 13+ messages in thread
From: Baolu Lu @ 2023-08-10  2:05 UTC (permalink / raw)
  To: Jason Gunthorpe
  Cc: baolu.lu, Yi Liu, joro, alex.williamson, kevin.tian,
	robin.murphy, cohuck, eric.auger, nicolinc, kvm, mjrosato,
	chao.p.peng, yi.y.sun, peterx, jasowang,
	shameerali.kolothum.thodi, lulu, suravee.suthikulpanit, iommu,
	linux-kernel, linux-kselftest, zhenzhong.duan

On 2023/8/10 0:16, Jason Gunthorpe wrote:
> On Wed, Aug 09, 2023 at 06:16:19PM +0800, Baolu Lu wrote:
>> On 2023/8/8 23:35, Yi Liu wrote:
>>> +static int iommufd_fill_hw_info(struct device *dev, void __user *user_ptr,
>>> +				unsigned int *length, u32 *type)
>>> +{
>>> +	const struct iommu_ops *ops;
>>> +	unsigned int data_len;
>>> +	void *data;
>>> +	int rc = 0;
>>> +
>>> +	ops = dev_iommu_ops(dev);
>>> +	if (!ops->hw_info) {
>>> +		*length = 0;
>>> +		*type = IOMMU_HW_INFO_TYPE_NONE;
>>> +		return 0;
>>> +	}
>>> +
>>> +	data = ops->hw_info(dev, &data_len, type);
>>> +	if (IS_ERR(data))
>>> +		return PTR_ERR(data);
>>> +
>>> +	/*
>>> +	 * drivers that have hw_info callback should have a unique
>>> +	 * iommu_hw_info_type.
>>> +	 */
>>> +	if (WARN_ON_ONCE(*type == IOMMU_HW_INFO_TYPE_NONE)) {
>>> +		rc = -ENODEV;
>>> +		goto err_free;
>>> +	}
>>> +
>>> +	*length = min(*length, data_len);
>>> +	if (copy_to_user(user_ptr, data, *length)) {
>> copy_to_user() returns the number of bytes that were successfully
>> copied, right?
> It returns length on failure and 0 on success

Then it's fine. Thanks for the explanation.

Best regards,
baolu

^ permalink raw reply	[flat|nested] 13+ messages in thread

* RE: [PATCH v6 3/4] iommufd: Add IOMMU_GET_HW_INFO
  2023-08-09 16:43   ` Jason Gunthorpe
@ 2023-08-10  3:35     ` Liu, Yi L
  0 siblings, 0 replies; 13+ messages in thread
From: Liu, Yi L @ 2023-08-10  3:35 UTC (permalink / raw)
  To: Jason Gunthorpe
  Cc: joro, alex.williamson, Tian, Kevin, robin.murphy, baolu.lu,
	cohuck, eric.auger, nicolinc, kvm, mjrosato, chao.p.peng,
	yi.y.sun, peterx, jasowang, shameerali.kolothum.thodi, lulu,
	suravee.suthikulpanit, iommu, linux-kernel, linux-kselftest,
	Duan, Zhenzhong

> From: Jason Gunthorpe <jgg@nvidia.com>
> Sent: Thursday, August 10, 2023 12:44 AM
> 
> On Tue, Aug 08, 2023 at 08:35:09AM -0700, Yi Liu wrote:
> > +static int iommufd_zero_fill_user(void __user *ptr, size_t bytes)
> > +{
> > +	int index = 0;
> > +
> > +	for (; index < bytes; index++) {
> > +		if (put_user(0, (uint8_t __user *)(ptr + index)))
> > +			return -EFAULT;
> > +	}
> 
> I've recently learned this routine is spelled 'clear_user()'

I see. Will replace with it.

Regards,
Yi Liu

^ permalink raw reply	[flat|nested] 13+ messages in thread

* RE: [PATCH v6 4/4] iommufd/selftest: Add coverage for IOMMU_GET_HW_INFO ioctl
  2023-08-09 16:45   ` Jason Gunthorpe
@ 2023-08-11  6:57     ` Liu, Yi L
  2023-08-11 12:01       ` Jason Gunthorpe
  0 siblings, 1 reply; 13+ messages in thread
From: Liu, Yi L @ 2023-08-11  6:57 UTC (permalink / raw)
  To: Jason Gunthorpe
  Cc: joro, alex.williamson, Tian, Kevin, robin.murphy, baolu.lu,
	cohuck, eric.auger, nicolinc, kvm, mjrosato, chao.p.peng,
	yi.y.sun, peterx, jasowang, shameerali.kolothum.thodi, lulu,
	suravee.suthikulpanit, iommu, linux-kernel, linux-kselftest,
	Duan, Zhenzhong

> From: Jason Gunthorpe <jgg@nvidia.com>
> Sent: Thursday, August 10, 2023 12:46 AM
> 
> On Tue, Aug 08, 2023 at 08:35:10AM -0700, Yi Liu wrote:
> > From: Nicolin Chen <nicolinc@nvidia.com>
> >
> > Add a mock_domain_hw_info function and an iommu_test_hw_info data
> > structure. This allows to test the IOMMU_GET_HW_INFO ioctl passing
> > the test_reg value for the mock_dev.
> >
> > Signed-off-by: Nicolin Chen <nicolinc@nvidia.com>
> > Signed-off-by: Yi Liu <yi.l.liu@intel.com>
> > ---
> >  drivers/iommu/iommufd/iommufd_test.h          |  9 +++++++
> >  drivers/iommu/iommufd/selftest.c              | 16 ++++++++++++
> >  tools/testing/selftests/iommu/iommufd.c       | 17 +++++++++++-
> >  tools/testing/selftests/iommu/iommufd_utils.h | 26 +++++++++++++++++++
> >  4 files changed, 67 insertions(+), 1 deletion(-)
> 
> Don't forget to add it to fail_nth

Sure. Btw. Would you share us the rule on determining whether an ioctl/path
requires fail_nth case or not.

Regards,
Yi Liu

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH v6 4/4] iommufd/selftest: Add coverage for IOMMU_GET_HW_INFO ioctl
  2023-08-11  6:57     ` Liu, Yi L
@ 2023-08-11 12:01       ` Jason Gunthorpe
  0 siblings, 0 replies; 13+ messages in thread
From: Jason Gunthorpe @ 2023-08-11 12:01 UTC (permalink / raw)
  To: Liu, Yi L
  Cc: joro, alex.williamson, Tian, Kevin, robin.murphy, baolu.lu,
	cohuck, eric.auger, nicolinc, kvm, mjrosato, chao.p.peng,
	yi.y.sun, peterx, jasowang, shameerali.kolothum.thodi, lulu,
	suravee.suthikulpanit, iommu, linux-kernel, linux-kselftest,
	Duan, Zhenzhong

On Fri, Aug 11, 2023 at 06:57:34AM +0000, Liu, Yi L wrote:
> > From: Jason Gunthorpe <jgg@nvidia.com>
> > Sent: Thursday, August 10, 2023 12:46 AM
> > 
> > On Tue, Aug 08, 2023 at 08:35:10AM -0700, Yi Liu wrote:
> > > From: Nicolin Chen <nicolinc@nvidia.com>
> > >
> > > Add a mock_domain_hw_info function and an iommu_test_hw_info data
> > > structure. This allows to test the IOMMU_GET_HW_INFO ioctl passing
> > > the test_reg value for the mock_dev.
> > >
> > > Signed-off-by: Nicolin Chen <nicolinc@nvidia.com>
> > > Signed-off-by: Yi Liu <yi.l.liu@intel.com>
> > > ---
> > >  drivers/iommu/iommufd/iommufd_test.h          |  9 +++++++
> > >  drivers/iommu/iommufd/selftest.c              | 16 ++++++++++++
> > >  tools/testing/selftests/iommu/iommufd.c       | 17 +++++++++++-
> > >  tools/testing/selftests/iommu/iommufd_utils.h | 26 +++++++++++++++++++
> > >  4 files changed, 67 insertions(+), 1 deletion(-)
> > 
> > Don't forget to add it to fail_nth
> 
> Sure. Btw. Would you share us the rule on determining whether an ioctl/path
> requires fail_nth case or not.

It always requires it :)

Jason

^ permalink raw reply	[flat|nested] 13+ messages in thread

end of thread, other threads:[~2023-08-11 12:01 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-08-08 15:35 [PATCH v6 0/4] iommufd: Add iommu hardware info reporting Yi Liu
2023-08-08 15:35 ` [PATCH v6 1/4] iommu: Move dev_iommu_ops() to private header Yi Liu
2023-08-08 15:35 ` [PATCH v6 2/4] iommu: Add new iommu op to get iommu hardware information Yi Liu
2023-08-08 15:35 ` [PATCH v6 3/4] iommufd: Add IOMMU_GET_HW_INFO Yi Liu
2023-08-09 10:16   ` Baolu Lu
2023-08-09 16:16     ` Jason Gunthorpe
2023-08-10  2:05       ` Baolu Lu
2023-08-09 16:43   ` Jason Gunthorpe
2023-08-10  3:35     ` Liu, Yi L
2023-08-08 15:35 ` [PATCH v6 4/4] iommufd/selftest: Add coverage for IOMMU_GET_HW_INFO ioctl Yi Liu
2023-08-09 16:45   ` Jason Gunthorpe
2023-08-11  6:57     ` Liu, Yi L
2023-08-11 12:01       ` Jason Gunthorpe

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).