[PATCH] m68k: nommu: fix memmove() with differently aligned src and dest for 68000

Daniel Palmer posted 1 patch 1 month, 3 weeks ago
arch/m68k/lib/memmove.c | 18 ++++++++++++++++++
1 file changed, 18 insertions(+)
[PATCH] m68k: nommu: fix memmove() with differently aligned src and dest for 68000
Posted by Daniel Palmer 1 month, 3 weeks ago
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>
---

This is from my "make 68000 work again" backlog.

I have had this fix for years and I think the few other people that
have various 68000 hobby builds must have something similar.

/root # uname -a
uClinux buildroot 6.18.0-12420-gdc1a468a2724 #120 Sat Dec 13 20:42:45 JST 2025 m68k GNU/Linux
/root # cat /proc/cpuinfo
CPU:            68000
MMU:            none
FPU:            none
Clocking:       1179.1MHz
BogoMips:       1758.00
Calibration:    879001600 loops
/root #

 arch/m68k/lib/memmove.c | 18 ++++++++++++++++++
 1 file changed, 18 insertions(+)

diff --git a/arch/m68k/lib/memmove.c b/arch/m68k/lib/memmove.c
index 6519f7f349f6..e33f00b02e4c 100644
--- a/arch/m68k/lib/memmove.c
+++ b/arch/m68k/lib/memmove.c
@@ -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;
-- 
2.51.0
Re: [PATCH] m68k: nommu: fix memmove() with differently aligned src and dest for 68000
Posted by Greg Ungerer 1 month, 2 weeks ago
Hi Daniel,

On 13/12/25 22:04, Daniel Palmer wrote:
> 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.

What is the nature of the failure, is it a trap?


> 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>

Seems to make sense from what we have in memcpy.c.

Acked-by: Greg Ungerer <gerg@linux-m68k.org>

Geert: if you are ok with this I can take it via the m68knommu tree?

Regards
Greg



> ---
> 
> This is from my "make 68000 work again" backlog.
> 
> I have had this fix for years and I think the few other people that
> have various 68000 hobby builds must have something similar.
> 
> /root # uname -a
> uClinux buildroot 6.18.0-12420-gdc1a468a2724 #120 Sat Dec 13 20:42:45 JST 2025 m68k GNU/Linux
> /root # cat /proc/cpuinfo
> CPU:            68000
> MMU:            none
> FPU:            none
> Clocking:       1179.1MHz
> BogoMips:       1758.00
> Calibration:    879001600 loops
> /root #
> 
>   arch/m68k/lib/memmove.c | 18 ++++++++++++++++++
>   1 file changed, 18 insertions(+)
> 
> diff --git a/arch/m68k/lib/memmove.c b/arch/m68k/lib/memmove.c
> index 6519f7f349f6..e33f00b02e4c 100644
> --- a/arch/m68k/lib/memmove.c
> +++ b/arch/m68k/lib/memmove.c
> @@ -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;
Re: [PATCH] m68k: nommu: fix memmove() with differently aligned src and dest for 68000
Posted by Greg Ungerer 3 weeks ago
Hi Daniel,

I'll add this to the m68knommu git tree, for-next branch.

Thanks
Greg



On 19/12/25 21:58, Greg Ungerer wrote:
> Hi Daniel,
> 
> On 13/12/25 22:04, Daniel Palmer wrote:
>> 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.
> 
> What is the nature of the failure, is it a trap?
> 
> 
>> 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>
> 
> Seems to make sense from what we have in memcpy.c.
> 
> Acked-by: Greg Ungerer <gerg@linux-m68k.org>
> 
> Geert: if you are ok with this I can take it via the m68knommu tree?
> 
> Regards
> Greg
> 
> 
> 
>> ---
>>
>> This is from my "make 68000 work again" backlog.
>>
>> I have had this fix for years and I think the few other people that
>> have various 68000 hobby builds must have something similar.
>>
>> /root # uname -a
>> uClinux buildroot 6.18.0-12420-gdc1a468a2724 #120 Sat Dec 13 20:42:45 JST 2025 m68k GNU/Linux
>> /root # cat /proc/cpuinfo
>> CPU:            68000
>> MMU:            none
>> FPU:            none
>> Clocking:       1179.1MHz
>> BogoMips:       1758.00
>> Calibration:    879001600 loops
>> /root #
>>
>>   arch/m68k/lib/memmove.c | 18 ++++++++++++++++++
>>   1 file changed, 18 insertions(+)
>>
>> diff --git a/arch/m68k/lib/memmove.c b/arch/m68k/lib/memmove.c
>> index 6519f7f349f6..e33f00b02e4c 100644
>> --- a/arch/m68k/lib/memmove.c
>> +++ b/arch/m68k/lib/memmove.c
>> @@ -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;
> 

Re: [PATCH] m68k: nommu: fix memmove() with differently aligned src and dest for 68000
Posted by Daniel Palmer 3 weeks ago
Hi Greg,

On Fri, 16 Jan 2026 at 20:03, Greg Ungerer <gerg@linux-m68k.org> wrote:
>
> Hi Daniel,
>
> I'll add this to the m68knommu git tree, for-next branch.
>
> Thanks
> Greg

Thanks!
Re: [PATCH] m68k: nommu: fix memmove() with differently aligned src and dest for 68000
Posted by Daniel Palmer 1 month, 2 weeks ago
Hi Greg,

On Fri, 19 Dec 2025 at 20:59, Greg Ungerer <gerg@linux-m68k.org> wrote:
>
> Hi Daniel,
>
> On 13/12/25 22:04, Daniel Palmer wrote:
> > 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.
>
> What is the nature of the failure, is it a trap?

Address error because of the unaligned address. This was actually a
real pain to work out because on QEMU it worked fine (mainline QEMU
allows the unaligned access[0]) and on the real CPU it just locked up.

Thanks!

Daniel

0 - https://gitlab.com/qemu-project/qemu/-/issues/2165