-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
selftests: add new kallsyms selftests
We lack find_symbol() selftests, so add one. This let's us stress test improvements easily on find_symbol() or optimizations. It also inherently allows us to test the limits of kallsyms on Linux today. We test a pathalogical use case for kallsyms by introducing modules which are automatically written for us with a larger number of symbols. We have 4 kallsyms test modules: A: has KALLSYSMS_NUMSYMS exported symbols B: uses one of A's symbols C: adds KALLSYMS_SCALE_FACTOR * KALLSYSMS_NUMSYMS exported D: adds 2 * the symbols than C By using anything much larger than KALLSYSMS_NUMSYMS as 10,000 and KALLSYMS_SCALE_FACTOR of 8 we segfault today. So we're capped at around 160000 symbols somehow today. We can inpsect that issue at our leasure later, but for now the real value to this test is that this will easily allow us to test improvements on find_symbol(). We want to enable this test on allyesmodconfig builds so we can't use this combination, so instead just use a safe value for now and be informative on the Kconfig symbol documentation about where our thresholds are for testers. We default then to KALLSYSMS_NUMSYMS of just 100 and KALLSYMS_SCALE_FACTOR of 8. On x86_64 we can use perf, for other architectures we just use 'time' and allow for customizations. For example a future enhancements could be done for parisc to check for unaligned accesses which triggers a special special exception handler assembler code inside the kernel. The negative impact on performance is so large on parisc that it keeps track of its accesses on /proc/cpuinfo as UAH: IRQ: CPU0 CPU1 3: 1332 0 SuperIO ttyS0 7: 1270013 0 SuperIO pata_ns87415 64: 320023012 320021431 CPU timer 65: 17080507 20624423 CPU IPI UAH: 10948640 58104 Unaligned access handler traps While at it, this tidies up lib/ test modules to allow us to have a new directory for them. The amount of test modules under lib/ is insane. This should also hopefully showcase how to start doing basic self module writing code, which may be more useful for more complex cases later in the future. Signed-off-by: Luis Chamberlain <mcgrof@kernel.org>
- Loading branch information
Luis Chamberlain
committed
Oct 24, 2024
1 parent
2295cf8
commit 84b4a51
Showing
9 changed files
with
350 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
obj-$(CONFIG_TEST_RUNTIME_MODULE) += module/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
test_kallsyms_a.c | ||
test_kallsyms_b.c | ||
test_kallsyms_c.c | ||
test_kallsyms_d.c |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
obj-$(CONFIG_TEST_KALLSYMS_A) += test_kallsyms_a.o | ||
obj-$(CONFIG_TEST_KALLSYMS_B) += test_kallsyms_b.o | ||
obj-$(CONFIG_TEST_KALLSYMS_C) += test_kallsyms_c.o | ||
obj-$(CONFIG_TEST_KALLSYMS_D) += test_kallsyms_d.o | ||
|
||
$(obj)/%.c: FORCE | ||
@$(kecho) " GEN $@" | ||
$(Q)$(srctree)/lib/tests/module/gen_test_kallsyms.sh $@\ | ||
$(CONFIG_TEST_KALLSYMS_NUMSYMS) \ | ||
$(CONFIG_TEST_KALLSYMS_SCALE_FACTOR) | ||
|
||
clean-files += test_kallsyms_a.c | ||
clean-files += test_kallsyms_b.c | ||
clean-files += test_kallsyms_c.c | ||
clean-files += test_kallsyms_d.c |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,128 @@ | ||
#!/bin/bash | ||
|
||
TARGET=$(basename $1) | ||
DIR=lib/tests/module | ||
TARGET="$DIR/$TARGET" | ||
NUM_SYMS=$2 | ||
SCALE_FACTOR=$3 | ||
TEST_TYPE=$(echo $TARGET | sed -e 's|lib/tests/module/test_kallsyms_||g') | ||
TEST_TYPE=$(echo $TEST_TYPE | sed -e 's|.c||g') | ||
|
||
gen_template_module_header() | ||
{ | ||
cat <<____END_MODULE | ||
// SPDX-License-Identifier: GPL-2.0-or-later OR copyleft-next-0.3.1 | ||
/* | ||
* Copyright (C) 2023 Luis Chamberlain <mcgrof@kernel.org> | ||
* | ||
* Automatically generated code for testing, do not edit manually. | ||
*/ | ||
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
#include <linux/init.h> | ||
#include <linux/module.h> | ||
#include <linux/printk.h> | ||
____END_MODULE | ||
} | ||
|
||
gen_num_syms() | ||
{ | ||
PREFIX=$1 | ||
NUM=$2 | ||
for i in $(seq 1 $NUM); do | ||
printf "int auto_test_%s_%010d = 0xff;\n" $PREFIX $i | ||
printf "EXPORT_SYMBOL_GPL(auto_test_%s_%010d);\n" $PREFIX $i | ||
done | ||
echo | ||
} | ||
|
||
gen_template_module_data_a() | ||
{ | ||
gen_num_syms a $1 | ||
cat <<____END_MODULE | ||
static int auto_runtime_test(void) | ||
{ | ||
return 0; | ||
} | ||
____END_MODULE | ||
} | ||
|
||
gen_template_module_data_b() | ||
{ | ||
printf "\nextern int auto_test_a_%010d;\n\n" 28 | ||
echo "static int auto_runtime_test(void)" | ||
echo "{" | ||
printf "\nreturn auto_test_a_%010d;\n" 28 | ||
echo "}" | ||
} | ||
|
||
gen_template_module_data_c() | ||
{ | ||
gen_num_syms c $1 | ||
cat <<____END_MODULE | ||
static int auto_runtime_test(void) | ||
{ | ||
return 0; | ||
} | ||
____END_MODULE | ||
} | ||
|
||
gen_template_module_data_d() | ||
{ | ||
gen_num_syms d $1 | ||
cat <<____END_MODULE | ||
static int auto_runtime_test(void) | ||
{ | ||
return 0; | ||
} | ||
____END_MODULE | ||
} | ||
|
||
gen_template_module_exit() | ||
{ | ||
cat <<____END_MODULE | ||
static int __init auto_test_module_init(void) | ||
{ | ||
return auto_runtime_test(); | ||
} | ||
module_init(auto_test_module_init); | ||
static void __exit auto_test_module_exit(void) | ||
{ | ||
} | ||
module_exit(auto_test_module_exit); | ||
MODULE_AUTHOR("Luis Chamberlain <mcgrof@kernel.org>"); | ||
MODULE_LICENSE("GPL"); | ||
____END_MODULE | ||
} | ||
|
||
case $TEST_TYPE in | ||
a) | ||
gen_template_module_header > $TARGET | ||
gen_template_module_data_a $NUM_SYMS >> $TARGET | ||
gen_template_module_exit >> $TARGET | ||
;; | ||
b) | ||
gen_template_module_header > $TARGET | ||
gen_template_module_data_b >> $TARGET | ||
gen_template_module_exit >> $TARGET | ||
;; | ||
c) | ||
gen_template_module_header > $TARGET | ||
gen_template_module_data_c $((NUM_SYMS * SCALE_FACTOR)) >> $TARGET | ||
gen_template_module_exit >> $TARGET | ||
;; | ||
d) | ||
gen_template_module_header > $TARGET | ||
gen_template_module_data_d $((NUM_SYMS * SCALE_FACTOR * 2)) >> $TARGET | ||
gen_template_module_exit >> $TARGET | ||
;; | ||
*) | ||
;; | ||
esac |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
# SPDX-License-Identifier: GPL-2.0-only | ||
# Makefile for module loading selftests | ||
|
||
# No binaries, but make sure arg-less "make" doesn't trigger "run_tests" | ||
all: | ||
|
||
TEST_PROGS := find_symbol.sh | ||
|
||
include ../lib.mk | ||
|
||
# Nothing to clean up. | ||
clean: |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
CONFIG_TEST_RUNTIME=y | ||
CONFIG_TEST_RUNTIME_MODULE=y | ||
CONFIG_TEST_KALLSYMS=m |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
#!/bin/bash | ||
# SPDX-License-Identifier: GPL-2.0-or-later OR copyleft-next-0.3.1 | ||
# Copyright (C) 2023 Luis Chamberlain <mcgrof@kernel.org> | ||
# | ||
# This is a stress test script for kallsyms through find_symbol() | ||
|
||
set -e | ||
|
||
# Kselftest framework requirement - SKIP code is 4. | ||
ksft_skip=4 | ||
|
||
test_reqs() | ||
{ | ||
if ! which modprobe 2> /dev/null > /dev/null; then | ||
echo "$0: You need modprobe installed" >&2 | ||
exit $ksft_skip | ||
fi | ||
|
||
if ! which kmod 2> /dev/null > /dev/null; then | ||
echo "$0: You need kmod installed" >&2 | ||
exit $ksft_skip | ||
fi | ||
|
||
if ! which perf 2> /dev/null > /dev/null; then | ||
echo "$0: You need perf installed" >&2 | ||
exit $ksft_skip | ||
fi | ||
|
||
uid=$(id -u) | ||
if [ $uid -ne 0 ]; then | ||
echo $msg must be run as root >&2 | ||
exit $ksft_skip | ||
fi | ||
} | ||
|
||
load_mod() | ||
{ | ||
local STATS="-e duration_time" | ||
STATS="$STATS -e user_time" | ||
STATS="$STATS -e system_time" | ||
STATS="$STATS -e page-faults" | ||
local MOD=$1 | ||
|
||
local ARCH="$(uname -m)" | ||
case "${ARCH}" in | ||
x86_64) | ||
perf stat $STATS $MODPROBE test_kallsyms_b | ||
;; | ||
*) | ||
time $MODPROBE test_kallsyms_b | ||
exit 1 | ||
;; | ||
esac | ||
} | ||
|
||
remove_all() | ||
{ | ||
$MODPROBE -r test_kallsyms_b | ||
for i in a b c d; do | ||
$MODPROBE -r test_kallsyms_$i | ||
done | ||
} | ||
test_reqs | ||
|
||
MODPROBE=$(</proc/sys/kernel/modprobe) | ||
|
||
remove_all | ||
load_mod test_kallsyms_b | ||
remove_all | ||
|
||
# Now pollute the namespace | ||
$MODPROBE test_kallsyms_c | ||
load_mod test_kallsyms_b | ||
|
||
# Now pollute the namespace with twice the number of symbols than the last time | ||
remove_all | ||
$MODPROBE test_kallsyms_c | ||
$MODPROBE test_kallsyms_d | ||
load_mod test_kallsyms_b | ||
|
||
exit 0 |