riscv: add platform-specific double word shifts for riscv32

Add riscv32-specific '__ashldi3()', '__ashrdi3()', and '__lshrdi3()'. 
Initially it was intended to fix the following link error observed when
building EFI-enabled kernel with CONFIG_EFI_STUB=y and
CONFIG_EFI_GENERIC_STUB=y:

riscv32-linux-gnu-ld: ./drivers/firmware/efi/libstub/lib-cmdline.stub.o: in function `__efistub_.L49':
__efistub_cmdline.c:(.init.text+0x1f2): undefined reference to `__efistub___ashldi3'
riscv32-linux-gnu-ld: __efistub_cmdline.c:(.init.text+0x202): undefined reference to `__efistub___lshrdi3'

Reported at [1] trying to build
https://patchew.org/linux/20260212164413.889625-1-dmantipov@yandex.ru,
tested with 'qemu-system-riscv32 -M virt' only.

Link: https://lore.kernel.org/20260519172259.908980-7-dmantipov@yandex.ru
Signed-off-by: Dmitry Antipov <dmantipov@yandex.ru>
Reported-by: kernel test robot <lkp@intel.com>
Closes: https://lore.kernel.org/oe-kbuild-all/202603041925.KLKqpK6N-lkp@intel.com [1]
Suggested-by: Ard Biesheuvel <ardb@kernel.org>
Tested-by: Charlie Jenkins <thecharlesjenkins@gmail.com>
Assisted-by: Gemini:gemini-3.1-pro-preview sashiko
Cc: Albert Ou <aou@eecs.berkeley.edu>
Cc: Alexandre Ghiti <alex@ghiti.fr>
Cc: Andriy Shevchenko <andriy.shevchenko@intel.com>
Cc: Palmer Dabbelt <palmer@dabbelt.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
This commit is contained in:
Dmitry Antipov 2026-05-19 20:22:57 +03:00 committed by Andrew Morton
parent 117d2bfa0a
commit a354b8de9a
7 changed files with 122 additions and 3 deletions

View File

@ -404,9 +404,6 @@ config ARCH_RV32I
bool "RV32I"
depends on NONPORTABLE
select 32BIT
select GENERIC_LIB_ASHLDI3
select GENERIC_LIB_ASHRDI3
select GENERIC_LIB_LSHRDI3
select GENERIC_LIB_UCMPDI2
config ARCH_RV64I

View File

@ -5,6 +5,10 @@
#include <linux/ftrace.h>
#include <asm-generic/asm-prototypes.h>
long long __lshrdi3(long long a, int b);
long long __ashrdi3(long long a, int b);
long long __ashldi3(long long a, int b);
long long __lshrti3(long long a, int b);
long long __ashrti3(long long a, int b);
long long __ashlti3(long long a, int b);

View File

@ -32,6 +32,15 @@ __efistub___init_text_end = __init_text_end;
__efistub_sysfb_primary_display = sysfb_primary_display;
#endif
/*
* These double-word integer shifts are used by the library code, and
* the first two of them are required to link EFI stub. Note __ashrdi3()
* is not actually used by the stub but this may change in the future.
*/
PROVIDE(__efistub___lshrdi3 = __lshrdi3);
PROVIDE(__efistub___ashldi3 = __ashldi3);
PROVIDE(__efistub___ashrdi3 = __ashrdi3);
#endif
#endif /* __RISCV_KERNEL_IMAGE_VARS_H */

View File

@ -16,6 +16,7 @@ ifeq ($(CONFIG_MMU), y)
lib-$(CONFIG_RISCV_ISA_V) += uaccess_vector.o
endif
lib-$(CONFIG_MMU) += uaccess.o
lib-$(CONFIG_32BIT) += ashldi3.o ashrdi3.o lshrdi3.o
lib-$(CONFIG_64BIT) += tishift.o
lib-$(CONFIG_RISCV_ISA_ZICBOZ) += clear_page.o
obj-$(CONFIG_FUNCTION_ERROR_INJECTION) += error-inject.o

36
arch/riscv/lib/ashldi3.S Normal file
View File

@ -0,0 +1,36 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
/**
* Adopted for the Linux kernel from IPXE project, see
* https://github.com/ipxe/ipxe/blob/master/src/arch/riscv32/libgcc/llshift.S
*/
#include <linux/linkage.h>
#include <asm/asm.h>
/**
* Shift left
*
* @v a1:a0 Value to shift
* @v a2 Shift amount
* @ret a1:a0 Shifted value
*/
SYM_FUNC_START(__ashldi3)
/* Perform shift by 32 bits, if applicable */
li t0, 32
sub t1, t0, a2
bgtz t1, 1f
mv a1, a0
mv a0, zero
1: /* Perform shift by modulo-32 bits, if applicable */
andi a2, a2, 0x1f
beqz a2, 2f
srl t2, a0, t1
sll a0, a0, a2
sll a1, a1, a2
or a1, a1, t2
2: ret
SYM_FUNC_END(__ashldi3)
EXPORT_SYMBOL(__ashldi3)

36
arch/riscv/lib/ashrdi3.S Normal file
View File

@ -0,0 +1,36 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
/**
* Adopted for the Linux kernel from IPXE project, see
* https://github.com/ipxe/ipxe/blob/master/src/arch/riscv32/libgcc/llshift.S
*/
#include <linux/linkage.h>
#include <asm/asm.h>
/**
* Arithmetic shift right
*
* @v a1:a0 Value to shift
* @v a2 Shift amount
* @ret a1:a0 Shifted value
*/
SYM_FUNC_START(__ashrdi3)
/* Perform shift by 32 bits, if applicable */
li t0, 32
sub t1, t0, a2
bgtz t1, 1f
mv a0, a1
srai a1, a1, 31
1: /* Perform shift by modulo-32 bits, if applicable */
andi a2, a2, 0x1f
beqz a2, 2f
sll t2, a1, t1
sra a1, a1, a2
srl a0, a0, a2
or a0, a0, t2
2: ret
SYM_FUNC_END(__ashrdi3)
EXPORT_SYMBOL(__ashrdi3)

36
arch/riscv/lib/lshrdi3.S Normal file
View File

@ -0,0 +1,36 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
/**
* Adopted for the Linux kernel from IPXE project, see
* https://github.com/ipxe/ipxe/blob/master/src/arch/riscv32/libgcc/llshift.S
*/
#include <linux/linkage.h>
#include <asm/asm.h>
/**
* Logical shift right
*
* @v a1:a0 Value to shift
* @v a2 Shift amount
* @ret a1:a0 Shifted value
*/
SYM_FUNC_START(__lshrdi3)
/* Perform shift by 32 bits, if applicable */
li t0, 32
sub t1, t0, a2
bgtz t1, 1f
mv a0, a1
mv a1, zero
1: /* Perform shift by modulo-32 bits, if applicable */
andi a2, a2, 0x1f
beqz a2, 2f
sll t2, a1, t1
srl a1, a1, a2
srl a0, a0, a2
or a0, a0, t2
2: ret
SYM_FUNC_END(__lshrdi3)
EXPORT_SYMBOL(__lshrdi3)