[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