diff mbox series

[next,2/2] support/testing/tests/package/test_kexec.py: new runtime test

Message ID 20230303222658.157671-2-ju.o@free.fr
State Accepted
Headers show
Series [next,1/2] DEVELOPERS: add Julien Olivain for package/kexec | expand

Commit Message

Julien Olivain March 3, 2023, 10:26 p.m. UTC
Signed-off-by: Julien Olivain <ju.o@free.fr>
---
Patch tested on branch next at commit b793f3a with commands:

    python3 -m flake8 \
        support/testing/tests/package/test_kexec.py
    [no-output]

    support/testing/run-tests \
        -d dl -o output_folder \
        tests.package.test_kexec
    ...
    OK
---
 DEVELOPERS                                    |  2 +
 support/testing/tests/package/test_kexec.py   | 93 +++++++++++++++++++
 .../package/test_kexec/linux-kexec.fragment   |  5 +
 3 files changed, 100 insertions(+)
 create mode 100644 support/testing/tests/package/test_kexec.py
 create mode 100644 support/testing/tests/package/test_kexec/linux-kexec.fragment

Comments

Thomas Petazzoni March 12, 2023, 1:13 p.m. UTC | #1
On Fri,  3 Mar 2023 23:26:58 +0100
Julien Olivain <ju.o@free.fr> wrote:

> Signed-off-by: Julien Olivain <ju.o@free.fr>
> ---
> Patch tested on branch next at commit b793f3a with commands:

Applied to next, thanks.

Thomas
Romain Naour May 26, 2023, 12:09 p.m. UTC | #2
Hello Julien,

Le 03/03/2023 à 23:26, Julien Olivain a écrit :
> Signed-off-by: Julien Olivain <ju.o@free.fr>
> ---
> Patch tested on branch next at commit b793f3a with commands:
> 
>     python3 -m flake8 \
>         support/testing/tests/package/test_kexec.py
>     [no-output]
> 
>     support/testing/run-tests \
>         -d dl -o output_folder \
>         tests.package.test_kexec
>     ...
>     OK

Thanks for the runtime test!

