All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/2] fpga: add dma-buf based FPGA programming interface
@ 2026-08-16 15:07 Aravind Thokala
  2026-08-16 15:07 ` [PATCH 1/2] fpga: Add dma-buf interface for FPGA programming Aravind Thokala
  2026-08-16 15:07 ` [PATCH 2/2] fpga: versal: add dma-buf programming support Aravind Thokala
  0 siblings, 2 replies; 5+ messages in thread
From: Aravind Thokala @ 2026-08-16 15:07 UTC (permalink / raw)
  To: mdf, yilun.xu, trix, sumit.semwal, christian.koenig
  Cc: corbet, skhan, linux-kernel, linux-fpga, linux-media, dri-devel,
	linaro-mm-sig, linux-doc, git, aravind.thokala,
	nava.kishore.manne

Some systems need to load large FPGA configuration images. The FPGA
subsystem allows loading images from the filesystem, but this requires
the entire image to be loaded into kernel memory first. For drivers
that need a DMA-capable buffer for programming, the data is then
copied again into DMA memory. This creates needless memory pressure
and delays due to the extra copy.

This series adds dma-buf support that allows userspace to allocate a
buffer directly from a DMA heap, write the FPGA image into it, and
pass the file descriptor to the kernel via ioctl — skipping the
intermediate kernel buffer entirely.

Userspace flow:
  1. Allocate buffer from /dev/dma_heap/ (e.g., CMA heap)
  2. mmap the buffer and write the FPGA image into it
  3. ioctl(/dev/fpgaX, FPGA_IOCTL_LOAD_DMA_BUF, &dmabuf_fd)

The dma-buf logic is implemented as a separate layer on top of the
FPGA manager, keeping buffer management separate from the write path.
Individual FPGA drivers opt in by calling fpga_dmabuf_register().
---
This work is based on the approach discussed in [1].

[1] https://lore.kernel.org/all/20231122053035.3758124-1-nava.kishore.manne@amd.com/
---
Aravind Thokala (2):
  fpga: Add dma-buf interface for FPGA programming
  fpga: versal: add dma-buf programming support

 .../userspace-api/ioctl/ioctl-number.rst      |   1 +
 MAINTAINERS                                   |   1 +
 drivers/fpga/Kconfig                          |   9 +
 drivers/fpga/Makefile                         |   2 +
 drivers/fpga/fpga-dmabuf.c                    | 198 ++++++++++++++++++
 drivers/fpga/versal-fpga.c                    |  33 ++-
 include/linux/fpga/fpga-dmabuf.h              |  22 ++
 include/linux/fpga/fpga-mgr.h                 |   1 +
 include/uapi/linux/fpga.h                     |  15 ++
 9 files changed, 281 insertions(+), 1 deletion(-)
 create mode 100644 drivers/fpga/fpga-dmabuf.c
 create mode 100644 include/linux/fpga/fpga-dmabuf.h
 create mode 100644 include/uapi/linux/fpga.h

-- 
2.34.1


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

* [PATCH 1/2] fpga: Add dma-buf interface for FPGA programming
  2026-08-16 15:07 [PATCH 0/2] fpga: add dma-buf based FPGA programming interface Aravind Thokala
