From: Feng Jiang Date: Sat, 4 Apr 2026 01:28:47 +0000 (-0600) Subject: riscv: lib: add strchr() implementation X-Git-Tag: v7.1-rc1~27^2~7 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=adf542133960d402f63c976b00e46be4d986d4c3;p=thirdparty%2Fkernel%2Flinux.git riscv: lib: add strchr() implementation Add an assembly implementation of strchr() for RISC-V. By eliminating stack frame management (prologue/epilogue) and optimizing the function entries, the assembly version provides significant relative gains for short strings where the fixed overhead of the C function is most prominent. As string length increases, performance converges with the generic C implementation. Benchmark results (QEMU TCG, rv64): Length | Original (MB/s) | Optimized (MB/s) | Improvement -------|-----------------|------------------|------------ 1 B | 21 | 22 | +4.8% 7 B | 113 | 121 | +7.1% 16 B | 195 | 202 | +3.6% 512 B | 376 | 389 | +3.5% 4096 B | 394 | 393 | -0.3% Signed-off-by: Feng Jiang Tested-by: Joel Stanley Link: https://patch.msgid.link/20260130025018.172925-8-jiangfeng@kylinos.cn Signed-off-by: Paul Walmsley --- diff --git a/arch/riscv/include/asm/string.h b/arch/riscv/include/asm/string.h index 16634d67c217..ca3ade82b124 100644 --- a/arch/riscv/include/asm/string.h +++ b/arch/riscv/include/asm/string.h @@ -31,6 +31,9 @@ extern asmlinkage int strncmp(const char *cs, const char *ct, size_t count); #define __HAVE_ARCH_STRNLEN extern asmlinkage __kernel_size_t strnlen(const char *, size_t); + +#define __HAVE_ARCH_STRCHR +extern asmlinkage char *strchr(const char *, int); #endif /* For those files which don't want to check by kasan. */ diff --git a/arch/riscv/lib/Makefile b/arch/riscv/lib/Makefile index 0969d8136df0..b7f804dce1c3 100644 --- a/arch/riscv/lib/Makefile +++ b/arch/riscv/lib/Makefile @@ -8,6 +8,7 @@ lib-y += strcmp.o lib-y += strlen.o lib-y += strncmp.o lib-y += strnlen.o +lib-y += strchr.o endif lib-y += csum.o ifeq ($(CONFIG_MMU), y) diff --git a/arch/riscv/lib/strchr.S b/arch/riscv/lib/strchr.S new file mode 100644 index 000000000000..48c3a9da53e3 --- /dev/null +++ b/arch/riscv/lib/strchr.S @@ -0,0 +1,35 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +/* + * Copyright (C) 2025 Feng Jiang + */ + +#include +#include + +/* char *strchr(const char *s, int c) */ +SYM_FUNC_START(strchr) + /* + * Parameters + * a0 - The string to be searched + * a1 - The character to search for + * + * Returns + * a0 - Address of first occurrence of 'c' or 0 + * + * Clobbers + * t0 + */ + andi a1, a1, 0xff +1: + lbu t0, 0(a0) + beq t0, a1, 2f + addi a0, a0, 1 + bnez t0, 1b + li a0, 0 +2: + ret +SYM_FUNC_END(strchr) + +SYM_FUNC_ALIAS_WEAK(__pi_strchr, strchr) +EXPORT_SYMBOL(strchr) diff --git a/arch/riscv/purgatory/Makefile b/arch/riscv/purgatory/Makefile index d7c0533108be..e7b3d748c913 100644 --- a/arch/riscv/purgatory/Makefile +++ b/arch/riscv/purgatory/Makefile @@ -2,7 +2,7 @@ purgatory-y := purgatory.o sha256.o entry.o string.o ctype.o memcpy.o memset.o ifeq ($(CONFIG_KASAN_GENERIC)$(CONFIG_KASAN_SW_TAGS),) -purgatory-y += strcmp.o strlen.o strncmp.o strnlen.o +purgatory-y += strcmp.o strlen.o strncmp.o strnlen.o strchr.o endif targets += $(purgatory-y) @@ -35,6 +35,9 @@ $(obj)/sha256.o: $(srctree)/lib/crypto/sha256.c FORCE $(obj)/strnlen.o: $(srctree)/arch/riscv/lib/strnlen.S FORCE $(call if_changed_rule,as_o_S) +$(obj)/strchr.o: $(srctree)/arch/riscv/lib/strchr.S FORCE + $(call if_changed_rule,as_o_S) + CFLAGS_sha256.o := -D__DISABLE_EXPORTS -D__NO_FORTIFY CFLAGS_string.o := -D__DISABLE_EXPORTS CFLAGS_ctype.o := -D__DISABLE_EXPORTS