[PATCH v2 3/3] iommufd/vdevice: add TSM guest request ioctl

Aneesh Kumar K.V (Arm) posted 3 patches 1 month ago
[PATCH v2 3/3] iommufd/vdevice: add TSM guest request ioctl
Posted by Aneesh Kumar K.V (Arm) 1 month ago
Add IOMMU_VDEVICE_TSM_GUEST_REQUEST for issuing TSM guest request/response
transactions against an iommufd vdevice.

The ioctl takes a vdevice_id plus request/response user buffers and length
fields, and forwards the request through tsm_guest_req() to the PCI TSM
backend. This provides the host-side passthrough path used by CoCo guests
for TSM device attestation and acceptance flows after the device has been
bound to TSM.

Also add the supporting tsm_guest_req() helper and associated TSM core
interface definitions.

Based on changes from: Alexey Kardashevskiy <aik@amd.com>

Cc: Kevin Tian <kevin.tian@intel.com>
Cc: Joerg Roedel <joro@8bytes.org>
Cc: Will Deacon <will@kernel.org>
Cc: Bjorn Helgaas <helgaas@kernel.org>
Cc: Jonathan Cameron <Jonathan.Cameron@huawei.com>
Cc: Dan Williams <dan.j.williams@intel.com>
Cc: Alexey Kardashevskiy <aik@amd.com>
Cc: Samuel Ortiz <sameo@rivosinc.com>
Cc: Xu Yilun <yilun.xu@linux.intel.com>
Cc: Jason Gunthorpe <jgg@ziepe.ca>
Cc: Suzuki K Poulose <Suzuki.Poulose@arm.com>
Cc: Steven Price <steven.price@arm.com>
Signed-off-by: Aneesh Kumar K.V (Arm) <aneesh.kumar@kernel.org>
---
 drivers/iommu/iommufd/iommufd_private.h |  7 ++++
 drivers/iommu/iommufd/main.c            |  3 ++
 drivers/iommu/iommufd/tsm.c             | 48 +++++++++++++++++++++++++
 drivers/virt/coco/tsm-core.c            | 14 ++++++++
 include/linux/tsm.h                     | 26 ++++++++++++++
 include/uapi/linux/iommufd.h            | 23 ++++++++++++
 6 files changed, 121 insertions(+)

diff --git a/drivers/iommu/iommufd/iommufd_private.h b/drivers/iommu/iommufd/iommufd_private.h
index aa1ceed924c2..7042993913dd 100644
--- a/drivers/iommu/iommufd/iommufd_private.h
+++ b/drivers/iommu/iommufd/iommufd_private.h
@@ -699,11 +699,18 @@ int iommufd_hw_queue_alloc_ioctl(struct iommufd_ucmd *ucmd);
 void iommufd_hw_queue_destroy(struct iommufd_object *obj);
 #ifdef CONFIG_TSM
 int iommufd_vdevice_tsm_op_ioctl(struct iommufd_ucmd *ucmd);
+int iommufd_vdevice_tsm_guest_request_ioctl(struct iommufd_ucmd *ucmd);
 #else
 static inline int iommufd_vdevice_tsm_op_ioctl(struct iommufd_ucmd *ucmd)
 {
 	return -EOPNOTSUPP;
 }
+
+static inline int
+iommufd_vdevice_tsm_guest_request_ioctl(struct iommufd_ucmd *ucmd)
+{
+	return -EOPNOTSUPP;
+}
 #endif
 
 static inline struct iommufd_vdevice *
