test_kexec.py 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  1. import os
  2. import infra.basetest
  3. class TestKexec(infra.basetest.BRTest):
  4. # A specific configuration is needed for using kexec:
  5. # - We use Aarch64 since it is well supported for kexec,
  6. # - A kernel config fragment enables all the kexec parts,
  7. # - The kernel Image is installed on target filesystem to be
  8. # reloaded through kexec,
  9. # - We use a ext4 rootfs image exposed as a virtio storage (rather
  10. # than cpio initrd). This avoids needing to install the initrd
  11. # inside the rootfs.
  12. config = \
  13. """
  14. BR2_aarch64=y
  15. BR2_TOOLCHAIN_EXTERNAL=y
  16. BR2_TARGET_GENERIC_GETTY_PORT="ttyAMA0"
  17. BR2_LINUX_KERNEL=y
  18. BR2_LINUX_KERNEL_CUSTOM_VERSION=y
  19. BR2_LINUX_KERNEL_CUSTOM_VERSION_VALUE="6.1.15"
  20. BR2_LINUX_KERNEL_USE_CUSTOM_CONFIG=y
  21. BR2_LINUX_KERNEL_CUSTOM_CONFIG_FILE="board/qemu/aarch64-virt/linux.config"
  22. BR2_LINUX_KERNEL_CONFIG_FRAGMENT_FILES="{}"
  23. BR2_LINUX_KERNEL_INSTALL_TARGET=y
  24. BR2_LINUX_KERNEL_NEEDS_HOST_OPENSSL=y
  25. BR2_PACKAGE_KEXEC=y
  26. BR2_TARGET_ROOTFS_EXT2=y
  27. BR2_TARGET_ROOTFS_EXT2_4=y
  28. # BR2_TARGET_ROOTFS_TAR is not set
  29. """.format(
  30. infra.filepath("tests/package/test_kexec/linux-kexec.fragment")
  31. )
  32. def test_run(self):
  33. hda = os.path.join(self.builddir, "images", "rootfs.ext4")
  34. kern = os.path.join(self.builddir, "images", "Image")
  35. # Notes:
  36. # Sufficient memory is needed to load the kernel: having at
  37. # least 512MB works. kexec could silently fail if not enough
  38. # memory is present. KASLR needs to be disabled for the test:
  39. # we pass "nokaslr" to kernel bootargs, and also pass
  40. # "dtb-kaslr-seed=off" to qemu virt machine.
  41. bootargs = ["root=/dev/vda console=ttyAMA0 nokaslr"]
  42. qemu_opts = ["-M", "virt,dtb-kaslr-seed=off", "-cpu", "cortex-a57", "-m", "512M",
  43. "-drive", f"file={hda},if=virtio,format=raw"]
  44. self.emulator.boot(arch="aarch64",
  45. kernel=kern,
  46. kernel_cmdline=bootargs,
  47. options=qemu_opts)
  48. self.emulator.login()
  49. # Test the program can execute
  50. self.assertRunOk("kexec --version")
  51. # Check the kexec kernel is NOT loaded:
  52. self.assertRunOk("test \"$(cat /sys/kernel/kexec_loaded)\" -eq 0")
  53. # Load the Kernel:
  54. # "--append br-test" adds a dummy kernel args we'll be able to
  55. # check in the second executed kernel.
  56. # We use the dtb image from /sys/firmware/fdt (since we don't
  57. # have the dtb file in the system)
  58. self.assertRunOk("kexec -d -l --dtb=/sys/firmware/fdt --reuse-cmdline --serial=ttyAMA0 --append=br-test /boot/Image")
  59. # Check the kexec kernel IS loaded:
  60. self.assertRunOk("test \"$(cat /sys/kernel/kexec_loaded)\" -eq 1")
  61. # Create a marker file in tmpfs which is supposed to disappear
  62. # after kexec kernel restart.
  63. self.assertRunOk("touch /dev/shm/br-kexec-marker")
  64. # Execute the loaded kernel (i.e perform a kexec reboot)
  65. # qemu.sendline() is used here because no exit code nor
  66. # program return is expected, since kexec is like a
  67. # reboot. The login is expected to be reached after the
  68. # command is issued.
  69. self.emulator.qemu.sendline("kexec -d -e")
  70. # Wait for the login, and log again
  71. self.emulator.login()
  72. # Check the "br-test" dummy kernel arg is present
  73. self.assertRunOk("grep br-test /proc/cmdline")
  74. # Check the test marker file is no longer here
  75. self.assertRunOk("test ! -e /dev/shm/br-kexec-marker")
  76. # After restart, the kernel is not supposed to have a kexec
  77. # loaded image:
  78. self.assertRunOk("test \"$(cat /sys/kernel/kexec_loaded)\" -eq 0")