All of lore.kernel.org
 help / color / mirror / Atom feed
From: Yafang Shao <laoar.shao@gmail.com>
To: jpoimboe@kernel.org, jikos@kernel.org, mbenes@suse.cz,
	pmladek@suse.com, joe.lawrence@redhat.com, song@kernel.org
Cc: live-patching@vger.kernel.org, Yafang Shao <laoar.shao@gmail.com>
Subject: [PATCH v8 2/9] selftests/livepatch: Adapt atomic replace tests to provides/obsoletes
Date: Wed,  9 Sep 2026 10:43:17 +0800	[thread overview]
Message-ID: <20260909024324.16002-3-laoar.shao@gmail.com> (raw)
In-Reply-To: <20260909024324.16002-1-laoar.shao@gmail.com>

The legacy "replace" field in struct klp_patch will be replaced by the
provides/obsoletes mechanism. As a result, the atomic replace
selftests fail to build against kernels that only support
provides/obsoletes.

Adapt the selftests so that they build and run on both old and new
kernels.  On kernels without the legacy "replace" support, the
replace-related test cases are skipped with a SKIP message instead
of being run.

The provides/obsoletes based selftests will be added later after the
provides/obsoletes are substituted.

Suggested-by: Petr Mladek <pmladek@suse.com>
Signed-off-by: Yafang Shao <laoar.shao@gmail.com>
---
 .../testing/selftests/livepatch/functions.sh  |  30 ++
 .../selftests/livepatch/test-callbacks.sh     | 209 ++++++------
 .../selftests/livepatch/test-livepatch.sh     | 303 +++++++++---------
 .../test_modules/test_klp_callbacks_demo2.c   |  16 +
 .../test_modules/test_klp_meminfo_lp.c        |  16 +
 .../livepatch/test_modules/test_klp_state.c   |   7 +
 .../livepatch/test_modules/test_klp_state2.c  |   7 +
 7 files changed, 347 insertions(+), 241 deletions(-)

diff --git a/tools/testing/selftests/livepatch/functions.sh b/tools/testing/selftests/livepatch/functions.sh
index 8352c8d509a5..11f3b87cae4c 100644
--- a/tools/testing/selftests/livepatch/functions.sh
+++ b/tools/testing/selftests/livepatch/functions.sh
@@ -314,6 +314,15 @@ function start_test {
 	log "===== TEST: $test ====="
 }
 
