* [PATCH] dma-direct: Clear pages before coherent remap
@ 2026-05-17 4:29 Rosen Penev
2026-05-18 11:32 ` Leon Romanovsky
2026-05-18 12:40 ` Robin Murphy
0 siblings, 2 replies; 4+ messages in thread
From: Rosen Penev @ 2026-05-17 4:29 UTC (permalink / raw)
To: iommu; +Cc: Marek Szyprowski, Robin Murphy, open list
Clear pages through their page mapping before creating a coherent
remap for dma-direct allocations. Some architectures implement the
coherent remap as uncached memory, where the generic memset() path may
use cache-only zeroing instructions that are not valid for the returned
CPU mapping.
Keep the existing memset() for non-remapped allocations, but avoid
normal memset() on the remapped coherent allocation path.
Assisted-by: Codex:GPT-5.5
Signed-off-by: Rosen Penev <rosenp@gmail.com>
---
kernel/dma/direct.c | 20 ++++++++++++++++++--
1 file changed, 18 insertions(+), 2 deletions(-)
diff --git a/kernel/dma/direct.c b/kernel/dma/direct.c
index 583c5922bca2..76f7bf43bd28 100644
--- a/kernel/dma/direct.c
+++ b/kernel/dma/direct.c
@@ -8,6 +8,7 @@
#include <linux/export.h>
#include <linux/mm.h>
#include <linux/dma-map-ops.h>
+#include <linux/highmem.h>
#include <linux/scatterlist.h>
#include <linux/pfn.h>
#include <linux/vmalloc.h>
@@ -104,6 +105,15 @@ static void __dma_direct_free_pages(struct device *dev, struct page *page,
dma_free_contiguous(dev, page, size);
}
+static void dma_direct_zero_pages(struct page *page, size_t size)
+{
+ unsigned long count = PAGE_ALIGN(size) >> PAGE_SHIFT;
+ unsigned long i;
+
+ for (i = 0; i < count; i++)
+ clear_highpage(page + i);
+}
+
static struct page *dma_direct_alloc_swiotlb(struct device *dev, size_t size)
{
struct page *page = swiotlb_alloc(dev, size);
@@ -268,6 +278,13 @@ void *dma_direct_alloc(struct device *dev, size_t size,
if (remap) {
pgprot_t prot = dma_pgprot(dev, PAGE_KERNEL, attrs);
+ /*
+ * Zero via the page mapping before creating a potentially
+ * uncached remap. Some architectures cannot safely run normal
+ * memset on uncached memory.
+ */
+ dma_direct_zero_pages(page, size);
+
if (force_dma_unencrypted(dev))
prot = pgprot_decrypted(prot);
@@ -283,10 +300,9 @@ void *dma_direct_alloc(struct device *dev, size_t size,
ret = page_address(page);
if (dma_set_decrypted(dev, ret, size))
goto out_leak_pages;
+ memset(ret, 0, size);
}
- memset(ret, 0, size);
-
if (set_uncached) {
arch_dma_prep_coherent(page, size);
ret = arch_dma_set_uncached(ret, size);
--
2.54.0
^ permalink raw reply related [flat|nested] 4+ messages in thread* Re: [PATCH] dma-direct: Clear pages before coherent remap
2026-05-17 4:29 [PATCH] dma-direct: Clear pages before coherent remap Rosen Penev
@ 2026-05-18 11:32 ` Leon Romanovsky
2026-05-18 12:40 ` Robin Murphy
1 sibling, 0 replies; 4+ messages in thread
From: Leon Romanovsky @ 2026-05-18 11:32 UTC (permalink / raw)
To: Rosen Penev; +Cc: iommu, Marek Szyprowski, Robin Murphy, open list
On Sat, May 16, 2026 at 09:29:55PM -0700, Rosen Penev wrote:
> Clear pages through their page mapping before creating a coherent
> remap for dma-direct allocations. Some architectures implement the
> coherent remap as uncached memory, where the generic memset() path may
> use cache-only zeroing instructions that are not valid for the returned
> CPU mapping.
>
> Keep the existing memset() for non-remapped allocations, but avoid
> normal memset() on the remapped coherent allocation path.
>
> Assisted-by: Codex:GPT-5.5
> Signed-off-by: Rosen Penev <rosenp@gmail.com>
> ---
> kernel/dma/direct.c | 20 ++++++++++++++++++--
> 1 file changed, 18 insertions(+), 2 deletions(-)
>
> diff --git a/kernel/dma/direct.c b/kernel/dma/direct.c
> index 583c5922bca2..76f7bf43bd28 100644
> --- a/kernel/dma/direct.c
> +++ b/kernel/dma/direct.c
> @@ -8,6 +8,7 @@
> #include <linux/export.h>
> #include <linux/mm.h>
> #include <linux/dma-map-ops.h>
> +#include <linux/highmem.h>
> #include <linux/scatterlist.h>
> #include <linux/pfn.h>
> #include <linux/vmalloc.h>
> @@ -104,6 +105,15 @@ static void __dma_direct_free_pages(struct device *dev, struct page *page,
> dma_free_contiguous(dev, page, size);
> }
>
> +static void dma_direct_zero_pages(struct page *page, size_t size)
> +{
> + unsigned long count = PAGE_ALIGN(size) >> PAGE_SHIFT;
> + unsigned long i;
> +
> + for (i = 0; i < count; i++)
> + clear_highpage(page + i);
> +}
> +
> static struct page *dma_direct_alloc_swiotlb(struct device *dev, size_t size)
> {
> struct page *page = swiotlb_alloc(dev, size);
> @@ -268,6 +278,13 @@ void *dma_direct_alloc(struct device *dev, size_t size,
> if (remap) {
> pgprot_t prot = dma_pgprot(dev, PAGE_KERNEL, attrs);
>
> + /*
> + * Zero via the page mapping before creating a potentially
> + * uncached remap. Some architectures cannot safely run normal
> + * memset on uncached memory.
> + */
I can't say whether this description is accurate, but if it is, I'd expect
all memset callers on such architectures to be affected, not only the remap
path. If this holds, we will need a safe memset() implementation.
Thanks
^ permalink raw reply [flat|nested] 4+ messages in thread* Re: [PATCH] dma-direct: Clear pages before coherent remap
2026-05-17 4:29 [PATCH] dma-direct: Clear pages before coherent remap Rosen Penev
2026-05-18 11:32 ` Leon Romanovsky
@ 2026-05-18 12:40 ` Robin Murphy
2026-05-18 21:05 ` Rosen Penev
1 sibling, 1 reply; 4+ messages in thread
From: Robin Murphy @ 2026-05-18 12:40 UTC (permalink / raw)
To: Rosen Penev, iommu; +Cc: Marek Szyprowski, open list
On 17/05/2026 5:29 am, Rosen Penev wrote:
> Clear pages through their page mapping before creating a coherent
> remap for dma-direct allocations. Some architectures implement the
> coherent remap as uncached memory, where the generic memset() path may
> use cache-only zeroing instructions that are not valid for the returned
> CPU mapping.
Which architectures? I'd fear they're just broken in that case - there's
every chance that once the caller gets a coherent allocation back, they
could also invoke memset() on it - either explicitly, or automatically
inserted by the compiler for a structure/array initialisation, or if the
buffer subsequently gets mmap()ed to userspace then who knows what. If
that's really a problem, this patch isn't going to solve it.
It's rather the point that we clear the buffer the same way that the
caller is subsequently going to access it (not least to minimise the
chance of any other possible weird coherency side-effects).
Thanks,
Robin.
> Keep the existing memset() for non-remapped allocations, but avoid
> normal memset() on the remapped coherent allocation path.
>
> Assisted-by: Codex:GPT-5.5
> Signed-off-by: Rosen Penev <rosenp@gmail.com>
> ---
> kernel/dma/direct.c | 20 ++++++++++++++++++--
> 1 file changed, 18 insertions(+), 2 deletions(-)
>
> diff --git a/kernel/dma/direct.c b/kernel/dma/direct.c
> index 583c5922bca2..76f7bf43bd28 100644
> --- a/kernel/dma/direct.c
> +++ b/kernel/dma/direct.c
> @@ -8,6 +8,7 @@
> #include <linux/export.h>
> #include <linux/mm.h>
> #include <linux/dma-map-ops.h>
> +#include <linux/highmem.h>
> #include <linux/scatterlist.h>
> #include <linux/pfn.h>
> #include <linux/vmalloc.h>
> @@ -104,6 +105,15 @@ static void __dma_direct_free_pages(struct device *dev, struct page *page,
> dma_free_contiguous(dev, page, size);
> }
>
> +static void dma_direct_zero_pages(struct page *page, size_t size)
> +{
> + unsigned long count = PAGE_ALIGN(size) >> PAGE_SHIFT;
> + unsigned long i;
> +
> + for (i = 0; i < count; i++)
> + clear_highpage(page + i);
> +}
> +
> static struct page *dma_direct_alloc_swiotlb(struct device *dev, size_t size)
> {
> struct page *page = swiotlb_alloc(dev, size);
> @@ -268,6 +278,13 @@ void *dma_direct_alloc(struct device *dev, size_t size,
> if (remap) {
> pgprot_t prot = dma_pgprot(dev, PAGE_KERNEL, attrs);
>
> + /*
> + * Zero via the page mapping before creating a potentially
> + * uncached remap. Some architectures cannot safely run normal
> + * memset on uncached memory.
> + */
> + dma_direct_zero_pages(page, size);
> +
> if (force_dma_unencrypted(dev))
> prot = pgprot_decrypted(prot);
>
> @@ -283,10 +300,9 @@ void *dma_direct_alloc(struct device *dev, size_t size,
> ret = page_address(page);
> if (dma_set_decrypted(dev, ret, size))
> goto out_leak_pages;
> + memset(ret, 0, size);
> }
>
> - memset(ret, 0, size);
> -
> if (set_uncached) {
> arch_dma_prep_coherent(page, size);
> ret = arch_dma_set_uncached(ret, size);
^ permalink raw reply [flat|nested] 4+ messages in thread* Re: [PATCH] dma-direct: Clear pages before coherent remap
2026-05-18 12:40 ` Robin Murphy
@ 2026-05-18 21:05 ` Rosen Penev
0 siblings, 0 replies; 4+ messages in thread
From: Rosen Penev @ 2026-05-18 21:05 UTC (permalink / raw)
To: Robin Murphy; +Cc: iommu, Marek Szyprowski, open list
On Mon, May 18, 2026 at 5:40 AM Robin Murphy <robin.murphy@arm.com> wrote:
>
> On 17/05/2026 5:29 am, Rosen Penev wrote:
> > Clear pages through their page mapping before creating a coherent
> > remap for dma-direct allocations. Some architectures implement the
> > coherent remap as uncached memory, where the generic memset() path may
> > use cache-only zeroing instructions that are not valid for the returned
> > CPU mapping.
>
> Which architectures?
PowerPC 44x See:
https://lore.kernel.org/all/2e3acfe63d289c6fba366e16973c9ab8369e8b75.1631803922.git.christophe.leroy@csgroup.eu/
Fixing it here exposed similar issues elsewhere. I've submitted
patches for those.
> I'd fear they're just broken in that case - there's
> every chance that once the caller gets a coherent allocation back, they
> could also invoke memset() on it - either explicitly, or automatically
> inserted by the compiler for a structure/array initialisation, or if the
> buffer subsequently gets mmap()ed to userspace then who knows what. If
> that's really a problem, this patch isn't going to solve it.
>
> It's rather the point that we clear the buffer the same way that the
> caller is subsequently going to access it (not least to minimise the
> chance of any other possible weird coherency side-effects).
>
> Thanks,
> Robin.
>
> > Keep the existing memset() for non-remapped allocations, but avoid
> > normal memset() on the remapped coherent allocation path.
> >
> > Assisted-by: Codex:GPT-5.5
> > Signed-off-by: Rosen Penev <rosenp@gmail.com>
> > ---
> > kernel/dma/direct.c | 20 ++++++++++++++++++--
> > 1 file changed, 18 insertions(+), 2 deletions(-)
> >
> > diff --git a/kernel/dma/direct.c b/kernel/dma/direct.c
> > index 583c5922bca2..76f7bf43bd28 100644
> > --- a/kernel/dma/direct.c
> > +++ b/kernel/dma/direct.c
> > @@ -8,6 +8,7 @@
> > #include <linux/export.h>
> > #include <linux/mm.h>
> > #include <linux/dma-map-ops.h>
> > +#include <linux/highmem.h>
> > #include <linux/scatterlist.h>
> > #include <linux/pfn.h>
> > #include <linux/vmalloc.h>
> > @@ -104,6 +105,15 @@ static void __dma_direct_free_pages(struct device *dev, struct page *page,
> > dma_free_contiguous(dev, page, size);
> > }
> >
> > +static void dma_direct_zero_pages(struct page *page, size_t size)
> > +{
> > + unsigned long count = PAGE_ALIGN(size) >> PAGE_SHIFT;
> > + unsigned long i;
> > +
> > + for (i = 0; i < count; i++)
> > + clear_highpage(page + i);
> > +}
> > +
> > static struct page *dma_direct_alloc_swiotlb(struct device *dev, size_t size)
> > {
> > struct page *page = swiotlb_alloc(dev, size);
> > @@ -268,6 +278,13 @@ void *dma_direct_alloc(struct device *dev, size_t size,
> > if (remap) {
> > pgprot_t prot = dma_pgprot(dev, PAGE_KERNEL, attrs);
> >
> > + /*
> > + * Zero via the page mapping before creating a potentially
> > + * uncached remap. Some architectures cannot safely run normal
> > + * memset on uncached memory.
> > + */
> > + dma_direct_zero_pages(page, size);
> > +
> > if (force_dma_unencrypted(dev))
> > prot = pgprot_decrypted(prot);
> >
> > @@ -283,10 +300,9 @@ void *dma_direct_alloc(struct device *dev, size_t size,
> > ret = page_address(page);
> > if (dma_set_decrypted(dev, ret, size))
> > goto out_leak_pages;
> > + memset(ret, 0, size);
> > }
> >
> > - memset(ret, 0, size);
> > -
> > if (set_uncached) {
> > arch_dma_prep_coherent(page, size);
> > ret = arch_dma_set_uncached(ret, size);
>
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2026-05-18 21:06 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-05-17 4:29 [PATCH] dma-direct: Clear pages before coherent remap Rosen Penev
2026-05-18 11:32 ` Leon Romanovsky
2026-05-18 12:40 ` Robin Murphy
2026-05-18 21:05 ` Rosen Penev
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.