]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
m68k: nommu: fix memmove() with differently aligned src and dest for 68000
authorDaniel Palmer <daniel@thingy.jp>
Sat, 13 Dec 2025 12:04:01 +0000 (21:04 +0900)
committerGreg Ungerer <gerg@kernel.org>
Tue, 27 Jan 2026 02:38:52 +0000 (12:38 +1000)
68000 has different alignment needs to 68020+.
memcpy() checks if the destination is aligned and does a smaller copy
to fix the alignment and then critically for 68000 it checks if the
source is still unaligned and if it is reverts to smaller copies.

memmove() does not currently do the second part and malfunctions if
one of the pointers is aligned and the other isn't.

This is apparently getting triggered by printk. If I put breakpoints
into the new checks added by this commit the first hit looks like this:

memmove (n=205, src=0x2f3971 <printk_shared_pbufs+205>, dest=0x2f3980 <printk_shared_pbufs+220>) at arch/m68k/lib/memmove.c:82

Signed-off-by: Daniel Palmer <daniel@thingy.jp>
Signed-off-by: Greg Ungerer <gerg@kernel.org>
arch/m68k/lib/memmove.c

index 6519f7f349f665d9f2321b6c87beee45f8d15645..e33f00b02e4c0f074a8195ca3759d9071cfde4ce 100644 (file)
@@ -24,6 +24,15 @@ void *memmove(void *dest, const void *src, size_t n)
                        src = csrc;
                        n--;
                }
+#if defined(CONFIG_M68000)
+               if ((long)src & 1) {
+                       char *cdest = dest;
+                       const char *csrc = src;
+                       for (; n; n--)
+                               *cdest++ = *csrc++;
+                       return xdest;
+               }
+#endif
                if (n > 2 && (long)dest & 2) {
                        short *sdest = dest;
                        const short *ssrc = src;
@@ -66,6 +75,15 @@ void *memmove(void *dest, const void *src, size_t n)
                        src = csrc;
                        n--;
                }
+#if defined(CONFIG_M68000)
+               if ((long)src & 1) {
+                       char *cdest = dest;
+                       const char *csrc = src;
+                       for (; n; n--)
+                               *--cdest = *--csrc;
+                       return xdest;
+               }
+#endif
                if (n > 2 && (long)dest & 2) {
                        short *sdest = dest;
                        const short *ssrc = src;