linux-arm-kernel.lists.infradead.org archive mirror
 help / color / mirror / Atom feed
* [PATCH RFC v1 0/3] Add set_rid_user and unset_rid_user support
@ 2023-04-06  6:25 Nicolin Chen
  2023-04-06  6:25 ` [PATCH RFC v1 1/3] iommu: Add set/unset_rid_user ops Nicolin Chen
                   ` (2 more replies)
  0 siblings, 3 replies; 4+ messages in thread
From: Nicolin Chen @ 2023-04-06  6:25 UTC (permalink / raw)
  To: jgg, robin.murphy, kevin.tian
  Cc: eric.auger, yi.l.liu, baolu.lu, will, joro,
	shameerali.kolothum.thodi, jean-philippe, linux-arm-kernel, iommu,
	linux-kernel

This is a pair of new uAPI/ops for user space to set a user space virtual
Request ID for a passthrough PCI device, down to the IOMMU driver. This's
primarily used by SMMUv3 driver for now, to link the vSID and the pSID of
a device behind the SMMU. The link (lookup table) will be used to verify
an ATC_INV command from the user space for that device, and then replace
the virtual SID with the corresponding physical SID.

This is a RFC series, since I am not confident at all about the uAPI/ops
namings. Hopefully we can finalize this small series soon and include it
in the next version of SMMUv3 nesting series.

This series is available on Github:
https://github.com/nicolinc/iommufd/commits/set_rid_user-rfc-v1

Thanks!
Nicolin

Nicolin Chen (3):
  iommu: Add set/unset_rid_user ops
  iommufd: Add IOMMUFD_CMD_DEVICE_SET_RID and
    IOMMUFD_CMD_DEVICE_UNSET_RID
  iommu/arm-smmu-v3: Implement set_rid_user and unset_rid_user

 drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c | 45 +++++++++++++++++++++
 drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h |  2 +
 drivers/iommu/iommufd/device.c              | 39 ++++++++++++++++++
 drivers/iommu/iommufd/iommufd_private.h     |  2 +
 drivers/iommu/iommufd/main.c                |  4 ++
 include/linux/iommu.h                       |  4 ++
 include/uapi/linux/iommufd.h                | 31 ++++++++++++++
 7 files changed, 127 insertions(+)

-- 
2.40.0


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH RFC v1 1/3] iommu: Add set/unset_rid_user ops
  2023-04-06  6:25 [PATCH RFC v1 0/3] Add set_rid_user and unset_rid_user support Nicolin Chen
@ 2023-04-06  6:25 ` Nicolin Chen
  2023-04-06  6:25 ` [PATCH RFC v1 2/3] iommufd: Add IOMMUFD_CMD_DEVICE_SET_RID and IOMMUFD_CMD_DEVICE_UNSET_RID Nicolin Chen
  2023-04-06  6:25 ` [PATCH RFC v1 3/3] iommu/arm-smmu-v3: Implement set_rid_user and unset_rid_user Nicolin Chen
  2 siblings, 0 replies; 4+ messages in thread
From: Nicolin Chen @ 2023-04-06  6:25 UTC (permalink / raw)
  To: jgg, robin.murphy, kevin.tian
  Cc: eric.auger, yi.l.liu, baolu.lu, will, joro,
	shameerali.kolothum.thodi, jean-philippe, linux-arm-kernel, iommu,
	linux-kernel

Add a pair of new ops to allow user space to set virtual RID of a device.
This can be converted to Stream ID for SMMUv3, so as to create the link
between a physical Stream ID and a virtual Stream ID.

Signed-off-by: Nicolin Chen <nicolinc@nvidia.com>
---
 include/linux/iommu.h | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/include/linux/iommu.h b/include/linux/iommu.h
index 080278c8154d..f85ce6f01408 100644
--- a/include/linux/iommu.h
+++ b/include/linux/iommu.h
@@ -248,6 +248,7 @@ struct iommu_iotlb_gather {
  *                      driver init to device driver init (default no)
  * @dev_enable/disable_feat: per device entries to enable/disable
  *                               iommu specific features.
+ * @set/unset_rid_user: per device entries to set/unset user space Request ID
  * @page_response: handle page request response
  * @def_domain_type: device default domain type, return value:
  *		- IOMMU_DOMAIN_IDENTITY: must use an identity domain
@@ -291,6 +292,9 @@ struct iommu_ops {
 	int (*dev_enable_feat)(struct device *dev, enum iommu_dev_features f);
 	int (*dev_disable_feat)(struct device *dev, enum iommu_dev_features f);
 
+	int (*set_rid_user)(struct device *dev, u32 rid, u32 rid_base);
+	int (*unset_rid_user)(struct device *dev);
+
 	int (*page_response)(struct device *dev,
 			     struct iommu_fault_event *evt,
 			     struct iommu_page_response *msg);
-- 
2.40.0


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH RFC v1 2/3] iommufd: Add IOMMUFD_CMD_DEVICE_SET_RID and IOMMUFD_CMD_DEVICE_UNSET_RID
  2023-04-06  6:25 [PATCH RFC v1 0/3] Add set_rid_user and unset_rid_user support Nicolin Chen
  2023-04-06  6:25 ` [PATCH RFC v1 1/3] iommu: Add set/unset_rid_user ops Nicolin Chen
