All of lore.kernel.org
 help / color / mirror / Atom feed
From: Mike Rapoport <rppt@kernel.org>
To: Jordan Richards <jordanrichards@google.com>
Cc: Pasha Tatashin <pasha.tatashin@soleen.com>,
	Pratyush Yadav <pratyush@kernel.org>,
	Shuah Khan <shuah@kernel.org>, Jason Miu <jasonmiu@google.com>,
	David Matlack <dmatlack@google.com>,
	linux-mm@kvack.org, linux-kernel@vger.kernel.org,
	linux-kselftest@vger.kernel.org
Subject: Re: [PATCH] selftests/liveupdate: add end to end test infrastructure and scripts
Date: Tue, 27 Jan 2026 19:33:37 +0200	[thread overview]
Message-ID: <aXj28ZAsPhp7s5sm@kernel.org> (raw)
In-Reply-To: <20260122214427.3568647-1-jordanrichards@google.com>

On Thu, Jan 22, 2026 at 09:44:27PM +0000, Jordan Richards wrote:
> From: Pasha Tatashin <pasha.tatashin@soleen.com>
> 
> Add the end to end testing infrastructure required to verify the
> liveupdate feature. This includes a custom init process, a test
> orchestration script, and a batch runner.
> 
> The framework consists of:
> 
> init.c:
> A lightweight init process that manages the kexec lifecycle.
> It mounts necessary filesystems, determines the current execution
> stage (1 or 2) via the kernel command line, and handles the
> kexec_file_load() sequence to transition between kernels.
> 
> luo_test.sh:
> The primary KTAP-compliant test driver. It handles:
> - Kernel configuration merging and building.
> - Cross-compilation detection for x86_64 and arm64.
> - Generation of the initrd containing the test binary and init.
> - QEMU execution with automatic accelerator detection (KVM, HVF,
>  or TCG).
> 
> run.sh:
> A wrapper script to discover and execute all `luo_*.c`
> tests across supported architectures, providing a summary of
> pass/fail/skip results.
> 
> Signed-off-by: Pasha Tatashin <pasha.tatashin@soleen.com>
> Co-developed-by: Jordan Richards <jordanrichards@google.com>
> Signed-off-by: Jordan Richards <jordanrichards@google.com>
> ---
> Changelog since luo v7 [1]:
> - Build test binaries with `-nostdlib -nostdinc`
> - Use minimal per-arch config instead of defconfig
> - Unhandled test errors now cause the test to fail instead of skip
> 
> [1] https://lore.kernel.org/all/20251122222351.1059049-20-pasha.tatashin@soleen.com/

...

> diff --git a/tools/testing/selftests/liveupdate/.gitignore b/tools/testing/selftests/liveupdate/.gitignore
> index 661827083ab6..7dc1e8aec44c 100644
> --- a/tools/testing/selftests/liveupdate/.gitignore
> +++ b/tools/testing/selftests/liveupdate/.gitignore
> @@ -6,4 +6,6 @@
>  !*.sh
>  !.gitignore
>  !config
> +!config.aarch64
> +!config.x86_64
>  !Makefile

Hmm, I missed it when tools/testing/selftests/liveupdate/ was posted.
I'm not a huge fun of negative logic in .gitignore.
Why can't we just exclude the patterns we don't want to track?