> ---
>  DEVELOPERS                                    |  2 +
>  support/testing/tests/package/test_kexec.py   | 93 +++++++++++++++++++
>  .../package/test_kexec/linux-kexec.fragment   |  5 +
>  3 files changed, 100 insertions(+)
>  create mode 100644 support/testing/tests/package/test_kexec.py
>  create mode 100644 support/testing/tests/package/test_kexec/linux-kexec.fragment
> 
> diff --git a/DEVELOPERS b/DEVELOPERS
> index 21ea2b53e8..5cebaeb4f3 100644
> --- a/DEVELOPERS
> +++ b/DEVELOPERS
> @@ -1719,6 +1719,8 @@ F:	support/testing/tests/package/sample_python_spake2.py
>  F:	support/testing/tests/package/test_gnupg2.py
>  F:	support/testing/tests/package/test_highway.py
>  F:	support/testing/tests/package/test_hwloc.py
> +F:	support/testing/tests/package/test_kexec.py
> +F:	support/testing/tests/package/test_kexec/
>  F:	support/testing/tests/package/test_libjxl.py
>  F:	support/testing/tests/package/test_ncdu.py
>  F:	support/testing/tests/package/test_octave.py
> diff --git a/support/testing/tests/package/test_kexec.py b/support/testing/tests/package/test_kexec.py
> new file mode 100644
> index 0000000000..77e383373e
> --- /dev/null
> +++ b/support/testing/tests/package/test_kexec.py
> @@ -0,0 +1,93 @@
> +import os
> +
> +import infra.basetest
> +
> +
> +class TestKexec(infra.basetest.BRTest):
> +
> +    # A specific configuration is needed for using kexec:
> +    # - We use Aarch64 since it is well supported for kexec,
> +    # - A kernel config fragment enables all the kexec parts,
> +    # - The kernel Image is installed on target filesystem to be
> +    #   reloaded through kexec,
> +    # - We use a ext4 rootfs image exposed as a virtio storage (rather
> +    #   than cpio initrd). This avoids needing to install the initrd
> +    #   inside the rootfs.
> +    config = \
> +        """
> +        BR2_aarch64=y
> +        BR2_TOOLCHAIN_EXTERNAL=y
> +        BR2_TARGET_GENERIC_GETTY_PORT="ttyAMA0"
> +        BR2_LINUX_KERNEL=y
> +        BR2_LINUX_KERNEL_CUSTOM_VERSION=y
> +        BR2_LINUX_KERNEL_CUSTOM_VERSION_VALUE="6.1.15"
> +        BR2_LINUX_KERNEL_USE_CUSTOM_CONFIG=y
> +        BR2_LINUX_KERNEL_CUSTOM_CONFIG_FILE="board/qemu/aarch64-virt/linux.config"
> +        BR2_LINUX_KERNEL_CONFIG_FRAGMENT_FILES="{}"
> +        BR2_LINUX_KERNEL_INSTALL_TARGET=y
> +        BR2_LINUX_KERNEL_NEEDS_HOST_OPENSSL=y
> +        BR2_PACKAGE_KEXEC=y
> +        BR2_TARGET_ROOTFS_EXT2=y
> +        BR2_TARGET_ROOTFS_EXT2_4=y
> +        # BR2_TARGET_ROOTFS_TAR is not set
> +        """.format(
> +            infra.filepath("tests/package/test_kexec/linux-kexec.fragment")
> +        )
> +
> +    def test_run(self):
> +        hda = os.path.join(self.builddir, "images", "rootfs.ext4")
> +        kern = os.path.join(self.builddir, "images", "Image")
> +        # Notes:
> +        # Sufficient memory is needed to load the kernel: having at
> +        # least 512MB works. kexec could silently fail if not enough
> +        # memory is present. KASLR needs to be disabled for the test:
> +        # we pass "nokaslr" to kernel bootargs, and also pass
> +        # "dtb-kaslr-seed=off" to qemu virt machine.
> +        bootargs = ["root=/dev/vda console=ttyAMA0 nokaslr"]
> +        qemu_opts = ["-M", "virt,dtb-kaslr-seed=off", "-cpu", "cortex-a57", "-m", "512M",

kaslr-seed requires at least qemu 5.1.x but the test fail in the gitlab runner
using a docker image

"qemu-system-aarch64: Property 'virt-5.2-machine.dtb-kaslr-seed' not found"

See: https://gitlab.com/buildroot.org/buildroot/-/jobs/4322819092

The test actually requires at least qemu 7.0.0 in order to be able to disable
kaslr_seed via dtb:

[qemu 7.0.x]
https://gitlab.com/qemu-project/qemu/-/commit/33973e1e1f88b7588fe9629645e279ff2c6ca1c4

Also dtb-kaslr-seed is aleady deprecaded by qemu.

[qemu 5.1.x]
https://gitlab.com/qemu-project/qemu/-/commit/60592cfed2b685ef114a454d176ef539528cb0cf

[qemu 7.1.x]
https://gitlab.com/qemu-project/qemu/-/commit/5242876f37ca21017e3f6eafbaefaa174babd9b7

Best regards,
Romain


> +                     "-drive", f"file={hda},if=virtio,format=raw"]
> +        self.emulator.boot(arch="aarch64",
> +                           kernel=kern,
> +                           kernel_cmdline=bootargs,
> +                           options=qemu_opts)
> +        self.emulator.login()
> +
> +        # Test the program can execute
> +        self.assertRunOk("kexec --version")
> +
> +        # Check the kexec kernel is NOT loaded:
> +        self.assertRunOk("test \"$(cat /sys/kernel/kexec_loaded)\" -eq 0")
> +
> +        # Load the Kernel:
> +        # "--append br-test" adds a dummy kernel args we'll be able to
> +        # check in the second executed kernel.
> +        # We use the dtb image from /sys/firmware/fdt (since we don't
> +        # have the dtb file in the system)
> +        self.assertRunOk("kexec -d -l --dtb=/sys/firmware/fdt --reuse-cmdline --serial=ttyAMA0 --append=br-test /boot/Image")
> +
> +        # Check the kexec kernel IS loaded:
> +        self.assertRunOk("test \"$(cat /sys/kernel/kexec_loaded)\" -eq 1")
> +
> +        # Create a marker file in tmpfs which is supposed to disappear
> +        # after kexec kernel restart.
> +        self.assertRunOk("touch /dev/shm/br-kexec-marker")
> +
> +        # Execute the loaded kernel (i.e perform a kexec reboot)
> +        # qemu.sendline() is used here because no exit code nor
> +        # program return is expected, since kexec is like a
> +        # reboot. The login is expected to be reached after the
> +        # command is issued.
> +        self.emulator.qemu.sendline("kexec -d -e")
> +
> +        # Wait for the login, and log again
> +        self.emulator.login()
> +
> +        # Check the "br-test" dummy kernel arg is present
> +        self.assertRunOk("grep br-test /proc/cmdline")
> +
> +        # Check the test marker file is no longer here
> +        self.assertRunOk("test ! -e /dev/shm/br-kexec-marker")
> +
> +        # After restart, the kernel is not supposed to have a kexec
> +        # loaded image:
> +        self.assertRunOk("test \"$(cat /sys/kernel/kexec_loaded)\" -eq 0")
> diff --git a/support/testing/tests/package/test_kexec/linux-kexec.fragment b/support/testing/tests/package/test_kexec/linux-kexec.fragment
> new file mode 100644
> index 0000000000..04c65f5cae
> --- /dev/null
> +++ b/support/testing/tests/package/test_kexec/linux-kexec.fragment
> @@ -0,0 +1,5 @@
> +CONFIG_KEXEC=y
> +CONFIG_KEXEC_FILE=y
> +CONFIG_PROC_KCORE=y
> +CONFIG_DEBUG_KERNEL=y
> +CONFIG_KALLSYMS_ALL=y
diff mbox series