@ 2023-04-06  6:25 ` Nicolin Chen
  2023-04-06  6:25 ` [PATCH RFC v1 3/3] iommu/arm-smmu-v3: Implement set_rid_user and unset_rid_user Nicolin Chen
  2 siblings, 0 replies; 4+ messages in thread
From: Nicolin Chen @ 2023-04-06  6:25 UTC (permalink / raw)
  To: jgg, robin.murphy, kevin.tian
  Cc: eric.auger, yi.l.liu, baolu.lu, will, joro,
	shameerali.kolothum.thodi, jean-philippe, linux-arm-kernel, iommu,
	linux-kernel

Add a new pair of ioctls to allow user space to set user space Request ID
for a passthrough PCI device. This is to create a link between a physical
RID and a virtual RID in the IOMMU driver that cares.

Signed-off-by: Nicolin Chen <nicolinc@nvidia.com>
---
 drivers/iommu/iommufd/device.c          | 39 +++++++++++++++++++++++++
 drivers/iommu/iommufd/iommufd_private.h |  2 ++
 drivers/iommu/iommufd/main.c            |  4 +++
 include/uapi/linux/iommufd.h            | 31 ++++++++++++++++++++
 4 files changed, 76 insertions(+)

diff --git a/drivers/iommu/iommufd/device.c b/drivers/iommu/iommufd/device.c
index 207b0e3fd9c8..db756e5cd77b 100644
--- a/drivers/iommu/iommufd/device.c
+++ b/drivers/iommu/iommufd/device.c
@@ -735,6 +735,45 @@ void iommufd_device_detach(struct iommufd_device *idev)
 }
 EXPORT_SYMBOL_NS_GPL(iommufd_device_detach, IOMMUFD);
 
