[PATCH] ARM: fix memset64() on big-endian

Thomas Weißschuh posted 1 patch 1 month, 1 week ago
arch/arm/include/asm/string.h | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
[PATCH] ARM: fix memset64() on big-endian
Posted by Thomas Weißschuh 1 month, 1 week ago
On big-endian systems the 32-bit low and high halves need to be swapped,
for the underlying assembly implemenation to work correctly.

Fixes: fd1d362600e2 ("ARM: implement memset32 & memset64")
Cc: stable@vger.kernel.org
Signed-off-by: Thomas Weißschuh <thomas.weissschuh@linutronix.de>
---
Found by the string_test_memset64 KUnit test.
---
 arch/arm/include/asm/string.h | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/arch/arm/include/asm/string.h b/arch/arm/include/asm/string.h
index 6c607c68f3ad..c35250c4991b 100644
--- a/arch/arm/include/asm/string.h
+++ b/arch/arm/include/asm/string.h
@@ -42,7 +42,10 @@ static inline void *memset32(uint32_t *p, uint32_t v, __kernel_size_t n)
 extern void *__memset64(uint64_t *, uint32_t low, __kernel_size_t, uint32_t hi);
 static inline void *memset64(uint64_t *p, uint64_t v, __kernel_size_t n)
 {
-	return __memset64(p, v, n * 8, v >> 32);
+	if (IS_ENABLED(CONFIG_CPU_LITTLE_ENDIAN))
+		return __memset64(p, v, n * 8, v >> 32);
+	else
+		return __memset64(p, v >> 32, n * 8, v);
 }
 
 /*

---
base-commit: 8f0b4cce4481fb22653697cced8d0d04027cb1e8
change-id: 20251230-armeb-memset64-01f2ae83f9ef

Best regards,
-- 
Thomas Weißschuh <thomas.weissschuh@linutronix.de>

Re: [PATCH] ARM: fix memset64() on big-endian
Posted by Matthew Wilcox 1 month, 1 week ago
On Fri, Jan 02, 2026 at 08:15:46AM +0100, Thomas Weißschuh wrote:
> On big-endian systems the 32-bit low and high halves need to be swapped,
> for the underlying assembly implemenation to work correctly.

Heh.  In my heart, ARM will always be a litte-endian architecture.
I'm not really surprised this bug took, er, 8 years to show up; big-endian
arm is rare enough and memset64() isn't much used on 32-bit systems.
And it turns out that many of the users pass a constant 0 as the value,
which was kind of not the point, but it seems to be an easier API to
use than memset, so whatever ;-)

> Fixes: fd1d362600e2 ("ARM: implement memset32 & memset64")
> Cc: stable@vger.kernel.org
> Signed-off-by: Thomas Weißschuh <thomas.weissschuh@linutronix.de>

Reviewed-by: Matthew Wilcox (Oracle) <willy@infradead.org>
Re: [PATCH] ARM: fix memset64() on big-endian
Posted by David Laight 1 month ago
On Fri, 2 Jan 2026 15:22:20 +0000
Matthew Wilcox <willy@infradead.org> wrote:

> On Fri, Jan 02, 2026 at 08:15:46AM +0100, Thomas Weißschuh wrote:
> > On big-endian systems the 32-bit low and high halves need to be swapped,
> > for the underlying assembly implemenation to work correctly.  
> 
> Heh.  In my heart, ARM will always be a litte-endian architecture.
> I'm not really surprised this bug took, er, 8 years to show up; big-endian
> arm is rare enough and memset64() isn't much used on 32-bit systems.
> And it turns out that many of the users pass a constant 0 as the value,
> which was kind of not the point, but it seems to be an easier API to
> use than memset, so whatever ;-)

I'd have thought that part of the point of memset64() was to remove
all the 'alignment' and 'tail handling' that a normal memset() has.
Clearly someone thought otherwise :-)

	David

> 
> > Fixes: fd1d362600e2 ("ARM: implement memset32 & memset64")
> > Cc: stable@vger.kernel.org
> > Signed-off-by: Thomas Weißschuh <thomas.weissschuh@linutronix.de>  
> 
> Reviewed-by: Matthew Wilcox (Oracle) <willy@infradead.org>
> 
Re: [PATCH] ARM: fix memset64() on big-endian
Posted by Arnd Bergmann 1 month, 1 week ago
On Fri, Jan 2, 2026, at 08:15, Thomas Weißschuh wrote:
> On big-endian systems the 32-bit low and high halves need to be swapped,
> for the underlying assembly implemenation to work correctly.
>
> Fixes: fd1d362600e2 ("ARM: implement memset32 & memset64")
> Cc: stable@vger.kernel.org
> Signed-off-by: Thomas Weißschuh <thomas.weissschuh@linutronix.de>
> ---
> Found by the string_test_memset64 KUnit test.

Good catch! I guess that likely means you are the first one to
run kunit test on armbe since the tests got added. Did you find
any other differences between BE and LE kernels running kunit?

Reviewed-by: Arnd Bergmann <arnd@arndb.de>
Re: [PATCH] ARM: fix memset64() on big-endian
Posted by Thomas Weißschuh 1 month, 1 week ago
On Fri, Jan 02, 2026 at 10:24:33AM +0100, Arnd Bergmann wrote:
> On Fri, Jan 2, 2026, at 08:15, Thomas Weißschuh wrote:
> > On big-endian systems the 32-bit low and high halves need to be swapped,
> > for the underlying assembly implemenation to work correctly.
> >
> > Fixes: fd1d362600e2 ("ARM: implement memset32 & memset64")
> > Cc: stable@vger.kernel.org
> > Signed-off-by: Thomas Weißschuh <thomas.weissschuh@linutronix.de>
> > ---
> > Found by the string_test_memset64 KUnit test.
> 
> Good catch! I guess that likely means you are the first one to
> run kunit test on armbe since the tests got added. Did you find
> any other differences between BE and LE kernels running kunit?

No other differences with the default set of tests.
There was a failure for both in test_polyval_preparekey_in_irqs, see [0].
To get some more exposure I propose a new kunit QEMU configuration in [1].

> Reviewed-by: Arnd Bergmann <arnd@arndb.de>

Thanks!

[0] https://lore.kernel.org/lkml/20260102-kunit-polyval-fix-v1-1-5313b5a65f35@linutronix.de/
[1] https://lore.kernel.org/lkml/20260102-kunit-armeb-v1-1-e8e5475d735c@linutronix.de/