Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 0 additions & 3 deletions arch/riscv/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -407,9 +407,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
Expand Down
7 changes: 7 additions & 0 deletions arch/riscv/kernel/image-vars.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,13 @@ __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 so EFI stub as well.
*/
PROVIDE(__efistub___lshrdi3 = __lshrdi3);
PROVIDE(__efistub___ashldi3 = __ashldi3);

#endif

#endif /* __RISCV_KERNEL_IMAGE_VARS_H */
1 change: 1 addition & 0 deletions arch/riscv/lib/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,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
Expand Down
36 changes: 36 additions & 0 deletions arch/riscv/lib/ashldi3.S
Original file line number Diff line number Diff line change
@@ -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)
37 changes: 37 additions & 0 deletions arch/riscv/lib/ashrdi3.S
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
/* 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, 16
srai a1, a1, 16
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 changes: 36 additions & 0 deletions arch/riscv/lib/lshrdi3.S
Original file line number Diff line number Diff line change
@@ -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)
4 changes: 4 additions & 0 deletions drivers/firmware/efi/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,10 @@ config EFI_ZBOOT
provided that the loader implements the decompression algorithm.
(The compression algorithm used is described in the zboot header)

config EFI_ZBOOT_USE_LIBGCC
bool
default y if RISCV && 32BIT

config EFI_ARMSTUB_DTB_LOADER
bool "Enable the DTB loader"
depends on EFI_GENERIC_STUB && !RISCV && !LOONGARCH
Expand Down
3 changes: 2 additions & 1 deletion drivers/firmware/efi/libstub/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,8 @@ CFLAGS_zboot-decompress-gzip.o += -I$(srctree)/lib/zlib_inflate
zboot-obj-$(CONFIG_KERNEL_ZSTD) := zboot-decompress-zstd.o lib-xxhash.o
CFLAGS_zboot-decompress-zstd.o += -I$(srctree)/lib/zstd

zboot-obj-$(CONFIG_RISCV) += lib-clz_ctz.o lib-ashldi3.o
zboot-libgcc-obj-$(CONFIG_EFI_ZBOOT_USE_LIBGCC) += lib-ashldi3.o lib-lshrdi3.o
zboot-obj-$(CONFIG_RISCV) += lib-clz_ctz.o $(zboot-libgcc-obj-y)
lib-$(CONFIG_EFI_ZBOOT) += zboot.o $(zboot-obj-y)

lib-$(CONFIG_UNACCEPTED_MEMORY) += unaccepted_memory.o bitmap.o find.o
Expand Down
10 changes: 10 additions & 0 deletions lib/Kconfig.debug
Original file line number Diff line number Diff line change
Expand Up @@ -2942,6 +2942,16 @@ config BITS_TEST

If unsure, say N.

config SHDI3_KUNIT_TEST
tristate "KUnit test for __ashldi3(), __ashrdi3(), and __lshrdi3()"
depends on KUNIT
depends on (32BIT || ARM)
help
This builds the unit test for __ashldi3(), __ashrdi3(), and
__lshrdi3() helper functions used to implement 64-bit arithmetic
shift left, arithmetic shift right and logical shift right,
respectively, on a 32-bit CPUs.

config SLUB_KUNIT_TEST
tristate "KUnit test for SLUB cache error detection" if !KUNIT_ALL_TESTS
depends on SLUB_DEBUG && KUNIT
Expand Down
1 change: 1 addition & 0 deletions lib/tests/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ obj-$(CONFIG_BASE64_KUNIT) += base64_kunit.o
obj-$(CONFIG_BITOPS_KUNIT) += bitops_kunit.o
obj-$(CONFIG_BITFIELD_KUNIT) += bitfield_kunit.o
obj-$(CONFIG_BITS_TEST) += test_bits.o
obj-$(CONFIG_SHDI3_KUNIT_TEST) += shdi3_kunit.o
obj-$(CONFIG_BLACKHOLE_DEV_KUNIT_TEST) += blackhole_dev_kunit.o
obj-$(CONFIG_CHECKSUM_KUNIT) += checksum_kunit.o
obj-$(CONFIG_CMDLINE_KUNIT_TEST) += cmdline_kunit.o
Expand Down
175 changes: 175 additions & 0 deletions lib/tests/shdi3_kunit.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,175 @@
// SPDX-License-Identifier: GPL-2.0-or-later OR Apache-2.0
/*
* Test cases for __ashldi3(), __ashrdi3(), and __lshrdi3().
*/

#include <linux/array_size.h>
#include <linux/module.h>
#include <linux/libgcc.h>
#include <kunit/test.h>

struct shdi3_test_entry {
long long input;
int shift;
long long result;
};