+function skip_test {
+	local test="$1"
+	local reason="$2"
+
+	echo -n "TEST: $test ... "
+	echo "SKIP ($reason)"
+	log "===== TEST: $test SKIPPED: $reason ====="
+}
+
 # check_result() - verify dmesg output
 #	TODO - better filter, out of order msgs, etc?
 function check_result {
@@ -357,6 +366,27 @@ function does_sysfs_exist() {
 	[[ -f "$SYSFS_KLP_DIR/$mod/$attr" ]]
 }
 
+# detect_provides_attr() - detect whether the running kernel supports the
+# livepatch "provides" attribute and set HAS_PROVIDES_ATTR accordingly.
+# The provides/obsoletes based tests are only run when HAS_PROVIDES_ATTR
+# is set.
+function detect_provides_attr() {
+	HAS_PROVIDES_ATTR=0
+
+	if [[ -r /proc/config.gz ]] &&
+	   zgrep -q "CONFIG_KLP_HAS_PROVIDES=y" /proc/config.gz 2>/dev/null; then
+		HAS_PROVIDES_ATTR=1
+		return 0
+	fi
+
+	load_lp test_klp_cmdline_lp
+	if does_sysfs_exist test_klp_cmdline_lp "provides"; then
+		HAS_PROVIDES_ATTR=1
+	fi
+	disable_lp test_klp_cmdline_lp
+	unload_lp test_klp_cmdline_lp
+}
+
 # check_sysfs_rights(modname, rel_path, expected_rights) - check sysfs
 # path permissions
 #	modname - livepatch module creating the sysfs interface
diff --git a/tools/testing/selftests/livepatch/test-callbacks.sh b/tools/testing/selftests/livepatch/test-callbacks.sh
index 2a03deb26a12..bda73853d2d1 100755
--- a/tools/testing/selftests/livepatch/test-callbacks.sh
+++ b/tools/testing/selftests/livepatch/test-callbacks.sh
@@ -10,6 +10,7 @@ MOD_TARGET=test_klp_callbacks_mod
 MOD_TARGET_BUSY=test_klp_callbacks_busy
 
 setup_config
+detect_provides_attr
 
 
 # Test a combination of loading a kernel module and a livepatch that
@@ -451,103 +452,117 @@ $MOD_TARGET_BUSY: busymod_work_func exit
 $MOD_TARGET_BUSY: ${MOD_TARGET_BUSY}_exit"
 
 
-# Test loading multiple livepatches.  This test-case is mainly for comparing
-# with the next test-case.
-#
-# - Load and unload two livepatches, pre and post (un)patch callbacks
-#   execute as each patch progresses through its (un)patching
-#   transition.
-
-start_test "multiple livepatches"
-
-load_lp $MOD_LIVEPATCH
-load_lp $MOD_LIVEPATCH2
-disable_lp $MOD_LIVEPATCH2
-disable_lp $MOD_LIVEPATCH
-unload_lp $MOD_LIVEPATCH2
-unload_lp $MOD_LIVEPATCH
-
-check_result "% insmod test_modules/$MOD_LIVEPATCH.ko
-livepatch: enabling patch '$MOD_LIVEPATCH'
-livepatch: '$MOD_LIVEPATCH': initializing patching transition
-$MOD_LIVEPATCH: pre_patch_callback: vmlinux
-livepatch: '$MOD_LIVEPATCH': starting patching transition
-livepatch: '$MOD_LIVEPATCH': completing patching transition
-$MOD_LIVEPATCH: post_patch_callback: vmlinux
-livepatch: '$MOD_LIVEPATCH': patching complete
-% insmod test_modules/$MOD_LIVEPATCH2.ko
-livepatch: enabling patch '$MOD_LIVEPATCH2'
-livepatch: '$MOD_LIVEPATCH2': initializing patching transition
-$MOD_LIVEPATCH2: pre_patch_callback: vmlinux
-livepatch: '$MOD_LIVEPATCH2': starting patching transition
-livepatch: '$MOD_LIVEPATCH2': completing patching transition
-$MOD_LIVEPATCH2: post_patch_callback: vmlinux
-livepatch: '$MOD_LIVEPATCH2': patching complete
-% echo 0 > $SYSFS_KLP_DIR/$MOD_LIVEPATCH2/enabled
-livepatch: '$MOD_LIVEPATCH2': initializing unpatching transition
-$MOD_LIVEPATCH2: pre_unpatch_callback: vmlinux
-livepatch: '$MOD_LIVEPATCH2': starting unpatching transition
-livepatch: '$MOD_LIVEPATCH2': completing unpatching transition
-$MOD_LIVEPATCH2: post_unpatch_callback: vmlinux
-livepatch: '$MOD_LIVEPATCH2': unpatching complete
-% echo 0 > $SYSFS_KLP_DIR/$MOD_LIVEPATCH/enabled
-livepatch: '$MOD_LIVEPATCH': initializing unpatching transition
-$MOD_LIVEPATCH: pre_unpatch_callback: vmlinux
-livepatch: '$MOD_LIVEPATCH': starting unpatching transition
-livepatch: '$MOD_LIVEPATCH': completing unpatching transition
-$MOD_LIVEPATCH: post_unpatch_callback: vmlinux
-livepatch: '$MOD_LIVEPATCH': unpatching complete
-% rmmod $MOD_LIVEPATCH2
-% rmmod $MOD_LIVEPATCH"
-
-
-# Load multiple livepatches, but the second as an 'atomic-replace'
-# patch.  When the latter loads, the original livepatch should be
-# disabled and *none* of its pre/post-unpatch callbacks executed.  On
-# the other hand, when the atomic-replace livepatch is disabled, its
-# pre/post-unpatch callbacks *should* be executed.
-#
-# - Load and unload two livepatches, the second of which has its
-#   .replace flag set true.
-#
-# - Pre and post patch callbacks are executed for both livepatches.
-#
-# - Once the atomic replace module is loaded, only its pre and post
-#   unpatch callbacks are executed.
-
-start_test "atomic replace"
-
-load_lp $MOD_LIVEPATCH
-load_lp $MOD_LIVEPATCH2 replace=1
-disable_lp $MOD_LIVEPATCH2
-unload_lp $MOD_LIVEPATCH2
-unload_lp $MOD_LIVEPATCH
-
-check_result "% insmod test_modules/$MOD_LIVEPATCH.ko
-livepatch: enabling patch '$MOD_LIVEPATCH'
-livepatch: '$MOD_LIVEPATCH': initializing patching transition
-$MOD_LIVEPATCH: pre_patch_callback: vmlinux
-livepatch: '$MOD_LIVEPATCH': starting patching transition
-livepatch: '$MOD_LIVEPATCH': completing patching transition
-$MOD_LIVEPATCH: post_patch_callback: vmlinux
-livepatch: '$MOD_LIVEPATCH': patching complete
-% insmod test_modules/$MOD_LIVEPATCH2.ko replace=1
-livepatch: enabling patch '$MOD_LIVEPATCH2'
-livepatch: '$MOD_LIVEPATCH2': initializing patching transition
-$MOD_LIVEPATCH2: pre_patch_callback: vmlinux
-livepatch: '$MOD_LIVEPATCH2': starting patching transition
-livepatch: '$MOD_LIVEPATCH2': completing patching transition
-$MOD_LIVEPATCH2: post_patch_callback: vmlinux
-livepatch: '$MOD_LIVEPATCH2': patching complete
-% echo 0 > $SYSFS_KLP_DIR/$MOD_LIVEPATCH2/enabled
-livepatch: '$MOD_LIVEPATCH2': initializing unpatching transition
-$MOD_LIVEPATCH2: pre_unpatch_callback: vmlinux
-livepatch: '$MOD_LIVEPATCH2': starting unpatching transition
-livepatch: '$MOD_LIVEPATCH2': completing unpatching transition
-$MOD_LIVEPATCH2: post_unpatch_callback: vmlinux
-livepatch: '$MOD_LIVEPATCH2': unpatching complete
-% rmmod $MOD_LIVEPATCH2
-% rmmod $MOD_LIVEPATCH"
+if [[ "$HAS_PROVIDES_ATTR" != "1" ]]; then
+	# Test loading multiple livepatches.  This test-case is mainly for comparing
+	# with the next test-case.
+	#
+	# - Load and unload two livepatches, pre and post (un)patch callbacks
+	#   execute as each patch progresses through its (un)patching
+	#   transition.
+
+	start_test "multiple livepatches"
+
+	load_lp $MOD_LIVEPATCH
+	load_lp $MOD_LIVEPATCH2
+	disable_lp $MOD_LIVEPATCH2
+	disable_lp $MOD_LIVEPATCH
+	unload_lp $MOD_LIVEPATCH2
+	unload_lp $MOD_LIVEPATCH
+
+	check_result "$(cat <<EOF | sed 's/^[[:space:]]*//'
+	% insmod test_modules/$MOD_LIVEPATCH.ko
+	livepatch: enabling patch '$MOD_LIVEPATCH'
+	livepatch: '$MOD_LIVEPATCH': initializing patching transition
+	$MOD_LIVEPATCH: pre_patch_callback: vmlinux
+	livepatch: '$MOD_LIVEPATCH': starting patching transition
+	livepatch: '$MOD_LIVEPATCH': completing patching transition
+	$MOD_LIVEPATCH: post_patch_callback: vmlinux
+	livepatch: '$MOD_LIVEPATCH': patching complete
+	% insmod test_modules/$MOD_LIVEPATCH2.ko
+	livepatch: enabling patch '$MOD_LIVEPATCH2'
+	livepatch: '$MOD_LIVEPATCH2': initializing patching transition
+	$MOD_LIVEPATCH2: pre_patch_callback: vmlinux
+	livepatch: '$MOD_LIVEPATCH2': starting patching transition
+	livepatch: '$MOD_LIVEPATCH2': completing patching transition
+	$MOD_LIVEPATCH2: post_patch_callback: vmlinux
+	livepatch: '$MOD_LIVEPATCH2': patching complete
+	% echo 0 > $SYSFS_KLP_DIR/$MOD_LIVEPATCH2/enabled
+	livepatch: '$MOD_LIVEPATCH2': initializing unpatching transition
+	$MOD_LIVEPATCH2: pre_unpatch_callback: vmlinux
+	livepatch: '$MOD_LIVEPATCH2': starting unpatching transition
+	livepatch: '$MOD_LIVEPATCH2': completing unpatching transition
+	$MOD_LIVEPATCH2: post_unpatch_callback: vmlinux
+	livepatch: '$MOD_LIVEPATCH2': unpatching complete
+	% echo 0 > $SYSFS_KLP_DIR/$MOD_LIVEPATCH/enabled
+	livepatch: '$MOD_LIVEPATCH': initializing unpatching transition
+	$MOD_LIVEPATCH: pre_unpatch_callback: vmlinux
+	livepatch: '$MOD_LIVEPATCH': starting unpatching transition
+	livepatch: '$MOD_LIVEPATCH': completing unpatching transition
+	$MOD_LIVEPATCH: post_unpatch_callback: vmlinux
+	livepatch: '$MOD_LIVEPATCH': unpatching complete
+	% rmmod $MOD_LIVEPATCH2
+	% rmmod $MOD_LIVEPATCH
+EOF
+	)"
+else
+	skip_test "multiple livepatches" "legacy replace attribute not present"
+fi
+
+
+if [[ "$HAS_PROVIDES_ATTR" != "1" ]]; then
+	# Load multiple livepatches, but the second as an 'atomic-replace'
+	# patch.  When the latter loads, the original livepatch should be
+	# disabled and *none* of its pre/post-unpatch callbacks executed.  On
+	# the other hand, when the atomic-replace livepatch is disabled, its
+	# pre/post-unpatch callbacks *should* be executed.
+	#
+	# - Load and unload two livepatches, the second of which has its
+	#   .replace flag set true.
+	#
+	# - Pre and post patch callbacks are executed for both livepatches.
+	#
+	# - Once the atomic replace module is loaded, only its pre and post
+	#   unpatch callbacks are executed.
+
+	start_test "atomic replace"
+
+	load_lp $MOD_LIVEPATCH
+	load_lp $MOD_LIVEPATCH2 replace=1
+	disable_lp $MOD_LIVEPATCH2
+	unload_lp $MOD_LIVEPATCH2
+	unload_lp $MOD_LIVEPATCH
+
+	check_result "$(cat <<EOF | sed 's/^[[:space:]]*//'
+	% insmod test_modules/$MOD_LIVEPATCH.ko
+	livepatch: enabling patch '$MOD_LIVEPATCH'
+	livepatch: '$MOD_LIVEPATCH': initializing patching transition
+	$MOD_LIVEPATCH: pre_patch_callback: vmlinux
+	livepatch: '$MOD_LIVEPATCH': starting patching transition
+	livepatch: '$MOD_LIVEPATCH': completing patching transition
+	$MOD_LIVEPATCH: post_patch_callback: vmlinux
+	livepatch: '$MOD_LIVEPATCH': patching complete
+	% insmod test_modules/$MOD_LIVEPATCH2.ko replace=1
+	livepatch: enabling patch '$MOD_LIVEPATCH2'
+	livepatch: '$MOD_LIVEPATCH2': initializing patching transition
+	$MOD_LIVEPATCH2: pre_patch_callback: vmlinux
+	livepatch: '$MOD_LIVEPATCH2': starting patching transition
+	livepatch: '$MOD_LIVEPATCH2': completing patching transition
+	$MOD_LIVEPATCH2: post_patch_callback: vmlinux
+	livepatch: '$MOD_LIVEPATCH2': patching complete
+	% echo 0 > $SYSFS_KLP_DIR/$MOD_LIVEPATCH2/enabled
+	livepatch: '$MOD_LIVEPATCH2': initializing unpatching transition
+	$MOD_LIVEPATCH2: pre_unpatch_callback: vmlinux
+	livepatch: '$MOD_LIVEPATCH2': starting unpatching transition
+	livepatch: '$MOD_LIVEPATCH2': completing unpatching transition
+	$MOD_LIVEPATCH2: post_unpatch_callback: vmlinux
+	livepatch: '$MOD_LIVEPATCH2': unpatching complete
+	% rmmod $MOD_LIVEPATCH2
+	% rmmod $MOD_LIVEPATCH
+EOF
+	)"
+else
+	skip_test "atomic replace" "legacy replace attribute not present"
+fi
 
 
 exit 0
