* Re: [PATCH v7 4/5] vfio/pci: implement get_tph and DMA_BUF_TPH feature [not found] <20260610193158.2614209-5-zhipingz@meta.com> @ 2026-06-11 20:25 ` sashiko-bot 2026-06-11 23:02 ` Zhiping Zhang 0 siblings, 1 reply; 6+ messages in thread From: sashiko-bot @ 2026-06-11 20:25 UTC (permalink / raw) To: Zhiping Zhang; +Cc: linux-pci, kvm, dri-devel Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider: - [Medium] Unconditional validation of the flag-gated 'ph' parameter can lead to spurious -EINVAL errors, breaking the syscall trust boundary. - [Medium] VFIO_DEVICE_FEATURE_PROBE falsely reports that VFIO_DEVICE_FEATURE_DMA_BUF_TPH is supported even if the hardware lacks TPH support. -- commit d57637d667ca6dc95def77a0a5bd339d62d4f506 Author: Zhiping Zhang <zhipingz@meta.com> vfio/pci: implement get_tph and DMA_BUF_TPH feature This commit implements dma-buf get_tph for vfio-pci exported dma-bufs and adds the VFIO_DEVICE_FEATURE_DMA_BUF_TPH feature. This allows userspace to publish TPH metadata for a VFIO-owned device. It checks completer support and protects the metadata under dmabuf->resv. > diff --git a/drivers/vfio/pci/vfio_pci_dmabuf.c b/drivers/vfio/pci/vfio_pci_dmabuf.c > index 1a177ce7de546..0a0705c8dbea6 100644 > --- a/drivers/vfio/pci/vfio_pci_dmabuf.c > +++ b/drivers/vfio/pci/vfio_pci_dmabuf.c [ ... ] > @@ -333,6 +360,71 @@ int vfio_pci_core_feature_dma_buf(struct vfio_pci_core_device *vdev, u32 flags, > return ret; > } > > +int vfio_pci_core_feature_dma_buf_tph(struct vfio_pci_core_device *vdev, > + u32 flags, > + struct vfio_device_feature_dma_buf_tph __user *arg, > + size_t argsz) > +{ > + struct vfio_device_feature_dma_buf_tph set_tph; > + struct vfio_pci_dma_buf *priv; > + struct dma_buf *dmabuf; > + u8 comp; > + int ret; > + > + ret = vfio_check_feature(flags, argsz, VFIO_DEVICE_FEATURE_SET, > + sizeof(set_tph)); > + if (ret != 1) > + return ret; [Severity: Medium] vfio_check_feature() returns 0 for VFIO_DEVICE_FEATURE_PROBE, causing an early return of success. Should the hardware capability check (pcie_tph_completer_type) occur before checking the feature flags, to avoid falsely reporting that the feature is supported on devices that lack TPH? > + > + if (copy_from_user(&set_tph, arg, sizeof(set_tph))) > + return -EFAULT; > + > + if (set_tph.flags & ~(VFIO_DMA_BUF_TPH_ST | VFIO_DMA_BUF_TPH_ST_EXT)) > + return -EINVAL; > + > + if (set_tph.ph & ~0x3) > + return -EINVAL; [Severity: Medium] When userspace clears the TPH metadata by passing flags == 0, is it required to zero-fill the unused ph field? Since this check is unconditional, could stack garbage in the uninitialized ph field cause spurious -EINVAL errors, rejecting a valid invalidation request? > + > + comp = pcie_tph_completer_type(vdev->pdev); > + if (comp == PCI_EXP_DEVCAP2_TPH_COMP_NONE) > + return -EOPNOTSUPP; [ ... ] -- Sashiko AI review · https://sashiko.dev/#/patchset/20260610193158.2614209-1-zhipingz@meta.com?part=4 ^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH v7 4/5] vfio/pci: implement get_tph and DMA_BUF_TPH feature 2026-06-11 20:25 ` [PATCH v7 4/5] vfio/pci: implement get_tph and DMA_BUF_TPH feature sashiko-bot @ 2026-06-11 23:02 ` Zhiping Zhang 2026-06-12 16:59 ` Alex Williamson 0 siblings, 1 reply; 6+ messages in thread From: Zhiping Zhang @ 2026-06-11 23:02 UTC (permalink / raw) To: sashiko-reviews; +Cc: linux-pci, kvm, dri-devel On Thu, Jun 11, 2026 at 1:25 PM <sashiko-bot@kernel.org> wrote: > > > > Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider: > - [Medium] Unconditional validation of the flag-gated 'ph' parameter can lead to spurious -EINVAL errors, breaking the syscall trust boundary. > - [Medium] VFIO_DEVICE_FEATURE_PROBE falsely reports that VFIO_DEVICE_FEATURE_DMA_BUF_TPH is supported even if the hardware lacks TPH support. > -- > > commit d57637d667ca6dc95def77a0a5bd339d62d4f506 > Author: Zhiping Zhang <zhipingz@meta.com> > > vfio/pci: implement get_tph and DMA_BUF_TPH feature > > This commit implements dma-buf get_tph for vfio-pci exported dma-bufs and > adds the VFIO_DEVICE_FEATURE_DMA_BUF_TPH feature. This allows userspace to > publish TPH metadata for a VFIO-owned device. It checks completer support > and protects the metadata under dmabuf->resv. > > > diff --git a/drivers/vfio/pci/vfio_pci_dmabuf.c b/drivers/vfio/pci/vfio_pci_dmabuf.c > > index 1a177ce7de546..0a0705c8dbea6 100644 > > --- a/drivers/vfio/pci/vfio_pci_dmabuf.c > > +++ b/drivers/vfio/pci/vfio_pci_dmabuf.c > > [ ... ] > > > @@ -333,6 +360,71 @@ int vfio_pci_core_feature_dma_buf(struct vfio_pci_core_device *vdev, u32 flags, > > return ret; > > } > > > > +int vfio_pci_core_feature_dma_buf_tph(struct vfio_pci_core_device *vdev, > > + u32 flags, > > + struct vfio_device_feature_dma_buf_tph __user *arg, > > + size_t argsz) > > +{ > > + struct vfio_device_feature_dma_buf_tph set_tph; > > + struct vfio_pci_dma_buf *priv; > > + struct dma_buf *dmabuf; > > + u8 comp; > > + int ret; > > + > > + ret = vfio_check_feature(flags, argsz, VFIO_DEVICE_FEATURE_SET, > > + sizeof(set_tph)); > > + if (ret != 1) > > + return ret; > > [Severity: Medium] > vfio_check_feature() returns 0 for VFIO_DEVICE_FEATURE_PROBE, causing an > early return of success. > > Should the hardware capability check (pcie_tph_completer_type) occur before > checking the feature flags, to avoid falsely reporting that the feature is > supported on devices that lack TPH? > Will fix it with a change like below: - if (ret != 1) + if (ret != 1) { + if (ret == 0 && + pcie_tph_completer_type(vdev->pdev) == + PCI_EXP_DEVCAP2_TPH_COMP_NONE) + return -EOPNOTSUPP; return ret; + } > > + > > + if (copy_from_user(&set_tph, arg, sizeof(set_tph))) > > + return -EFAULT; > > + > > + if (set_tph.flags & ~(VFIO_DMA_BUF_TPH_ST | VFIO_DMA_BUF_TPH_ST_EXT)) > > + return -EINVAL; > > + > > + if (set_tph.ph & ~0x3) > > + return -EINVAL; > > [Severity: Medium] > When userspace clears the TPH metadata by passing flags == 0, is it required > to zero-fill the unused ph field? > Not an issue. ^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH v7 4/5] vfio/pci: implement get_tph and DMA_BUF_TPH feature 2026-06-11 23:02 ` Zhiping Zhang @ 2026-06-12 16:59 ` Alex Williamson 0 siblings, 0 replies; 6+ messages in thread From: Alex Williamson @ 2026-06-12 16:59 UTC (permalink / raw) To: Zhiping Zhang; +Cc: sashiko-reviews, linux-pci, kvm, dri-devel, alex On Thu, 11 Jun 2026 16:02:25 -0700 Zhiping Zhang <zhipingz@meta.com> wrote: > On Thu, Jun 11, 2026 at 1:25 PM <sashiko-bot@kernel.org> wrote: > > > > > > > Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider: > > - [Medium] Unconditional validation of the flag-gated 'ph' parameter can lead to spurious -EINVAL errors, breaking the syscall trust boundary. > > - [Medium] VFIO_DEVICE_FEATURE_PROBE falsely reports that VFIO_DEVICE_FEATURE_DMA_BUF_TPH is supported even if the hardware lacks TPH support. > > -- > > > > commit d57637d667ca6dc95def77a0a5bd339d62d4f506 > > Author: Zhiping Zhang <zhipingz@meta.com> > > > > vfio/pci: implement get_tph and DMA_BUF_TPH feature > > > > This commit implements dma-buf get_tph for vfio-pci exported dma-bufs and > > adds the VFIO_DEVICE_FEATURE_DMA_BUF_TPH feature. This allows userspace to > > publish TPH metadata for a VFIO-owned device. It checks completer support > > and protects the metadata under dmabuf->resv. > > > > > diff --git a/drivers/vfio/pci/vfio_pci_dmabuf.c b/drivers/vfio/pci/vfio_pci_dmabuf.c > > > index 1a177ce7de546..0a0705c8dbea6 100644 > > > --- a/drivers/vfio/pci/vfio_pci_dmabuf.c > > > +++ b/drivers/vfio/pci/vfio_pci_dmabuf.c > > > > [ ... ] > > > > > @@ -333,6 +360,71 @@ int vfio_pci_core_feature_dma_buf(struct vfio_pci_core_device *vdev, u32 flags, > > > return ret; > > > } > > > > > > +int vfio_pci_core_feature_dma_buf_tph(struct vfio_pci_core_device *vdev, > > > + u32 flags, > > > + struct vfio_device_feature_dma_buf_tph __user *arg, > > > + size_t argsz) > > > +{ > > > + struct vfio_device_feature_dma_buf_tph set_tph; > > > + struct vfio_pci_dma_buf *priv; > > > + struct dma_buf *dmabuf; > > > + u8 comp; > > > + int ret; > > > + > > > + ret = vfio_check_feature(flags, argsz, VFIO_DEVICE_FEATURE_SET, > > > + sizeof(set_tph)); > > > + if (ret != 1) > > > + return ret; > > > > [Severity: Medium] > > vfio_check_feature() returns 0 for VFIO_DEVICE_FEATURE_PROBE, causing an > > early return of success. > > > > Should the hardware capability check (pcie_tph_completer_type) occur before > > checking the feature flags, to avoid falsely reporting that the feature is > > supported on devices that lack TPH? > > > > Will fix it with a change like below: > - if (ret != 1) > + if (ret != 1) { > + if (ret == 0 && > + pcie_tph_completer_type(vdev->pdev) == > + PCI_EXP_DEVCAP2_TPH_COMP_NONE) > + return -EOPNOTSUPP; > return ret; > + } Typically this is done before the check feature call. Thanks, Alex ^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH v7 0/5] vfio/dma-buf: add TPH support for peer-to-peer access @ 2026-06-11 16:11 Zhiping Zhang 2026-06-11 16:11 ` [PATCH v7 4/5] vfio/pci: implement get_tph and DMA_BUF_TPH feature Zhiping Zhang 0 siblings, 1 reply; 6+ messages in thread From: Zhiping Zhang @ 2026-06-11 16:11 UTC (permalink / raw) To: netdev; +Cc: kvm, linux-rdma, linux-pci, dri-devel, Zhiping Zhang This series adds TLP Processing Hints (TPH) support to the VFIO dma-buf export path, allowing importing drivers (e.g. mlx5) to use the exporter's steering tag when performing peer-to-peer DMA into a VFIO-owned device. There is no separate in-tree vendor kernel driver for the target device: vfio-pci is the in-tree driver and the targeted device is managed from userspace via VFIO passthrough. That is why the ST has to flow through a uAPI: userspace owns the device and its ST table, so it is the entity that can publish a meaningful value for a given dma-buf. The kernel-visible participants are still in-tree: vfio-pci exports the dma-buf and mlx5 imports it. On the effect: the endpoint's PCIe ingress block uses the 8-bit ST as an in-band instruction for the incoming P2P TLP -- selecting a target cache partition and, on writes, an in-flight operation on the data before it lands. The dma-buf callback keeps this opaque to the framework -- only the producer (userspace owner of the VFIO device) and the consumer (endpoint block) need to interpret the value. The dma-buf get_tph callback itself is optional for workloads that depend on the endpoint's in-flight operation that fallback does not produce the same result. The dma-buf hook is intentionally generic and discoverable rather than a private side channel. The exporter owns the completing address space for the dma-buf and decides whether it can provide a meaningful ST/PH tuple for that completer; the dma-buf core keeps the tuple opaque, and importers merely request the namespace they support and place the returned value on generated TLPs. Exporters that cannot derive a meaningful tuple simply return -EOPNOTSUPP. Patch 1 is a pre-existing fix split out from the series: mlx5_st_dealloc_index() removed the xarray entry but never freed the backing struct, so repeated alloc/dealloc cycles leaked memory. Patch 2 adds small PCI/TPH type helpers so drivers can query the enabled TPH requester mode and the device's TPH Completer Supported field without reaching into pci_dev internals (and so callers in CONFIG_PCIE_TPH=n builds get a clean fallback). Patch 3 adds the optional dma_buf_ops::get_tph callback plus the dma_buf_get_tph() importer wrapper so importers can fetch TPH metadata from an exporter under dmabuf->resv. Patch 4 implements get_tph in vfio-pci and adds the new uAPI (VFIO_DEVICE_FEATURE_DMA_BUF_TPH) for userspace to attach the metadata. Patch 5 wires up the mlx5 RDMA driver as a consumer. Build-tested with both CONFIG_PCIE_TPH=y and CONFIG_PCIE_TPH=n. Functional validation on the target topology: PCIe analyzer captures on the P2P TLPs confirm the ST emitted by mlx5 matches the value published through VFIO_DEVICE_FEATURE_DMA_BUF_TPH, and the end-to-end P2P workload only produces results consistent with the endpoint's ST-selected in-flight operation. For example, with userspace publishing 8-bit ST=0xf0 and PH=2, an analyzer capture of a peer-to- peer MWr64 shows "STP MWr64 TC=0 OHC=2 ..." followed by "OHC-B ST=F0h PH=2 HV=1": (TLP Captures) 08000260 -> STP MWr64 TC=0 OHC=2 TS=0 Attr=0 L=8 F0000004 -> RID=4h:0h.0h EP- Tag=F0h E0200000 -> AddrH=000020E0h 00080006 -> AddrL=06000800h 90F00000 -> OHC-B ST=F0h PH=2 HV=1 AMA=0 AV- Previous link: v6: https://lore.kernel.org/dri-devel/20260608185646.4085127-1-zhipingz@meta.com/ v5: https://lore.kernel.org/dri-devel/20260526144401.1485788-1-zhipingz@meta.com/ v4: https://lore.kernel.org/linux-pci/20260519201401.1558410-1-zhipingz@meta.com/ v3: https://lore.kernel.org/linux-pci/20260512184755.4137227-1-zhipingz@meta.com/ v2: https://lore.kernel.org/linux-pci/20260430200704.352228-1-zhipingz@meta.com/ Zhiping Zhang (5): net/mlx5: free mlx5_st_idx_data on final dealloc PCI/TPH: Add requester/completer type helpers dma-buf: add optional get_tph() callback vfio/pci: implement get_tph and DMA_BUF_TPH feature RDMA/mlx5: get tph for p2p access when registering dma-buf mr drivers/dma-buf/dma-buf.c | 25 ++++ drivers/infiniband/core/frmr_pools.c | 20 +++- drivers/infiniband/hw/mlx5/mr.c | 111 +++++++++++++++++- .../net/ethernet/mellanox/mlx5/core/lib/st.c | 50 ++++++-- drivers/pci/tph.c | 43 +++++++ drivers/vfio/pci/vfio_pci_core.c | 3 + drivers/vfio/pci/vfio_pci_dmabuf.c | 94 ++++++++++++++- drivers/vfio/pci/vfio_pci_priv.h | 12 ++ include/linux/dma-buf.h | 21 ++++ include/linux/mlx5/driver.h | 12 ++ include/linux/pci-tph.h | 8 ++ include/rdma/frmr_pools.h | 5 +- include/uapi/linux/vfio.h | 37 ++++++ 13 files changed, 421 insertions(+), 20 deletions(-) -- 2.53.0-Meta ^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH v7 4/5] vfio/pci: implement get_tph and DMA_BUF_TPH feature 2026-06-11 16:11 [PATCH v7 0/5] vfio/dma-buf: add TPH support for peer-to-peer access Zhiping Zhang @ 2026-06-11 16:11 ` Zhiping Zhang 2026-06-12 16:46 ` sashiko-bot 2026-06-12 17:10 ` Alex Williamson 0 siblings, 2 replies; 6+ messages in thread From: Zhiping Zhang @ 2026-06-11 16:11 UTC (permalink / raw) To: netdev; +Cc: kvm, linux-rdma, linux-pci, dri-devel, Zhiping Zhang Implement dma-buf get_tph for vfio-pci exported dma-bufs and add VFIO_DEVICE_FEATURE_DMA_BUF_TPH so userspace can publish TPH metadata for a VFIO-owned device. 8-bit ST and 16-bit Extended ST are distinct PCIe TPH namespaces; the uAPI carries both with explicit validity flags, and get_tph() returns the value matching the importer's requested namespace or -EOPNOTSUPP. Publish and read the TPH descriptor under dmabuf->resv, matching the locking used for other importer-visible dma-buf state. The SET ioctl takes dma_resv_lock_interruptible(), while the callback runs under DMA-buf's asserted resv lock. Reject requests the device cannot consume as a completer: pcie_tph_completer_type() must report at least PCI_EXP_DEVCAP2_TPH_COMP_TPH_ONLY, and Extended ST requires PCI_EXP_DEVCAP2_TPH_COMP_EXT_TPH. Validate fields before the completer check so userspace gets the narrowest errno. Signed-off-by: Zhiping Zhang <zhipingz@meta.com> --- drivers/vfio/pci/vfio_pci_core.c | 3 + drivers/vfio/pci/vfio_pci_dmabuf.c | 94 +++++++++++++++++++++++++++++- drivers/vfio/pci/vfio_pci_priv.h | 12 ++++ include/uapi/linux/vfio.h | 37 ++++++++++++ 4 files changed, 145 insertions(+), 1 deletion(-) diff --git a/drivers/vfio/pci/vfio_pci_core.c b/drivers/vfio/pci/vfio_pci_core.c index 050e7542952e..4fa36f2f7555 100644 --- a/drivers/vfio/pci/vfio_pci_core.c +++ b/drivers/vfio/pci/vfio_pci_core.c @@ -1569,6 +1569,9 @@ int vfio_pci_core_ioctl_feature(struct vfio_device *device, u32 flags, return vfio_pci_core_feature_token(vdev, flags, arg, argsz); case VFIO_DEVICE_FEATURE_DMA_BUF: return vfio_pci_core_feature_dma_buf(vdev, flags, arg, argsz); + case VFIO_DEVICE_FEATURE_DMA_BUF_TPH: + return vfio_pci_core_feature_dma_buf_tph(vdev, flags, arg, + argsz); default: return -ENOTTY; } diff --git a/drivers/vfio/pci/vfio_pci_dmabuf.c b/drivers/vfio/pci/vfio_pci_dmabuf.c index 1a177ce7de54..0a0705c8dbea 100644 --- a/drivers/vfio/pci/vfio_pci_dmabuf.c +++ b/drivers/vfio/pci/vfio_pci_dmabuf.c @@ -3,6 +3,7 @@ */ #include <linux/dma-buf-mapping.h> #include <linux/pci-p2pdma.h> +#include <linux/pci-tph.h> #include <linux/dma-resv.h> #include "vfio_pci_priv.h" @@ -19,7 +20,12 @@ struct vfio_pci_dma_buf { u32 nr_ranges; struct kref kref; struct completion comp; - u8 revoked : 1; + u8 tph_st_valid:1; + u8 tph_st_ext_valid:1; + u8 tph_ph:2; + u8 tph_st; + u16 tph_st_ext; + u8 revoked:1; }; static int vfio_pci_dma_buf_attach(struct dma_buf *dmabuf, @@ -69,6 +75,26 @@ vfio_pci_dma_buf_map(struct dma_buf_attachment *attachment, return ret; } +static int vfio_pci_dma_buf_get_tph(struct dma_buf *dmabuf, bool extended, + u16 *steering_tag, u8 *ph) +{ + struct vfio_pci_dma_buf *priv = dmabuf->priv; + + dma_resv_assert_held(dmabuf->resv); + + if (extended) { + if (!priv->tph_st_ext_valid) + return -EOPNOTSUPP; + *steering_tag = priv->tph_st_ext; + } else { + if (!priv->tph_st_valid) + return -EOPNOTSUPP; + *steering_tag = priv->tph_st; + } + *ph = priv->tph_ph; + return 0; +} + static void vfio_pci_dma_buf_unmap(struct dma_buf_attachment *attachment, struct sg_table *sgt, enum dma_data_direction dir) @@ -101,6 +127,7 @@ static void vfio_pci_dma_buf_release(struct dma_buf *dmabuf) static const struct dma_buf_ops vfio_pci_dmabuf_ops = { .attach = vfio_pci_dma_buf_attach, + .get_tph = vfio_pci_dma_buf_get_tph, .map_dma_buf = vfio_pci_dma_buf_map, .unmap_dma_buf = vfio_pci_dma_buf_unmap, .release = vfio_pci_dma_buf_release, @@ -333,6 +360,71 @@ int vfio_pci_core_feature_dma_buf(struct vfio_pci_core_device *vdev, u32 flags, return ret; } +int vfio_pci_core_feature_dma_buf_tph(struct vfio_pci_core_device *vdev, + u32 flags, + struct vfio_device_feature_dma_buf_tph __user *arg, + size_t argsz) +{ + struct vfio_device_feature_dma_buf_tph set_tph; + struct vfio_pci_dma_buf *priv; + struct dma_buf *dmabuf; + u8 comp; + int ret; + + ret = vfio_check_feature(flags, argsz, VFIO_DEVICE_FEATURE_SET, + sizeof(set_tph)); + if (ret != 1) + return ret; + + if (copy_from_user(&set_tph, arg, sizeof(set_tph))) + return -EFAULT; + + if (set_tph.flags & ~(VFIO_DMA_BUF_TPH_ST | VFIO_DMA_BUF_TPH_ST_EXT)) + return -EINVAL; + + if (set_tph.ph & ~0x3) + return -EINVAL; + + comp = pcie_tph_completer_type(vdev->pdev); + if (comp == PCI_EXP_DEVCAP2_TPH_COMP_NONE) + return -EOPNOTSUPP; + if ((set_tph.flags & VFIO_DMA_BUF_TPH_ST_EXT) && + comp != PCI_EXP_DEVCAP2_TPH_COMP_EXT_TPH) + return -EOPNOTSUPP; + + dmabuf = dma_buf_get(set_tph.dmabuf_fd); + if (IS_ERR(dmabuf)) + return PTR_ERR(dmabuf); + + if (dmabuf->ops != &vfio_pci_dmabuf_ops) { + ret = -EINVAL; + goto out_put; + } + + priv = dmabuf->priv; + if (priv->vdev != vdev) { + ret = -EINVAL; + goto out_put; + } + + ret = dma_resv_lock_interruptible(dmabuf->resv, NULL); + if (ret) + goto out_put; + + priv->tph_st = set_tph.steering_tag; + priv->tph_st_ext = set_tph.steering_tag_ext; + priv->tph_ph = set_tph.ph; + priv->tph_st_valid = !!(set_tph.flags & VFIO_DMA_BUF_TPH_ST); + priv->tph_st_ext_valid = + !!(set_tph.flags & VFIO_DMA_BUF_TPH_ST_EXT); + dma_resv_unlock(dmabuf->resv); + ret = 0; + +out_put: + dma_buf_put(dmabuf); + return ret; +} + void vfio_pci_dma_buf_move(struct vfio_pci_core_device *vdev, bool revoked) { struct vfio_pci_dma_buf *priv; diff --git a/drivers/vfio/pci/vfio_pci_priv.h b/drivers/vfio/pci/vfio_pci_priv.h index fca9d0dfac90..c58f369be4b3 100644 --- a/drivers/vfio/pci/vfio_pci_priv.h +++ b/drivers/vfio/pci/vfio_pci_priv.h @@ -118,6 +118,10 @@ static inline bool vfio_pci_is_vga(struct pci_dev *pdev) int vfio_pci_core_feature_dma_buf(struct vfio_pci_core_device *vdev, u32 flags, struct vfio_device_feature_dma_buf __user *arg, size_t argsz); +int vfio_pci_core_feature_dma_buf_tph(struct vfio_pci_core_device *vdev, + u32 flags, + struct vfio_device_feature_dma_buf_tph __user *arg, + size_t argsz); void vfio_pci_dma_buf_cleanup(struct vfio_pci_core_device *vdev); void vfio_pci_dma_buf_move(struct vfio_pci_core_device *vdev, bool revoked); #else @@ -128,6 +132,14 @@ vfio_pci_core_feature_dma_buf(struct vfio_pci_core_device *vdev, u32 flags, { return -ENOTTY; } + +static inline int +vfio_pci_core_feature_dma_buf_tph(struct vfio_pci_core_device *vdev, u32 flags, + struct vfio_device_feature_dma_buf_tph __user *arg, + size_t argsz) +{ + return -ENOTTY; +} static inline void vfio_pci_dma_buf_cleanup(struct vfio_pci_core_device *vdev) { } diff --git a/include/uapi/linux/vfio.h b/include/uapi/linux/vfio.h index 5de618a3a5ee..5dd693220a0d 100644 --- a/include/uapi/linux/vfio.h +++ b/include/uapi/linux/vfio.h @@ -1534,6 +1534,43 @@ struct vfio_device_feature_dma_buf { */ #define VFIO_DEVICE_FEATURE_MIG_PRECOPY_INFOv2 12 +/** + * Upon VFIO_DEVICE_FEATURE_SET associate TPH (TLP Processing Hints) metadata + * with a vfio-exported dma-buf. The dma-buf must have been created by + * VFIO_DEVICE_FEATURE_DMA_BUF on this device, and the device must report + * TPH Completer support in Device Capabilities 2 (bits 13:12); requests + * carrying VFIO_DMA_BUF_TPH_ST_EXT additionally require the device to + * report the Extended TPH Completer encoding. Otherwise the ioctl + * returns -EOPNOTSUPP. + * + * dmabuf_fd is the file descriptor returned by VFIO_DEVICE_FEATURE_DMA_BUF. + * + * 8-bit ST (steering_tag) and 16-bit Extended ST (steering_tag_ext) are + * distinct namespaces. Userspace supplies whichever values are valid and sets + * the matching VFIO_DMA_BUF_TPH_ST / VFIO_DMA_BUF_TPH_ST_EXT bits in @flags; + * an importer requests one namespace and receives the matching value. + * + * @flags == 0 marks any previously published ST / Extended-ST as invalid + * for future get_tph() requests on this dma-buf. + * + * ph is the 2-bit TLP Processing Hint and must be in the range [0, 3]. + * + * Userspace must publish TPH before handing the dma-buf fd to an importer. + * Calling SET again replaces the published values. + */ +#define VFIO_DEVICE_FEATURE_DMA_BUF_TPH 13 + +#define VFIO_DMA_BUF_TPH_ST (1 << 0) +#define VFIO_DMA_BUF_TPH_ST_EXT (1 << 1) + +struct vfio_device_feature_dma_buf_tph { + __s32 dmabuf_fd; + __u32 flags; + __u16 steering_tag_ext; + __u8 steering_tag; + __u8 ph; +}; + /* -------- API for Type1 VFIO IOMMU -------- */ /** -- 2.53.0-Meta ^ permalink raw reply related [flat|nested] 6+ messages in thread
* Re: [PATCH v7 4/5] vfio/pci: implement get_tph and DMA_BUF_TPH feature 2026-06-11 16:11 ` [PATCH v7 4/5] vfio/pci: implement get_tph and DMA_BUF_TPH feature Zhiping Zhang @ 2026-06-12 16:46 ` sashiko-bot 2026-06-12 17:10 ` Alex Williamson 1 sibling, 0 replies; 6+ messages in thread From: sashiko-bot @ 2026-06-12 16:46 UTC (permalink / raw) To: Zhiping Zhang; +Cc: kvm, dri-devel, linux-pci Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider: - [Medium] Unconditional validation of the flag-gated `ph` parameter outside its flag gate. - [Medium] VFIO_DEVICE_FEATURE_PROBE incorrectly reports that the DMA_BUF_TPH feature is supported for devices that lack TPH completer capabilities. -- commit cadaa92f5a8da2be3b081b506699064b7bf68059 Author: Zhiping Zhang <zhipingz@meta.com> vfio/pci: implement get_tph and DMA_BUF_TPH feature Implement dma-buf get_tph for vfio-pci exported dma-bufs and add VFIO_DEVICE_FEATURE_DMA_BUF_TPH so userspace can publish TPH metadata for a VFIO-owned device. > diff --git a/drivers/vfio/pci/vfio_pci_dmabuf.c b/drivers/vfio/pci/vfio_pci_dmabuf.c > index 1a177ce7de546..0a0705c8dbea6 100644 > --- a/drivers/vfio/pci/vfio_pci_dmabuf.c > +++ b/drivers/vfio/pci/vfio_pci_dmabuf.c [ ... ] > @@ -333,6 +360,71 @@ int vfio_pci_core_feature_dma_buf(struct vfio_pci_core_device *vdev, u32 flags, > return ret; > } > > +int vfio_pci_core_feature_dma_buf_tph(struct vfio_pci_core_device *vdev, > + u32 flags, > + struct vfio_device_feature_dma_buf_tph __user *arg, > + size_t argsz) > +{ > + struct vfio_device_feature_dma_buf_tph set_tph; > + struct vfio_pci_dma_buf *priv; > + struct dma_buf *dmabuf; > + u8 comp; > + int ret; > + > + ret = vfio_check_feature(flags, argsz, VFIO_DEVICE_FEATURE_SET, > + sizeof(set_tph)); > + if (ret != 1) > + return ret; [Severity: Medium] Will VFIO_DEVICE_FEATURE_PROBE incorrectly report that the feature is supported on all devices? vfio_check_feature() returns 0 for probe requests, which means this code will return 0 (success) before checking the hardware's TPH completer capabilities below. Should the hardware capability check happen before returning the probe result? > + > + if (copy_from_user(&set_tph, arg, sizeof(set_tph))) > + return -EFAULT; > + > + if (set_tph.flags & ~(VFIO_DMA_BUF_TPH_ST | VFIO_DMA_BUF_TPH_ST_EXT)) > + return -EINVAL; > + > + if (set_tph.ph & ~0x3) > + return -EINVAL; [Severity: Medium] Does this code reject valid clear requests if the unused ph field contains uninitialized data? When userspace sets flags == 0 to clear the metadata, ph is effectively unused and might contain garbage. Validating it unconditionally outside of its flag gate could cause valid API usage to fail with -EINVAL. Should the ph validation only happen if VFIO_DMA_BUF_TPH_ST or VFIO_DMA_BUF_TPH_ST_EXT are set? > + > + comp = pcie_tph_completer_type(vdev->pdev); > + if (comp == PCI_EXP_DEVCAP2_TPH_COMP_NONE) > + return -EOPNOTSUPP; -- Sashiko AI review · https://sashiko.dev/#/patchset/20260611161546.4075580-1-zhipingz@meta.com?part=4 ^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH v7 4/5] vfio/pci: implement get_tph and DMA_BUF_TPH feature 2026-06-11 16:11 ` [PATCH v7 4/5] vfio/pci: implement get_tph and DMA_BUF_TPH feature Zhiping Zhang 2026-06-12 16:46 ` sashiko-bot @ 2026-06-12 17:10 ` Alex Williamson 1 sibling, 0 replies; 6+ messages in thread From: Alex Williamson @ 2026-06-12 17:10 UTC (permalink / raw) To: Zhiping Zhang; +Cc: netdev, kvm, linux-rdma, linux-pci, dri-devel, alex On Thu, 11 Jun 2026 09:11:19 -0700 Zhiping Zhang <zhipingz@meta.com> wrote: > Implement dma-buf get_tph for vfio-pci exported dma-bufs and add > VFIO_DEVICE_FEATURE_DMA_BUF_TPH so userspace can publish TPH metadata > for a VFIO-owned device. > > 8-bit ST and 16-bit Extended ST are distinct PCIe TPH namespaces; the > uAPI carries both with explicit validity flags, and get_tph() returns > the value matching the importer's requested namespace or -EOPNOTSUPP. > > Publish and read the TPH descriptor under dmabuf->resv, matching the > locking used for other importer-visible dma-buf state. The SET ioctl > takes dma_resv_lock_interruptible(), while the callback runs under > DMA-buf's asserted resv lock. > > Reject requests the device cannot consume as a completer: > pcie_tph_completer_type() must report at least > PCI_EXP_DEVCAP2_TPH_COMP_TPH_ONLY, and Extended ST requires > PCI_EXP_DEVCAP2_TPH_COMP_EXT_TPH. Validate fields before the completer > check so userspace gets the narrowest errno. > > Signed-off-by: Zhiping Zhang <zhipingz@meta.com> > --- > drivers/vfio/pci/vfio_pci_core.c | 3 + > drivers/vfio/pci/vfio_pci_dmabuf.c | 94 +++++++++++++++++++++++++++++- > drivers/vfio/pci/vfio_pci_priv.h | 12 ++++ > include/uapi/linux/vfio.h | 37 ++++++++++++ > 4 files changed, 145 insertions(+), 1 deletion(-) > > diff --git a/drivers/vfio/pci/vfio_pci_core.c b/drivers/vfio/pci/vfio_pci_core.c > index 050e7542952e..4fa36f2f7555 100644 > --- a/drivers/vfio/pci/vfio_pci_core.c > +++ b/drivers/vfio/pci/vfio_pci_core.c > @@ -1569,6 +1569,9 @@ int vfio_pci_core_ioctl_feature(struct vfio_device *device, u32 flags, > return vfio_pci_core_feature_token(vdev, flags, arg, argsz); > case VFIO_DEVICE_FEATURE_DMA_BUF: > return vfio_pci_core_feature_dma_buf(vdev, flags, arg, argsz); > + case VFIO_DEVICE_FEATURE_DMA_BUF_TPH: > + return vfio_pci_core_feature_dma_buf_tph(vdev, flags, arg, > + argsz); > default: > return -ENOTTY; > } > diff --git a/drivers/vfio/pci/vfio_pci_dmabuf.c b/drivers/vfio/pci/vfio_pci_dmabuf.c > index 1a177ce7de54..0a0705c8dbea 100644 > --- a/drivers/vfio/pci/vfio_pci_dmabuf.c > +++ b/drivers/vfio/pci/vfio_pci_dmabuf.c > @@ -3,6 +3,7 @@ > */ > #include <linux/dma-buf-mapping.h> > #include <linux/pci-p2pdma.h> > +#include <linux/pci-tph.h> > #include <linux/dma-resv.h> > > #include "vfio_pci_priv.h" > @@ -19,7 +20,12 @@ struct vfio_pci_dma_buf { > u32 nr_ranges; > struct kref kref; > struct completion comp; > - u8 revoked : 1; > + u8 tph_st_valid:1; > + u8 tph_st_ext_valid:1; > + u8 tph_ph:2; > + u8 tph_st; > + u16 tph_st_ext; > + u8 revoked:1; If these bitfields are now all protected under dma_resv_lock they should be grouped together with a comment to that effect, no need for revoked to get kicked out to its own storage unit. In [1] I'm proposing runtime modified flags each get their own storage unit, but for more isolated cases, so long as we keep track and enforce serialized updates, I'm ok with runtime bitfields. Thanks, Alex [1]https://lore.kernel.org/all/20260611213539.4100590-1-alex.williamson@nvidia.com/ > }; > > static int vfio_pci_dma_buf_attach(struct dma_buf *dmabuf, > @@ -69,6 +75,26 @@ vfio_pci_dma_buf_map(struct dma_buf_attachment *attachment, > return ret; > } > > +static int vfio_pci_dma_buf_get_tph(struct dma_buf *dmabuf, bool extended, > + u16 *steering_tag, u8 *ph) > +{ > + struct vfio_pci_dma_buf *priv = dmabuf->priv; > + > + dma_resv_assert_held(dmabuf->resv); > + > + if (extended) { > + if (!priv->tph_st_ext_valid) > + return -EOPNOTSUPP; > + *steering_tag = priv->tph_st_ext; > + } else { > + if (!priv->tph_st_valid) > + return -EOPNOTSUPP; > + *steering_tag = priv->tph_st; > + } > + *ph = priv->tph_ph; > + return 0; > +} > + > static void vfio_pci_dma_buf_unmap(struct dma_buf_attachment *attachment, > struct sg_table *sgt, > enum dma_data_direction dir) > @@ -101,6 +127,7 @@ static void vfio_pci_dma_buf_release(struct dma_buf *dmabuf) > > static const struct dma_buf_ops vfio_pci_dmabuf_ops = { > .attach = vfio_pci_dma_buf_attach, > + .get_tph = vfio_pci_dma_buf_get_tph, > .map_dma_buf = vfio_pci_dma_buf_map, > .unmap_dma_buf = vfio_pci_dma_buf_unmap, > .release = vfio_pci_dma_buf_release, > @@ -333,6 +360,71 @@ int vfio_pci_core_feature_dma_buf(struct vfio_pci_core_device *vdev, u32 flags, > return ret; > } > > +int vfio_pci_core_feature_dma_buf_tph(struct vfio_pci_core_device *vdev, > + u32 flags, > + struct vfio_device_feature_dma_buf_tph __user *arg, > + size_t argsz) > +{ > + struct vfio_device_feature_dma_buf_tph set_tph; > + struct vfio_pci_dma_buf *priv; > + struct dma_buf *dmabuf; > + u8 comp; > + int ret; > + > + ret = vfio_check_feature(flags, argsz, VFIO_DEVICE_FEATURE_SET, > + sizeof(set_tph)); > + if (ret != 1) > + return ret; > + > + if (copy_from_user(&set_tph, arg, sizeof(set_tph))) > + return -EFAULT; > + > + if (set_tph.flags & ~(VFIO_DMA_BUF_TPH_ST | VFIO_DMA_BUF_TPH_ST_EXT)) > + return -EINVAL; > + > + if (set_tph.ph & ~0x3) > + return -EINVAL; > + > + comp = pcie_tph_completer_type(vdev->pdev); > + if (comp == PCI_EXP_DEVCAP2_TPH_COMP_NONE) > + return -EOPNOTSUPP; > + if ((set_tph.flags & VFIO_DMA_BUF_TPH_ST_EXT) && > + comp != PCI_EXP_DEVCAP2_TPH_COMP_EXT_TPH) > + return -EOPNOTSUPP; > + > + dmabuf = dma_buf_get(set_tph.dmabuf_fd); > + if (IS_ERR(dmabuf)) > + return PTR_ERR(dmabuf); > + > + if (dmabuf->ops != &vfio_pci_dmabuf_ops) { > + ret = -EINVAL; > + goto out_put; > + } > + > + priv = dmabuf->priv; > + if (priv->vdev != vdev) { > + ret = -EINVAL; > + goto out_put; > + } > + > + ret = dma_resv_lock_interruptible(dmabuf->resv, NULL); > + if (ret) > + goto out_put; > + > + priv->tph_st = set_tph.steering_tag; > + priv->tph_st_ext = set_tph.steering_tag_ext; > + priv->tph_ph = set_tph.ph; > + priv->tph_st_valid = !!(set_tph.flags & VFIO_DMA_BUF_TPH_ST); > + priv->tph_st_ext_valid = > + !!(set_tph.flags & VFIO_DMA_BUF_TPH_ST_EXT); > + dma_resv_unlock(dmabuf->resv); > + ret = 0; > + > +out_put: > + dma_buf_put(dmabuf); > + return ret; > +} > + > void vfio_pci_dma_buf_move(struct vfio_pci_core_device *vdev, bool revoked) > { > struct vfio_pci_dma_buf *priv; > diff --git a/drivers/vfio/pci/vfio_pci_priv.h b/drivers/vfio/pci/vfio_pci_priv.h > index fca9d0dfac90..c58f369be4b3 100644 > --- a/drivers/vfio/pci/vfio_pci_priv.h > +++ b/drivers/vfio/pci/vfio_pci_priv.h > @@ -118,6 +118,10 @@ static inline bool vfio_pci_is_vga(struct pci_dev *pdev) > int vfio_pci_core_feature_dma_buf(struct vfio_pci_core_device *vdev, u32 flags, > struct vfio_device_feature_dma_buf __user *arg, > size_t argsz); > +int vfio_pci_core_feature_dma_buf_tph(struct vfio_pci_core_device *vdev, > + u32 flags, > + struct vfio_device_feature_dma_buf_tph __user *arg, > + size_t argsz); > void vfio_pci_dma_buf_cleanup(struct vfio_pci_core_device *vdev); > void vfio_pci_dma_buf_move(struct vfio_pci_core_device *vdev, bool revoked); > #else > @@ -128,6 +132,14 @@ vfio_pci_core_feature_dma_buf(struct vfio_pci_core_device *vdev, u32 flags, > { > return -ENOTTY; > } > + > +static inline int > +vfio_pci_core_feature_dma_buf_tph(struct vfio_pci_core_device *vdev, u32 flags, > + struct vfio_device_feature_dma_buf_tph __user *arg, > + size_t argsz) > +{ > + return -ENOTTY; > +} > static inline void vfio_pci_dma_buf_cleanup(struct vfio_pci_core_device *vdev) > { > } > diff --git a/include/uapi/linux/vfio.h b/include/uapi/linux/vfio.h > index 5de618a3a5ee..5dd693220a0d 100644 > --- a/include/uapi/linux/vfio.h > +++ b/include/uapi/linux/vfio.h > @@ -1534,6 +1534,43 @@ struct vfio_device_feature_dma_buf { > */ > #define VFIO_DEVICE_FEATURE_MIG_PRECOPY_INFOv2 12 > > +/** > + * Upon VFIO_DEVICE_FEATURE_SET associate TPH (TLP Processing Hints) metadata > + * with a vfio-exported dma-buf. The dma-buf must have been created by > + * VFIO_DEVICE_FEATURE_DMA_BUF on this device, and the device must report > + * TPH Completer support in Device Capabilities 2 (bits 13:12); requests > + * carrying VFIO_DMA_BUF_TPH_ST_EXT additionally require the device to > + * report the Extended TPH Completer encoding. Otherwise the ioctl > + * returns -EOPNOTSUPP. > + * > + * dmabuf_fd is the file descriptor returned by VFIO_DEVICE_FEATURE_DMA_BUF. > + * > + * 8-bit ST (steering_tag) and 16-bit Extended ST (steering_tag_ext) are > + * distinct namespaces. Userspace supplies whichever values are valid and sets > + * the matching VFIO_DMA_BUF_TPH_ST / VFIO_DMA_BUF_TPH_ST_EXT bits in @flags; > + * an importer requests one namespace and receives the matching value. > + * > + * @flags == 0 marks any previously published ST / Extended-ST as invalid > + * for future get_tph() requests on this dma-buf. > + * > + * ph is the 2-bit TLP Processing Hint and must be in the range [0, 3]. > + * > + * Userspace must publish TPH before handing the dma-buf fd to an importer. > + * Calling SET again replaces the published values. > + */ > +#define VFIO_DEVICE_FEATURE_DMA_BUF_TPH 13 > + > +#define VFIO_DMA_BUF_TPH_ST (1 << 0) > +#define VFIO_DMA_BUF_TPH_ST_EXT (1 << 1) > + > +struct vfio_device_feature_dma_buf_tph { > + __s32 dmabuf_fd; > + __u32 flags; > + __u16 steering_tag_ext; > + __u8 steering_tag; > + __u8 ph; > +}; > + > /* -------- API for Type1 VFIO IOMMU -------- */ > > /** ^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2026-06-12 17:10 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
[not found] <20260610193158.2614209-5-zhipingz@meta.com>
2026-06-11 20:25 ` [PATCH v7 4/5] vfio/pci: implement get_tph and DMA_BUF_TPH feature sashiko-bot
2026-06-11 23:02 ` Zhiping Zhang
2026-06-12 16:59 ` Alex Williamson
2026-06-11 16:11 [PATCH v7 0/5] vfio/dma-buf: add TPH support for peer-to-peer access Zhiping Zhang
2026-06-11 16:11 ` [PATCH v7 4/5] vfio/pci: implement get_tph and DMA_BUF_TPH feature Zhiping Zhang
2026-06-12 16:46 ` sashiko-bot
2026-06-12 17:10 ` Alex Williamson
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox