tuxrun_baselines.py 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410
  1. # Functional test that boots known good tuxboot images the same way
  2. # that tuxrun (www.tuxrun.org) does. This tool is used by things like
  3. # the LKFT project to run regression tests on kernels.
  4. #
  5. # Copyright (c) 2023 Linaro Ltd.
  6. #
  7. # Author:
  8. # Alex Bennée <alex.bennee@linaro.org>
  9. #
  10. # SPDX-License-Identifier: GPL-2.0-or-later
  11. import os
  12. import time
  13. from avocado import skip, skipIf
  14. from avocado_qemu import QemuSystemTest
  15. from avocado_qemu import exec_command, exec_command_and_wait_for_pattern
  16. from avocado_qemu import wait_for_console_pattern
  17. from avocado.utils import process
  18. from avocado.utils.path import find_command
  19. class TuxRunBaselineTest(QemuSystemTest):
  20. """
  21. :avocado: tags=accel:tcg
  22. """
  23. KERNEL_COMMON_COMMAND_LINE = 'printk.time=0'
  24. # Tests are ~10-40s, allow for --debug/--enable-gcov overhead
  25. timeout = 100
  26. def get_tag(self, tagname, default=None):
  27. """
  28. Get the metadata tag or return the default.
  29. """
  30. utag = self._get_unique_tag_val(tagname)
  31. print(f"{tagname}/{default} -> {utag}")
  32. if utag:
  33. return utag
  34. return default
  35. def setUp(self):
  36. super().setUp()
  37. # We need zstd for all the tuxrun tests
  38. # See https://github.com/avocado-framework/avocado/issues/5609
  39. zstd = find_command('zstd', False)
  40. if zstd is False:
  41. self.cancel('Could not find "zstd", which is required to '
  42. 'decompress rootfs')
  43. self.zstd = zstd
  44. # Process the TuxRun specific tags, most machines work with
  45. # reasonable defaults but we sometimes need to tweak the
  46. # config. To avoid open coding everything we store all these
  47. # details in the metadata for each test.
  48. # The tuxboot tag matches the root directory
  49. self.tuxboot = self.get_tag('tuxboot')
  50. # Most Linux's use ttyS0 for their serial port
  51. self.console = self.get_tag('console', "ttyS0")
  52. # Does the machine shutdown QEMU nicely on "halt"
  53. self.shutdown = self.get_tag('shutdown')
  54. # The name of the kernel Image file
  55. self.image = self.get_tag('image', "Image")
  56. self.root = self.get_tag('root', "vda")
  57. # Occasionally we need extra devices to hook things up
  58. self.extradev = self.get_tag('extradev')
  59. def wait_for_console_pattern(self, success_message, vm=None):
  60. wait_for_console_pattern(self, success_message,
  61. failure_message='Kernel panic - not syncing',
  62. vm=vm)
  63. def fetch_tuxrun_assets(self, dt=None):
  64. """
  65. Fetch the TuxBoot assets. They are stored in a standard way so we
  66. use the per-test tags to fetch details.
  67. """
  68. base_url = f"https://storage.tuxboot.com/{self.tuxboot}/"
  69. kernel_image = self.fetch_asset(base_url + self.image)
  70. disk_image_zst = self.fetch_asset(base_url + "rootfs.ext4.zst")
  71. cmd = f"{self.zstd} -d {disk_image_zst} -o {self.workdir}/rootfs.ext4"
  72. process.run(cmd)
  73. if dt:
  74. dtb = self.fetch_asset(base_url + dt)
  75. else:
  76. dtb = None
  77. return (kernel_image, self.workdir + "/rootfs.ext4", dtb)
  78. def prepare_run(self, kernel, disk, drive, dtb=None, console_index=0):
  79. """
  80. Setup to run and add the common parameters to the system
  81. """
  82. self.vm.set_console(console_index=console_index)
  83. # all block devices are raw ext4's
  84. blockdev = "driver=raw,file.driver=file," \
  85. + f"file.filename={disk},node-name=hd0"
  86. kcmd_line = self.KERNEL_COMMON_COMMAND_LINE
  87. kcmd_line += f" root=/dev/{self.root}"
  88. kcmd_line += f" console={self.console}"
  89. self.vm.add_args('-kernel', kernel,
  90. '-append', kcmd_line,
  91. '-blockdev', blockdev)
  92. # Sometimes we need extra devices attached
  93. if self.extradev:
  94. self.vm.add_args('-device', self.extradev)
  95. self.vm.add_args('-device',
  96. f"{drive},drive=hd0")
  97. # Some machines need an explicit DTB
  98. if dtb:
  99. self.vm.add_args('-dtb', dtb)
  100. def run_tuxtest_tests(self, haltmsg):
  101. """
  102. Wait for the system to boot up, wait for the login prompt and
  103. then do a few things on the console. Trigger a shutdown and
  104. wait to exit cleanly.
  105. """
  106. self.wait_for_console_pattern("Welcome to TuxTest")
  107. time.sleep(0.2)
  108. exec_command(self, 'root')
  109. time.sleep(0.2)
  110. exec_command(self, 'cat /proc/interrupts')
  111. time.sleep(0.1)
  112. exec_command(self, 'cat /proc/self/maps')
  113. time.sleep(0.1)
  114. exec_command(self, 'uname -a')
  115. time.sleep(0.1)
  116. exec_command_and_wait_for_pattern(self, 'halt', haltmsg)
  117. # Wait for VM to shut down gracefully if it can
  118. if self.shutdown == "nowait":
  119. self.vm.shutdown()
  120. else:
  121. self.vm.wait()
  122. def common_tuxrun(self, dt=None,
  123. drive="virtio-blk-device",
  124. haltmsg="reboot: System halted",
  125. console_index=0):
  126. """
  127. Common path for LKFT tests. Unless we need to do something
  128. special with the command line we can process most things using
  129. the tag metadata.
  130. """
  131. (kernel, disk, dtb) = self.fetch_tuxrun_assets(dt)
  132. self.prepare_run(kernel, disk, drive, dtb, console_index)
  133. self.vm.launch()
  134. self.run_tuxtest_tests(haltmsg)
  135. #
  136. # The tests themselves. The configuration is derived from how
  137. # tuxrun invokes qemu (with minor tweaks like using -blockdev
  138. # consistently). The tuxrun equivalent is something like:
  139. #
  140. # tuxrun --device qemu-{ARCH} \
  141. # --kernel https://storage.tuxboot.com/{TUXBOOT}/{IMAGE}
  142. #
  143. def test_arm64(self):
  144. """
  145. :avocado: tags=arch:aarch64
  146. :avocado: tags=cpu:cortex-a57
  147. :avocado: tags=machine:virt
  148. :avocado: tags=tuxboot:arm64
  149. :avocado: tags=console:ttyAMA0
  150. :avocado: tags=shutdown:nowait
  151. """
  152. self.common_tuxrun()
  153. def test_arm64be(self):
  154. """
  155. :avocado: tags=arch:aarch64
  156. :avocado: tags=cpu:cortex-a57
  157. :avocado: tags=endian:big
  158. :avocado: tags=machine:virt
  159. :avocado: tags=tuxboot:arm64be
  160. :avocado: tags=console:ttyAMA0
  161. :avocado: tags=shutdown:nowait
  162. """
  163. self.common_tuxrun()
  164. def test_armv5(self):
  165. """
  166. :avocado: tags=arch:arm
  167. :avocado: tags=cpu:arm926
  168. :avocado: tags=machine:versatilepb
  169. :avocado: tags=tuxboot:armv5
  170. :avocado: tags=image:zImage
  171. :avocado: tags=console:ttyAMA0
  172. :avocado: tags=shutdown:nowait
  173. """
  174. self.common_tuxrun(drive="virtio-blk-pci",
  175. dt="versatile-pb.dtb")
  176. def test_armv7(self):
  177. """
  178. :avocado: tags=arch:arm
  179. :avocado: tags=cpu:cortex-a15
  180. :avocado: tags=machine:virt
  181. :avocado: tags=tuxboot:armv7
  182. :avocado: tags=image:zImage
  183. :avocado: tags=console:ttyAMA0
  184. :avocado: tags=shutdown:nowait
  185. """
  186. self.common_tuxrun()
  187. def test_armv7be(self):
  188. """
  189. :avocado: tags=arch:arm
  190. :avocado: tags=cpu:cortex-a15
  191. :avocado: tags=endian:big
  192. :avocado: tags=machine:virt
  193. :avocado: tags=tuxboot:armv7be
  194. :avocado: tags=image:zImage
  195. :avocado: tags=console:ttyAMA0
  196. :avocado: tags=shutdown:nowait
  197. """
  198. self.common_tuxrun()
  199. def test_i386(self):
  200. """
  201. :avocado: tags=arch:i386
  202. :avocado: tags=cpu:coreduo
  203. :avocado: tags=machine:q35
  204. :avocado: tags=tuxboot:i386
  205. :avocado: tags=image:bzImage
  206. :avocado: tags=shutdown:nowait
  207. """
  208. self.common_tuxrun(drive="virtio-blk-pci")
  209. def test_mips32(self):
  210. """
  211. :avocado: tags=arch:mips
  212. :avocado: tags=machine:malta
  213. :avocado: tags=cpu:mips32r6-generic
  214. :avocado: tags=endian:big
  215. :avocado: tags=tuxboot:mips32
  216. :avocado: tags=image:vmlinux
  217. :avocado: tags=root:sda
  218. :avocado: tags=shutdown:nowait
  219. """
  220. self.common_tuxrun(drive="driver=ide-hd,bus=ide.0,unit=0")
  221. def test_mips32el(self):
  222. """
  223. :avocado: tags=arch:mipsel
  224. :avocado: tags=machine:malta
  225. :avocado: tags=cpu:mips32r6-generic
  226. :avocado: tags=tuxboot:mips32el
  227. :avocado: tags=image:vmlinux
  228. :avocado: tags=root:sda
  229. :avocado: tags=shutdown:nowait
  230. """
  231. self.common_tuxrun(drive="driver=ide-hd,bus=ide.0,unit=0")
  232. def test_mips64(self):
  233. """
  234. :avocado: tags=arch:mips64
  235. :avocado: tags=machine:malta
  236. :avocado: tags=tuxboot:mips64
  237. :avocado: tags=endian:big
  238. :avocado: tags=image:vmlinux
  239. :avocado: tags=root:sda
  240. :avocado: tags=shutdown:nowait
  241. """
  242. self.common_tuxrun(drive="driver=ide-hd,bus=ide.0,unit=0")
  243. def test_mips64el(self):
  244. """
  245. :avocado: tags=arch:mips64el
  246. :avocado: tags=machine:malta
  247. :avocado: tags=tuxboot:mips64el
  248. :avocado: tags=image:vmlinux
  249. :avocado: tags=root:sda
  250. :avocado: tags=shutdown:nowait
  251. """
  252. self.common_tuxrun(drive="driver=ide-hd,bus=ide.0,unit=0")
  253. def test_ppc32(self):
  254. """
  255. :avocado: tags=arch:ppc
  256. :avocado: tags=machine:ppce500
  257. :avocado: tags=cpu:e500mc
  258. :avocado: tags=tuxboot:ppc32
  259. :avocado: tags=image:uImage
  260. :avocado: tags=shutdown:nowait
  261. """
  262. self.common_tuxrun(drive="virtio-blk-pci")
  263. def test_ppc64(self):
  264. """
  265. :avocado: tags=arch:ppc64
  266. :avocado: tags=machine:pseries
  267. :avocado: tags=cpu:POWER8
  268. :avocado: tags=endian:big
  269. :avocado: tags=console:hvc0
  270. :avocado: tags=tuxboot:ppc64
  271. :avocado: tags=image:vmlinux
  272. :avocado: tags=extradev:driver=spapr-vscsi
  273. :avocado: tags=root:sda
  274. """
  275. self.common_tuxrun(drive="scsi-hd")
  276. def test_ppc64le(self):
  277. """
  278. :avocado: tags=arch:ppc64
  279. :avocado: tags=machine:pseries
  280. :avocado: tags=cpu:POWER8
  281. :avocado: tags=console:hvc0
  282. :avocado: tags=tuxboot:ppc64le
  283. :avocado: tags=image:vmlinux
  284. :avocado: tags=extradev:driver=spapr-vscsi
  285. :avocado: tags=root:sda
  286. """
  287. self.common_tuxrun(drive="scsi-hd")
  288. def test_riscv32(self):
  289. """
  290. :avocado: tags=arch:riscv32
  291. :avocado: tags=machine:virt
  292. :avocado: tags=tuxboot:riscv32
  293. """
  294. self.common_tuxrun()
  295. def test_riscv64(self):
  296. """
  297. :avocado: tags=arch:riscv64
  298. :avocado: tags=machine:virt
  299. :avocado: tags=tuxboot:riscv64
  300. """
  301. self.common_tuxrun()
  302. def test_s390(self):
  303. """
  304. :avocado: tags=arch:s390x
  305. :avocado: tags=endian:big
  306. :avocado: tags=tuxboot:s390
  307. :avocado: tags=image:bzImage
  308. :avocado: tags=shutdown:nowait
  309. """
  310. self.common_tuxrun(drive="virtio-blk-ccw",
  311. haltmsg="Requesting system halt")
  312. # Note: some segfaults caused by unaligned userspace access
  313. @skipIf(os.getenv('GITLAB_CI'), 'Skipping unstable test on GitLab')
  314. def test_sh4(self):
  315. """
  316. :avocado: tags=arch:sh4
  317. :avocado: tags=machine:r2d
  318. :avocado: tags=cpu:sh7785
  319. :avocado: tags=tuxboot:sh4
  320. :avocado: tags=image:zImage
  321. :avocado: tags=root:sda
  322. :avocado: tags=console:ttySC1
  323. """
  324. # The test is currently too unstable to do much in userspace
  325. # so we skip common_tuxrun and do a minimal boot and shutdown.
  326. (kernel, disk, dtb) = self.fetch_tuxrun_assets()
  327. # the console comes on the second serial port
  328. self.prepare_run(kernel, disk,
  329. "driver=ide-hd,bus=ide.0,unit=0",
  330. console_index=1)
  331. self.vm.launch()
  332. self.wait_for_console_pattern("Welcome to TuxTest")
  333. time.sleep(0.1)
  334. exec_command(self, 'root')
  335. time.sleep(0.1)
  336. exec_command_and_wait_for_pattern(self, 'halt',
  337. "reboot: System halted")
  338. def test_sparc64(self):
  339. """
  340. :avocado: tags=arch:sparc64
  341. :avocado: tags=tuxboot:sparc64
  342. :avocado: tags=image:vmlinux
  343. :avocado: tags=root:sda
  344. :avocado: tags=shutdown:nowait
  345. """
  346. self.common_tuxrun(drive="driver=ide-hd,bus=ide.0,unit=0")
  347. def test_x86_64(self):
  348. """
  349. :avocado: tags=arch:x86_64
  350. :avocado: tags=machine:q35
  351. :avocado: tags=cpu:Nehalem
  352. :avocado: tags=tuxboot:x86_64
  353. :avocado: tags=image:bzImage
  354. :avocado: tags=root:sda
  355. :avocado: tags=shutdown:nowait
  356. """
  357. self.common_tuxrun(drive="driver=ide-hd,bus=ide.0,unit=0")