diff --git a/tools/testing/selftests/livepatch/test-livepatch.sh b/tools/testing/selftests/livepatch/test-livepatch.sh
index 5380b5f174d4..e6a278646ed0 100755
--- a/tools/testing/selftests/livepatch/test-livepatch.sh
+++ b/tools/testing/selftests/livepatch/test-livepatch.sh
@@ -12,6 +12,7 @@ MOD_TARGET=test_klp_mod_target
 MOD_TARGET_PATCH=test_klp_mod_patch
 
 setup_config
+detect_provides_attr
 
 
 # - load a livepatch that modifies the output from /proc/cmdline and
@@ -49,153 +50,167 @@ livepatch: '$MOD_LIVEPATCH1': unpatching complete
 % rmmod $MOD_LIVEPATCH1"
 
 
-# - load a livepatch that modifies the output from /proc/cmdline and
-#   verify correct behavior
-# - load another livepatch and verify that both livepatches are active
-# - unload the second livepatch and verify that the first is still active
-# - unload the first livepatch and verify none are active
-
-start_test "multiple livepatches"
-
-load_lp $MOD_LIVEPATCH1
-
-grep 'live patched' /proc/cmdline > /dev/kmsg
-grep 'live patched' /proc/meminfo > /dev/kmsg
-
-load_lp $MOD_REPLACE replace=0
-
-grep 'live patched' /proc/cmdline > /dev/kmsg
-grep 'live patched' /proc/meminfo > /dev/kmsg
-
-disable_lp $MOD_REPLACE
-unload_lp $MOD_REPLACE
-
-grep 'live patched' /proc/cmdline > /dev/kmsg
-grep 'live patched' /proc/meminfo > /dev/kmsg
-
-disable_lp $MOD_LIVEPATCH1
-unload_lp $MOD_LIVEPATCH1
-
-grep 'live patched' /proc/cmdline > /dev/kmsg
-grep 'live patched' /proc/meminfo > /dev/kmsg
-
-check_result "% insmod test_modules/$MOD_LIVEPATCH1.ko
-livepatch: enabling patch '$MOD_LIVEPATCH1'
-livepatch: '$MOD_LIVEPATCH1': initializing patching transition
-livepatch: '$MOD_LIVEPATCH1': starting patching transition
-livepatch: '$MOD_LIVEPATCH1': completing patching transition
-livepatch: '$MOD_LIVEPATCH1': patching complete
-$MOD_LIVEPATCH1: this has been live patched
-% insmod test_modules/$MOD_REPLACE.ko replace=0
-livepatch: enabling patch '$MOD_REPLACE'
-livepatch: '$MOD_REPLACE': initializing patching transition
-livepatch: '$MOD_REPLACE': starting patching transition
-livepatch: '$MOD_REPLACE': completing patching transition
-livepatch: '$MOD_REPLACE': patching complete
-$MOD_LIVEPATCH1: this has been live patched
-$MOD_REPLACE: this has been live patched
-% echo 0 > $SYSFS_KLP_DIR/$MOD_REPLACE/enabled
-livepatch: '$MOD_REPLACE': initializing unpatching transition
-livepatch: '$MOD_REPLACE': starting unpatching transition
-livepatch: '$MOD_REPLACE': completing unpatching transition
-livepatch: '$MOD_REPLACE': unpatching complete
-% rmmod $MOD_REPLACE
-$MOD_LIVEPATCH1: this has been live patched
-% echo 0 > $SYSFS_KLP_DIR/$MOD_LIVEPATCH1/enabled
-livepatch: '$MOD_LIVEPATCH1': initializing unpatching transition
-livepatch: '$MOD_LIVEPATCH1': starting unpatching transition
-livepatch: '$MOD_LIVEPATCH1': completing unpatching transition
-livepatch: '$MOD_LIVEPATCH1': unpatching complete
-% rmmod $MOD_LIVEPATCH1"
-
-
-# - load a livepatch that modifies the output from /proc/cmdline and
-#   verify correct behavior
-# - load two additional livepatches and check the number of livepatch modules
-#   applied
-# - load an atomic replace livepatch and check that the other three modules were
-#   disabled
-# - remove all livepatches besides the atomic replace one and verify that the
-#   atomic replace livepatch is still active
-# - remove the atomic replace livepatch and verify that none are active
-
-start_test "atomic replace livepatch"
-
-load_lp $MOD_LIVEPATCH1
-
-grep 'live patched' /proc/cmdline > /dev/kmsg
-grep 'live patched' /proc/meminfo > /dev/kmsg
-
-for mod in $MOD_LIVEPATCH2 $MOD_LIVEPATCH3; do
-	load_lp "$mod"
-done
-
-mods=($SYSFS_KLP_DIR/*)
-nmods=${#mods[@]}
-if [ "$nmods" -ne 3 ]; then
-	die "Expecting three modules listed, found $nmods"
+if [[ "$HAS_PROVIDES_ATTR" != "1" ]]; then
+	# - load a livepatch that modifies the output from /proc/cmdline and
+	#   verify correct behavior
+	# - load another livepatch and verify that both livepatches are active
+	# - unload the second livepatch and verify that the first is still active
+	# - unload the first livepatch and verify none are active
+
+	start_test "multiple livepatches"
+
+	load_lp $MOD_LIVEPATCH1
+
+	grep 'live patched' /proc/cmdline > /dev/kmsg
+	grep 'live patched' /proc/meminfo > /dev/kmsg
+
+	load_lp $MOD_REPLACE replace=0
+
+	grep 'live patched' /proc/cmdline > /dev/kmsg
+	grep 'live patched' /proc/meminfo > /dev/kmsg
+
+	disable_lp $MOD_REPLACE
+	unload_lp $MOD_REPLACE
+
+	grep 'live patched' /proc/cmdline > /dev/kmsg
+	grep 'live patched' /proc/meminfo > /dev/kmsg
+
+	disable_lp $MOD_LIVEPATCH1
+	unload_lp $MOD_LIVEPATCH1
+
+	grep 'live patched' /proc/cmdline > /dev/kmsg
+	grep 'live patched' /proc/meminfo > /dev/kmsg
+
+	check_result "$(cat <<-EOF | sed 's/^[[:space:]]*//'
+	% insmod test_modules/$MOD_LIVEPATCH1.ko
+	livepatch: enabling patch '$MOD_LIVEPATCH1'
+	livepatch: '$MOD_LIVEPATCH1': initializing patching transition
+	livepatch: '$MOD_LIVEPATCH1': starting patching transition
+	livepatch: '$MOD_LIVEPATCH1': completing patching transition
+	livepatch: '$MOD_LIVEPATCH1': patching complete
+	$MOD_LIVEPATCH1: this has been live patched
+	% insmod test_modules/$MOD_REPLACE.ko replace=0
+	livepatch: enabling patch '$MOD_REPLACE'
+	livepatch: '$MOD_REPLACE': initializing patching transition
+	livepatch: '$MOD_REPLACE': starting patching transition
+	livepatch: '$MOD_REPLACE': completing patching transition
+	livepatch: '$MOD_REPLACE': patching complete
+	$MOD_LIVEPATCH1: this has been live patched
+	$MOD_REPLACE: this has been live patched
+	% echo 0 > $SYSFS_KLP_DIR/$MOD_REPLACE/enabled
+	livepatch: '$MOD_REPLACE': initializing unpatching transition
+	livepatch: '$MOD_REPLACE': starting unpatching transition
+	livepatch: '$MOD_REPLACE': completing unpatching transition
+	livepatch: '$MOD_REPLACE': unpatching complete
+	% rmmod $MOD_REPLACE
+	$MOD_LIVEPATCH1: this has been live patched
+	% echo 0 > $SYSFS_KLP_DIR/$MOD_LIVEPATCH1/enabled
+	livepatch: '$MOD_LIVEPATCH1': initializing unpatching transition
+	livepatch: '$MOD_LIVEPATCH1': starting unpatching transition
+	livepatch: '$MOD_LIVEPATCH1': completing unpatching transition
+	livepatch: '$MOD_LIVEPATCH1': unpatching complete
+	% rmmod $MOD_LIVEPATCH1
+EOF
+	)"
+else
+	skip_test "multiple livepatches" "legacy replace attribute not present"
 fi
 
-load_lp $MOD_REPLACE replace=1
-
-grep 'live patched' /proc/cmdline > /dev/kmsg
-grep 'live patched' /proc/meminfo > /dev/kmsg
 
-loop_until 'mods=($SYSFS_KLP_DIR/*); nmods=${#mods[@]}; [[ "$nmods" -eq 1 ]]' ||
-        die "Expecting only one moduled listed, found $nmods"
-
-# These modules were disabled by the atomic replace
-for mod in $MOD_LIVEPATCH3 $MOD_LIVEPATCH2 $MOD_LIVEPATCH1; do
-	unload_lp "$mod"
-done
-
-grep 'live patched' /proc/cmdline > /dev/kmsg
-grep 'live patched' /proc/meminfo > /dev/kmsg
-
-disable_lp $MOD_REPLACE
-unload_lp $MOD_REPLACE
-
-grep 'live patched' /proc/cmdline > /dev/kmsg
-grep 'live patched' /proc/meminfo > /dev/kmsg
-
-check_result "% insmod test_modules/$MOD_LIVEPATCH1.ko
-livepatch: enabling patch '$MOD_LIVEPATCH1'
-livepatch: '$MOD_LIVEPATCH1': initializing patching transition
-livepatch: '$MOD_LIVEPATCH1': starting patching transition
-livepatch: '$MOD_LIVEPATCH1': completing patching transition
-livepatch: '$MOD_LIVEPATCH1': patching complete
-$MOD_LIVEPATCH1: this has been live patched
-% insmod test_modules/$MOD_LIVEPATCH2.ko
-livepatch: enabling patch '$MOD_LIVEPATCH2'
-livepatch: '$MOD_LIVEPATCH2': initializing patching transition
-livepatch: '$MOD_LIVEPATCH2': starting patching transition
-livepatch: '$MOD_LIVEPATCH2': completing patching transition
-livepatch: '$MOD_LIVEPATCH2': patching complete
-% insmod test_modules/$MOD_LIVEPATCH3.ko
-livepatch: enabling patch '$MOD_LIVEPATCH3'
-livepatch: '$MOD_LIVEPATCH3': initializing patching transition
-$MOD_LIVEPATCH3: pre_patch_callback: vmlinux
-livepatch: '$MOD_LIVEPATCH3': starting patching transition
-livepatch: '$MOD_LIVEPATCH3': completing patching transition
-$MOD_LIVEPATCH3: post_patch_callback: vmlinux
-livepatch: '$MOD_LIVEPATCH3': patching complete
-% insmod test_modules/$MOD_REPLACE.ko replace=1
-livepatch: enabling patch '$MOD_REPLACE'
-livepatch: '$MOD_REPLACE': initializing patching transition
-livepatch: '$MOD_REPLACE': starting patching transition
-livepatch: '$MOD_REPLACE': completing patching transition
-livepatch: '$MOD_REPLACE': patching complete
-$MOD_REPLACE: this has been live patched
-% rmmod $MOD_LIVEPATCH3
-% rmmod $MOD_LIVEPATCH2
-% rmmod $MOD_LIVEPATCH1
-$MOD_REPLACE: this has been live patched
-% echo 0 > $SYSFS_KLP_DIR/$MOD_REPLACE/enabled
-livepatch: '$MOD_REPLACE': initializing unpatching transition
-livepatch: '$MOD_REPLACE': starting unpatching transition
-livepatch: '$MOD_REPLACE': completing unpatching transition
-livepatch: '$MOD_REPLACE': unpatching complete
-% rmmod $MOD_REPLACE"
+if [[ "$HAS_PROVIDES_ATTR" != "1" ]]; then
+	# - load a livepatch that modifies the output from /proc/cmdline and
+	#   verify correct behavior
+	# - load two additional livepatches and check the number of livepatch modules
+	#   applied
+	# - load an atomic replace livepatch and check that the other three modules were
+	#   disabled
+	# - remove all livepatches besides the atomic replace one and verify that the
+	#   atomic replace livepatch is still active
+	# - remove the atomic replace livepatch and verify that none are active
+
+	start_test "atomic replace livepatch"
+
+	load_lp $MOD_LIVEPATCH1
+
+	grep 'live patched' /proc/cmdline > /dev/kmsg
+	grep 'live patched' /proc/meminfo > /dev/kmsg
+
+	for mod in $MOD_LIVEPATCH2 $MOD_LIVEPATCH3; do
+		load_lp "$mod"
+	done
+
+	mods=($SYSFS_KLP_DIR/*)
+	nmods=${#mods[@]}
+	if [ "$nmods" -ne 3 ]; then
+		die "Expecting three modules listed, found $nmods"
+	fi
+
+	load_lp $MOD_REPLACE replace=1
+
+	grep 'live patched' /proc/cmdline > /dev/kmsg
+	grep 'live patched' /proc/meminfo > /dev/kmsg
+
+	loop_until 'mods=($SYSFS_KLP_DIR/*); nmods=${#mods[@]}; [[ "$nmods" -eq 1 ]]' ||
+		die "Expecting only one moduled listed, found $nmods"
+
+	# These modules were disabled by the atomic replace
+	for mod in $MOD_LIVEPATCH3 $MOD_LIVEPATCH2 $MOD_LIVEPATCH1; do
+		unload_lp "$mod"
+	done
+
+	grep 'live patched' /proc/cmdline > /dev/kmsg
+	grep 'live patched' /proc/meminfo > /dev/kmsg
+
+	disable_lp $MOD_REPLACE
+	unload_lp $MOD_REPLACE
+
+	grep 'live patched' /proc/cmdline > /dev/kmsg
+	grep 'live patched' /proc/meminfo > /dev/kmsg
+
+	check_result "$(cat <<EOF | sed 's/^[[:space:]]*//'
+	% insmod test_modules/$MOD_LIVEPATCH1.ko
+	livepatch: enabling patch '$MOD_LIVEPATCH1'
+	livepatch: '$MOD_LIVEPATCH1': initializing patching transition
+	livepatch: '$MOD_LIVEPATCH1': starting patching transition
+	livepatch: '$MOD_LIVEPATCH1': completing patching transition
+	livepatch: '$MOD_LIVEPATCH1': patching complete
+	$MOD_LIVEPATCH1: this has been live patched
+	% insmod test_modules/$MOD_LIVEPATCH2.ko
+	livepatch: enabling patch '$MOD_LIVEPATCH2'
+	livepatch: '$MOD_LIVEPATCH2': initializing patching transition
+	livepatch: '$MOD_LIVEPATCH2': starting patching transition
+	livepatch: '$MOD_LIVEPATCH2': completing patching transition
+	livepatch: '$MOD_LIVEPATCH2': patching complete
+	% insmod test_modules/$MOD_LIVEPATCH3.ko
+	livepatch: enabling patch '$MOD_LIVEPATCH3'
+	livepatch: '$MOD_LIVEPATCH3': initializing patching transition
+	$MOD_LIVEPATCH3: pre_patch_callback: vmlinux
+	livepatch: '$MOD_LIVEPATCH3': starting patching transition
+	livepatch: '$MOD_LIVEPATCH3': completing patching transition
+	$MOD_LIVEPATCH3: post_patch_callback: vmlinux
+	livepatch: '$MOD_LIVEPATCH3': patching complete
+	% insmod test_modules/$MOD_REPLACE.ko replace=1
+	livepatch: enabling patch '$MOD_REPLACE'
+	livepatch: '$MOD_REPLACE': initializing patching transition
+	livepatch: '$MOD_REPLACE': starting patching transition
+	livepatch: '$MOD_REPLACE': completing patching transition
+	livepatch: '$MOD_REPLACE': patching complete
+	$MOD_REPLACE: this has been live patched
+	% rmmod $MOD_LIVEPATCH3
+	% rmmod $MOD_LIVEPATCH2
+	% rmmod $MOD_LIVEPATCH1
+	$MOD_REPLACE: this has been live patched
+	% echo 0 > $SYSFS_KLP_DIR/$MOD_REPLACE/enabled
+	livepatch: '$MOD_REPLACE': initializing unpatching transition
+	livepatch: '$MOD_REPLACE': starting unpatching transition
+	livepatch: '$MOD_REPLACE': completing unpatching transition
+	livepatch: '$MOD_REPLACE': unpatching complete
+	% rmmod $MOD_REPLACE
+EOF
+	)"
+else
+	skip_test "atomic replace livepatch" "legacy replace attribute not present"
+fi
 
 
 # - load a target module that provides /proc/test_klp_mod_target with