> +static int kexec_load(void)
> +{
> +	char cmdline[COMMAND_LINE_SIZE];
> +	int kernel_fd, initrd_fd, err;
> +	ssize_t len;
> +	int fd;
> +
> +	fd = open("/proc/cmdline", O_RDONLY);
> +	if (fd < 0) {
> +		fprintf(stderr, "INIT: Failed to read /proc/cmdline\n");
> +
> +		return -1;
> +	}
> +
> +	len = read(fd, cmdline, sizeof(cmdline) - 1);
> +	close(fd);
> +	if (len < 0)
> +		return -1;
> +
> +	cmdline[len] = 0;
> +	if (len > 0 && cmdline[len - 1] == '\n')
> +		cmdline[len - 1] = 0;
> +
> +	strncat(cmdline, " luo_stage=2", sizeof(cmdline) - strlen(cmdline) - 1);
> +
> +	kernel_fd = open(KERNEL_IMAGE, O_RDONLY);
> +	if (kernel_fd < 0) {
> +		fprintf(stderr, "INIT: Failed to open kernel image\n");
> +		return -1;
> +	}
> +
> +	initrd_fd = open(INITRD_IMAGE, O_RDONLY);
> +	if (initrd_fd < 0) {
> +		fprintf(stderr, "INIT: Failed to open initrd image\n");
> +		close(kernel_fd);
> +		return -1;
> +	}
> +
> +	err = kexec_file_load(kernel_fd, initrd_fd, strlen(cmdline) + 1,
> +			      cmdline, 0);
> +
> +	close(initrd_fd);
> +	close(kernel_fd);
> +
> +	return err ? : 0;

Just return err?

> diff --git a/tools/testing/selftests/liveupdate/luo_test.sh b/tools/testing/selftests/liveupdate/luo_test.sh
> new file mode 100755
> index 000000000000..90ecb16e87bb
> --- /dev/null
> +++ b/tools/testing/selftests/liveupdate/luo_test.sh

...

> +function detect_cross_compile() {
> +	local target=$1
> +	local host=$(uname -m)
> +

This function works fine if you run luo_test.sh directly or have cross
compilers named the way it expects in $PATH.

But if I run
CROSS_COMPILE=~/cross/gcc-13.2.0-nolibc/aarch64-linux/bin/aarch64-linux- ./run.sh
on x86, x86 tests fail

> +	if [ -n "$CROSS_COMPILE" ]; then
> +		return
> +	fi
> +
> +	[[ "$host" == "arm64" ]] && host="aarch64"
> +	[[ "$target" == "arm64" ]] && target="aarch64"
> +
> +	if [[ "$host" == "$target" ]]; then
> +		CROSS_COMPILE=""
> +		return
> +	fi
> +
> +	local candidate=""
> +	case "$target" in
> +		aarch64) candidate="aarch64-linux-gnu-" ;;
> +		x86_64)  candidate="x86_64-linux-gnu-" ;;
> +		*)       skip "Auto-detection for target '$target' not supported. Please set CROSS_COMPILE manually." ;;
> +	esac
> +
> +	if command -v "${candidate}gcc" &> /dev/null; then
> +		CROSS_COMPILE="$candidate"
> +	else
> +		skip "Compiler '${candidate}gcc' not found. Please install it (e.g., 'apt install gcc-aarch64-linux-gnu') or set CROSS_COMPILE."
> +	fi
> +}
> +
> +function build_kernel() {
> +	local build_dir=$1
> +	local make_cmd=$2
> +	local kimage=$3
> +	local target_arch=$4
> +
> +	local kconfig="$build_dir/.config"
> +	local common_conf="$test_dir/config"
> +	local arch_conf="$test_dir/config.$target_arch"
> +
> +	echo "# Building kernel in: $build_dir"
> +
> +	local fragments=()
> +
> +	if [[ -f "$common_conf" ]]; then
> +		fragments+=("$common_conf")
> +	fi
> +
> +	if [[ -f "$arch_conf" ]]; then
> +		fragments+=("$arch_conf")
> +	fi

I think the common and arch config fragments are required and we can just
assign fragments directly and run merge_config.sh.

> +
> +	if [[ ${#fragments[@]} > 1 ]]; then
> +		echo $fragments
> +		"$kernel_dir/scripts/kconfig/merge_config.sh" \
> +			-Q -m -O "$build_dir" "${fragments[@]}" >> /dev/null
> +	else
> +		cp ${fragments[0]} $kconfig
> +	fi
> +	cat $kconfig
> +
> +	$make_cmd olddefconfig
> +	$make_cmd "$kimage"
> +	$make_cmd headers_install INSTALL_HDR_PATH="$headers_dir"
> +}

...

> +function run_qemu() {
> +	local qemu_cmd=$1
> +	local cmdline=$2
> +	local kernel_path=$3
> +	local serial="$workspace_dir/qemu.serial"
> +
> +	local accel="-accel tcg"
> +	local host_machine=$(uname -m)
> +
> +	[[ "$host_machine" == "arm64" ]] && host_machine="aarch64"
> +	[[ "$host_machine" == "x86_64" ]] && host_machine="x86_64"
> +
> +	if [[ "$qemu_cmd" == *"$host_machine"* ]]; then
> +		if [ -w /dev/kvm ]; then
> +			accel="-accel kvm"
> +		fi
> +	fi

Do we care that much about qemu warnings about invalid accelerator to have
this logic here?

-accel kvm -accel hvf -accel tcg 

seems to cover all bases.

> +
> +	cmdline="$cmdline liveupdate=on panic=-1"
> +

...

> diff --git a/tools/testing/selftests/liveupdate/luo_test_utils.c b/tools/testing/selftests/liveupdate/luo_test_utils.c
> index 3c8721c505df..7ee80b6ed4cb 100644
> --- a/tools/testing/selftests/liveupdate/luo_test_utils.c
> +++ b/tools/testing/selftests/liveupdate/luo_test_utils.c
> @@ -13,6 +13,7 @@
>  #include <getopt.h>
>  #include <fcntl.h>
>  #include <unistd.h>
> +#include <sys.h>

This breaks running normal make:

luo_test_utils.c:16:10: fatal error: sys.h: No such file or directory
   16 | #include <sys.h>
      |          ^~~~~~~

NOLIBC specific includes and calls should be guarded with #ifdef NOLIBC

>  #include <sys/ioctl.h>
>  #include <sys/syscall.h>
>  #include <sys/mman.h>
> @@ -21,8 +22,20 @@
>  #include <errno.h>
>  #include <stdarg.h>
> 
> +#include <linux/unistd.h>
> +
>  #include "luo_test_utils.h"
> 
> +int sys_ftruncate(int fd, off_t length)
> +{
> +	return my_syscall2(__NR_ftruncate, fd, length);
> +}
> +
> +int ftruncate(int fd, off_t length)
> +{
> +	return __sysret(sys_ftruncate(fd, length));
> +}

These should be added to nolibc I suppose.

> +

,,,

> diff --git a/tools/testing/selftests/liveupdate/run.sh b/tools/testing/selftests/liveupdate/run.sh
> new file mode 100755
> index 000000000000..3f6b29a26648
> --- /dev/null
> +++ b/tools/testing/selftests/liveupdate/run.sh
> @@ -0,0 +1,68 @@
> +#!/bin/bash
> +# SPDX-License-Identifier: GPL-2.0
> +
> +OUTPUT_DIR="results_$(date +%Y%m%d_%H%M%S)"

I don't think that putting the results in the current directory rather than
in SCRIPT_DIR or in an explicitly named directory is a good idea.

> +SCRIPT_DIR=$(dirname "$(realpath "$0")")
> +TEST_RUNNER="$SCRIPT_DIR/luo_test.sh"
> +
> +TARGETS=("x86_64" "aarch64")
> +
> +GREEN='\033[0;32m'
> +RED='\033[0;31m'
> +YELLOW='\033[1;33m'
> +NC='\033[0m'
> +
> +PASSED=()
> +FAILED=()
> +SKIPPED=()
> +
> +mkdir -p "$OUTPUT_DIR"
> +
> +TEST_NAMES=()
> +while IFS= read -r file; do
> +    TEST_NAMES+=("$(basename "$file" .c)")
> +done < <(find "$SCRIPT_DIR" -maxdepth 1 -name "luo_*.c" ! -name "luo_test_utils.c")

I don't like name based detection of tests. Listing them explicitly seems a
viable option.

> +
> +if [ ${#TEST_NAMES[@]} -eq 0 ]; then
> +    echo "No tests found in $SCRIPT_DIR"
> +    exit 1
> +fi
> +

-- 
Sincerely yours,
Mike.

  reply	other threads:[~2026-01-27 17:33 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-01-22 21:44 [PATCH] selftests/liveupdate: add end to end test infrastructure and scripts Jordan Richards
2026-01-27 17:33 ` Mike Rapoport [this message]
2026-01-29 22:51   ` David Matlack
2026-02-02 21:48   ` Jordan Richards
2026-02-03 18:24     ` Mike Rapoport
2026-02-05 22:11   ` Jordan Richards
  -- strict thread matches above, loose matches on Subject: below --
2026-01-23  8:01 kernel test robot
2026-01-23  8:32 kernel test robot

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=aXj28ZAsPhp7s5sm@kernel.org \
    --to=rppt@kernel.org \
    --cc=dmatlack@google.com \
    --cc=jasonmiu@google.com \
    --cc=jordanrichards@google.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-kselftest@vger.kernel.org \
    --cc=linux-mm@kvack.org \
    --cc=pasha.tatashin@soleen.com \
    --cc=pratyush@kernel.org \
    --cc=shuah@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.