[PATCH] riscv: Fix alignment-ignorant memcpy hwprobe
Charlie Jenkins
charlie@rivosinc.com
Wed May 14 19:15:12 GMT 2025
The hwprobe API for RISCV_HWPROBE_KEY_CPUPERF_0 had some unforutunate
wording. It included a value labeled RISCV_HWPROBE_MISALIGNED_MASK which
was not, in fact, a mask but rather a maximum value. This code fell for the
trap and used RISCV_HWPROBE_MISALIGNED_MASK as a mask, so "(pair.value &
RISCV_HWPROBE_MISALIGNED_MASK) == RISCV_HWPROBE_MISALIGNED_FAST" ends up
being "(pair.value & (7 << 0)) == (3 << 0)" which will always evaluate
to false.
Because of this wording issue, RISCV_HWPROBE_KEY_CPUPERF_0 was
deprecated by Linux in commit c42e2f076769 ("RISC-V: hwprobe: Add
MISALIGNED_PERF key").
Change the hwprobe call to use RISCV_HWPROBE_KEY_MISALIGNED_SCALAR_PERF
instead to fix this issue and have the hwprobe call succeed.
Signed-off-by: Charlie Jenkins <charlie@rivosinc.com>
---
Tested by using the kernel flags RISCV_SLOW_UNALIGNED_ACCESS and
RISCV_EFFICIENT_UNALIGNED_ACCESS which cause the Linux kernel to report
slow/fast unaligned accesses respectively through hwprobe and checking
that the proper code path was being used.
---
sysdeps/unix/sysv/linux/riscv/multiarch/ifunc-impl-list.c | 5 ++---
sysdeps/unix/sysv/linux/riscv/multiarch/memcpy.c | 4 ++--
2 files changed, 4 insertions(+), 5 deletions(-)
diff --git a/sysdeps/unix/sysv/linux/riscv/multiarch/ifunc-impl-list.c b/sysdeps/unix/sysv/linux/riscv/multiarch/ifunc-impl-list.c
index 1c1deca8f664cab9726895d723b3a3f11e3b3f14..ce620fa20a499b166c08efbbb4677d5df6f8a39d 100644
--- a/sysdeps/unix/sysv/linux/riscv/multiarch/ifunc-impl-list.c
+++ b/sysdeps/unix/sysv/linux/riscv/multiarch/ifunc-impl-list.c
@@ -28,10 +28,9 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array,
bool fast_unaligned = false;
- struct riscv_hwprobe pair = { .key = RISCV_HWPROBE_KEY_CPUPERF_0 };
+ struct riscv_hwprobe pair = { .key = RISCV_HWPROBE_KEY_MISALIGNED_SCALAR_PERF };
if (__riscv_hwprobe (&pair, 1, 0, NULL, 0) == 0
- && (pair.value & RISCV_HWPROBE_MISALIGNED_MASK)
- == RISCV_HWPROBE_MISALIGNED_FAST)
+ && pair.value == RISCV_HWPROBE_MISALIGNED_SCALAR_FAST)
fast_unaligned = true;
IFUNC_IMPL (i, name, memcpy,
diff --git a/sysdeps/unix/sysv/linux/riscv/multiarch/memcpy.c b/sysdeps/unix/sysv/linux/riscv/multiarch/memcpy.c
index 8544f5402ab3e8d6e82b82dfa0c95ec14e665519..6d8cb5a3ad045ee953746d0ae6dce002d9d29960 100644
--- a/sysdeps/unix/sysv/linux/riscv/multiarch/memcpy.c
+++ b/sysdeps/unix/sysv/linux/riscv/multiarch/memcpy.c
@@ -37,8 +37,8 @@ static inline __typeof (__redirect_memcpy) *
select_memcpy_ifunc (uint64_t dl_hwcap, __riscv_hwprobe_t hwprobe_func)
{
unsigned long long int v;
- if (__riscv_hwprobe_one (hwprobe_func, RISCV_HWPROBE_KEY_CPUPERF_0, &v) == 0
- && (v & RISCV_HWPROBE_MISALIGNED_MASK) == RISCV_HWPROBE_MISALIGNED_FAST)
+ if (__riscv_hwprobe_one (hwprobe_func, RISCV_HWPROBE_KEY_MISALIGNED_SCALAR_PERF, &v) == 0
+ && v == RISCV_HWPROBE_MISALIGNED_SCALAR_FAST)
return __memcpy_noalignment;
return __memcpy_generic;
---
base-commit: ad966bc4efd9e69cbbda2073121cc68f1deb9588
change-id: 20250513-fix_misaligned_access-37178356d9d3
--
- Charlie
More information about the Libc-alpha
mailing list