[PATCH] riscv: Fix alignment-ignorant memcpy hwprobe
enh
enh@google.com
Wed May 14 19:45:16 GMT 2025
On Wed, May 14, 2025 at 3:15 PM Charlie Jenkins <charlie@rivosinc.com> wrote:
>
> 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.
erm ... no it won't?
> 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