static const struct shdi3_test_entry ashldi3_testdata[] = {
/* https://github.com/llvm/llvm-project/compiler-rt/test/builtins/Unit/ashldi3_test.c */
{ 0x0123456789ABCDEFLL, 0, 0x123456789ABCDEFLL },
{ 0x0123456789ABCDEFLL, 1, 0x2468ACF13579BDELL },
{ 0x0123456789ABCDEFLL, 2, 0x48D159E26AF37BCLL },
{ 0x0123456789ABCDEFLL, 3, 0x91A2B3C4D5E6F78LL },
{ 0x0123456789ABCDEFLL, 4, 0x123456789ABCDEF0LL },
{ 0x0123456789ABCDEFLL, 28, 0x789ABCDEF0000000LL },
{ 0x0123456789ABCDEFLL, 29, 0xF13579BDE0000000LL },
{ 0x0123456789ABCDEFLL, 30, 0xE26AF37BC0000000LL },
{ 0x0123456789ABCDEFLL, 31, 0xC4D5E6F780000000LL },
{ 0x0123456789ABCDEFLL, 32, 0x89ABCDEF00000000LL },
{ 0x0123456789ABCDEFLL, 33, 0x13579BDE00000000LL },
{ 0x0123456789ABCDEFLL, 34, 0x26AF37BC00000000LL },
{ 0x0123456789ABCDEFLL, 35, 0x4D5E6F7800000000LL },
{ 0x0123456789ABCDEFLL, 36, 0x9ABCDEF000000000LL },
{ 0x0123456789ABCDEFLL, 60, 0xF000000000000000LL },
{ 0x0123456789ABCDEFLL, 61, 0xE000000000000000LL },
{ 0x0123456789ABCDEFLL, 62, 0xC000000000000000LL },
{ 0x0123456789ABCDEFLL, 63, 0x8000000000000000LL },
};

static void shdi3_test_ashldi3(struct kunit *test)
{
const struct shdi3_test_entry *e;
long long ret;

for (e = ashldi3_testdata;
e < ashldi3_testdata + ARRAY_SIZE(ashldi3_testdata); e++) {
ret = __ashldi3(e->input, e->shift);
KUNIT_EXPECT_EQ_MSG(test, ret, e->result,
" when evaluating __ashldi3(%lld, %d)",
e->input, e->shift);
}
}

static const struct shdi3_test_entry ashrdi3_testdata[] = {
/* https://github.com/llvm/llvm-project/compiler-rt/test/builtins/Unit/ashrdi3_test.c */
{ 0x0123456789ABCDEFLL, 0, 0x123456789ABCDEFLL },
{ 0x0123456789ABCDEFLL, 1, 0x91A2B3C4D5E6F7LL },
{ 0x0123456789ABCDEFLL, 2, 0x48D159E26AF37BLL },
{ 0x0123456789ABCDEFLL, 3, 0x2468ACF13579BDLL },
{ 0x0123456789ABCDEFLL, 4, 0x123456789ABCDELL },
{ 0x0123456789ABCDEFLL, 28, 0x12345678LL },
{ 0x0123456789ABCDEFLL, 29, 0x91A2B3CLL },
{ 0x0123456789ABCDEFLL, 30, 0x48D159ELL },
{ 0x0123456789ABCDEFLL, 31, 0x2468ACFLL },
{ 0x0123456789ABCDEFLL, 32, 0x1234567LL },
{ 0x0123456789ABCDEFLL, 33, 0x91A2B3LL },
{ 0x0123456789ABCDEFLL, 34, 0x48D159LL },
{ 0x0123456789ABCDEFLL, 35, 0x2468ACLL },
{ 0x0123456789ABCDEFLL, 36, 0x123456LL },
{ 0x0123456789ABCDEFLL, 60, 0 },
{ 0x0123456789ABCDEFLL, 61, 0 },
{ 0x0123456789ABCDEFLL, 62, 0 },
{ 0x0123456789ABCDEFLL, 63, 0 },
{ 0xFEDCBA9876543210LL, 0, 0xFEDCBA9876543210LL },
{ 0xFEDCBA9876543210LL, 1, 0xFF6E5D4C3B2A1908LL },
{ 0xFEDCBA9876543210LL, 2, 0xFFB72EA61D950C84LL },
{ 0xFEDCBA9876543210LL, 3, 0xFFDB97530ECA8642LL },
{ 0xFEDCBA9876543210LL, 4, 0xFFEDCBA987654321LL },
{ 0xFEDCBA9876543210LL, 28, 0xFFFFFFFFEDCBA987LL },
{ 0xFEDCBA9876543210LL, 29, 0xFFFFFFFFF6E5D4C3LL },
{ 0xFEDCBA9876543210LL, 30, 0xFFFFFFFFFB72EA61LL },
{ 0xFEDCBA9876543210LL, 31, 0xFFFFFFFFFDB97530LL },
{ 0xFEDCBA9876543210LL, 32, 0xFFFFFFFFFEDCBA98LL },
{ 0xFEDCBA9876543210LL, 33, 0xFFFFFFFFFF6E5D4CLL },
{ 0xFEDCBA9876543210LL, 34, 0xFFFFFFFFFFB72EA6LL },
{ 0xFEDCBA9876543210LL, 35, 0xFFFFFFFFFFDB9753LL },
{ 0xFEDCBA9876543210LL, 36, 0xFFFFFFFFFFEDCBA9LL },
{ 0xAEDCBA9876543210LL, 60, 0xFFFFFFFFFFFFFFFALL },
{ 0xAEDCBA9876543210LL, 61, 0xFFFFFFFFFFFFFFFDLL },
{ 0xAEDCBA9876543210LL, 62, 0xFFFFFFFFFFFFFFFELL },
{ 0xAEDCBA9876543210LL, 63, 0xFFFFFFFFFFFFFFFFLL },
};