diff --git a/tools/testing/selftests/livepatch/test_modules/test_klp_callbacks_demo2.c b/tools/testing/selftests/livepatch/test_modules/test_klp_callbacks_demo2.c
index 5417573e80af..de4eabd4b924 100644
--- a/tools/testing/selftests/livepatch/test_modules/test_klp_callbacks_demo2.c
+++ b/tools/testing/selftests/livepatch/test_modules/test_klp_callbacks_demo2.c
@@ -7,9 +7,16 @@
 #include <linux/kernel.h>
 #include <linux/livepatch.h>
 
+#ifndef CONFIG_KLP_HAS_PROVIDES
 static int replace;
 module_param(replace, int, 0644);
 MODULE_PARM_DESC(replace, "replace (default=0)");
+#else
+/*
+ * TODO: Add provides/obsoletes module parameters for the
+ * provides/obsoletes based tests (to be added later).
+ */
+#endif
 
 static const char *const module_state[] = {
 	[MODULE_STATE_LIVE]	= "[MODULE_STATE_LIVE] Normal state",
@@ -72,12 +79,21 @@ static struct klp_object objs[] = {
 static struct klp_patch patch = {
 	.mod = THIS_MODULE,
 	.objs = objs,
+#ifndef CONFIG_KLP_HAS_PROVIDES
 	/* set .replace in the init function below for demo purposes */
+#endif
 };
 
 static int test_klp_callbacks_demo2_init(void)
 {
+#ifndef CONFIG_KLP_HAS_PROVIDES
 	patch.replace = replace;
+#else
+	/*
+	 * TODO: Set provides/obsoletes from the module parameters
+	 * for the provides/obsoletes based tests (to be added later).
+	 */
+#endif
 	return klp_enable_patch(&patch);
 }
 
diff --git a/tools/testing/selftests/livepatch/test_modules/test_klp_meminfo_lp.c b/tools/testing/selftests/livepatch/test_modules/test_klp_meminfo_lp.c
index f2477b217aab..842efa5b22db 100644
--- a/tools/testing/selftests/livepatch/test_modules/test_klp_meminfo_lp.c
+++ b/tools/testing/selftests/livepatch/test_modules/test_klp_meminfo_lp.c
@@ -7,9 +7,16 @@
 #include <linux/kernel.h>
 #include <linux/livepatch.h>
 
+#ifndef CONFIG_KLP_HAS_PROVIDES
 static int replace;
 module_param(replace, int, 0644);
 MODULE_PARM_DESC(replace, "replace (default=0)");
+#else
+/*
+ * TODO: Add provides/obsoletes module parameters for the
+ * provides/obsoletes based tests (to be added later).
+ */
+#endif
 
 #include <linux/seq_file.h>
 static int livepatch_meminfo_proc_show(struct seq_file *m, void *v)
@@ -36,12 +43,21 @@ static struct klp_object objs[] = {
 static struct klp_patch patch = {
 	.mod = THIS_MODULE,
 	.objs = objs,
+#ifndef CONFIG_KLP_HAS_PROVIDES
 	/* set .replace in the init function below for demo purposes */
+#endif
 };
 
 static int test_klp_meminfo_lp_init(void)
 {
+#ifndef CONFIG_KLP_HAS_PROVIDES
 	patch.replace = replace;
+#else
+	/*
+	 * TODO: Set provides/obsoletes from the module parameters
+	 * for the provides/obsoletes based tests (to be added later).
+	 */
+#endif
 	return klp_enable_patch(&patch);
 }
 
diff --git a/tools/testing/selftests/livepatch/test_modules/test_klp_state.c b/tools/testing/selftests/livepatch/test_modules/test_klp_state.c
index 57a4253acb01..69825ea8d65d 100644
--- a/tools/testing/selftests/livepatch/test_modules/test_klp_state.c
+++ b/tools/testing/selftests/livepatch/test_modules/test_klp_state.c
@@ -142,7 +142,14 @@ static struct klp_patch patch = {
 	.mod = THIS_MODULE,
 	.objs = objs,
 	.states = states,
+#ifndef CONFIG_KLP_HAS_PROVIDES
 	.replace = true,
+#else
+	/*
+	 * TODO: Add provides/obsoletes module parameters for the
+	 * provides/obsoletes based tests (to be added later).
+	 */
+#endif
 };
 
 static int test_klp_callbacks_demo_init(void)
diff --git a/tools/testing/selftests/livepatch/test_modules/test_klp_state2.c b/tools/testing/selftests/livepatch/test_modules/test_klp_state2.c
index c978ea4d5e67..3274f084b035 100644
--- a/tools/testing/selftests/livepatch/test_modules/test_klp_state2.c
+++ b/tools/testing/selftests/livepatch/test_modules/test_klp_state2.c
@@ -171,7 +171,14 @@ static struct klp_patch patch = {
 	.mod = THIS_MODULE,
 	.objs = objs,
 	.states = states,
+#ifndef CONFIG_KLP_HAS_PROVIDES
 	.replace = true,
+#else
+	/*
+	 * TODO: Add provides/obsoletes module parameters for the
+	 * provides/obsoletes based tests (to be added later).
+	 */
+#endif
 };
 
 static int test_klp_callbacks_demo_init(void)
-- 
2.52.0


  parent reply	other threads:[~2026-09-09  2:43 UTC|newest]

Thread overview: 19+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-09-09  2:43 [PATCH v8 0/9] livepatch: Add support for scoped atomic replace Yafang Shao
2026-09-09  2:43 ` [PATCH v8 1/9] selftests/livepatch: Clarify test module file names Yafang Shao
2026-09-09  5:22   ` Song Liu
2026-09-09  2:43 ` Yafang Shao [this message]
2026-09-09  5:27   ` [PATCH v8 2/9] selftests/livepatch: Adapt atomic replace tests to provides/obsoletes Song Liu
2026-09-09  6:59     ` Yafang Shao
2026-09-09  2:43 ` [PATCH v8 3/9] livepatch: Make klp_find_func() non static Yafang Shao
2026-09-09  2:43 ` [PATCH v8 4/9] livepatch: Call klp_init_patch_early() earlier Yafang Shao
2026-09-09  2:56   ` sashiko-bot
2026-09-09  3:44     ` Yafang Shao
2026-09-09  2:43 ` [PATCH v8 5/9] livepatch: Implement provides and obsoletes for scoped atomic replace Yafang Shao
2026-09-09  2:43 ` [PATCH v8 6/9] livepatch: Deprecate stack_order Yafang Shao
2026-09-09  2:43 ` [PATCH v8 7/9] selftests/livepatch: Add provides/obsoletes test scenarios Yafang Shao
2026-09-09  2:43 ` [PATCH v8 8/9] selftests/livepatch: Add state test for provides/obsoletes Yafang Shao
2026-09-09  2:57   ` sashiko-bot
2026-09-09  7:30     ` Yafang Shao
2026-09-09  2:43 ` [PATCH v8 9/9] selftests/livepatch: Add function " Yafang Shao
2026-09-09  2:56   ` sashiko-bot
2026-09-09  7:01     ` Yafang Shao

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260909024324.16002-3-laoar.shao@gmail.com \
    --to=laoar.shao@gmail.com \
    --cc=jikos@kernel.org \
    --cc=joe.lawrence@redhat.com \
    --cc=jpoimboe@kernel.org \
    --cc=live-patching@vger.kernel.org \
    --cc=mbenes@suse.cz \
    --cc=pmladek@suse.com \
    --cc=song@kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.