@ 2026-08-16 15:07 ` Aravind Thokala
  2026-08-16 15:19   ` sashiko-bot
  2026-08-16 15:07 ` [PATCH 2/2] fpga: versal: add dma-buf programming support Aravind Thokala
  1 sibling, 1 reply; 5+ messages in thread
From: Aravind Thokala @ 2026-08-16 15:07 UTC (permalink / raw)
  To: mdf, yilun.xu, trix, sumit.semwal, christian.koenig
  Cc: corbet, skhan, linux-kernel, linux-fpga, linux-media, dri-devel,
	linaro-mm-sig, linux-doc, git, aravind.thokala,
	nava.kishore.manne

Loading FPGA images through the firmware interface requires the image
to be loaded into kernel memory first and then copied into DMA memory.
This extra copy creates needless memory pressure and delays.

Add a module that allows userspace to pass a pre-allocated DMA buffer
directly to the FPGA manager via ioctl, eliminating the extra copy.
A miscdevice (/dev/fpgaX) is created for each FPGA manager that
registers dma-buf support. The module imports the dma-buf fd, maps it
for DMA, and calls the FPGA manager load API with the scatter-gather
table.

Co-developed-by: Nava kishore Manne <nava.kishore.manne@amd.com>
Signed-off-by: Nava kishore Manne <nava.kishore.manne@amd.com>
Signed-off-by: Aravind Thokala <aravind.thokala@amd.com>
---
 .../userspace-api/ioctl/ioctl-number.rst      |   1 +
 MAINTAINERS                                   |   1 +
 drivers/fpga/Kconfig                          |   9 +
 drivers/fpga/Makefile                         |   2 +
 drivers/fpga/fpga-dmabuf.c                    | 198 ++++++++++++++++++
 include/linux/fpga/fpga-dmabuf.h              |  22 ++
 include/linux/fpga/fpga-mgr.h                 |   1 +
 include/uapi/linux/fpga.h                     |  15 ++
 8 files changed, 249 insertions(+)
 create mode 100644 drivers/fpga/fpga-dmabuf.c
 create mode 100644 include/linux/fpga/fpga-dmabuf.h
 create mode 100644 include/uapi/linux/fpga.h

diff --git a/Documentation/userspace-api/ioctl/ioctl-number.rst b/Documentation/userspace-api/ioctl/ioctl-number.rst
index 3f0ef1e27eb0..f8537dd23463 100644
--- a/Documentation/userspace-api/ioctl/ioctl-number.rst
+++ b/Documentation/userspace-api/ioctl/ioctl-number.rst
@@ -170,6 +170,7 @@ Code  Seq#    Include File                                             Comments
 'I'   all    linux/isdn.h                                              conflict!
 'I'   00-0F  drivers/isdn/divert/isdn_divert.h                         conflict!
 'I'   40-4F  linux/mISDNif.h                                           conflict!
+'J'   01     uapi/linux/fpga.h                                         FPGA DMA buffer interface
 'K'   all    linux/kd.h
 'L'   00-1F  linux/loop.h                                              conflict!
 'L'   10-1F  drivers/scsi/mpt3sas/mpt3sas_ctl.h                        conflict!
diff --git a/MAINTAINERS b/MAINTAINERS
index 5114e6db7307..7551dfa35d1c 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -10217,6 +10217,7 @@ F:	Documentation/driver-api/fpga/
 F:	Documentation/fpga/
 F:	drivers/fpga/
 F:	include/linux/fpga/
+F:	include/uapi/linux/fpga.h
 
 FRAMEBUFFER CONSOLE
 M:	Helge Deller <deller@gmx.de>
diff --git a/drivers/fpga/Kconfig b/drivers/fpga/Kconfig
index 748fc210c135..e3ad791c9808 100644
--- a/drivers/fpga/Kconfig
+++ b/drivers/fpga/Kconfig
@@ -157,6 +157,15 @@ config OF_FPGA_REGION
 	  Support for loading FPGA images by applying a Device Tree
 	  overlay.
 
+config FPGA_DMA_BUF
+	tristate "FPGA DMA Buffer Support"
+	depends on DMA_SHARED_BUFFER
+	help
+	  Support for programming FPGAs from a pre-allocated DMA buffer
+	  shared via dma-buf. A miscdevice (/dev/fpgaX) accepts a dma-buf
+	  file descriptor via ioctl to load the FPGA image without
+	  redundant memory copies.
+
 config FPGA_DFL
 	tristate "FPGA Device Feature List (DFL) support"
 	select FPGA_BRIDGE
diff --git a/drivers/fpga/Makefile b/drivers/fpga/Makefile
index 6f5798b27e0d..e52154296d2d 100644
--- a/drivers/fpga/Makefile
+++ b/drivers/fpga/Makefile
@@ -40,6 +40,8 @@ obj-$(CONFIG_XILINX_PR_DECOUPLER)	+= xilinx-pr-decoupler.o
 # High Level Interfaces
 obj-$(CONFIG_FPGA_REGION)		+= fpga-region.o
 obj-$(CONFIG_OF_FPGA_REGION)		+= of-fpga-region.o
+# FPGA DMA Buffer Interface
+obj-$(CONFIG_FPGA_DMA_BUF)		+= fpga-dmabuf.o
 
 # FPGA Device Feature List Support
 obj-$(CONFIG_FPGA_DFL)			+= dfl.o
diff --git a/drivers/fpga/fpga-dmabuf.c b/drivers/fpga/fpga-dmabuf.c
new file mode 100644
index 000000000000..0e92eb134698
--- /dev/null
+++ b/drivers/fpga/fpga-dmabuf.c
@@ -0,0 +1,198 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * FPGA Manager DMA Buffer Support
+ *
+ * Copyright (C) 2026 Advanced Micro Devices, Inc.
+ */
+#include <linux/capability.h>
+#include <linux/dma-buf.h>
+#include <linux/fpga/fpga-dmabuf.h>
+#include <linux/fpga/fpga-mgr.h>
+#include <linux/kref.h>
+#include <linux/miscdevice.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/slab.h>
+#include <uapi/linux/fpga.h>
+
+struct fpga_dmabuf_priv {
+	struct kref ref;
+	struct mutex lock; /* serializes ioctl against teardown */
+	bool dead;
+	struct fpga_manager *mgr;
+	struct miscdevice miscdev;
+};
+
+static void fpga_dmabuf_free(struct kref *ref)
+{
+	struct fpga_dmabuf_priv *priv = container_of(ref,
+					struct fpga_dmabuf_priv, ref);
+
+	put_device(&priv->mgr->dev);
+	kfree(priv->miscdev.name);
+	kfree(priv);
+}
+
+static int fpga_dmabuf_load(struct fpga_manager *mgr, int buffd)
+{
+	struct fpga_image_info *info;
+	struct dma_buf_attachment *attach;
+	struct dma_buf *dmabuf;
+	struct sg_table *sgt;
+	int ret;
+
+	dmabuf = dma_buf_get(buffd);
+	if (IS_ERR(dmabuf))
+		return PTR_ERR(dmabuf);
+
+	info = fpga_image_info_alloc(mgr->dev.parent);
+	if (!info) {
+		ret = -ENOMEM;
+		goto err_put;
+	}
+
+	attach = dma_buf_attach(dmabuf, mgr->dev.parent);
+	if (IS_ERR(attach)) {
+		ret = PTR_ERR(attach);
+		goto err_free_info;
+	}
+
+	sgt = dma_buf_map_attachment_unlocked(attach, DMA_TO_DEVICE);
+	if (IS_ERR(sgt)) {
+		ret = PTR_ERR(sgt);
+		goto err_detach;
+	}
+
+	info->sgt = sgt;
+
+	ret = fpga_mgr_lock(mgr);
+	if (ret)
+		goto err_unmap;
+
+	ret = fpga_mgr_load(mgr, info);
+	fpga_mgr_unlock(mgr);
+
+err_unmap:
+	dma_buf_unmap_attachment_unlocked(attach, sgt, DMA_TO_DEVICE);
+err_detach:
+	dma_buf_detach(dmabuf, attach);
+err_free_info:
+	fpga_image_info_free(info);
+err_put:
+	dma_buf_put(dmabuf);
+
+	return ret;
+}
+
+static int fpga_dmabuf_open(struct inode *inode, struct file *file)
+{
+	struct miscdevice *miscdev = file->private_data;
+	struct fpga_dmabuf_priv *priv;
+
+	priv = container_of(miscdev, struct fpga_dmabuf_priv, miscdev);
+	kref_get(&priv->ref);
+	file->private_data = priv;
+
+	return 0;
+}
+
+static int fpga_dmabuf_release(struct inode *inode, struct file *file)
+{
+	struct fpga_dmabuf_priv *priv = file->private_data;
+
+	kref_put(&priv->ref, fpga_dmabuf_free);
+	return 0;
+}
+
+static long fpga_dmabuf_ioctl(struct file *file, unsigned int cmd,
+			      unsigned long arg)
+{
+	struct fpga_dmabuf_priv *priv = file->private_data;
+	int buffd;
+	int ret;
+
+	switch (cmd) {
+	case FPGA_IOCTL_LOAD_DMA_BUF:
+		if (!capable(CAP_SYS_RAWIO))
+			return -EPERM;
+		if (copy_from_user(&buffd, (void __user *)arg, sizeof(buffd)))
+			return -EFAULT;
+
+		mutex_lock(&priv->lock);
+		if (priv->dead) {
+			mutex_unlock(&priv->lock);
+			return -ENODEV;
+		}
+		ret = fpga_dmabuf_load(priv->mgr, buffd);
+		mutex_unlock(&priv->lock);
+		return ret;
+	default:
+		return -ENOTTY;
+	}
+}
+
+static const struct file_operations fpga_dmabuf_fops = {
+	.owner		= THIS_MODULE,
+	.open		= fpga_dmabuf_open,
+	.release	= fpga_dmabuf_release,
+	.unlocked_ioctl	= fpga_dmabuf_ioctl,
+	.compat_ioctl	= compat_ptr_ioctl,
+};
+
+int fpga_dmabuf_register(struct fpga_manager *mgr)
+{
+	struct fpga_dmabuf_priv *priv;
+	int ret;
+
+	priv = kzalloc_obj(*priv);
+	if (!priv)
+		return -ENOMEM;
+
+	kref_init(&priv->ref);
+	mutex_init(&priv->lock);
+	get_device(&mgr->dev);
+	priv->mgr = mgr;
+	priv->miscdev.minor = MISC_DYNAMIC_MINOR;
+	priv->miscdev.name = kstrdup(dev_name(&mgr->dev), GFP_KERNEL);
+	if (!priv->miscdev.name) {
+		put_device(&mgr->dev);
+		kfree(priv);
+		return -ENOMEM;
+	}
+	priv->miscdev.fops = &fpga_dmabuf_fops;
+	priv->miscdev.parent = &mgr->dev;
+
+	ret = misc_register(&priv->miscdev);
+	if (ret) {
+		kfree(priv->miscdev.name);
+		put_device(&mgr->dev);
+		kfree(priv);
+		return ret;
+	}
+
+	mgr->dmabuf_priv = priv;
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(fpga_dmabuf_register);
+
+void fpga_dmabuf_unregister(struct fpga_manager *mgr)
+{
+	struct fpga_dmabuf_priv *priv = mgr->dmabuf_priv;
+
+	if (!priv)
+		return;
+
+	mutex_lock(&priv->lock);
+	priv->dead = true;
+	mutex_unlock(&priv->lock);
+
+	misc_deregister(&priv->miscdev);
+	mgr->dmabuf_priv = NULL;
+	kref_put(&priv->ref, fpga_dmabuf_free);
+}
+EXPORT_SYMBOL_GPL(fpga_dmabuf_unregister);
+
+MODULE_IMPORT_NS("DMA_BUF");
+MODULE_DESCRIPTION("FPGA DMA Buffer Interface");
+MODULE_LICENSE("GPL");
diff --git a/include/linux/fpga/fpga-dmabuf.h b/include/linux/fpga/fpga-dmabuf.h
new file mode 100644
index 000000000000..bf54bdfdf968
--- /dev/null
+++ b/include/linux/fpga/fpga-dmabuf.h
@@ -0,0 +1,22 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2026 Advanced Micro Devices, Inc.
+ */
+#ifndef _LINUX_FPGA_DMABUF_H
+#define _LINUX_FPGA_DMABUF_H
+
+struct fpga_manager;
+
+#if IS_REACHABLE(CONFIG_FPGA_DMA_BUF)
+int fpga_dmabuf_register(struct fpga_manager *mgr);
+void fpga_dmabuf_unregister(struct fpga_manager *mgr);
+#else
+static inline int fpga_dmabuf_register(struct fpga_manager *mgr)
+{
+	return 0;
+}
+
+static inline void fpga_dmabuf_unregister(struct fpga_manager *mgr) {}
+#endif
+
+#endif /* _LINUX_FPGA_DMABUF_H */
diff --git a/include/linux/fpga/fpga-mgr.h b/include/linux/fpga/fpga-mgr.h
index 0d4fe068f3d8..38af47f60503 100644
--- a/include/linux/fpga/fpga-mgr.h
+++ b/include/linux/fpga/fpga-mgr.h
@@ -213,6 +213,7 @@ struct fpga_manager {
 	const struct fpga_manager_ops *mops;
 	struct module *mops_owner;
 	void *priv;
+	void *dmabuf_priv;
 };
 
 #define to_fpga_manager(d) container_of(d, struct fpga_manager, dev)
diff --git a/include/uapi/linux/fpga.h b/include/uapi/linux/fpga.h
new file mode 100644
index 000000000000..868650c66526
--- /dev/null
+++ b/include/uapi/linux/fpga.h
@@ -0,0 +1,15 @@
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
+/*
+ * FPGA userspace API
+ *
+ * Copyright (C) 2026 Advanced Micro Devices, Inc.
+ */
+#ifndef _UAPI_LINUX_FPGA_H
+#define _UAPI_LINUX_FPGA_H
+
+#include <linux/ioctl.h>
+#include <linux/types.h>
+
+#define FPGA_IOCTL_LOAD_DMA_BUF	_IOW('J', 1, __s32)
+
+#endif /* _UAPI_LINUX_FPGA_H */
-- 
2.34.1


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

* [PATCH 2/2] fpga: versal: add dma-buf programming support
  2026-08-16 15:07 [PATCH 0/2] fpga: add dma-buf based FPGA programming interface Aravind Thokala
  2026-08-16 15:07 ` [PATCH 1/2] fpga: Add dma-buf interface for FPGA programming Aravind Thokala