+int iommufd_device_set_rid(struct iommufd_ucmd *ucmd)
+{
+	struct iommufd_device_set_rid *cmd = ucmd->cmd;
+	struct iommufd_device *idev;
+	const struct iommu_ops *ops;
+	int rc = 0;
+
+	if (!cmd->rid)
+		return -EINVAL;
+
+	idev = iommufd_get_device(ucmd, cmd->dev_id);
+	if (IS_ERR(idev))
+		return PTR_ERR(idev);
+
+	ops = dev_iommu_ops(idev->dev);
+	if (ops && ops->set_rid_user)
+		rc = ops->set_rid_user(idev->dev, cmd->rid, cmd->rid_base);
+	iommufd_put_object(&idev->obj);
+	return rc;
+}
+
+int iommufd_device_unset_rid(struct iommufd_ucmd *ucmd)
+{
+	struct iommufd_device_unset_rid *cmd = ucmd->cmd;
+	struct iommufd_device *idev;
+	const struct iommu_ops *ops;
+	int rc = 0;
+
+	idev = iommufd_get_device(ucmd, cmd->dev_id);
+	if (IS_ERR(idev))
+		return PTR_ERR(idev);
+
+	ops = dev_iommu_ops(idev->dev);
+	if (ops && ops->unset_rid_user)
+		rc = ops->unset_rid_user(idev->dev);
+	iommufd_put_object(&idev->obj);
+	return rc;
+}
+
 void iommufd_access_destroy_object(struct iommufd_object *obj)
 {
 	struct iommufd_access *access =
diff --git a/drivers/iommu/iommufd/iommufd_private.h b/drivers/iommu/iommufd/iommufd_private.h
index e52fd9d8c160..d65617727c0c 100644
--- a/drivers/iommu/iommufd/iommufd_private.h
+++ b/drivers/iommu/iommufd/iommufd_private.h
@@ -320,6 +320,8 @@ iommufd_get_device(struct iommufd_ucmd *ucmd, u32 id)
 
 void iommufd_device_destroy(struct iommufd_object *obj);
 int iommufd_device_get_hw_info(struct iommufd_ucmd *ucmd);
+int iommufd_device_set_rid(struct iommufd_ucmd *ucmd);
+int iommufd_device_unset_rid(struct iommufd_ucmd *ucmd);
 
 extern const u64 iommufd_hwpt_type_bitmaps[];
 
diff --git a/drivers/iommu/iommufd/main.c b/drivers/iommu/iommufd/main.c
index 7ec3ceac01b3..113fac4d4de0 100644
--- a/drivers/iommu/iommufd/main.c
+++ b/drivers/iommu/iommufd/main.c
@@ -317,6 +317,10 @@ static const struct iommufd_ioctl_op iommufd_ioctl_ops[] = {
 		 val64),
 	IOCTL_OP(IOMMU_VFIO_IOAS, iommufd_vfio_ioas, struct iommu_vfio_ioas,
 		 __reserved),
+	IOCTL_OP(IOMMU_DEVICE_SET_RID, iommufd_device_set_rid,
+		 struct iommufd_device_set_rid, rid_base),
+	IOCTL_OP(IOMMU_DEVICE_UNSET_RID, iommufd_device_unset_rid,
+		 struct iommufd_device_unset_rid, dev_id),
 #ifdef CONFIG_IOMMUFD_TEST
 	IOCTL_OP(IOMMU_TEST_CMD, iommufd_test, struct iommu_test_cmd, last),
 #endif
diff --git a/include/uapi/linux/iommufd.h b/include/uapi/linux/iommufd.h
index 59a44ceff27d..5188a4318e22 100644
--- a/include/uapi/linux/iommufd.h
+++ b/include/uapi/linux/iommufd.h
@@ -48,6 +48,8 @@ enum {
 	IOMMUFD_CMD_HWPT_ALLOC,
 	IOMMUFD_CMD_DEVICE_GET_HW_INFO,
 	IOMMUFD_CMD_HWPT_INVALIDATE,
+	IOMMUFD_CMD_DEVICE_SET_RID,
+	IOMMUFD_CMD_DEVICE_UNSET_RID,
 };
 
 /**
@@ -482,4 +484,33 @@ struct iommu_hwpt_invalidate {
 	__aligned_u64 data_uptr;
 };
 #define IOMMU_HWPT_INVALIDATE _IO(IOMMUFD_TYPE, IOMMUFD_CMD_HWPT_INVALIDATE)
+
+/**
+ * struct iommufd_device_set_rid - ioctl(IOMMU_DEVICE_SET_RID)
+ * @size: sizeof(struct iommufd_device_set_rid)
+ * @dev_id: The device to set a Request ID
+ * @rid: PCI Request ID
+ *       Bits [15:8] are the Bus number.
+ *       Bits [7:3] are the Device number.
+ *       Bits [2:0] are the Function number.
+ * @rid_base: Base ID to map PCI Request ID
+ */
+struct iommufd_device_set_rid {
+	__u32 size;
+	__u32 dev_id;
+	__u32 rid;
+	__u32 rid_base;
+};
+#define IOMMU_DEVICE_SET_RID _IO(IOMMUFD_TYPE, IOMMUFD_CMD_DEVICE_SET_RID)
+
+/**
+ * struct iommufd_device_unset_rid - ioctl(IOMMU_DEVICE_UNSET_RID)
+ * @size: sizeof(struct iommufd_device_unset_rid)
+ * @dev_id: The device to unset a Request ID
+ */
+struct iommufd_device_unset_rid {
+	__u32 size;
+	__u32 dev_id;
+};
+#define IOMMU_DEVICE_UNSET_RID _IO(IOMMUFD_TYPE, IOMMUFD_CMD_DEVICE_UNSET_RID)
 #endif
-- 
2.40.0


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH RFC v1 3/3] iommu/arm-smmu-v3: Implement set_rid_user and unset_rid_user
  2023-04-06  6:25 [PATCH RFC v1 0/3] Add set_rid_user and unset_rid_user support Nicolin Chen
  2023-04-06  6:25 ` [PATCH RFC v1 1/3] iommu: Add set/unset_rid_user ops Nicolin Chen
  2023-04-06  6:25 ` [PATCH RFC v1 2/3] iommufd: Add IOMMUFD_CMD_DEVICE_SET_RID and IOMMUFD_CMD_DEVICE_UNSET_RID Nicolin Chen