Patch

diff --git a/DEVELOPERS b/DEVELOPERS
index 21ea2b53e8..5cebaeb4f3 100644
--- a/DEVELOPERS
+++ b/DEVELOPERS
@@ -1719,6 +1719,8 @@  F:	support/testing/tests/package/sample_python_spake2.py
 F:	support/testing/tests/package/test_gnupg2.py
 F:	support/testing/tests/package/test_highway.py
 F:	support/testing/tests/package/test_hwloc.py
+F:	support/testing/tests/package/test_kexec.py
+F:	support/testing/tests/package/test_kexec/
 F:	support/testing/tests/package/test_libjxl.py
 F:	support/testing/tests/package/test_ncdu.py
 F:	support/testing/tests/package/test_octave.py
diff --git a/support/testing/tests/package/test_kexec.py b/support/testing/tests/package/test_kexec.py
new file mode 100644
index 0000000000..77e383373e
--- /dev/null
+++ b/support/testing/tests/package/test_kexec.py
@@ -0,0 +1,93 @@ 
+import os
+
+import infra.basetest
+
+
+class TestKexec(infra.basetest.BRTest):
+
+    # A specific configuration is needed for using kexec:
+    # - We use Aarch64 since it is well supported for kexec,
+    # - A kernel config fragment enables all the kexec parts,
+    # - The kernel Image is installed on target filesystem to be
+    #   reloaded through kexec,
+    # - We use a ext4 rootfs image exposed as a virtio storage (rather
+    #   than cpio initrd). This avoids needing to install the initrd
+    #   inside the rootfs.
+    config = \
+        """
+        BR2_aarch64=y
+        BR2_TOOLCHAIN_EXTERNAL=y
+        BR2_TARGET_GENERIC_GETTY_PORT="ttyAMA0"
+        BR2_LINUX_KERNEL=y
+        BR2_LINUX_KERNEL_CUSTOM_VERSION=y
+        BR2_LINUX_KERNEL_CUSTOM_VERSION_VALUE="6.1.15"
+        BR2_LINUX_KERNEL_USE_CUSTOM_CONFIG=y
+        BR2_LINUX_KERNEL_CUSTOM_CONFIG_FILE="board/qemu/aarch64-virt/linux.config"
+        BR2_LINUX_KERNEL_CONFIG_FRAGMENT_FILES="{}"
+        BR2_LINUX_KERNEL_INSTALL_TARGET=y
+        BR2_LINUX_KERNEL_NEEDS_HOST_OPENSSL=y
+        BR2_PACKAGE_KEXEC=y
+        BR2_TARGET_ROOTFS_EXT2=y
+        BR2_TARGET_ROOTFS_EXT2_4=y
+        # BR2_TARGET_ROOTFS_TAR is not set
+        """.format(
+            infra.filepath("tests/package/test_kexec/linux-kexec.fragment")
+        )
+
+    def test_run(self):
+        hda = os.path.join(self.builddir, "images", "rootfs.ext4")
+        kern = os.path.join(self.builddir, "images", "Image")
+        # Notes:
+        # Sufficient memory is needed to load the kernel: having at
+        # least 512MB works. kexec could silently fail if not enough
+        # memory is present. KASLR needs to be disabled for the test:
+        # we pass "nokaslr" to kernel bootargs, and also pass
+        # "dtb-kaslr-seed=off" to qemu virt machine.
+        bootargs = ["root=/dev/vda console=ttyAMA0 nokaslr"]
+        qemu_opts = ["-M", "virt,dtb-kaslr-seed=off", "-cpu", "cortex-a57", "-m", "512M",
+                     "-drive", f"file={hda},if=virtio,format=raw"]
+        self.emulator.boot(arch="aarch64",
+                           kernel=kern,
+                           kernel_cmdline=bootargs,
+                           options=qemu_opts)
+        self.emulator.login()
+
+        # Test the program can execute
+        self.assertRunOk("kexec --version")
+
+        # Check the kexec kernel is NOT loaded:
+        self.assertRunOk("test \"$(cat /sys/kernel/kexec_loaded)\" -eq 0")
+
+        # Load the Kernel:
+        # "--append br-test" adds a dummy kernel args we'll be able to
+        # check in the second executed kernel.
+        # We use the dtb image from /sys/firmware/fdt (since we don't
+        # have the dtb file in the system)
+        self.assertRunOk("kexec -d -l --dtb=/sys/firmware/fdt --reuse-cmdline --serial=ttyAMA0 --append=br-test /boot/Image")
+
+        # Check the kexec kernel IS loaded:
+        self.assertRunOk("test \"$(cat /sys/kernel/kexec_loaded)\" -eq 1")
+
+        # Create a marker file in tmpfs which is supposed to disappear
+        # after kexec kernel restart.
+        self.assertRunOk("touch /dev/shm/br-kexec-marker")
+
+        # Execute the loaded kernel (i.e perform a kexec reboot)
+        # qemu.sendline() is used here because no exit code nor
+        # program return is expected, since kexec is like a
+        # reboot. The login is expected to be reached after the
+        # command is issued.
+        self.emulator.qemu.sendline("kexec -d -e")
+
+        # Wait for the login, and log again
+        self.emulator.login()
+
+        # Check the "br-test" dummy kernel arg is present
+        self.assertRunOk("grep br-test /proc/cmdline")
+
+        # Check the test marker file is no longer here
+        self.assertRunOk("test ! -e /dev/shm/br-kexec-marker")
+
+        # After restart, the kernel is not supposed to have a kexec
+        # loaded image:
+        self.assertRunOk("test \"$(cat /sys/kernel/kexec_loaded)\" -eq 0")
diff --git a/support/testing/tests/package/test_kexec/linux-kexec.fragment b/support/testing/tests/package/test_kexec/linux-kexec.fragment
new file mode 100644
index 0000000000..04c65f5cae
--- /dev/null
+++ b/support/testing/tests/package/test_kexec/linux-kexec.fragment
@@ -0,0 +1,5 @@ 
+CONFIG_KEXEC=y
+CONFIG_KEXEC_FILE=y
+CONFIG_PROC_KCORE=y
+CONFIG_DEBUG_KERNEL=y
+CONFIG_KALLSYMS_ALL=y