@ 2026-08-16 15:07 ` Aravind Thokala
  2026-08-16 15:18   ` sashiko-bot
  1 sibling, 1 reply; 5+ messages in thread
From: Aravind Thokala @ 2026-08-16 15:07 UTC (permalink / raw)
  To: mdf, yilun.xu, trix, sumit.semwal, christian.koenig
  Cc: corbet, skhan, linux-kernel, linux-fpga, linux-media, dri-devel,
	linaro-mm-sig, linux-doc, git, aravind.thokala,
	nava.kishore.manne

The existing .write callback allocates a DMA-coherent buffer and
copies the image into it before passing the address to firmware. With
dma-buf, the buffer is already DMA-mapped by userspace.

Add a .write_sg callback that extracts the DMA address directly from
the scatter-gather table and passes it to zynqmp_pm_load_pdi(),
avoiding the intermediate copy. Register the dma-buf interface in
probe with devres-managed cleanup.

Co-developed-by: Nava kishore Manne <nava.kishore.manne@amd.com>
Signed-off-by: Nava kishore Manne <nava.kishore.manne@amd.com>
Signed-off-by: Aravind Thokala <aravind.thokala@amd.com>
---
 drivers/fpga/versal-fpga.c | 33 ++++++++++++++++++++++++++++++++-
 1 file changed, 32 insertions(+), 1 deletion(-)

