Unaligned memory access on various CPU architectures
Some time ago, I was doing some hardening work on Tundra, and one part of it was to eliminate any potential unaligned memory accesses, because they can sometimes be problematic. The level of problematicness varies between CPU architectures – in the best case, they are transparently handled by the hardware and they only cause a negligible slowdown, whereas in the worst case, they may even cause a trap which cannot be reasonably handled and thus crash the program. If you want to know more, I recommend this article from the Linux kernel documentation.
While doing that, I got interested in this topic and therefore did a bit of research on the specific ways in which different CPU architectures handle unaligned memory reads/writes, and what problems exactly do they cause on various platforms. I did not get as far as to study individual architectures’ official reference manuals; rather, this blog post is more of a compilation of information from a bunch of secondary sources that I came across and found useful.
Linux kernel
When doing Linux kernel development, programmers may make use of the
HAVE_EFFICIENT_UNALIGNED_ACCESS
Kconfig option/macro
to create different code paths for platforms which can perform unaligned accesses
efficiently (i.e. directly in hardware without a huge performance hit) and for those
which cannot
(see example).
If an architecture supports such accesses, its Kconfig file enables this option. I simply
grepped through these files and here are the results (for Linux 6.13):
Architectures that HAVE efficient unaligned access:
Architectures that MAY OR MAY NOT HAVE efficient unaligned access:
- arm if on ARMv6/ARMv7
- riscv if
RISCV_EFFICIENT_UNALIGNED_ACCESSis enabled - m68k if
CPU_HAS_NO_UNALIGNEDis disabled - loongarch if
ARCH_STRICT_ALIGNis disabled - arc if
ARC_USE_UNALIGNED_MEM_ACCESSis enabled
Architectures that DO NOT HAVE efficient unaligned access:
At first look, it may seem that CPUs with efficient unaligned access are rare, but upon closer inspection, it becomes clear that the ones which support it are actually the most commonly used (in servers and desktops) as of today (x86, ARM64, …), whereas the ones which do not are usually quite obscure and/or historic (MIPS, SPARC, DEC Alpha, …). However, it is good to note that some OpenWRT-supported SOHO routers are built on MIPS to this day, so keep this in mind if you want your software to be runnable on such platforms.
Debian wiki
On the Debian wiki, there is the ArchitectureSpecificsMemo page which, among other things, discusses the issue of memory alignment. Here are a few interesting points that I found relevant:
- Even though x86 generally supports unaligned accesses, this is not the case for some SIMD (e.g. SSE) instructions – more on that here.
- On ARM/ARM64, some instructions support unaligned accesses but others do not (e.g. VFP floating-point loads/stores), so it is probably a good idea ensure proper data alignment.
- On the emerging RISC-V architecture, it is generally also not a good idea to perform unaligned accesses (more info).
Here, it could be useful to note that even if your program does not use SIMD instructions
directly, they may still be emitted if you compile with
vectorization
turned on, for example by using GCC’s -O3 option.
Debian mailing list
Finally, on the debian-devel mailing list, there was a discussion/thread on this topic
some years ago, and some interesting things have also been said there:
“Architectures where unaligned access is (not) OK?”
(initial message)