diff --git a/drivers/iommu/iommufd/main.c b/drivers/iommu/iommufd/main.c
index d73e6b391c6f..7f4bbdd0bda5 100644
--- a/drivers/iommu/iommufd/main.c
+++ b/drivers/iommu/iommufd/main.c
@@ -433,6 +433,7 @@ union ucmd_buffer {
 	struct iommu_vfio_ioas vfio_ioas;
 	struct iommu_viommu_alloc viommu;
 	struct iommu_vdevice_tsm_op tsm_op;
+	struct iommu_vdevice_tsm_guest_request gr;
 #ifdef CONFIG_IOMMUFD_TEST
 	struct iommu_test_cmd test;
 #endif
@@ -496,6 +497,8 @@ static const struct iommufd_ioctl_op iommufd_ioctl_ops[] = {
 		 struct iommu_viommu_alloc, out_viommu_id),
 	IOCTL_OP(IOMMU_VDEVICE_TSM_OP, iommufd_vdevice_tsm_op_ioctl,
 		 struct iommu_vdevice_tsm_op, vdevice_id),
+	IOCTL_OP(IOMMU_VDEVICE_TSM_GUEST_REQUEST, iommufd_vdevice_tsm_guest_request_ioctl,
+		 struct iommu_vdevice_tsm_guest_request, resp_uptr),
 #ifdef CONFIG_IOMMUFD_TEST
 	IOCTL_OP(IOMMU_TEST_CMD, iommufd_test, struct iommu_test_cmd, last),
 #endif
diff --git a/drivers/iommu/iommufd/tsm.c b/drivers/iommu/iommufd/tsm.c
index 401469110752..6b96d0aef25f 100644
--- a/drivers/iommu/iommufd/tsm.c
+++ b/drivers/iommu/iommufd/tsm.c
@@ -65,3 +65,51 @@ int iommufd_vdevice_tsm_op_ioctl(struct iommufd_ucmd *ucmd)
 	iommufd_put_object(ucmd->ictx, &vdev->obj);
 	return rc;
 }
+
+/**
+ * iommufd_vdevice_tsm_guest_request_ioctl - Forward guest TSM requests
+ * @ucmd: user command data for IOMMU_VDEVICE_TSM_GUEST_REQUEST
+ *
+ * Resolve @iommu_vdevice_tsm_guest_request::vdevice_id to a vdevice and pass
+ * the request/response buffers to the TSM core.
+ *
+ * Return:
+ *  -errno on error.
+ *  positive residue if response/request bytes were left unconsumed.
+ *    if response buffer is provided, residue indicates the number of bytes
+ *    not used in response buffer
+ *    if there is no response buffer, residue indicates the number of bytes
+ *    not consumed in req buffer
+ *  0 otherwise.
+ */
+int iommufd_vdevice_tsm_guest_request_ioctl(struct iommufd_ucmd *ucmd)
+{
+	int rc;
+	struct iommufd_vdevice *vdev;
+	struct iommu_vdevice_tsm_guest_request *cmd = ucmd->cmd;
+	struct tsm_guest_req_info info = {
+		.scope = cmd->scope,
+		.req   = {
+			.user = u64_to_user_ptr(cmd->req_uptr),
+			.is_kernel = false,
+		},
+		.req_len = cmd->req_len,
+		.resp    =  {
+			.user = u64_to_user_ptr(cmd->resp_uptr),
+			.is_kernel = false,
+		},
+		.resp_len = cmd->resp_len,
+	};
+
+	vdev = container_of(iommufd_get_object(ucmd->ictx, cmd->vdevice_id,
+					       IOMMUFD_OBJ_VDEVICE),
+			    struct iommufd_vdevice, obj);
+	if (IS_ERR(vdev))
+		return PTR_ERR(vdev);
+
+	rc = tsm_guest_req(vdev->idev->dev, &info);
+
+	/* No inline response, hence we don't need to copy the response */
+	iommufd_put_object(ucmd->ictx, &vdev->obj);
+	return rc;
+}
diff --git a/drivers/virt/coco/tsm-core.c b/drivers/virt/coco/tsm-core.c
index f0e35fc38776..317fcb53e4bf 100644
--- a/drivers/virt/coco/tsm-core.c
+++ b/drivers/virt/coco/tsm-core.c
@@ -259,6 +259,20 @@ int tsm_unbind(struct device *dev)
 }
 EXPORT_SYMBOL_GPL(tsm_unbind);
 