diff --git a/drivers/fpga/versal-fpga.c b/drivers/fpga/versal-fpga.c
index e6189106c468..bdaa15a6c991 100644
--- a/drivers/fpga/versal-fpga.c
+++ b/drivers/fpga/versal-fpga.c
@@ -4,6 +4,7 @@
  */
 
 #include <linux/dma-mapping.h>
+#include <linux/fpga/fpga-dmabuf.h>
 #include <linux/fpga/fpga-mgr.h>
 #include <linux/io.h>
 #include <linux/kernel.h>
@@ -37,11 +38,34 @@ static int versal_fpga_ops_write(struct fpga_manager *mgr,
 	return ret;
 }
 
+static int versal_fpga_ops_write_sg(struct fpga_manager *mgr,
+				    struct sg_table *sgt)
+{
+	dma_addr_t dma_addr;
+
+	/* zynqmp_pm_load_pdi() takes a single base address */
+	if (sgt->nents != 1) {
+		dev_err(&mgr->dev, "dma-buf has %u segments, need exactly 1\n",
+			sgt->nents);
+		return -EINVAL;
+	}
+
+	dma_addr = sg_dma_address(sgt->sgl);
+
+	return zynqmp_pm_load_pdi(PDI_SRC_DDR, dma_addr);
+}
+
 static const struct fpga_manager_ops versal_fpga_ops = {
 	.write_init = versal_fpga_ops_write_init,
 	.write = versal_fpga_ops_write,
+	.write_sg = versal_fpga_ops_write_sg,
 };
 
