mirror of
https://github.com/linux-msm/laptops-kernel.git
synced 2026-08-13 14:19:53 -07:00
Merge patch series "riscv: Add remaining module relocations and tests"
Charlie Jenkins <charlie@rivosinc.com> says: A handful of module relocations were missing, this patch includes the remaining ones. I also wrote some test cases to ensure that module loading works properly. Some relocations cannot be supported in the kernel, these include the ones that rely on thread local storage and dynamic linking. This patch also overhauls the implementation of ADD/SUB/SET/ULEB128 relocations to handle overflow. "Overflow" is different for ULEB128 since it is a variable-length encoding that the compiler can be expected to generate enough space for. Instead of overflowing, ULEB128 will expand into the next 8-bit segment of the location. A psABI proposal [1] was merged that mandates that SET_ULEB128 and SUB_ULEB128 are paired, however the discussion following the merging of the pull request revealed that while the pull request was valid, it would be better for linkers to properly handle this overflow. This patch proactively implements this methodology for future compatibility. This can be tested by enabling KUNIT, RUNTIME_KERNEL_TESTING_MENU, and RISCV_MODULE_LINKING_KUNIT. [1] https://github.com/riscv-non-isa/riscv-elf-psabi-doc/pull/403 * b4-shazam-merge: riscv: Add tests for riscv module loading riscv: Add remaining module relocations riscv: Avoid unaligned access when relocating modules Link: https://lore.kernel.org/r/20231101-module_relocations-v9-0-8dfa3483c400@rivosinc.com Signed-off-by: Palmer Dabbelt <palmer@rivosinc.com>
This commit is contained in:
@@ -0,0 +1 @@
|
||||
source "arch/riscv/kernel/tests/Kconfig.debug"
|
||||
|
||||
@@ -49,6 +49,7 @@ typedef union __riscv_fp_state elf_fpregset_t;
|
||||
#define R_RISCV_TLS_DTPREL64 9
|
||||
#define R_RISCV_TLS_TPREL32 10
|
||||
#define R_RISCV_TLS_TPREL64 11
|
||||
#define R_RISCV_IRELATIVE 58
|
||||
|
||||
/* Relocation types not used by the dynamic linker */
|
||||
#define R_RISCV_BRANCH 16
|
||||
@@ -81,7 +82,6 @@ typedef union __riscv_fp_state elf_fpregset_t;
|
||||
#define R_RISCV_ALIGN 43
|
||||
#define R_RISCV_RVC_BRANCH 44
|
||||
#define R_RISCV_RVC_JUMP 45
|
||||
#define R_RISCV_LUI 46
|
||||
#define R_RISCV_GPREL_I 47
|
||||
#define R_RISCV_GPREL_S 48
|
||||
#define R_RISCV_TPREL_I 49
|
||||
@@ -93,6 +93,9 @@ typedef union __riscv_fp_state elf_fpregset_t;
|
||||
#define R_RISCV_SET16 55
|
||||
#define R_RISCV_SET32 56
|
||||
#define R_RISCV_32_PCREL 57
|
||||
#define R_RISCV_PLT32 59
|
||||
#define R_RISCV_SET_ULEB128 60
|
||||
#define R_RISCV_SUB_ULEB128 61
|
||||
|
||||
|
||||
#endif /* _UAPI_ASM_RISCV_ELF_H */
|
||||
|
||||
@@ -57,6 +57,7 @@ obj-y += stacktrace.o
|
||||
obj-y += cacheinfo.o
|
||||
obj-y += patch.o
|
||||
obj-y += probes/
|
||||
obj-y += tests/
|
||||
obj-$(CONFIG_MMU) += vdso.o vdso/
|
||||
|
||||
obj-$(CONFIG_RISCV_MISALIGNED) += traps_misaligned.o
|
||||
|
||||
+499
-104
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,35 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
menu "arch/riscv/kernel Testing and Coverage"
|
||||
|
||||
config AS_HAS_ULEB128
|
||||
def_bool $(as-instr,.reloc label$(comma) R_RISCV_SET_ULEB128$(comma) 127\n.reloc label$(comma) R_RISCV_SUB_ULEB128$(comma) 127\nlabel:\n.word 0)
|
||||
|
||||
menuconfig RUNTIME_KERNEL_TESTING_MENU
|
||||
bool "arch/riscv/kernel runtime Testing"
|
||||
def_bool y
|
||||
help
|
||||
Enable riscv kernel runtime testing.
|
||||
|
||||
if RUNTIME_KERNEL_TESTING_MENU
|
||||
|
||||
config RISCV_MODULE_LINKING_KUNIT
|
||||
bool "KUnit test riscv module linking at runtime" if !KUNIT_ALL_TESTS
|
||||
depends on KUNIT
|
||||
default KUNIT_ALL_TESTS
|
||||
help
|
||||
Enable this option to test riscv module linking at boot. This will
|
||||
enable a module called "test_module_linking".
|
||||
|
||||
KUnit tests run during boot and output the results to the debug log
|
||||
in TAP format (http://testanything.org/). Only useful for kernel devs
|
||||
running the KUnit test harness, and not intended for inclusion into a
|
||||
production build.
|
||||
|
||||
For more information on KUnit and unit tests in general please refer
|
||||
to the KUnit documentation in Documentation/dev-tools/kunit/.
|
||||
|
||||
If unsure, say N.
|
||||
|
||||
endif # RUNTIME_TESTING_MENU
|
||||
|
||||
endmenu # "arch/riscv/kernel runtime Testing"
|
||||
@@ -0,0 +1 @@
|
||||
obj-$(CONFIG_RISCV_MODULE_LINKING_KUNIT) += module_test/
|
||||
@@ -0,0 +1,15 @@
|
||||
obj-m += test_module_linking.o
|
||||
|
||||
test_sub := test_sub6.o test_sub8.o test_sub16.o test_sub32.o test_sub64.o
|
||||
|
||||
test_set := test_set6.o test_set8.o test_set16.o test_set32.o
|
||||
|
||||
test_module_linking-objs += $(test_sub)
|
||||
|
||||
test_module_linking-objs += $(test_set)
|
||||
|
||||
ifeq ($(CONFIG_AS_HAS_ULEB128),y)
|
||||
test_module_linking-objs += test_uleb128.o
|
||||
endif
|
||||
|
||||
test_module_linking-objs += test_module_linking_main.o
|
||||
@@ -0,0 +1,88 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Copyright (C) 2023 Rivos Inc.
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
#include <kunit/test.h>
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_DESCRIPTION("Test module linking");
|
||||
|
||||
extern int test_set32(void);
|
||||
extern int test_set16(void);
|
||||
extern int test_set8(void);
|
||||
extern int test_set6(void);
|
||||
extern long test_sub64(void);
|
||||
extern int test_sub32(void);
|
||||
extern int test_sub16(void);
|
||||
extern int test_sub8(void);
|
||||
extern int test_sub6(void);
|
||||
|
||||
#ifdef CONFIG_AS_HAS_ULEB128
|
||||
extern int test_uleb_basic(void);
|
||||
extern int test_uleb_large(void);
|
||||
#endif
|
||||
|
||||
#define CHECK_EQ(lhs, rhs) KUNIT_ASSERT_EQ(test, lhs, rhs)
|
||||
|
||||
void run_test_set(struct kunit *test);
|
||||
void run_test_sub(struct kunit *test);
|
||||
void run_test_uleb(struct kunit *test);
|
||||
|
||||
void run_test_set(struct kunit *test)
|
||||
{
|
||||
int val32 = test_set32();
|
||||
int val16 = test_set16();
|
||||
int val8 = test_set8();
|
||||
int val6 = test_set6();
|
||||
|
||||
CHECK_EQ(val32, 0);
|
||||
CHECK_EQ(val16, 0);
|
||||
CHECK_EQ(val8, 0);
|
||||
CHECK_EQ(val6, 0);
|
||||
}
|
||||
|
||||
void run_test_sub(struct kunit *test)
|
||||
{
|
||||
int val64 = test_sub64();
|
||||
int val32 = test_sub32();
|
||||
int val16 = test_sub16();
|
||||
int val8 = test_sub8();
|
||||
int val6 = test_sub6();
|
||||
|
||||
CHECK_EQ(val64, 0);
|
||||
CHECK_EQ(val32, 0);
|
||||
CHECK_EQ(val16, 0);
|
||||
CHECK_EQ(val8, 0);
|
||||
CHECK_EQ(val6, 0);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_AS_HAS_ULEB128
|
||||
void run_test_uleb(struct kunit *test)
|
||||
{
|
||||
int val_uleb = test_uleb_basic();
|
||||
int val_uleb2 = test_uleb_large();
|
||||
|
||||
CHECK_EQ(val_uleb, 0);
|
||||
CHECK_EQ(val_uleb2, 0);
|
||||
}
|
||||
#endif
|
||||
|
||||
static struct kunit_case __refdata riscv_module_linking_test_cases[] = {
|
||||
KUNIT_CASE(run_test_set),
|
||||
KUNIT_CASE(run_test_sub),
|
||||
#ifdef CONFIG_AS_HAS_ULEB128
|
||||
KUNIT_CASE(run_test_uleb),
|
||||
#endif
|
||||
{}
|
||||
};
|
||||
|
||||
static struct kunit_suite riscv_module_linking_test_suite = {
|
||||
.name = "riscv_checksum",
|
||||
.test_cases = riscv_module_linking_test_cases,
|
||||
};
|
||||
|
||||
kunit_test_suites(&riscv_module_linking_test_suite);
|
||||
@@ -0,0 +1,23 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Copyright (C) 2023 Rivos Inc.
|
||||
*/
|
||||
|
||||
.text
|
||||
.global test_set16
|
||||
test_set16:
|
||||
lw a0, set16
|
||||
la t0, set16
|
||||
#ifdef CONFIG_32BIT
|
||||
slli t0, t0, 16
|
||||
srli t0, t0, 16
|
||||
#else
|
||||
slli t0, t0, 48
|
||||
srli t0, t0, 48
|
||||
#endif
|
||||
sub a0, a0, t0
|
||||
ret
|
||||
.data
|
||||
set16:
|
||||
.reloc set16, R_RISCV_SET16, set16
|
||||
.word 0
|
||||
@@ -0,0 +1,20 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Copyright (C) 2023 Rivos Inc.
|
||||
*/
|
||||
|
||||
.text
|
||||
.global test_set32
|
||||
test_set32:
|
||||
lw a0, set32
|
||||
la t0, set32
|
||||
#ifndef CONFIG_32BIT
|
||||
slli t0, t0, 32
|
||||
srli t0, t0, 32
|
||||
#endif
|
||||
sub a0, a0, t0
|
||||
ret
|
||||
.data
|
||||
set32:
|
||||
.reloc set32, R_RISCV_SET32, set32
|
||||
.word 0
|
||||
@@ -0,0 +1,23 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Copyright (C) 2023 Rivos Inc.
|
||||
*/
|
||||
|
||||
.text
|
||||
.global test_set6
|
||||
test_set6:
|
||||
lw a0, set6
|
||||
la t0, set6
|
||||
#ifdef CONFIG_32BIT
|
||||
slli t0, t0, 26
|
||||
srli t0, t0, 26
|
||||
#else
|
||||
slli t0, t0, 58
|
||||
srli t0, t0, 58
|
||||
#endif
|
||||
sub a0, a0, t0
|
||||
ret
|
||||
.data
|
||||
set6:
|
||||
.reloc set6, R_RISCV_SET6, set6
|
||||
.word 0
|
||||
@@ -0,0 +1,23 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Copyright (C) 2023 Rivos Inc.
|
||||
*/
|
||||
|
||||
.text
|
||||
.global test_set8
|
||||
test_set8:
|
||||
lw a0, set8
|
||||
la t0, set8
|
||||
#ifdef CONFIG_32BIT
|
||||
slli t0, t0, 24
|
||||
srli t0, t0, 24
|
||||
#else
|
||||
slli t0, t0, 56
|
||||
srli t0, t0, 56
|
||||
#endif
|
||||
sub a0, a0, t0
|
||||
ret
|
||||
.data
|
||||
set8:
|
||||
.reloc set8, R_RISCV_SET8, set8
|
||||
.word 0
|
||||
@@ -0,0 +1,20 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Copyright (C) 2023 Rivos Inc.
|
||||
*/
|
||||
|
||||
.text
|
||||
.global test_sub16
|
||||
test_sub16:
|
||||
lh a0, sub16
|
||||
addi a0, a0, -32
|
||||
ret
|
||||
first:
|
||||
.space 32
|
||||
second:
|
||||
|
||||
.data
|
||||
sub16:
|
||||
.reloc sub16, R_RISCV_ADD16, second
|
||||
.reloc sub16, R_RISCV_SUB16, first
|
||||
.half 0
|
||||
@@ -0,0 +1,20 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Copyright (C) 2023 Rivos Inc.
|
||||
*/
|
||||
|
||||
.text
|
||||
.global test_sub32
|
||||
test_sub32:
|
||||
lw a0, sub32
|
||||
addi a0, a0, -32
|
||||
ret
|
||||
first:
|
||||
.space 32
|
||||
second:
|
||||
|
||||
.data
|
||||
sub32:
|
||||
.reloc sub32, R_RISCV_ADD32, second
|
||||
.reloc sub32, R_RISCV_SUB32, first
|
||||
.word 0
|
||||
@@ -0,0 +1,20 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Copyright (C) 2023 Rivos Inc.
|
||||
*/
|
||||
|
||||
.text
|
||||
.global test_sub6
|
||||
test_sub6:
|
||||
lb a0, sub6
|
||||
addi a0, a0, -32
|
||||
ret
|
||||
first:
|
||||
.space 32
|
||||
second:
|
||||
|
||||
.data
|
||||
sub6:
|
||||
.reloc sub6, R_RISCV_SET6, second
|
||||
.reloc sub6, R_RISCV_SUB6, first
|
||||
.byte 0
|
||||
@@ -0,0 +1,25 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Copyright (C) 2023 Rivos Inc.
|
||||
*/
|
||||
|
||||
.text
|
||||
.global test_sub64
|
||||
test_sub64:
|
||||
#ifdef CONFIG_32BIT
|
||||
lw a0, sub64
|
||||
#else
|
||||
ld a0, sub64
|
||||
#endif
|
||||
addi a0, a0, -32
|
||||
ret
|
||||
first:
|
||||
.space 32
|
||||
second:
|
||||
|
||||
.data
|
||||
sub64:
|
||||
.reloc sub64, R_RISCV_ADD64, second
|
||||
.reloc sub64, R_RISCV_SUB64, first
|
||||
.word 0
|
||||
.word 0
|
||||
@@ -0,0 +1,20 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Copyright (C) 2023 Rivos Inc.
|
||||
*/
|
||||
|
||||
.text
|
||||
.global test_sub8
|
||||
test_sub8:
|
||||
lb a0, sub8
|
||||
addi a0, a0, -32
|
||||
ret
|
||||
first:
|
||||
.space 32
|
||||
second:
|
||||
|
||||
.data
|
||||
sub8:
|
||||
.reloc sub8, R_RISCV_ADD8, second
|
||||
.reloc sub8, R_RISCV_SUB8, first
|
||||
.byte 0
|
||||
@@ -0,0 +1,31 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Copyright (C) 2023 Rivos Inc.
|
||||
*/
|
||||
|
||||
.text
|
||||
.global test_uleb_basic
|
||||
test_uleb_basic:
|
||||
ld a0, second
|
||||
addi a0, a0, -127
|
||||
ret
|
||||
|
||||
.global test_uleb_large
|
||||
test_uleb_large:
|
||||
ld a0, fourth
|
||||
addi a0, a0, -0x07e8
|
||||
ret
|
||||
|
||||
.data
|
||||
first:
|
||||
.space 127
|
||||
second:
|
||||
.reloc second, R_RISCV_SET_ULEB128, second
|
||||
.reloc second, R_RISCV_SUB_ULEB128, first
|
||||
.dword 0
|
||||
third:
|
||||
.space 1000
|
||||
fourth:
|
||||
.reloc fourth, R_RISCV_SET_ULEB128, fourth
|
||||
.reloc fourth, R_RISCV_SUB_ULEB128, third
|
||||
.dword 0
|
||||
Reference in New Issue
Block a user