r/kernel • u/tommythorn • 15d ago
Enabling unaligned access on RISC-V is broken on v7.2
I was looking at it a Linux v7.2 boot that was taking longer than expected, so I sampled a random spot which turned out to be hit xxh64_update. It was crock full of like this:
lbu t6, a5, 0000000000000000
lbu t5, a5, 0000000000000001
lbu t4, a5, 0000000000000002
lbu t3, a5, 0000000000000003
lbu a2, a5, 0000000000000004
lbu s3, a5, 0000000000000005
lbu s2, a5, 0000000000000006
lbu a1, a5, 0000000000000007
sb t6, s0, 00000000ffffff88
sb t5, s0, 00000000ffffff89
sb t4, s0, 00000000ffffff8a
sb t3, s0, 00000000ffffff8b
sb a2, s0, 00000000ffffff8c
sb s3, s0, 00000000ffffff8d
sb s2, s0, 00000000ffffff8e
sb a1, s0, 00000000ffffff8f
ld a1, s0, 00000000ffffff88
which is like the worst way to do unaligned loads, especially when the platform handles it.
Much digging later, this is a Linux (v7.2) bug. Grossly, you have to turn on "nonportable efficient unaligned" (Why is this "nonportable"? RISC-V requires unaligned support!)
CONFIG_NONPORTABLE=y
CONFIG_RISCV_EFFICIENT_UNALIGNED_ACCESS=y
but, here's the bug, it doesn't work, because:
"...
The default tune is rocket. rocket, sifive-3-series, and sifive-5-series all set slow_unaligned_access = true; thead-c906 and size set it false. arch/riscv/Makefile never sets -mtune at all, so under GCC, CONFIG_RISCV_EFFICIENT_UNALIGNED_ACCESS=y is largely decorative for by-pieces expansions — it flips the Kconfig selects and passes a flag that the tune model then vetoes. That's a legitimate upstream bug worth reporting to linux-riscv; I'd be surprised if it's intentional."
The workaround:
make CROSS_COMPILE=riscv64-linux-gnu- ARCH=riscv KCFLAGS="-mtune=generic-ooo"