static void shdi3_test_ashrdi3(struct kunit *test)
{
const struct shdi3_test_entry *e;
long long ret;

for (e = ashrdi3_testdata;
e < ashrdi3_testdata + ARRAY_SIZE(ashrdi3_testdata); e++) {
ret = __ashrdi3(e->input, e->shift);
KUNIT_EXPECT_EQ_MSG(test, ret, e->result,
" when evaluating __ashrdi3(%lld, %d)",
e->input, e->shift);
}
}

static const struct shdi3_test_entry lshrdi3_testdata[] = {
/* https://github.com/llvm/llvm-project/compiler-rt/test/builtins/Unit/lshrdi3_test.c */
{ 0x0123456789ABCDEFLL, 0, 0x123456789ABCDEFLL },
{ 0x0123456789ABCDEFLL, 1, 0x91A2B3C4D5E6F7LL },
{ 0x0123456789ABCDEFLL, 2, 0x48D159E26AF37BLL },
{ 0x0123456789ABCDEFLL, 3, 0x2468ACF13579BDLL },
{ 0x0123456789ABCDEFLL, 4, 0x123456789ABCDELL },
{ 0x0123456789ABCDEFLL, 28, 0x12345678LL },
{ 0x0123456789ABCDEFLL, 29, 0x91A2B3CLL },
{ 0x0123456789ABCDEFLL, 30, 0x48D159ELL },
{ 0x0123456789ABCDEFLL, 31, 0x2468ACFLL },
{ 0x0123456789ABCDEFLL, 32, 0x1234567LL },
{ 0x0123456789ABCDEFLL, 33, 0x91A2B3LL },
{ 0x0123456789ABCDEFLL, 34, 0x48D159LL },
{ 0x0123456789ABCDEFLL, 35, 0x2468ACLL },
{ 0x0123456789ABCDEFLL, 36, 0x123456LL },
{ 0x0123456789ABCDEFLL, 60, 0 },
{ 0x0123456789ABCDEFLL, 61, 0 },
{ 0x0123456789ABCDEFLL, 62, 0 },
{ 0x0123456789ABCDEFLL, 63, 0 },
{ 0xFEDCBA9876543210LL, 0, 0xFEDCBA9876543210LL },
{ 0xFEDCBA9876543210LL, 1, 0x7F6E5D4C3B2A1908LL },
{ 0xFEDCBA9876543210LL, 2, 0x3FB72EA61D950C84LL },
{ 0xFEDCBA9876543210LL, 3, 0x1FDB97530ECA8642LL },
{ 0xFEDCBA9876543210LL, 4, 0xFEDCBA987654321LL },
{ 0xFEDCBA9876543210LL, 28, 0xFEDCBA987LL },
{ 0xFEDCBA9876543210LL, 29, 0x7F6E5D4C3LL },
{ 0xFEDCBA9876543210LL, 30, 0x3FB72EA61LL },
{ 0xFEDCBA9876543210LL, 31, 0x1FDB97530LL },
{ 0xFEDCBA9876543210LL, 32, 0xFEDCBA98LL },
{ 0xFEDCBA9876543210LL, 33, 0x7F6E5D4CLL },
{ 0xFEDCBA9876543210LL, 34, 0x3FB72EA6LL },
{ 0xFEDCBA9876543210LL, 35, 0x1FDB9753LL },
{ 0xFEDCBA9876543210LL, 36, 0xFEDCBA9LL },
{ 0xAEDCBA9876543210LL, 60, 0xALL },
{ 0xAEDCBA9876543210LL, 61, 0x5LL },
{ 0xAEDCBA9876543210LL, 62, 0x2LL },
{ 0xAEDCBA9876543210LL, 63, 0x1LL },
};

static void shdi3_test_lshrdi3(struct kunit *test)
{
const struct shdi3_test_entry *e;
long long ret;

for (e = lshrdi3_testdata;
e < lshrdi3_testdata + ARRAY_SIZE(lshrdi3_testdata); e++) {
ret = __lshrdi3(e->input, e->shift);
KUNIT_EXPECT_EQ_MSG(test, ret, e->result,
" when evaluating __lshrdi3(%lld, %d)",
e->input, e->shift);
}
}

static struct kunit_case shdi3_test_cases[] = {
KUNIT_CASE(shdi3_test_ashldi3),
KUNIT_CASE(shdi3_test_ashrdi3),
KUNIT_CASE(shdi3_test_lshrdi3),
{}
};

static struct kunit_suite shdi3_test_suite = {
.name = "shdi3",
.test_cases = shdi3_test_cases,
};
kunit_test_suite(shdi3_test_suite);

MODULE_DESCRIPTION("Test cases for __ashldi3(), __ashrdi3(), and __lshrdi3()");
MODULE_LICENSE("GPL");
Loading