* [PATCH v2 0/5] remoteproc: cleanup shared carveout and resource-table helpers
@ 2026-05-14 16:21 Ben Levinsky
2026-05-14 16:21 ` [PATCH v2 1/5] remoteproc: add common wc-ioremap carveout callbacks Ben Levinsky
` (4 more replies)
0 siblings, 5 replies; 9+ messages in thread
From: Ben Levinsky @ 2026-05-14 16:21 UTC (permalink / raw)
To: andersson, mathieu.poirier, linux-remoteproc
Cc: Frank.Li, s.hauer, kernel, festevam, geert+renesas, magnus.damm,
patrice.chotard, mcoquelin.stm32, alexandre.torgue,
arnaud.pouliquen, daniel.baluta, tanmay.shah, imx,
linux-arm-kernel, linux-kernel, linux-renesas-soc, linux-stm32
This series is a preparatory remoteproc cleanup split out from review of
the AMD BRAM-based remoteproc series.
During review, there was a request to move the duplicated plain
ioremap_wc()/iounmap() carveout callbacks into common code and to
factor the "missing resource table is OK" ELF parsing path into a
common helper as well. There was also a request to send that cleanup as
its own patchset first, with the AMD BRAM series respun afterwards on
top once this cleanup is merged.
This version keeps the same overall cleanup goals as v1, but reworks
the series based on review:
- keep the shared wc-ioremap callback addition behavior-neutral
- add the common ioremap failure message in the shared helper
- split mem->is_iomem handling into its own follow-up patch with
framework-level justification
- keep logging policy out of the optional resource-table helper
- retain thin driver-local parse_fw() wrappers so each platform keeps
control over whether the missing-table case is logged and at what
level
This series now does that in five patches:
1. add common subsystem-private callbacks for the exact-match
wc-ioremap carveout case
2. switch the in-tree exact-match users over to those callbacks
3. mark carveouts mapped through the shared wc-ioremap helper as
iomem so the framework uses the proper I/O accessors
4. add a common helper for drivers that treat a missing ELF resource
table as optional, returning success on -EINVAL and propagating
other errors unchanged
5. switch the matching in-tree drivers over to that helper while
keeping per-driver logging decisions local
For the carveout map/unmap cleanup, this series covers the exact-match
users called out in review: xlnx_r5_remoteproc, rcar_rproc,
st_remoteproc, stm32_rproc, imx_rproc, and imx_dsp_rproc. The zynqmp R5
TCM mapping path is left alone because it also clears the mapped memory
and is not an exact match.
For the optional resource-table handling, this series converts
xlnx_r5_remoteproc, rcar_rproc, stm32_rproc, imx_rproc, and
imx_dsp_rproc. st_remoteproc is intentionally left unchanged because its
parse_fw() callback also builds carveouts and is therefore not a direct
match for the helper introduced here.
Changes in v2:
- split the mem->is_iomem change out into a separate patch
- add a common error message on ioremap_wc() failure
- drop logging from the optional resource-table helper
- keep driver-local parse_fw() wrappers to preserve per-platform
missing-resource-table logging policy
Ben Levinsky (5):
remoteproc: add common wc-ioremap carveout callbacks
remoteproc: switch exact-match drivers to wc-ioremap callbacks
remoteproc: mark wc-ioremap carveouts as iomem
remoteproc: add helper for optional ELF resource tables
remoteproc: switch drivers to optional resource-table helper
drivers/remoteproc/imx_dsp_rproc.c | 60 ++++++----------
drivers/remoteproc/imx_rproc.c | 57 +++++----------
drivers/remoteproc/rcar_rproc.c | 58 +++++-----------
drivers/remoteproc/remoteproc_internal.h | 38 +++++++++-
drivers/remoteproc/st_remoteproc.c | 31 +--------
drivers/remoteproc/stm32_rproc.c | 57 +++++----------
drivers/remoteproc/xlnx_r5_remoteproc.c | 88 +++++-------------------
7 files changed, 128 insertions(+), 261 deletions(-)
--
2.34.1
^ permalink raw reply [flat|nested] 9+ messages in thread* [PATCH v2 1/5] remoteproc: add common wc-ioremap carveout callbacks 2026-05-14 16:21 [PATCH v2 0/5] remoteproc: cleanup shared carveout and resource-table helpers Ben Levinsky @ 2026-05-14 16:21 ` Ben Levinsky 2026-05-14 16:21 ` [PATCH v2 2/5] remoteproc: switch exact-match drivers to wc-ioremap callbacks Ben Levinsky ` (3 subsequent siblings) 4 siblings, 0 replies; 9+ messages in thread From: Ben Levinsky @ 2026-05-14 16:21 UTC (permalink / raw) To: andersson, mathieu.poirier, linux-remoteproc Cc: Frank.Li, s.hauer, kernel, festevam, geert+renesas, magnus.damm, patrice.chotard, mcoquelin.stm32, alexandre.torgue, arnaud.pouliquen, daniel.baluta, tanmay.shah, imx, linux-arm-kernel, linux-kernel, linux-renesas-soc, linux-stm32 Several remoteproc drivers open-code the same ioremap_wc() and iounmap() callbacks for carveout mappings. Add subsystem-private helpers in remoteproc_internal.h so those drivers can share the same implementation. Keep this change behavior-neutral. The helper now emits a common error message on ioremap_wc() failure, but leaves mem->is_iomem handling to a follow-on patch so that the behavioral change can be justified separately. Signed-off-by: Ben Levinsky <ben.levinsky@amd.com> --- drivers/remoteproc/remoteproc_internal.h | 28 +++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/drivers/remoteproc/remoteproc_internal.h b/drivers/remoteproc/remoteproc_internal.h index 0a5e15744b1d..f5b34aabed5b 100644 --- a/drivers/remoteproc/remoteproc_internal.h +++ b/drivers/remoteproc/remoteproc_internal.h @@ -12,8 +12,9 @@ #ifndef REMOTEPROC_INTERNAL_H #define REMOTEPROC_INTERNAL_H -#include <linux/irqreturn.h> #include <linux/firmware.h> +#include <linux/io.h> +#include <linux/irqreturn.h> struct rproc; @@ -122,6 +123,31 @@ rproc_find_carveout_by_name(struct rproc *rproc, const char *name, ...); void rproc_add_rvdev(struct rproc *rproc, struct rproc_vdev *rvdev); void rproc_remove_rvdev(struct rproc_vdev *rvdev); +static inline int rproc_mem_entry_ioremap_wc(struct rproc *rproc, + struct rproc_mem_entry *mem) +{ + void __iomem *va; + + va = ioremap_wc(mem->dma, mem->len); + if (!va) { + dev_err(&rproc->dev, "Unable to map memory region: %pa+%zx\n", + &mem->dma, mem->len); + return -ENOMEM; + } + + mem->va = (__force void *)va; + + return 0; +} + +static inline int rproc_mem_entry_iounmap(struct rproc *rproc, + struct rproc_mem_entry *mem) +{ + iounmap((__force __iomem void *)mem->va); + + return 0; +} + static inline int rproc_prepare_device(struct rproc *rproc) { if (rproc->ops->prepare) -- 2.34.1 ^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH v2 2/5] remoteproc: switch exact-match drivers to wc-ioremap callbacks 2026-05-14 16:21 [PATCH v2 0/5] remoteproc: cleanup shared carveout and resource-table helpers Ben Levinsky 2026-05-14 16:21 ` [PATCH v2 1/5] remoteproc: add common wc-ioremap carveout callbacks Ben Levinsky @ 2026-05-14 16:21 ` Ben Levinsky 2026-05-14 21:00 ` sashiko-bot 2026-05-14 16:21 ` [PATCH v2 3/5] remoteproc: mark wc-ioremap carveouts as iomem Ben Levinsky ` (2 subsequent siblings) 4 siblings, 1 reply; 9+ messages in thread From: Ben Levinsky @ 2026-05-14 16:21 UTC (permalink / raw) To: andersson, mathieu.poirier, linux-remoteproc Cc: Frank.Li, s.hauer, kernel, festevam, geert+renesas, magnus.damm, patrice.chotard, mcoquelin.stm32, alexandre.torgue, arnaud.pouliquen, daniel.baluta, tanmay.shah, imx, linux-arm-kernel, linux-kernel, linux-renesas-soc, linux-stm32 Replace the exact-match carveout map and unmap callbacks in the existing remoteproc drivers with the common wc-ioremap helpers. This covers xlnx_r5_remoteproc, rcar_rproc, st_remoteproc, stm32_rproc, imx_rproc, and imx_dsp_rproc. Leave the zynqmp R5 TCM callbacks alone because they also clear the mapped memory and are therefore not exact matches for the shared helpers. Signed-off-by: Ben Levinsky <ben.levinsky@amd.com> Reviewed-by: Geert Uytterhoeven <geert+renesas@glider.be> # renesas --- drivers/remoteproc/imx_dsp_rproc.c | 36 ++++--------------- drivers/remoteproc/imx_rproc.c | 32 ++--------------- drivers/remoteproc/rcar_rproc.c | 33 ++--------------- drivers/remoteproc/st_remoteproc.c | 31 ++-------------- drivers/remoteproc/stm32_rproc.c | 34 ++---------------- drivers/remoteproc/xlnx_r5_remoteproc.c | 47 +++---------------------- 6 files changed, 18 insertions(+), 195 deletions(-) diff --git a/drivers/remoteproc/imx_dsp_rproc.c b/drivers/remoteproc/imx_dsp_rproc.c index 008741af9f11..2d9f14fbef1d 100644 --- a/drivers/remoteproc/imx_dsp_rproc.c +++ b/drivers/remoteproc/imx_dsp_rproc.c @@ -644,32 +644,6 @@ static void imx_dsp_rproc_free_mbox(struct imx_dsp_rproc *priv) mbox_free_channel(priv->rxdb_ch); } -static int imx_dsp_rproc_mem_alloc(struct rproc *rproc, - struct rproc_mem_entry *mem) -{ - struct device *dev = rproc->dev.parent; - void *va; - - va = ioremap_wc(mem->dma, mem->len); - if (!va) { - dev_err(dev, "Unable to map memory region: %pa+%zx\n", - &mem->dma, mem->len); - return -ENOMEM; - } - - mem->va = va; - - return 0; -} - -static int imx_dsp_rproc_mem_release(struct rproc *rproc, - struct rproc_mem_entry *mem) -{ - iounmap(mem->va); - - return 0; -} - /** * imx_dsp_rproc_add_carveout() - request mailbox channels * @priv: private data pointer @@ -700,8 +674,10 @@ static int imx_dsp_rproc_add_carveout(struct imx_dsp_rproc *priv) /* Register memory region */ mem = rproc_mem_entry_init(dev, NULL, (dma_addr_t)att->sa, - att->size, da, imx_dsp_rproc_mem_alloc, - imx_dsp_rproc_mem_release, "dsp_mem"); + att->size, da, + rproc_mem_entry_ioremap_wc, + rproc_mem_entry_iounmap, + "dsp_mem"); if (mem) rproc_coredump_add_segment(rproc, da, att->size); @@ -732,8 +708,8 @@ static int imx_dsp_rproc_add_carveout(struct imx_dsp_rproc *priv) /* Register memory region */ mem = rproc_mem_entry_init(dev, NULL, (dma_addr_t)res.start, resource_size(&res), da, - imx_dsp_rproc_mem_alloc, - imx_dsp_rproc_mem_release, + rproc_mem_entry_ioremap_wc, + rproc_mem_entry_iounmap, "%.*s", strchrnul(res.name, '@') - res.name, res.name); if (!mem) return -ENOMEM; diff --git a/drivers/remoteproc/imx_rproc.c b/drivers/remoteproc/imx_rproc.c index 7f54322244ac..6249815b54d8 100644 --- a/drivers/remoteproc/imx_rproc.c +++ b/drivers/remoteproc/imx_rproc.c @@ -600,35 +600,6 @@ static void *imx_rproc_da_to_va(struct rproc *rproc, u64 da, size_t len, bool *i return va; } -static int imx_rproc_mem_alloc(struct rproc *rproc, - struct rproc_mem_entry *mem) -{ - struct device *dev = rproc->dev.parent; - void *va; - - dev_dbg(dev, "map memory: %p+%zx\n", &mem->dma, mem->len); - va = ioremap_wc(mem->dma, mem->len); - if (IS_ERR_OR_NULL(va)) { - dev_err(dev, "Unable to map memory region: %p+%zx\n", - &mem->dma, mem->len); - return -ENOMEM; - } - - /* Update memory entry va */ - mem->va = va; - - return 0; -} - -static int imx_rproc_mem_release(struct rproc *rproc, - struct rproc_mem_entry *mem) -{ - dev_dbg(rproc->dev.parent, "unmap memory: %pa\n", &mem->dma); - iounmap(mem->va); - - return 0; -} - static int imx_rproc_sm_lmm_prepare(struct rproc *rproc) { struct imx_rproc *priv = rproc->priv; @@ -692,7 +663,8 @@ static int imx_rproc_prepare(struct rproc *rproc) /* Register memory region */ mem = rproc_mem_entry_init(priv->dev, NULL, (dma_addr_t)res.start, resource_size(&res), da, - imx_rproc_mem_alloc, imx_rproc_mem_release, + rproc_mem_entry_ioremap_wc, + rproc_mem_entry_iounmap, "%.*s", strchrnul(res.name, '@') - res.name, res.name); if (!mem) diff --git a/drivers/remoteproc/rcar_rproc.c b/drivers/remoteproc/rcar_rproc.c index 3c25625f966d..e3121fadd292 100644 --- a/drivers/remoteproc/rcar_rproc.c +++ b/drivers/remoteproc/rcar_rproc.c @@ -19,35 +19,6 @@ struct rcar_rproc { struct reset_control *rst; }; -static int rcar_rproc_mem_alloc(struct rproc *rproc, - struct rproc_mem_entry *mem) -{ - struct device *dev = &rproc->dev; - void *va; - - dev_dbg(dev, "map memory: %pa+%zx\n", &mem->dma, mem->len); - va = ioremap_wc(mem->dma, mem->len); - if (!va) { - dev_err(dev, "Unable to map memory region: %pa+%zx\n", - &mem->dma, mem->len); - return -ENOMEM; - } - - /* Update memory entry va */ - mem->va = va; - - return 0; -} - -static int rcar_rproc_mem_release(struct rproc *rproc, - struct rproc_mem_entry *mem) -{ - dev_dbg(&rproc->dev, "unmap memory: %pa\n", &mem->dma); - iounmap(mem->va); - - return 0; -} - static int rcar_rproc_prepare(struct rproc *rproc) { struct device *dev = rproc->dev.parent; @@ -73,8 +44,8 @@ static int rcar_rproc_prepare(struct rproc *rproc) mem = rproc_mem_entry_init(dev, NULL, res.start, resource_size(&res), da, - rcar_rproc_mem_alloc, - rcar_rproc_mem_release, + rproc_mem_entry_ioremap_wc, + rproc_mem_entry_iounmap, res.name); if (!mem) diff --git a/drivers/remoteproc/st_remoteproc.c b/drivers/remoteproc/st_remoteproc.c index a07edf7217d2..486180cdccb4 100644 --- a/drivers/remoteproc/st_remoteproc.c +++ b/drivers/remoteproc/st_remoteproc.c @@ -88,33 +88,6 @@ static void st_rproc_kick(struct rproc *rproc, int vqid) dev_err(dev, "failed to send message via mbox: %d\n", ret); } -static int st_rproc_mem_alloc(struct rproc *rproc, - struct rproc_mem_entry *mem) -{ - struct device *dev = rproc->dev.parent; - void *va; - - va = ioremap_wc(mem->dma, mem->len); - if (!va) { - dev_err(dev, "Unable to map memory region: %pa+%zx\n", - &mem->dma, mem->len); - return -ENOMEM; - } - - /* Update memory entry va */ - mem->va = va; - - return 0; -} - -static int st_rproc_mem_release(struct rproc *rproc, - struct rproc_mem_entry *mem) -{ - iounmap(mem->va); - - return 0; -} - static int st_rproc_parse_fw(struct rproc *rproc, const struct firmware *fw) { struct device *dev = rproc->dev.parent; @@ -138,8 +111,8 @@ static int st_rproc_parse_fw(struct rproc *rproc, const struct firmware *fw) mem = rproc_mem_entry_init(dev, NULL, (dma_addr_t)res.start, resource_size(&res), res.start, - st_rproc_mem_alloc, - st_rproc_mem_release, + rproc_mem_entry_ioremap_wc, + rproc_mem_entry_iounmap, "%.*s", strchrnul(res.name, '@') - res.name, res.name); diff --git a/drivers/remoteproc/stm32_rproc.c b/drivers/remoteproc/stm32_rproc.c index 632614013dc6..7ac8265b60ac 100644 --- a/drivers/remoteproc/stm32_rproc.c +++ b/drivers/remoteproc/stm32_rproc.c @@ -113,35 +113,6 @@ static int stm32_rproc_pa_to_da(struct rproc *rproc, phys_addr_t pa, u64 *da) return -EINVAL; } -static int stm32_rproc_mem_alloc(struct rproc *rproc, - struct rproc_mem_entry *mem) -{ - struct device *dev = rproc->dev.parent; - void *va; - - dev_dbg(dev, "map memory: %pad+%zx\n", &mem->dma, mem->len); - va = (__force void *)ioremap_wc(mem->dma, mem->len); - if (IS_ERR_OR_NULL(va)) { - dev_err(dev, "Unable to map memory region: %pad+0x%zx\n", - &mem->dma, mem->len); - return -ENOMEM; - } - - /* Update memory entry va */ - mem->va = va; - - return 0; -} - -static int stm32_rproc_mem_release(struct rproc *rproc, - struct rproc_mem_entry *mem) -{ - dev_dbg(rproc->dev.parent, "unmap memory: %pa\n", &mem->dma); - iounmap((__force __iomem void *)mem->va); - - return 0; -} - static int stm32_rproc_of_memory_translations(struct platform_device *pdev, struct stm32_rproc *ddata) { @@ -237,8 +208,8 @@ static int stm32_rproc_prepare(struct rproc *rproc) mem = rproc_mem_entry_init(dev, NULL, (dma_addr_t)res.start, resource_size(&res), da, - stm32_rproc_mem_alloc, - stm32_rproc_mem_release, + rproc_mem_entry_ioremap_wc, + rproc_mem_entry_iounmap, "%.*s", strchrnul(res.name, '@') - res.name, res.name); if (mem) @@ -957,4 +928,3 @@ MODULE_DESCRIPTION("STM32 Remote Processor Control Driver"); MODULE_AUTHOR("Ludovic Barre <ludovic.barre@st.com>"); MODULE_AUTHOR("Fabien Dessenne <fabien.dessenne@st.com>"); MODULE_LICENSE("GPL v2"); - diff --git a/drivers/remoteproc/xlnx_r5_remoteproc.c b/drivers/remoteproc/xlnx_r5_remoteproc.c index 45a62cb98072..e5d1903c9636 100644 --- a/drivers/remoteproc/xlnx_r5_remoteproc.c +++ b/drivers/remoteproc/xlnx_r5_remoteproc.c @@ -447,45 +447,6 @@ static int zynqmp_r5_rproc_stop(struct rproc *rproc) return ret; } -/* - * zynqmp_r5_mem_region_map() - * @rproc: single R5 core's corresponding rproc instance - * @mem: mem descriptor to map reserved memory-regions - * - * Callback to map va for memory-region's carveout. - * - * return 0 on success, otherwise non-zero value on failure - */ -static int zynqmp_r5_mem_region_map(struct rproc *rproc, - struct rproc_mem_entry *mem) -{ - void __iomem *va; - - va = ioremap_wc(mem->dma, mem->len); - if (IS_ERR_OR_NULL(va)) - return -ENOMEM; - - mem->va = (void *)va; - - return 0; -} - -/* - * zynqmp_r5_rproc_mem_unmap - * @rproc: single R5 core's corresponding rproc instance - * @mem: mem entry to unmap - * - * Unmap memory-region carveout - * - * return: always returns 0 - */ -static int zynqmp_r5_mem_region_unmap(struct rproc *rproc, - struct rproc_mem_entry *mem) -{ - iounmap((void __iomem *)mem->va); - return 0; -} - /* * add_mem_regions_carveout() * @rproc: single R5 core's corresponding rproc instance @@ -522,8 +483,8 @@ static int add_mem_regions_carveout(struct rproc *rproc) rproc_mem = rproc_mem_entry_init(&rproc->dev, NULL, (dma_addr_t)res.start, resource_size(&res), res.start, - zynqmp_r5_mem_region_map, - zynqmp_r5_mem_region_unmap, + rproc_mem_entry_ioremap_wc, + rproc_mem_entry_iounmap, "%.*s", strchrnul(res.name, '@') - res.name, res.name); @@ -560,8 +521,8 @@ static int add_sram_carveouts(struct rproc *rproc) rproc_mem = rproc_mem_entry_init(&rproc->dev, NULL, dma_addr, len, da, - zynqmp_r5_mem_region_map, - zynqmp_r5_mem_region_unmap, + rproc_mem_entry_ioremap_wc, + rproc_mem_entry_iounmap, sram->sram_res.name); if (!rproc_mem) { dev_err(&rproc->dev, "failed to add sram %s da=0x%x, size=0x%lx", -- 2.34.1 ^ permalink raw reply related [flat|nested] 9+ messages in thread
* Re: [PATCH v2 2/5] remoteproc: switch exact-match drivers to wc-ioremap callbacks 2026-05-14 16:21 ` [PATCH v2 2/5] remoteproc: switch exact-match drivers to wc-ioremap callbacks Ben Levinsky @ 2026-05-14 21:00 ` sashiko-bot 0 siblings, 0 replies; 9+ messages in thread From: sashiko-bot @ 2026-05-14 21:00 UTC (permalink / raw) To: Ben Levinsky; +Cc: Frank.Li, imx, wsa+renesas Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider: - [High] Format string vulnerability when initializing rproc_mem_entry using device tree node names -- commit 1e23984cace57551a1444d0f4d0c49192a7ec852 Author: Ben Levinsky <ben.levinsky@amd.com> remoteproc: switch exact-match drivers to wc-ioremap callbacks This patch replaces the exact-match carveout map and unmap callbacks in existing remoteproc drivers with the common wc-ioremap helpers. > diff --git a/drivers/remoteproc/rcar_rproc.c b/drivers/remoteproc/rcar_rproc.c > index 3c25625f966dc..e3121fadd2925 100644 > --- a/drivers/remoteproc/rcar_rproc.c > +++ b/drivers/remoteproc/rcar_rproc.c [ ... ] > @@ -73,8 +44,8 @@ static int rcar_rproc_prepare(struct rproc *rproc) > mem = rproc_mem_entry_init(dev, NULL, > res.start, > resource_size(&res), da, > - rcar_rproc_mem_alloc, > - rcar_rproc_mem_release, > + rproc_mem_entry_ioremap_wc, > + rproc_mem_entry_iounmap, > res.name); This isn't a regression introduced by this patch, but since these lines are being modified, could this cause a format string issue? Looking at rproc_mem_entry_init(), it takes a format string as the name parameter and passes it to vsnprintf(). If a dynamically loaded device tree overlay has a node name in res.name containing format specifiers, could it lead to arbitrary stack reads? Would it be safer to use "%s", res.name here? [ ... ] > diff --git a/drivers/remoteproc/xlnx_r5_remoteproc.c b/drivers/remoteproc/xlnx_r5_remoteproc.c > index 45a62cb980725..e5d1903c9636a 100644 > --- a/drivers/remoteproc/xlnx_r5_remoteproc.c > +++ b/drivers/remoteproc/xlnx_r5_remoteproc.c [ ... ] > @@ -560,8 +521,8 @@ static int add_sram_carveouts(struct rproc *rproc) > rproc_mem = rproc_mem_entry_init(&rproc->dev, NULL, > dma_addr, > len, da, > - zynqmp_r5_mem_region_map, > - zynqmp_r5_mem_region_unmap, > + rproc_mem_entry_ioremap_wc, > + rproc_mem_entry_iounmap, > sram->sram_res.name); Similarly here, can passing sram->sram_res.name directly to rproc_mem_entry_init() trigger a format string vulnerability if the node name contains format specifiers? -- Sashiko AI review · https://sashiko.dev/#/patchset/20260514162129.1504162-1-ben.levinsky@amd.com?part=2 ^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH v2 3/5] remoteproc: mark wc-ioremap carveouts as iomem 2026-05-14 16:21 [PATCH v2 0/5] remoteproc: cleanup shared carveout and resource-table helpers Ben Levinsky 2026-05-14 16:21 ` [PATCH v2 1/5] remoteproc: add common wc-ioremap carveout callbacks Ben Levinsky 2026-05-14 16:21 ` [PATCH v2 2/5] remoteproc: switch exact-match drivers to wc-ioremap callbacks Ben Levinsky @ 2026-05-14 16:21 ` Ben Levinsky 2026-05-14 21:48 ` sashiko-bot 2026-05-14 16:21 ` [PATCH v2 4/5] remoteproc: add helper for optional ELF resource tables Ben Levinsky 2026-05-14 16:21 ` [PATCH v2 5/5] remoteproc: switch drivers to optional resource-table helper Ben Levinsky 4 siblings, 1 reply; 9+ messages in thread From: Ben Levinsky @ 2026-05-14 16:21 UTC (permalink / raw) To: andersson, mathieu.poirier, linux-remoteproc Cc: Frank.Li, s.hauer, kernel, festevam, geert+renesas, magnus.damm, patrice.chotard, mcoquelin.stm32, alexandre.torgue, arnaud.pouliquen, daniel.baluta, tanmay.shah, imx, linux-arm-kernel, linux-kernel, linux-renesas-soc, linux-stm32 Carveouts registered through the shared wc-ioremap helper are backed by I/O memory, but rproc_da_to_va() only reports that to its callers when mem->is_iomem is set on the carveout. Without that flag, the remoteproc ELF loader and coredump paths can fall back to normal memcpy()/memset() accessors instead of the I/O helpers used for iomapped memory. Mark shared wc-ioremap carveouts as iomem so the framework uses the proper memcpy_toio(), memset_io(), and memcpy_fromio() accessors for these regions. Signed-off-by: Ben Levinsky <ben.levinsky@amd.com> --- drivers/remoteproc/remoteproc_internal.h | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/remoteproc/remoteproc_internal.h b/drivers/remoteproc/remoteproc_internal.h index f5b34aabed5b..9955e512f073 100644 --- a/drivers/remoteproc/remoteproc_internal.h +++ b/drivers/remoteproc/remoteproc_internal.h @@ -136,6 +136,7 @@ static inline int rproc_mem_entry_ioremap_wc(struct rproc *rproc, } mem->va = (__force void *)va; + mem->is_iomem = true; return 0; } -- 2.34.1 ^ permalink raw reply related [flat|nested] 9+ messages in thread
* Re: [PATCH v2 3/5] remoteproc: mark wc-ioremap carveouts as iomem 2026-05-14 16:21 ` [PATCH v2 3/5] remoteproc: mark wc-ioremap carveouts as iomem Ben Levinsky @ 2026-05-14 21:48 ` sashiko-bot 0 siblings, 0 replies; 9+ messages in thread From: sashiko-bot @ 2026-05-14 21:48 UTC (permalink / raw) To: Ben Levinsky; +Cc: imx, wsa+renesas, Frank.Li Thank you for your contribution! Sashiko AI review found 4 potential issue(s) to consider: - [Critical] Integer Overflow in `rproc_elf_load_segments` allowing Out-of-Bounds Read. - [Critical] Integer Overflow in `rproc_da_to_va` bounds check allowing Out-of-Bounds Write. - [High] The patch correctly fixes the generic `rproc_mem_entry_ioremap_wc()` helper but overlooks driver-specific allocators and `da_to_va` callbacks that exhibit the exact same bug. - [High] Debugfs interface `rproc_trace_read` performs standard memory accesses on I/O memory, triggering panics. -- commit 185669571331faa11cc44eacd2568b0e202bcf9d Author: Ben Levinsky <ben.levinsky@amd.com> remoteproc: mark wc-ioremap carveouts as iomem This commit marks shared wc-ioremap carveouts as iomem in the generic rproc_mem_entry_ioremap_wc() helper. This ensures the remoteproc ELF loader uses the proper I/O memory accessors instead of falling back to standard memcpy() and memset(). > diff --git a/drivers/remoteproc/remoteproc_internal.h b/drivers/remoteproc/remoteproc_internal.h > index f5b34aabed5bb..9955e512f073d 100644 > --- a/drivers/remoteproc/remoteproc_internal.h > +++ b/drivers/remoteproc/remoteproc_internal.h > @@ -136,6 +136,7 @@ static inline int rproc_mem_entry_ioremap_wc(struct rproc *rproc, > } > > mem->va = (__force void *)va; > + mem->is_iomem = true; Does this change also need to be applied to driver-specific allocators and da_to_va callbacks? For example, in drivers/remoteproc/xlnx_r5_remoteproc.c, tcm_mem_map() maps memory via ioremap_wc() but does not set is_iomem to true. Similarly, keystone_rproc_da_to_va() and omap_rproc_da_to_va() appear to ignore the is_iomem pointer despite returning devm_ioremap_resource mapped memory. In imx_rproc_da_to_sys(), is_iomem is left false for regions mapped via devm_ioremap_wc() when ATT_IOMEM is not set. > > return 0; > } Are there potential integer overflows in rproc_elf_load_segments() when parsing ELF headers? If offset and filesz are parsed directly from 64-bit ELF program headers, could their sum wrap around: rproc_elf_load_segments() { ... if (offset + filesz > fw->size) ... memcpy(ptr, elf_data + offset, filesz); ... } If offset is near the maximum 64-bit value and filesz is small, the bounds check could be bypassed, resulting in an out-of-bounds read. Is there a similar overflow risk in the bounds check within rproc_da_to_va()? rproc_da_to_va() { ... if (offset + len > carveout->len) ... } If len is a size_t and offset is an int, could an ELF segment with a memsz near the maximum size_t value cause the sum to wrap around and bypass the bounds check? This could affect rproc_elf_load_segments() if it executes a memset using the large memsz value, resulting in an out-of-bounds write. Does the debugfs interface have a related regression with I/O memory access? In rproc_trace_read(), the memory type is ignored by passing NULL for the is_iomem flag to rproc_da_to_va(): rproc_trace_read() { ... va = rproc_da_to_va(rproc, trace->da, trace->len, NULL); ... } If the returned virtual address is mapped as device memory, such as via devm_ioremap_resource() in keystone_remoteproc.c, could passing it directly to strnlen() and simple_read_from_buffer() trigger alignment faults on strict architectures? -- Sashiko AI review · https://sashiko.dev/#/patchset/20260514162129.1504162-1-ben.levinsky@amd.com?part=3 ^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH v2 4/5] remoteproc: add helper for optional ELF resource tables 2026-05-14 16:21 [PATCH v2 0/5] remoteproc: cleanup shared carveout and resource-table helpers Ben Levinsky ` (2 preceding siblings ...) 2026-05-14 16:21 ` [PATCH v2 3/5] remoteproc: mark wc-ioremap carveouts as iomem Ben Levinsky @ 2026-05-14 16:21 ` Ben Levinsky 2026-05-14 16:21 ` [PATCH v2 5/5] remoteproc: switch drivers to optional resource-table helper Ben Levinsky 4 siblings, 0 replies; 9+ messages in thread From: Ben Levinsky @ 2026-05-14 16:21 UTC (permalink / raw) To: andersson, mathieu.poirier, linux-remoteproc Cc: Frank.Li, s.hauer, kernel, festevam, geert+renesas, magnus.damm, patrice.chotard, mcoquelin.stm32, alexandre.torgue, arnaud.pouliquen, daniel.baluta, tanmay.shah, imx, linux-arm-kernel, linux-kernel, linux-renesas-soc, linux-stm32 Add a small helper around rproc_elf_load_rsc_table() for remoteproc drivers that treat a missing ELF resource table as optional. The helper returns success on -EINVAL and propagates other failures unchanged. Keep logging policy out of the helper so platform drivers can decide whether a missing resource table should be reported and at what log level. Signed-off-by: Ben Levinsky <ben.levinsky@amd.com> --- drivers/remoteproc/remoteproc_internal.h | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/drivers/remoteproc/remoteproc_internal.h b/drivers/remoteproc/remoteproc_internal.h index 9955e512f073..565b35256945 100644 --- a/drivers/remoteproc/remoteproc_internal.h +++ b/drivers/remoteproc/remoteproc_internal.h @@ -149,6 +149,15 @@ static inline int rproc_mem_entry_iounmap(struct rproc *rproc, return 0; } +static inline int rproc_elf_load_rsc_table_optional(struct rproc *rproc, + const struct firmware *fw) +{ + int ret; + + ret = rproc_elf_load_rsc_table(rproc, fw); + return ret == -EINVAL ? 0 : ret; +} + static inline int rproc_prepare_device(struct rproc *rproc) { if (rproc->ops->prepare) -- 2.34.1 ^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH v2 5/5] remoteproc: switch drivers to optional resource-table helper 2026-05-14 16:21 [PATCH v2 0/5] remoteproc: cleanup shared carveout and resource-table helpers Ben Levinsky ` (3 preceding siblings ...) 2026-05-14 16:21 ` [PATCH v2 4/5] remoteproc: add helper for optional ELF resource tables Ben Levinsky @ 2026-05-14 16:21 ` Ben Levinsky 2026-05-14 22:14 ` sashiko-bot 4 siblings, 1 reply; 9+ messages in thread From: Ben Levinsky @ 2026-05-14 16:21 UTC (permalink / raw) To: andersson, mathieu.poirier, linux-remoteproc Cc: Frank.Li, s.hauer, kernel, festevam, geert+renesas, magnus.damm, patrice.chotard, mcoquelin.stm32, alexandre.torgue, arnaud.pouliquen, daniel.baluta, tanmay.shah, imx, linux-arm-kernel, linux-kernel, linux-renesas-soc, linux-stm32 Use the shared optional resource-table helper in the remoteproc drivers that already treat a missing resource table as non-fatal: xlnx_r5_remoteproc, rcar_rproc, stm32_rproc, imx_rproc, and imx_dsp_rproc. Keep thin local parse_fw() wrappers in each driver so the helper only centralizes the return-value handling. That lets each platform retain control over whether the missing-table case is logged and at what severity, while other parsing failures continue to propagate to the caller. Signed-off-by: Ben Levinsky <ben.levinsky@amd.com> --- drivers/remoteproc/imx_dsp_rproc.c | 24 ++++++++++----- drivers/remoteproc/imx_rproc.c | 25 ++++++++------- drivers/remoteproc/rcar_rproc.c | 25 ++++++++------- drivers/remoteproc/stm32_rproc.c | 23 +++++++++----- drivers/remoteproc/xlnx_r5_remoteproc.c | 41 +++++++++---------------- 5 files changed, 73 insertions(+), 65 deletions(-) diff --git a/drivers/remoteproc/imx_dsp_rproc.c b/drivers/remoteproc/imx_dsp_rproc.c index 2d9f14fbef1d..2ff74f7938f6 100644 --- a/drivers/remoteproc/imx_dsp_rproc.c +++ b/drivers/remoteproc/imx_dsp_rproc.c @@ -954,14 +954,6 @@ static int imx_dsp_rproc_elf_load_segments(struct rproc *rproc, const struct fir return ret; } -static int imx_dsp_rproc_parse_fw(struct rproc *rproc, const struct firmware *fw) -{ - if (rproc_elf_load_rsc_table(rproc, fw)) - dev_warn(&rproc->dev, "no resource table found for this firmware\n"); - - return 0; -} - static int imx_dsp_rproc_load(struct rproc *rproc, const struct firmware *fw) { struct imx_dsp_rproc *priv = rproc->priv; @@ -990,6 +982,22 @@ static int imx_dsp_rproc_load(struct rproc *rproc, const struct firmware *fw) return 0; } +static int imx_dsp_rproc_parse_fw(struct rproc *rproc, + const struct firmware *fw) +{ + int ret; + + ret = rproc_elf_load_rsc_table_optional(rproc, fw); + if (ret) + return ret; + + if (!rproc->table_ptr) + dev_warn(&rproc->dev, + "no resource table found for this firmware\n"); + + return 0; +} + static const struct rproc_ops imx_dsp_rproc_ops = { .prepare = imx_dsp_rproc_prepare, .unprepare = imx_dsp_rproc_unprepare, diff --git a/drivers/remoteproc/imx_rproc.c b/drivers/remoteproc/imx_rproc.c index 6249815b54d8..58c63f97ebf7 100644 --- a/drivers/remoteproc/imx_rproc.c +++ b/drivers/remoteproc/imx_rproc.c @@ -680,17 +680,6 @@ static int imx_rproc_prepare(struct rproc *rproc) return 0; } -static int imx_rproc_parse_fw(struct rproc *rproc, const struct firmware *fw) -{ - int ret; - - ret = rproc_elf_load_rsc_table(rproc, fw); - if (ret) - dev_info(&rproc->dev, "No resource table in elf\n"); - - return 0; -} - static void imx_rproc_kick(struct rproc *rproc, int vqid) { struct imx_rproc *priv = rproc->priv; @@ -768,6 +757,20 @@ imx_rproc_elf_find_loaded_rsc_table(struct rproc *rproc, const struct firmware * return rproc_elf_find_loaded_rsc_table(rproc, fw); } +static int imx_rproc_parse_fw(struct rproc *rproc, const struct firmware *fw) +{ + int ret; + + ret = rproc_elf_load_rsc_table_optional(rproc, fw); + if (ret) + return ret; + + if (!rproc->table_ptr) + dev_info(&rproc->dev, "No resource table in elf\n"); + + return 0; +} + static const struct rproc_ops imx_rproc_ops = { .prepare = imx_rproc_prepare, .attach = imx_rproc_attach, diff --git a/drivers/remoteproc/rcar_rproc.c b/drivers/remoteproc/rcar_rproc.c index e3121fadd292..b7a39014b6bb 100644 --- a/drivers/remoteproc/rcar_rproc.c +++ b/drivers/remoteproc/rcar_rproc.c @@ -55,17 +55,6 @@ static int rcar_rproc_prepare(struct rproc *rproc) } } -static int rcar_rproc_parse_fw(struct rproc *rproc, const struct firmware *fw) -{ - int ret; - - ret = rproc_elf_load_rsc_table(rproc, fw); - if (ret) - dev_info(&rproc->dev, "No resource table in elf\n"); - - return 0; -} - static int rcar_rproc_start(struct rproc *rproc) { struct rcar_rproc *priv = rproc->priv; @@ -99,6 +88,20 @@ static int rcar_rproc_stop(struct rproc *rproc) return err; } +static int rcar_rproc_parse_fw(struct rproc *rproc, const struct firmware *fw) +{ + int ret; + + ret = rproc_elf_load_rsc_table_optional(rproc, fw); + if (ret) + return ret; + + if (!rproc->table_ptr) + dev_info(&rproc->dev, "No resource table in elf\n"); + + return 0; +} + static struct rproc_ops rcar_rproc_ops = { .prepare = rcar_rproc_prepare, .start = rcar_rproc_start, diff --git a/drivers/remoteproc/stm32_rproc.c b/drivers/remoteproc/stm32_rproc.c index 7ac8265b60ac..a4d42b755c74 100644 --- a/drivers/remoteproc/stm32_rproc.c +++ b/drivers/remoteproc/stm32_rproc.c @@ -232,14 +232,6 @@ static int stm32_rproc_prepare(struct rproc *rproc) } } -static int stm32_rproc_parse_fw(struct rproc *rproc, const struct firmware *fw) -{ - if (rproc_elf_load_rsc_table(rproc, fw)) - dev_warn(&rproc->dev, "no resource table found for this firmware\n"); - - return 0; -} - static irqreturn_t stm32_rproc_wdg(int irq, void *data) { struct platform_device *pdev = data; @@ -623,6 +615,21 @@ stm32_rproc_get_loaded_rsc_table(struct rproc *rproc, size_t *table_sz) return (__force struct resource_table *)ddata->rsc_va; } +static int stm32_rproc_parse_fw(struct rproc *rproc, const struct firmware *fw) +{ + int ret; + + ret = rproc_elf_load_rsc_table_optional(rproc, fw); + if (ret) + return ret; + + if (!rproc->table_ptr) + dev_warn(&rproc->dev, + "no resource table found for this firmware\n"); + + return 0; +} + static const struct rproc_ops st_rproc_ops = { .prepare = stm32_rproc_prepare, .start = stm32_rproc_start, diff --git a/drivers/remoteproc/xlnx_r5_remoteproc.c b/drivers/remoteproc/xlnx_r5_remoteproc.c index e5d1903c9636..9b9f07d152e6 100644 --- a/drivers/remoteproc/xlnx_r5_remoteproc.c +++ b/drivers/remoteproc/xlnx_r5_remoteproc.c @@ -664,33 +664,6 @@ static int add_tcm_banks(struct rproc *rproc) return ret; } -/* - * zynqmp_r5_parse_fw() - * @rproc: single R5 core's corresponding rproc instance - * @fw: ptr to firmware to be loaded onto r5 core - * - * get resource table if available - * - * return 0 on success, otherwise non-zero value on failure - */ -static int zynqmp_r5_parse_fw(struct rproc *rproc, const struct firmware *fw) -{ - int ret; - - ret = rproc_elf_load_rsc_table(rproc, fw); - if (ret == -EINVAL) { - /* - * resource table only required for IPC. - * if not present, this is not necessarily an error; - * for example, loading r5 hello world application - * so simply inform user and keep going. - */ - dev_info(&rproc->dev, "no resource table found.\n"); - ret = 0; - } - return ret; -} - /** * zynqmp_r5_rproc_prepare() - prepare core to boot/attach * adds carveouts for TCM bank and reserved memory regions @@ -843,6 +816,20 @@ static int zynqmp_r5_detach(struct rproc *rproc) return 0; } +static int zynqmp_r5_parse_fw(struct rproc *rproc, const struct firmware *fw) +{ + int ret; + + ret = rproc_elf_load_rsc_table_optional(rproc, fw); + if (ret) + return ret; + + if (!rproc->table_ptr) + dev_info(&rproc->dev, "no resource table found.\n"); + + return 0; +} + static const struct rproc_ops zynqmp_r5_rproc_ops = { .prepare = zynqmp_r5_rproc_prepare, .unprepare = zynqmp_r5_rproc_unprepare, -- 2.34.1 ^ permalink raw reply related [flat|nested] 9+ messages in thread
* Re: [PATCH v2 5/5] remoteproc: switch drivers to optional resource-table helper 2026-05-14 16:21 ` [PATCH v2 5/5] remoteproc: switch drivers to optional resource-table helper Ben Levinsky @ 2026-05-14 22:14 ` sashiko-bot 0 siblings, 0 replies; 9+ messages in thread From: sashiko-bot @ 2026-05-14 22:14 UTC (permalink / raw) To: Ben Levinsky; +Cc: imx, wsa+renesas, Frank.Li Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider: - [High] This problem wasn't introduced by this patch, but an integer overflow in ELF segment bounds checking in `imx_dsp_rproc_elf_load_segments()` allows an attacker to bypass validations and perform an out-of-bounds read. `offset` and `filesz` are 64-bit values (`u64`) parsed directly from ELF program headers. The boundary check `if (offset + filesz > fw->size)` lacks protection against integer overflow. A malicious or corrupted firmware can supply a massive `offset` (e.g., 0xFFFFFFFFFFFFFFFE) and a small `filesz` (e.g., 0x10), causing `offset + filesz` to wrap around to a small integer (0x0E). This bypasses the `> fw->size` check. The code then executes `imx_dsp_rproc_memcpy(ptr, elf_data + offset, filesz);`, where pointer arithmetic on `elf_data + offset` resolves outside the firmware buffer, resulting in an out-of-bounds read that leaks kernel memory or causes a kernel panic. -- commit 71c8dfba5336b57c340ad4c8970a2211c5b78f4f Author: Ben Levinsky <ben.levinsky@amd.com> remoteproc: switch drivers to optional resource-table helper This commit switches several remoteproc drivers to use the shared optional resource-table helper for firmware that treats a missing resource table as non-fatal. It retains local parse_fw() wrappers to manage return-value logging and severity. > diff --git a/drivers/remoteproc/imx_dsp_rproc.c b/drivers/remoteproc/imx_dsp_rproc.c > index 2d9f14fbef1da..2ff74f7938f61 100644 > --- a/drivers/remoteproc/imx_dsp_rproc.c > +++ b/drivers/remoteproc/imx_dsp_rproc.c > @@ -954,14 +954,6 @@ static int imx_dsp_rproc_elf_load_segments(struct rproc *rproc, const struct fir > return ret; > } This problem wasn't introduced by this patch, but while reviewing imx_dsp_rproc_elf_load_segments(), I noticed a potential integer overflow in the ELF segment bounds checking. Since offset and filesz are 64-bit values (u64) parsed directly from the ELF program headers, does this code overflow offset + filesz? drivers/remoteproc/imx_dsp_rproc.c:imx_dsp_rproc_elf_load_segments() { ... if (offset + filesz > fw->size) { dev_err(dev, "truncated fw: need 0x%llx avail 0x%zx\n", offset + filesz, fw->size); ret = -EINVAL; break; } ... if (filesz) { ret = imx_dsp_rproc_memcpy(ptr, elf_data + offset, filesz); ... } A malicious or corrupted firmware could supply a massive offset (e.g., 0xFFFFFFFFFFFFFFFE) and a small filesz (e.g., 0x10). This would cause offset + filesz to wrap around to a small integer (0x0E), bypassing the bounds check. Could this lead to pointer arithmetic on elf_data + offset resolving outside the firmware buffer, resulting in an out-of-bounds read during the memcpy? [ ... ] -- Sashiko AI review · https://sashiko.dev/#/patchset/20260514162129.1504162-1-ben.levinsky@amd.com?part=5 ^ permalink raw reply [flat|nested] 9+ messages in thread
end of thread, other threads:[~2026-05-14 22:14 UTC | newest] Thread overview: 9+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2026-05-14 16:21 [PATCH v2 0/5] remoteproc: cleanup shared carveout and resource-table helpers Ben Levinsky 2026-05-14 16:21 ` [PATCH v2 1/5] remoteproc: add common wc-ioremap carveout callbacks Ben Levinsky 2026-05-14 16:21 ` [PATCH v2 2/5] remoteproc: switch exact-match drivers to wc-ioremap callbacks Ben Levinsky 2026-05-14 21:00 ` sashiko-bot 2026-05-14 16:21 ` [PATCH v2 3/5] remoteproc: mark wc-ioremap carveouts as iomem Ben Levinsky 2026-05-14 21:48 ` sashiko-bot 2026-05-14 16:21 ` [PATCH v2 4/5] remoteproc: add helper for optional ELF resource tables Ben Levinsky 2026-05-14 16:21 ` [PATCH v2 5/5] remoteproc: switch drivers to optional resource-table helper Ben Levinsky 2026-05-14 22:14 ` 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.