On 2025-08-01 13:06:30+0300, Mike Rapoport wrote: > From: "Mike Rapoport (Microsoft)" <r...@kernel.org> > > Testing kexec handover requires a kernel driver that will generate some > data and preserve it with KHO on the first boot and then restore that > data and verify it was preserved properly after kexec. > > To facilitate such test, along with the kernel driver responsible for > data generation, preservation and restoration add a script that runs a > kernel in a VM with a minimal /init. The /init enables KHO, loads a > kernel image for kexec and runs kexec reboot. After the boot of the > kexeced kernel, the driver verifies that the data was properly > preserved. > > Signed-off-by: Mike Rapoport (Microsoft) <r...@kernel.org>
Looking at it while awake brought up some more nitpicks. In any case: Reviewed-by: Thomas Weißschuh <li...@weissschuh.net> # for the nolibc usage > diff --git a/tools/testing/selftests/kho/init.c > b/tools/testing/selftests/kho/init.c > new file mode 100644 > index 000000000000..8044ca56fff5 > --- /dev/null > +++ b/tools/testing/selftests/kho/init.c > @@ -0,0 +1,98 @@ > +// SPDX-License-Identifier: GPL-2.0 > + > +#include <errno.h> Not actually used. > +#include <stdio.h> > +#include <unistd.h> > +#include <fcntl.h> > +#include <sys/syscall.h> > +#include <sys/mount.h> > +#include <sys/reboot.h> > + > +/* from arch/x86/include/asm/setup.h */ > +#define COMMAND_LINE_SIZE 2048 > + > +/* from include/linux/kexex.h */ "kexec.h" > +#define KEXEC_FILE_NO_INITRAMFS 0x00000004 This is actually part of the UAPI headers, why not use it from there? > + > +#define KHO_FINILIZE "/debugfs/kho/out/finalize" KHO_FINALIZE > +#define KERNEL_IMAGE "/kernel" > + > +static int mount_filesystems(void) > +{ > + if (mount("debugfs", "/debugfs", "debugfs", 0, NULL) < 0) > + return -1; > + > + return mount("proc", "/proc", "proc", 0, NULL); > +} > + > +static int kho_enable(void) > +{ > + const char enable[] = "1"; > + int fd; > + > + fd = open(KHO_FINILIZE, O_RDWR); > + if (fd < 0) > + return -1; > + > + if (write(fd, enable, sizeof(enable)) != sizeof(enable)) > + return 1; > + > + close(fd); > + return 0; > +} > + > +static long kexec_file_load(int kernel_fd, int initrd_fd, > + unsigned long cmdline_len, const char *cmdline, > + unsigned long flags) > +{ > + return syscall(__NR_kexec_file_load, kernel_fd, initrd_fd, cmdline_len, > + cmdline, flags); > +} > + > +static int kexec_load(void) > +{ > + char cmdline[COMMAND_LINE_SIZE]; > + ssize_t len; > + int fd, err; > + > + fd = open("/proc/cmdline", O_RDONLY); > + if (fd < 0) > + return -1; > + > + len = read(fd, cmdline, sizeof(cmdline)); > + close(fd); > + if (len < 0) > + return -1; > + > + /* replace \n with \0 */ > + cmdline[len - 1] = 0; > + fd = open(KERNEL_IMAGE, O_RDONLY); > + if (fd < 0) > + return -1; > + > + err = kexec_file_load(fd, -1, len, cmdline, KEXEC_FILE_NO_INITRAMFS); > + close(fd); > + > + return err ? : 0; > +} > + > +int main(int argc, char *argv[]) > +{ > + if (mount_filesystems()) > + goto err_reboot; > + > + if (kho_enable()) > + goto err_reboot; > + > + if (kexec_load()) > + goto err_reboot; > + > + if (reboot(RB_KEXEC)) > + goto err_reboot; > + > + return 0; > + > +err_reboot: > + reboot(RB_AUTOBOOT); > + return -1; > +} > diff --git a/tools/testing/selftests/kho/vmtest.sh > b/tools/testing/selftests/kho/vmtest.sh > new file mode 100755 > index 000000000000..3f6c17166846 > --- /dev/null > +++ b/tools/testing/selftests/kho/vmtest.sh (...) > +function mkinitrd() { > + local kernel=$1 > + > + "$CROSS_COMPILE"gcc -s -static -Os -nostdinc -nostdlib \ > + -fno-asynchronous-unwind-tables -fno-ident \ > + -I "$headers_dir/include" \ > + -I "$kernel_dir/tools/include/nolibc" \ > + -o "$tmp_dir/init" "$test_dir/init.c" You could build this as a userprog as part of kbuild. Then it will also work automatically with clang. > + > + cat > "$tmp_dir/cpio_list" <<EOF > +dir /dev 0755 0 0 > +dir /proc 0755 0 0 > +dir /debugfs 0755 0 0 > +nod /dev/console 0600 0 0 c 5 1 > +file /init $tmp_dir/init 0755 0 0 > +file /kernel $kernel 0644 0 0 > +EOF > + > + "$build_dir/usr/gen_init_cpio" "$tmp_dir/cpio_list" > "$initrd" This could also be hooked up to kbuild. > +} (...)