+static void versal_fpga_dmabuf_remove(void *data)
+{
+	fpga_dmabuf_unregister(data);
+}
+
 static int versal_fpga_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
@@ -56,7 +80,14 @@ static int versal_fpga_probe(struct platform_device *pdev)
 
 	mgr = devm_fpga_mgr_register(dev, "Xilinx Versal FPGA Manager",
 				     &versal_fpga_ops, NULL);
-	return PTR_ERR_OR_ZERO(mgr);
+	if (IS_ERR(mgr))
+		return PTR_ERR(mgr);
+
+	ret = fpga_dmabuf_register(mgr);
+	if (ret)
+		return ret;
+
+	return devm_add_action_or_reset(dev, versal_fpga_dmabuf_remove, mgr);
 }
 
 static const struct of_device_id versal_fpga_of_match[] = {
-- 
2.34.1


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

* Re: [PATCH 2/2] fpga: versal: add dma-buf programming support
  2026-08-16 15:07 ` [PATCH 2/2] fpga: versal: add dma-buf programming support Aravind Thokala
@ 2026-08-16 15:18   ` sashiko-bot
  0 siblings, 0 replies; 5+ messages in thread
From: sashiko-bot @ 2026-08-16 15:18 UTC (permalink / raw)
  To: Aravind Thokala; +Cc: dri-devel, media-ci

Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Medium] Passing a user-accessible dma-buf directly to the PMC firmware introduces a speculative Time-of-Check to Time-of-Use (TOCTOU) vulnerability that can potentially bypass FPGA bitstream authentication.
--