@ 2023-04-06  6:25 ` Nicolin Chen
  2 siblings, 0 replies; 4+ messages in thread
From: Nicolin Chen @ 2023-04-06  6:25 UTC (permalink / raw)
  To: jgg, robin.murphy, kevin.tian
  Cc: eric.auger, yi.l.liu, baolu.lu, will, joro,
	shameerali.kolothum.thodi, jean-philippe, linux-arm-kernel, iommu,
	linux-kernel

Implement the new set_rid_user and unset_rid_user ops, by using an xarray
to store the stream pointer indexed by a given user space Stream ID. This
will be used by user cache invalidation hypercall, to check the SID field
of an ATC_INV command and replace it with the corresponding physical SID.

Signed-off-by: Nicolin Chen <nicolinc@nvidia.com>
---
 drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c | 45 +++++++++++++++++++++
 drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h |  2 +
 2 files changed, 47 insertions(+)

diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
index f2425b0f0cd6..17bb90e78547 100644
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
@@ -2843,6 +2843,48 @@ static void arm_smmu_remove_dev_pasid(struct device *dev, ioasid_t pasid)
 	arm_smmu_sva_remove_dev_pasid(domain, dev, pasid);
 }
 
+static int arm_smmu_set_rid_user(struct device *dev, u32 rid, u32 rid_base)
+{
+	struct arm_smmu_master *master = dev_iommu_priv_get(dev);
+	struct arm_smmu_stream *stream = &master->streams[0];
+	struct arm_smmu_device *smmu = master->smmu;
+	u32 sid_user = rid_base | rid;
+	int ret = 0;
+
+	if (!sid_user)
+		return -EINVAL;
+
+	ret = xa_alloc(&smmu->streams_user, &sid_user, stream,
+			XA_LIMIT(sid_user, sid_user), GFP_KERNEL_ACCOUNT);
+	if (ret)
+		return ret;
+	stream->id_user = sid_user;
+	return 0;
+}
+
+static int arm_smmu_unset_rid_user(struct device *dev)
+{
+	struct arm_smmu_master *master = dev_iommu_priv_get(dev);
+	struct arm_smmu_stream *stream = &master->streams[0];
+	struct arm_smmu_device *smmu = master->smmu;
+	u32 sid_user = stream->id_user;
+
+	if (!sid_user)
+		return -ENODEV;
+
+	xa_lock(&smmu->streams_user);
+	stream = __xa_erase(&smmu->streams_user, sid_user);
+	if (stream != master->streams) {
+		WARN_ON(__xa_alloc(&smmu->streams_user, &sid_user, stream,
+				   XA_LIMIT(sid_user, sid_user),
+				   GFP_KERNEL_ACCOUNT));
+		xa_unlock(&smmu->streams_user);
+		return -EINVAL;
+	}
+	xa_unlock(&smmu->streams_user);
+	return 0;
+}
+
 static struct iommu_ops arm_smmu_ops = {
 	.capable		= arm_smmu_capable,
 	.domain_alloc		= arm_smmu_domain_alloc,
@@ -2854,6 +2896,8 @@ static struct iommu_ops arm_smmu_ops = {
 	.remove_dev_pasid	= arm_smmu_remove_dev_pasid,
 	.dev_enable_feat	= arm_smmu_dev_enable_feature,
 	.dev_disable_feat	= arm_smmu_dev_disable_feature,
+	.set_rid_user		= arm_smmu_set_rid_user,
+	.unset_rid_user		= arm_smmu_unset_rid_user,
 	.page_response		= arm_smmu_page_response,
 	.def_domain_type	= arm_smmu_def_domain_type,
 	.pgsize_bitmap		= -1UL, /* Restricted during device attach */
@@ -3082,6 +3126,7 @@ static int arm_smmu_init_structures(struct arm_smmu_device *smmu)
 
 	mutex_init(&smmu->streams_mutex);
 	smmu->streams = RB_ROOT;
+	xa_init_flags(&smmu->streams_user, XA_FLAGS_ALLOC1 | XA_FLAGS_ACCOUNT);
 
 	ret = arm_smmu_init_queues(smmu);
 	if (ret)
diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
index 8d772ea8a583..8ccea2e84bbb 100644
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
@@ -674,10 +674,12 @@ struct arm_smmu_device {
 
 	struct rb_root			streams;
 	struct mutex			streams_mutex;
+	struct xarray			streams_user;
 };
 
 struct arm_smmu_stream {
 	u32				id;
+	u32				id_user;
 	struct arm_smmu_master		*master;
 	struct rb_node			node;
 };
-- 
2.40.0


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

end of thread, other threads:[~2023-04-06  6:27 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2023-04-06  6:25 [PATCH RFC v1 0/3] Add set_rid_user and unset_rid_user support Nicolin Chen
2023-04-06  6:25 ` [PATCH RFC v1 1/3] iommu: Add set/unset_rid_user ops Nicolin Chen
2023-04-06  6:25 ` [PATCH RFC v1 2/3] iommufd: Add IOMMUFD_CMD_DEVICE_SET_RID and IOMMUFD_CMD_DEVICE_UNSET_RID Nicolin Chen
2023-04-06  6:25 ` [PATCH RFC v1 3/3] iommu/arm-smmu-v3: Implement set_rid_user and unset_rid_user Nicolin Chen

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).