+ssize_t tsm_guest_req(struct device *dev, struct tsm_guest_req_info *info)
+{
+	ssize_t ret;
+
+	if (!dev_is_pci(dev))
+		return -EINVAL;
+
+	ret = pci_tsm_guest_req(to_pci_dev(dev), info->scope,
+				info->req, info->req_len,
+				info->resp, info->resp_len, NULL);
+	return ret;
+}
+EXPORT_SYMBOL_GPL(tsm_guest_req);
+
 static void tsm_release(struct device *dev)
 {
 	struct tsm_dev *tsm_dev = container_of(dev, typeof(*tsm_dev), dev);
diff --git a/include/linux/tsm.h b/include/linux/tsm.h
index 9f2a7868021a..5231d5abf84d 100644
--- a/include/linux/tsm.h
+++ b/include/linux/tsm.h
@@ -6,6 +6,7 @@
 #include <linux/types.h>
 #include <linux/uuid.h>
 #include <linux/device.h>
+#include <linux/sockptr.h>
 
 #define TSM_REPORT_INBLOB_MAX 64
 #define TSM_REPORT_OUTBLOB_MAX SZ_16M
@@ -131,6 +132,24 @@ void tsm_ide_stream_unregister(struct pci_ide *ide);
 int tsm_bind(struct device *dev, struct kvm *kvm, u64 tdi_id);
 int tsm_unbind(struct device *dev);
 
+/**
+ * struct tsm_guest_req_info - parameter for tsm_guest_req()
+ * @scope: scope for tsm guest request
+ * @req: request data buffer filled by guest
+ * @req_len: the size of @req filled by guest
+ * @resp: response data buffer filled by host
+ * @resp_len: for input, the size of @resp buffer filled by guest
+ *	      for output, the size of actual response data filled by host
+ */
+struct tsm_guest_req_info {
+	u32 scope;
+	sockptr_t req;
+	size_t req_len;
+	sockptr_t resp;
+	size_t resp_len;
+};
+ssize_t tsm_guest_req(struct device *dev, struct tsm_guest_req_info *info);
+
 #else
 
 static inline int tsm_bind(struct device *dev, struct kvm *kvm, u64 tdi_id)
@@ -142,6 +161,13 @@ static inline int tsm_unbind(struct device *dev)
 {
 	return 0;
 }
+
+struct tsm_guest_req_info;
+static inline ssize_t tsm_guest_req(struct device *dev,
+				    struct tsm_guest_req_info *info)
+{
+	return -EINVAL;
+}
 #endif
 
 #endif /* __TSM_H */
diff --git a/include/uapi/linux/iommufd.h b/include/uapi/linux/iommufd.h
index 653402e7048a..b0d1ecd81638 100644
--- a/include/uapi/linux/iommufd.h
+++ b/include/uapi/linux/iommufd.h
@@ -58,6 +58,7 @@ enum {
 	IOMMUFD_CMD_VEVENTQ_ALLOC = 0x93,
 	IOMMUFD_CMD_HW_QUEUE_ALLOC = 0x94,
 	IOMMUFD_CMD_VDEVICE_TSM_OP = 0x95,
+	IOMMUFD_CMD_VDEVICE_TSM_GUEST_REQUEST = 0x96,
 };
 
 /**
@@ -1367,4 +1368,26 @@ struct iommu_hw_queue_alloc {
 	__aligned_u64 length;
 };
 #define IOMMU_HW_QUEUE_ALLOC _IO(IOMMUFD_TYPE, IOMMUFD_CMD_HW_QUEUE_ALLOC)
+
+/**
+ * struct iommu_vdevice_tsm_guest_request - ioctl(IOMMU_VDEVICE_TSM_GUEST_REQUEST)
+ * @size: sizeof(struct iommu_vdevice_tsm_guest_request)
+ * @vdevice_id: vDevice ID the guest request is for
+ * @scope: scope of tsm guest request
+ * @req_len: the blob size for @req_uptr, filled by guest
+ * @resp_len: the blob size for @resp_uptr, filled by guest
+ * @req_uptr: request data buffer filled by guest
+ * @resp_uptr: response data buffer
+ */
+struct iommu_vdevice_tsm_guest_request {
+	__u32 size;
+	__u32 vdevice_id;
+	__u32 scope;
+	__u32 req_len;
+	__u32 resp_len;
+	__aligned_u64 req_uptr;
+	__aligned_u64 resp_uptr;
+};
+#define IOMMU_VDEVICE_TSM_GUEST_REQUEST _IO(IOMMUFD_TYPE, IOMMUFD_CMD_VDEVICE_TSM_GUEST_REQUEST)
+
 #endif
-- 
2.43.0
RE: [PATCH v2 3/3] iommufd/vdevice: add TSM guest request ioctl
Posted by Tian, Kevin 3 weeks, 3 days ago
> From: Aneesh Kumar K.V (Arm) <aneesh.kumar@kernel.org>
> Sent: Monday, March 9, 2026 7:17 PM
> 
> Add IOMMU_VDEVICE_TSM_GUEST_REQUEST for issuing TSM guest
> request/response
> transactions against an iommufd vdevice.

Does adding '_GUEST_' in the name give any meaningful context?
It's a transparent interface connecting to tsm. why do we care
whether this request actually comes from guest or from the VMM
itself? will there be a TSM_HOST_REQUEST in the future?

I know this has been made this way in many places in this path.
but from uapi p.o.v. let's stick to the minimal required naming.

> 
> The ioctl takes a vdevice_id plus request/response user buffers and length
> fields, and forwards the request through tsm_guest_req() to the PCI TSM
> backend. This provides the host-side passthrough path used by CoCo guests
> for TSM device attestation and acceptance flows after the device has been
> bound to TSM.

tsm cores use "TVM". let's be consistent here (regarding to 'CoCo guests')
Re: [PATCH v2 3/3] iommufd/vdevice: add TSM guest request ioctl
Posted by Jason Gunthorpe 3 weeks, 5 days ago
On Mon, Mar 09, 2026 at 04:47:04PM +0530, Aneesh Kumar K.V (Arm) wrote:
> +/**
> + * struct iommu_vdevice_tsm_guest_request - ioctl(IOMMU_VDEVICE_TSM_GUEST_REQUEST)
> + * @size: sizeof(struct iommu_vdevice_tsm_guest_request)
> + * @vdevice_id: vDevice ID the guest request is for
> + * @scope: scope of tsm guest request
> + * @req_len: the blob size for @req_uptr, filled by guest
> + * @resp_len: the blob size for @resp_uptr, filled by guest
> + * @req_uptr: request data buffer filled by guest
> + * @resp_uptr: response data buffer
> + */

This needs a much better kdoc.

Refer to specs that define this.

Explain WTF scope is

> +struct iommu_vdevice_tsm_guest_request {
> +	__u32 size;
> +	__u32 vdevice_id;
> +	__u32 scope;
> +	__u32 req_len;
> +	__u32 resp_len;

do not leave implicit padding, add a reserved, and check it is 0

Jason
Re: [PATCH v2 3/3] iommufd/vdevice: add TSM guest request ioctl
Posted by Aneesh Kumar K.V 3 weeks, 3 days ago
Jason Gunthorpe <jgg@ziepe.ca> writes:

> On Mon, Mar 09, 2026 at 04:47:04PM +0530, Aneesh Kumar K.V (Arm) wrote:
>> +/**
>> + * struct iommu_vdevice_tsm_guest_request - ioctl(IOMMU_VDEVICE_TSM_GUEST_REQUEST)
>> + * @size: sizeof(struct iommu_vdevice_tsm_guest_request)
>> + * @vdevice_id: vDevice ID the guest request is for
>> + * @scope: scope of tsm guest request
>> + * @req_len: the blob size for @req_uptr, filled by guest
>> + * @resp_len: the blob size for @resp_uptr, filled by guest
>> + * @req_uptr: request data buffer filled by guest
>> + * @resp_uptr: response data buffer
>> + */
>
> This needs a much better kdoc.
>
> Refer to specs that define this.
>
> Explain WTF scope is
>
>> +struct iommu_vdevice_tsm_guest_request {
>> +	__u32 size;
>> +	__u32 vdevice_id;
>> +	__u32 scope;
>> +	__u32 req_len;
>> +	__u32 resp_len;
>
> do not leave implicit padding, add a reserved, and check it is 0
>
> Jason
 
How about this change?

modified   drivers/iommu/iommufd/tsm.c
@@ -94,6 +94,9 @@ int iommufd_vdevice_tsm_guest_request_ioctl(struct iommufd_ucmd *ucmd)
 		.resp_len = cmd->resp_len,
 	};
 
+	if (cmd->__reserved)
+		return -EOPNOTSUPP;
+
 	vdev = iommufd_get_vdevice(ucmd->ictx, cmd->vdevice_id);
 	if (IS_ERR(vdev))
 		return PTR_ERR(vdev);
modified   include/uapi/linux/iommufd.h
@@ -1370,11 +1370,27 @@ struct iommu_hw_queue_alloc {
  * struct iommu_vdevice_tsm_guest_request - ioctl(IOMMU_VDEVICE_TSM_GUEST_REQUEST)
  * @size: sizeof(struct iommu_vdevice_tsm_guest_request)
  * @vdevice_id: vDevice ID the guest request is for
- * @scope: scope of tsm guest request
- * @req_len: the blob size for @req_uptr, filled by guest
- * @resp_len: the blob size for @resp_uptr, filled by guest
- * @req_uptr: request data buffer filled by guest
- * @resp_uptr: response data buffer
+ * @scope: Scope classification of the guest request, one of enum
+ *         pci_tsm_req_scope values accepted by pci_tsm_guest_req()
+ * @req_len: Size in bytes of the input payload at @req_uptr
+ * @resp_len: Size in bytes of the output buffer at @resp_uptr
+ * @__reserved: Must be 0
+ * @req_uptr: Userspace pointer to the guest-provided request payload
+ * @resp_uptr: Userspace pointer to the guest response buffer
+ *
+ * Forward a guest request to the TSM bound vDevice. This is intended for
+ * guest TSM/TDISP message transport where the host kernel only marshals
+ * bytes between userspace and the TSM implementation.
+ *
+ * @scope limits requests to TDISP state management, or limited debug.
+ * Requests outside the allowed scope are rejected.
+ *
+ * The request payload is read from @req_uptr/@req_len. If a response is
+ * expected, userspace provides @resp_uptr/@resp_len as writable storage for
+ * response bytes returned by the TSM path.
+ *
+ * The ioctl is only suitable for commands and results that the host kernel
+ * has no use, the host is only facilitating guest to TSM communication.
  */
 struct iommu_vdevice_tsm_guest_request {
 	__u32 size;
@@ -1382,6 +1398,7 @@ struct iommu_vdevice_tsm_guest_request {
 	__u32 scope;
 	__u32 req_len;
 	__u32 resp_len;
+	__u32 __reserved;
 	__aligned_u64 req_uptr;
 	__aligned_u64 resp_uptr;
 };
RE: [PATCH v2 3/3] iommufd/vdevice: add TSM guest request ioctl
Posted by Tian, Kevin 3 weeks, 3 days ago
> From: Aneesh Kumar K.V <aneesh.kumar@kernel.org>
> Sent: Monday, March 16, 2026 1:48 PM
> + * @scope: Scope classification of the guest request, one of enum
> + *         pci_tsm_req_scope values accepted by pci_tsm_guest_req()

from what this patch does the tsm core supports device types other
than PCI (though currently only PCI is supported).

suppose there may be other bus-specific scope values accepted?

if yes here better say that for the meaning of scope values please
refer to bus specific tsm definitions. Then in the following detailed
description take PCI as an example referring to pci_tsm_req_scope. 
Re: [PATCH v2 3/3] iommufd/vdevice: add TSM guest request ioctl
Posted by Dan Williams 3 weeks, 5 days ago
Jason Gunthorpe wrote:
> On Mon, Mar 09, 2026 at 04:47:04PM +0530, Aneesh Kumar K.V (Arm) wrote:
> > +/**
> > + * struct iommu_vdevice_tsm_guest_request - ioctl(IOMMU_VDEVICE_TSM_GUEST_REQUEST)
> > + * @size: sizeof(struct iommu_vdevice_tsm_guest_request)
> > + * @vdevice_id: vDevice ID the guest request is for
> > + * @scope: scope of tsm guest request
> > + * @req_len: the blob size for @req_uptr, filled by guest
> > + * @resp_len: the blob size for @resp_uptr, filled by guest
> > + * @req_uptr: request data buffer filled by guest
> > + * @resp_uptr: response data buffer
> > + */
> 
> This needs a much better kdoc.
> 
> Refer to specs that define this.
> 
> Explain WTF scope is

I proposed @scope, yes this needs more documentation, but really it
needs more discussion first. It was inspired by 'enum fwctl_rpc_scope'

Guests that are moving the device through the TDISP setup state machine
need to ask for host services because only the host passes messages over
SPDM in all of these architectures. That is, one SPDM session per
physical device, not per assigned virtual function. In the AMD case
there is less guest direct access to the TSM so it needs to pass
additional messages that the CPU mode based TSMs do not.

Those requests are varying degrees of: host kernel cares, host kernel
does not care but can see the contents of the message, and host kernel
does not care and can not see the contents of the message beyond
envelope.

As far as the host kernel security model is concerned this becomes a
opaque implementation specific passthrough. So the role of @scope is to
have the TSM drivers declare the security model for various messages.
Put the explicit onus on the implmentations to declare that the
guest_request operation being executed in response to a KVM exit is
contained within a given security scope. See 'enum pci_tsm_req_scope'.
RE: [PATCH v2 3/3] iommufd/vdevice: add TSM guest request ioctl
Posted by Tian, Kevin 3 weeks, 3 days ago
> From: Williams, Dan J <dan.j.williams@intel.com>
> Sent: Saturday, March 14, 2026 6:18 AM
> 
> Jason Gunthorpe wrote:
> > On Mon, Mar 09, 2026 at 04:47:04PM +0530, Aneesh Kumar K.V (Arm)
> wrote:
> > > +/**
> > > + * struct iommu_vdevice_tsm_guest_request -
> ioctl(IOMMU_VDEVICE_TSM_GUEST_REQUEST)
> > > + * @size: sizeof(struct iommu_vdevice_tsm_guest_request)
> > > + * @vdevice_id: vDevice ID the guest request is for
> > > + * @scope: scope of tsm guest request
> > > + * @req_len: the blob size for @req_uptr, filled by guest
> > > + * @resp_len: the blob size for @resp_uptr, filled by guest
> > > + * @req_uptr: request data buffer filled by guest
> > > + * @resp_uptr: response data buffer
> > > + */
> >
> > This needs a much better kdoc.
> >
> > Refer to specs that define this.
> >
> > Explain WTF scope is
> 
> I proposed @scope, yes this needs more documentation, but really it
> needs more discussion first. It was inspired by 'enum fwctl_rpc_scope'
> 
> Guests that are moving the device through the TDISP setup state machine
> need to ask for host services because only the host passes messages over
> SPDM in all of these architectures. That is, one SPDM session per
> physical device, not per assigned virtual function. In the AMD case
> there is less guest direct access to the TSM so it needs to pass
> additional messages that the CPU mode based TSMs do not.
> 
> Those requests are varying degrees of: host kernel cares, host kernel
> does not care but can see the contents of the message, and host kernel
> does not care and can not see the contents of the message beyond
> envelope.

"host kernel cares" means that the host kernel may check CAP_SYS_RAW_IO
or taint itself to limit commands according to the description of
enum pci_tsm_req_scope?

interestingly commit c316c75d57fb ("PCI/TSM: Add pci_tsm_guest_req()
for managing TDIs ") has the following description:

"
    This path is purely a transport for messages from TVM to platform TSM. By
    design the host kernel does not and must not care about the content of
    these messages. I.e. the host kernel is not in the TCB of the TVM.
"

how to associate "must not care" with above "host kernel cares"?

> 
> As far as the host kernel security model is concerned this becomes a
> opaque implementation specific passthrough. So the role of @scope is to
> have the TSM drivers declare the security model for various messages.
> Put the explicit onus on the implmentations to declare that the
> guest_request operation being executed in response to a KVM exit is
> contained within a given security scope. See 'enum pci_tsm_req_scope'.

dumb question - what about a malicious userspace specifies a scope 
with a smaller value than what's defined for a request? Would (could) the
tsm driver verify that it’s a wrong value (but if it can then why we need
this field at all)?
Re: [PATCH v2 3/3] iommufd/vdevice: add TSM guest request ioctl
Posted by Jonathan Cameron 4 weeks ago
On Mon,  9 Mar 2026 16:47:04 +0530
"Aneesh Kumar K.V (Arm)" <aneesh.kumar@kernel.org> wrote:

> Add IOMMU_VDEVICE_TSM_GUEST_REQUEST for issuing TSM guest request/response
> transactions against an iommufd vdevice.
> 
> The ioctl takes a vdevice_id plus request/response user buffers and length
> fields, and forwards the request through tsm_guest_req() to the PCI TSM
> backend. This provides the host-side passthrough path used by CoCo guests
> for TSM device attestation and acceptance flows after the device has been
> bound to TSM.
> 
> Also add the supporting tsm_guest_req() helper and associated TSM core
> interface definitions.
> 
> Based on changes from: Alexey Kardashevskiy <aik@amd.com>

> Signed-off-by: Aneesh Kumar K.V (Arm) <aneesh.kumar@kernel.org>
Minor stuff inline.

thanks,

Jonathan

> diff --git a/drivers/iommu/iommufd/tsm.c b/drivers/iommu/iommufd/tsm.c
> index 401469110752..6b96d0aef25f 100644
> --- a/drivers/iommu/iommufd/tsm.c
> +++ b/drivers/iommu/iommufd/tsm.c
> @@ -65,3 +65,51 @@ int iommufd_vdevice_tsm_op_ioctl(struct iommufd_ucmd *ucmd)
>  	iommufd_put_object(ucmd->ictx, &vdev->obj);
>  	return rc;
>  }
> +
> +/**
> + * iommufd_vdevice_tsm_guest_request_ioctl - Forward guest TSM requests
> + * @ucmd: user command data for IOMMU_VDEVICE_TSM_GUEST_REQUEST
> + *
> + * Resolve @iommu_vdevice_tsm_guest_request::vdevice_id to a vdevice and pass
> + * the request/response buffers to the TSM core.
> + *
> + * Return:
> + *  -errno on error.
> + *  positive residue if response/request bytes were left unconsumed.
> + *    if response buffer is provided, residue indicates the number of bytes
> + *    not used in response buffer
> + *    if there is no response buffer, residue indicates the number of bytes
> + *    not consumed in req buffer
> + *  0 otherwise.
> + */
> +int iommufd_vdevice_tsm_guest_request_ioctl(struct iommufd_ucmd *ucmd)
> +{
> +	int rc;
> +	struct iommufd_vdevice *vdev;
> +	struct iommu_vdevice_tsm_guest_request *cmd = ucmd->cmd;
> +	struct tsm_guest_req_info info = {
> +		.scope = cmd->scope,
> +		.req   = {
> +			.user = u64_to_user_ptr(cmd->req_uptr),
> +			.is_kernel = false,
> +		},
> +		.req_len = cmd->req_len,
> +		.resp    =  {
> +			.user = u64_to_user_ptr(cmd->resp_uptr),
> +			.is_kernel = false,
> +		},
> +		.resp_len = cmd->resp_len,
> +	};
> +
> +	vdev = container_of(iommufd_get_object(ucmd->ictx, cmd->vdevice_id,
> +					       IOMMUFD_OBJ_VDEVICE),

As in previous, can the object be PTR_ERR()?  Maybe not, but I'd
be surprised if the static analysis tools are convinced.
This might work for now if obj is first element but that's not
elegant or matainable.

> +			    struct iommufd_vdevice, obj);
> +	if (IS_ERR(vdev))
> +		return PTR_ERR(vdev);
> +
> +	rc = tsm_guest_req(vdev->idev->dev, &info);

This is otherwise effectively the pattern I'm suggesting for previous patch.

> +
> +	/* No inline response, hence we don't need to copy the response */
> +	iommufd_put_object(ucmd->ictx, &vdev->obj);
> +	return rc;
> +}
> diff --git a/drivers/virt/coco/tsm-core.c b/drivers/virt/coco/tsm-core.c
> index f0e35fc38776..317fcb53e4bf 100644
> --- a/drivers/virt/coco/tsm-core.c
> +++ b/drivers/virt/coco/tsm-core.c
> @@ -259,6 +259,20 @@ int tsm_unbind(struct device *dev)
>  }
>  EXPORT_SYMBOL_GPL(tsm_unbind);
>  
> +ssize_t tsm_guest_req(struct device *dev, struct tsm_guest_req_info *info)
> +{
> +	ssize_t ret;
> +
> +	if (!dev_is_pci(dev))
> +		return -EINVAL;
> +
> +	ret = pci_tsm_guest_req(to_pci_dev(dev), info->scope,
> +				info->req, info->req_len,
> +				info->resp, info->resp_len, NULL);
> +	return ret;

return pci_tsm....

Given there are no more patches in this series that much change that.


> +}
> +EXPORT_SYMBOL_GPL(tsm_guest_req);
Re: [PATCH v2 3/3] iommufd/vdevice: add TSM guest request ioctl
Posted by Jason Gunthorpe 3 weeks, 5 days ago
On Wed, Mar 11, 2026 at 09:43:43PM +0000, Jonathan Cameron wrote:
> > +	vdev = container_of(iommufd_get_object(ucmd->ictx, cmd->vdevice_id,
> > +					       IOMMUFD_OBJ_VDEVICE),
> 
> As in previous, can the object be PTR_ERR()?  Maybe not, but I'd
> be surprised if the static analysis tools are convinced.
> This might work for now if obj is first element but that's not
> elegant or matainable.

The compiler enforces first element:

#define __iommufd_object_alloc(ictx, ptr, type, obj)                           \
        container_of(_iommufd_object_alloc(                                    \
                             ictx,                                             \
                             sizeof(*(ptr)) + BUILD_BUG_ON_ZERO(               \
                                                      offsetof(typeof(*(ptr)), \
                                                               obj) != 0),     \
                             type),                                            \
                     typeof(*(ptr)), obj)

I have a lovely little series 

https://github.com/jgunthorpe/linux/commits/container_of/

For this that I keep meaning to send but then never do

Jason