--- Patch [2]: [PATCH 2/2] fpga: versal: add dma-buf programming support ---
commit 92384704c37fbbfe16cd9659151fbb8646c178cc
Author: Aravind Thokala <aravind.thokala@amd.com>

fpga: versal: add dma-buf programming support

This commit adds a .write_sg callback to the Versal FPGA driver to support
dma-buf based programming. It extracts the DMA address from the scatter-gather
table and passes it directly to the firmware, avoiding an intermediate buffer
copy.

> diff --git a/drivers/fpga/versal-fpga.c b/drivers/fpga/versal-fpga.c
> index e6189106c4686..bdaa15a6c9913 100644
> --- a/drivers/fpga/versal-fpga.c
> +++ b/drivers/fpga/versal-fpga.c

[ ... ]

> @@ -37,11 +38,34 @@ static int versal_fpga_ops_write(struct fpga_manager *mgr,
>  	return ret;
>  }
>  
> +static int versal_fpga_ops_write_sg(struct fpga_manager *mgr,
> +				    struct sg_table *sgt)
> +{
> +	dma_addr_t dma_addr;
> +
> +	/* zynqmp_pm_load_pdi() takes a single base address */
> +	if (sgt->nents != 1) {
> +		dev_err(&mgr->dev, "dma-buf has %u segments, need exactly 1\n",
> +			sgt->nents);
> +		return -EINVAL;
> +	}
> +
> +	dma_addr = sg_dma_address(sgt->sgl);
> +
> +	return zynqmp_pm_load_pdi(PDI_SRC_DDR, dma_addr);

[Severity: Medium]
Does this expose the firmware to a Time-of-Check to Time-of-Use (TOCTOU)
vulnerability if the Xilinx PMC firmware double-fetches the payload?

By extracting the DMA address from the user-provided dma-buf and passing
it directly to zynqmp_pm_load_pdi() without copying it to a kernel-owned
isolated buffer, a process could potentially modify the bitstream
concurrently during the firmware's authentication and loading process.

If a user with CAP_SYS_RAWIO maintains a writable memory mapping to the
dma-buf (for instance, using udmabuf) and invokes FPGA_IOCTL_LOAD_DMA_BUF,
they could overwrite the memory while the firmware reads it.

If the firmware re-reads any part of the bitstream after authentication,
could this be abused to bypass secure boot boundaries?

> +}
> +

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260816150734.2092802-1-aravind.thokala@amd.com?part=2

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

* Re: [PATCH 1/2] fpga: Add dma-buf interface for FPGA programming
  2026-08-16 15:07 ` [PATCH 1/2] fpga: Add dma-buf interface for FPGA programming Aravind Thokala
@ 2026-08-16 15:19   ` sashiko-bot
  0 siblings, 0 replies; 5+ messages in thread
From: sashiko-bot @ 2026-08-16 15:19 UTC (permalink / raw)
  To: Aravind Thokala; +Cc: media-ci, dri-devel

Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
- [Critical] Passing a DMA-mapped dma-buf scatterlist to the FPGA manager core causes double-mapping or CPU access of device memory, triggering kernel panics.
- [High] The FPGA_IOCTL_LOAD_DMA_BUF ioctl lacks a firmware size parameter, causing the full page-aligned dma-buf capacity to be pushed into the FPGA port, corrupting configuration.
--

