test_kexec.py 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100
  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_DTS_SUPPORT=y
  24. BR2_LINUX_KERNEL_CUSTOM_DTS_PATH="{}"
  25. BR2_LINUX_KERNEL_INSTALL_TARGET=y
  26. BR2_LINUX_KERNEL_NEEDS_HOST_OPENSSL=y
  27. BR2_PACKAGE_KEXEC=y
  28. BR2_TARGET_ROOTFS_EXT2=y
  29. BR2_TARGET_ROOTFS_EXT2_4=y
  30. # BR2_TARGET_ROOTFS_TAR is not set
  31. """.format(
  32. infra.filepath("tests/package/test_kexec/linux-kexec.fragment"),
  33. infra.filepath("tests/package/test_kexec/qemu-aarch64-virt-5.2-machine.dts")
  34. )
  35. def test_run(self):
  36. hda = os.path.join(self.builddir, "images", "rootfs.ext4")
  37. kern = os.path.join(self.builddir, "images", "Image")
  38. dtb = os.path.join(self.builddir, "images", "qemu-aarch64-virt-5.2-machine.dtb")
  39. # Notes:
  40. # Sufficient memory is needed to load the kernel: having at
  41. # least 512MB works. kexec could silently fail if not enough
  42. # memory is present. KASLR needs to be disabled for the test:
  43. # we pass "nokaslr" to kernel bootargs, and also pass a custom
  44. # devicetree to qemu virt machine. This devicetree is based on
  45. # qemu aarch64 5.2 dts with kaslr-seed set 0.
  46. # With newer qemu >= 7.0 we can disable KASLR from the qemu
  47. # command line using "dtb-kaslr-seed=off".
  48. bootargs = ["root=/dev/vda console=ttyAMA0 nokaslr"]
  49. qemu_opts = ["-M", "virt", "-dtb", dtb, "-cpu", "cortex-a57", "-m", "512M",
  50. "-drive", f"file={hda},if=virtio,format=raw"]
  51. self.emulator.boot(arch="aarch64",
  52. kernel=kern,
  53. kernel_cmdline=bootargs,
  54. options=qemu_opts)
  55. self.emulator.login()
  56. # Test the program can execute
  57. self.assertRunOk("kexec --version")
  58. # Check the kexec kernel is NOT loaded:
  59. self.assertRunOk("test \"$(cat /sys/kernel/kexec_loaded)\" -eq 0")
  60. # Load the Kernel:
  61. # "--append br-test" adds a dummy kernel args we'll be able to
  62. # check in the second executed kernel.
  63. # We use the dtb image from /sys/firmware/fdt (since we don't
  64. # have the dtb file in the system)
  65. self.assertRunOk("kexec -d -l --dtb=/sys/firmware/fdt --reuse-cmdline --serial=ttyAMA0 --append=br-test /boot/Image")
  66. # Check the kexec kernel IS loaded:
  67. self.assertRunOk("test \"$(cat /sys/kernel/kexec_loaded)\" -eq 1")
  68. # Create a marker file in tmpfs which is supposed to disappear
  69. # after kexec kernel restart.
  70. self.assertRunOk("touch /dev/shm/br-kexec-marker")
  71. # Execute the loaded kernel (i.e perform a kexec reboot)
  72. # qemu.sendline() is used here because no exit code nor
  73. # program return is expected, since kexec is like a
  74. # reboot. The login is expected to be reached after the
  75. # command is issued.
  76. self.emulator.qemu.sendline("kexec -d -e")
  77. # Wait for the login, and log again
  78. self.emulator.login()
  79. # Check the "br-test" dummy kernel arg is present
  80. self.assertRunOk("grep br-test /proc/cmdline")
  81. # Check the test marker file is no longer here
  82. self.assertRunOk("test ! -e /dev/shm/br-kexec-marker")
  83. # After restart, the kernel is not supposed to have a kexec
  84. # loaded image:
  85. self.assertRunOk("test \"$(cat /sys/kernel/kexec_loaded)\" -eq 0")