--- Patch [1]: [PATCH 1/2] fpga: Add dma-buf interface for FPGA programming ---
commit 9a25ee19d33999a56fc7670a1a9dbec98cb947aa
Author: Aravind Thokala <aravind.thokala@amd.com>

fpga: Add dma-buf interface for FPGA programming

This commit adds a module that allows userspace to pass a pre-allocated DMA
buffer directly to the FPGA manager via ioctl. It creates a miscdevice for
each FPGA manager that registers dma-buf support to map and load the image
without an extra memory copy.

> diff --git a/drivers/fpga/fpga-dmabuf.c b/drivers/fpga/fpga-dmabuf.c
> new file mode 100644
> index 0000000000000..0e92eb1346981
> --- /dev/null
> +++ b/drivers/fpga/fpga-dmabuf.c

[ ... ]

> +static int fpga_dmabuf_load(struct fpga_manager *mgr, int buffd)
> +{
> +	struct fpga_image_info *info;
> +	struct dma_buf_attachment *attach;
> +	struct dma_buf *dmabuf;
> +	struct sg_table *sgt;
> +	int ret;

[ ... ]

> +	sgt = dma_buf_map_attachment_unlocked(attach, DMA_TO_DEVICE);
> +	if (IS_ERR(sgt)) {
> +		ret = PTR_ERR(sgt);
> +		goto err_detach;
> +	}
> +
> +	info->sgt = sgt;
> +
> +	ret = fpga_mgr_lock(mgr);
> +	if (ret)
> +		goto err_unmap;
> +
> +	ret = fpga_mgr_load(mgr, info);

[Severity: Critical]
Does passing a DMA-mapped sg_table into fpga_mgr_load() cause issues with the
underlying FPGA manager drivers?

Hardware drivers typically expect an unmapped CPU sg_table and will call
dma_map_sgtable() on it. Calling dma_map_sgtable() on an already mapped
sg_table can overwrite DMA addresses and corrupt the DMA state.

Additionally, the core manager may fall back to CPU PIO to read the image
header via sg_miter (which internally uses kmap). If the dma-buf is backed
by P2P device memory, this could dereference invalid struct pages and cause
a kernel panic. It also bypasses cache coherency since
dma_buf_begin_cpu_access() is never called.

[ ... ]

> diff --git a/include/uapi/linux/fpga.h b/include/uapi/linux/fpga.h
> new file mode 100644
> index 0000000000000..868650c66526b
> --- /dev/null
> +++ b/include/uapi/linux/fpga.h
> @@ -0,0 +1,15 @@
> +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
> +/*
> + * FPGA userspace API
> + *
> + * Copyright (C) 2026 Advanced Micro Devices, Inc.
> + */
> +#ifndef _UAPI_LINUX_FPGA_H
> +#define _UAPI_LINUX_FPGA_H
> +
> +#include <linux/ioctl.h>
> +#include <linux/types.h>
> +
> +#define FPGA_IOCTL_LOAD_DMA_BUF	_IOW('J', 1, __s32)

[Severity: High]
Since this IOCTL only takes a file descriptor (__s32), how does userspace
supply the exact payload size of the firmware?

In fpga_dmabuf_load(), the info struct is zero-allocated, leaving
info->data_size as 0. When fpga_mgr_buf_load_sg() evaluates the scatterlist,
if data_size is 0, it loops over the entire mapped capacity of the sg_table.

Because dma-bufs are typically page-aligned, will this result in writing
padding bytes at the end of the buffer directly into the FPGA configuration
port, potentially corrupting the hardware state?

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260816150734.2092802-1-aravind.thokala@amd.com?part=1

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

end of thread, other threads:[~2026-08-16 15:19 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-08-16 15:07 [PATCH 0/2] fpga: add dma-buf based FPGA programming interface Aravind Thokala
2026-08-16 15:07 ` [PATCH 1/2] fpga: Add dma-buf interface for FPGA programming Aravind Thokala
2026-08-16 15:19   ` sashiko-bot
2026-08-16 15:07 ` [PATCH 2/2] fpga: versal: add dma-buf programming support Aravind Thokala
2026-08-16 15:18   ` sashiko-bot

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.