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.
5 # Copyright (c) 2023 Linaro Ltd.
8 # Alex Bennée <alex.bennee@linaro.org>
10 # SPDX-License-Identifier: GPL-2.0-or-later
16 from avocado
import skip
, skipIf
17 from avocado_qemu
import QemuSystemTest
18 from avocado_qemu
import exec_command
, exec_command_and_wait_for_pattern
19 from avocado_qemu
import wait_for_console_pattern
20 from avocado
.utils
import process
21 from avocado
.utils
.path
import find_command
23 class TuxRunBaselineTest(QemuSystemTest
):
25 :avocado: tags=accel:tcg
28 KERNEL_COMMON_COMMAND_LINE
= 'printk.time=0'
29 # Tests are ~10-40s, allow for --debug/--enable-gcov overhead
32 def get_tag(self
, tagname
, default
=None):
34 Get the metadata tag or return the default.
36 utag
= self
._get
_unique
_tag
_val
(tagname
)
37 print(f
"{tagname}/{default} -> {utag}")
46 # We need zstd for all the tuxrun tests
47 # See https://github.com/avocado-framework/avocado/issues/5609
48 zstd
= find_command('zstd', False)
50 self
.cancel('Could not find "zstd", which is required to '
54 # Process the TuxRun specific tags, most machines work with
55 # reasonable defaults but we sometimes need to tweak the
56 # config. To avoid open coding everything we store all these
57 # details in the metadata for each test.
59 # The tuxboot tag matches the root directory
60 self
.tuxboot
= self
.get_tag('tuxboot')
62 # Most Linux's use ttyS0 for their serial port
63 self
.console
= self
.get_tag('console', "ttyS0")
65 # Does the machine shutdown QEMU nicely on "halt"
66 self
.shutdown
= self
.get_tag('shutdown')
68 # The name of the kernel Image file
69 self
.image
= self
.get_tag('image', "Image")
71 self
.root
= self
.get_tag('root', "vda")
73 # Occasionally we need extra devices to hook things up
74 self
.extradev
= self
.get_tag('extradev')
76 self
.qemu_img
= super().get_qemu_img()
78 def wait_for_console_pattern(self
, success_message
, vm
=None):
79 wait_for_console_pattern(self
, success_message
,
80 failure_message
='Kernel panic - not syncing',
83 def fetch_tuxrun_assets(self
, csums
=None, dt
=None):
85 Fetch the TuxBoot assets. They are stored in a standard way so we
86 use the per-test tags to fetch details.
88 base_url
= f
"https://storage.tuxboot.com/20230331/{self.tuxboot}/"
90 # empty hash if we weren't passed one
91 csums
= {} if csums
is None else csums
92 ksum
= csums
.get(self
.image
, None)
93 isum
= csums
.get("rootfs.ext4.zst", None)
95 kernel_image
= self
.fetch_asset(base_url
+ self
.image
,
98 disk_image_zst
= self
.fetch_asset(base_url
+ "rootfs.ext4.zst",
100 algorithm
= "sha256")
102 cmd
= f
"{self.zstd} -d {disk_image_zst} -o {self.workdir}/rootfs.ext4"
106 dsum
= csums
.get(dt
, None)
107 dtb
= self
.fetch_asset(base_url
+ dt
,
109 algorithm
= "sha256")
113 return (kernel_image
, self
.workdir
+ "/rootfs.ext4", dtb
)
115 def prepare_run(self
, kernel
, disk
, drive
, dtb
=None, console_index
=0):
117 Setup to run and add the common parameters to the system
119 self
.vm
.set_console(console_index
=console_index
)
121 # all block devices are raw ext4's
122 blockdev
= "driver=raw,file.driver=file," \
123 + f
"file.filename={disk},node-name=hd0"
125 kcmd_line
= self
.KERNEL_COMMON_COMMAND_LINE
126 kcmd_line
+= f
" root=/dev/{self.root}"
127 kcmd_line
+= f
" console={self.console}"
129 self
.vm
.add_args('-kernel', kernel
,
130 '-append', kcmd_line
,
131 '-blockdev', blockdev
)
133 # Sometimes we need extra devices attached
135 self
.vm
.add_args('-device', self
.extradev
)
137 self
.vm
.add_args('-device',
138 f
"{drive},drive=hd0")
140 # Some machines need an explicit DTB
142 self
.vm
.add_args('-dtb', dtb
)
144 def run_tuxtest_tests(self
, haltmsg
):
146 Wait for the system to boot up, wait for the login prompt and
147 then do a few things on the console. Trigger a shutdown and
148 wait to exit cleanly.
150 self
.wait_for_console_pattern("Welcome to TuxTest")
152 exec_command(self
, 'root')
154 exec_command(self
, 'cat /proc/interrupts')
156 exec_command(self
, 'cat /proc/self/maps')
158 exec_command(self
, 'uname -a')
160 exec_command_and_wait_for_pattern(self
, 'halt', haltmsg
)
162 # Wait for VM to shut down gracefully if it can
163 if self
.shutdown
== "nowait":
168 def common_tuxrun(self
,
171 drive
="virtio-blk-device",
172 haltmsg
="reboot: System halted",
175 Common path for LKFT tests. Unless we need to do something
176 special with the command line we can process most things using
179 (kernel
, disk
, dtb
) = self
.fetch_tuxrun_assets(csums
, dt
)
181 self
.prepare_run(kernel
, disk
, drive
, dtb
, console_index
)
183 self
.run_tuxtest_tests(haltmsg
)
185 def ppc64_common_tuxrun(self
, sums
, prefix
):
186 # add device args to command line.
187 self
.require_netdev('user')
188 self
.vm
.add_args('-netdev', 'user,id=vnet,hostfwd=:127.0.0.1:0-:22',
189 '-device', 'virtio-net,netdev=vnet')
190 self
.vm
.add_args('-netdev', '{"type":"user","id":"hostnet0"}',
191 '-device', '{"driver":"virtio-net-pci","netdev":'
192 '"hostnet0","id":"net0","mac":"52:54:00:4c:e3:86",'
193 '"bus":"pci.0","addr":"0x9"}')
194 self
.vm
.add_args('-device', '{"driver":"qemu-xhci","p2":15,"p3":15,'
195 '"id":"usb","bus":"pci.0","addr":"0x2"}')
196 self
.vm
.add_args('-device', '{"driver":"virtio-scsi-pci","id":"scsi0"'
197 ',"bus":"pci.0","addr":"0x3"}')
198 self
.vm
.add_args('-device', '{"driver":"virtio-serial-pci","id":'
199 '"virtio-serial0","bus":"pci.0","addr":"0x4"}')
200 self
.vm
.add_args('-device', '{"driver":"scsi-cd","bus":"scsi0.0"'
201 ',"channel":0,"scsi-id":0,"lun":0,"device_id":'
202 '"drive-scsi0-0-0-0","id":"scsi0-0-0-0"}')
203 self
.vm
.add_args('-device', '{"driver":"virtio-balloon-pci",'
204 '"id":"balloon0","bus":"pci.0","addr":"0x6"}')
205 self
.vm
.add_args('-audiodev', '{"id":"audio1","driver":"none"}')
206 self
.vm
.add_args('-device', '{"driver":"usb-tablet","id":"input0"'
207 ',"bus":"usb.0","port":"1"}')
208 self
.vm
.add_args('-device', '{"driver":"usb-kbd","id":"input1"'
209 ',"bus":"usb.0","port":"2"}')
210 self
.vm
.add_args('-device', '{"driver":"VGA","id":"video0",'
211 '"vgamem_mb":16,"bus":"pci.0","addr":"0x7"}')
212 self
.vm
.add_args('-object', '{"qom-type":"rng-random","id":"objrng0"'
213 ',"filename":"/dev/urandom"}',
214 '-device', '{"driver":"virtio-rng-pci","rng":"objrng0"'
215 ',"id":"rng0","bus":"pci.0","addr":"0x8"}')
216 self
.vm
.add_args('-object', '{"qom-type":"cryptodev-backend-builtin",'
217 '"id":"objcrypto0","queues":1}',
218 '-device', '{"driver":"virtio-crypto-pci",'
219 '"cryptodev":"objcrypto0","id":"crypto0","bus"'
220 ':"pci.0","addr":"0xa"}')
221 self
.vm
.add_args('-device', '{"driver":"spapr-pci-host-bridge"'
222 ',"index":1,"id":"pci.1"}')
223 self
.vm
.add_args('-device', '{"driver":"spapr-vscsi","id":"scsi1"'
225 self
.vm
.add_args('-m', '2G,slots=32,maxmem=4G',
226 '-object', 'memory-backend-ram,id=ram1,size=1G',
227 '-device', 'pc-dimm,id=dimm1,memdev=ram1')
229 # Create a temporary qcow2 and launch the test-case
230 with tempfile
.NamedTemporaryFile(prefix
=prefix
,
231 suffix
='.qcow2') as qcow2
:
232 process
.run(self
.qemu_img
+ ' create -f qcow2 ' +
235 self
.vm
.add_args('-drive', 'file=' + qcow2
.name
+
236 ',format=qcow2,if=none,id='
237 'drive-virtio-disk1',
238 '-device', 'virtio-blk-pci,scsi=off,bus=pci.0,'
239 'addr=0xb,drive=drive-virtio-disk1,id=virtio-disk1'
241 self
.common_tuxrun(csums
=sums
, drive
="scsi-hd")
244 # The tests themselves. The configuration is derived from how
245 # tuxrun invokes qemu (with minor tweaks like using -blockdev
246 # consistently). The tuxrun equivalent is something like:
248 # tuxrun --device qemu-{ARCH} \
249 # --kernel https://storage.tuxboot.com/{TUXBOOT}/{IMAGE}
252 def test_arm64(self
):
254 :avocado: tags=arch:aarch64
255 :avocado: tags=cpu:cortex-a57
256 :avocado: tags=machine:virt
257 :avocado: tags=tuxboot:arm64
258 :avocado: tags=console:ttyAMA0
259 :avocado: tags=shutdown:nowait
262 "ce95a7101a5fecebe0fe630deee6bd97b32ba41bc8754090e9ad8961ea8674c7",
264 "bbd5ed4b9c7d3f4ca19ba71a323a843c6b585e880115df3b7765769dbd9dd061"}
265 self
.common_tuxrun(csums
=sums
)
267 def test_arm64be(self
):
269 :avocado: tags=arch:aarch64
270 :avocado: tags=cpu:cortex-a57
271 :avocado: tags=endian:big
272 :avocado: tags=machine:virt
273 :avocado: tags=tuxboot:arm64be
274 :avocado: tags=console:ttyAMA0
275 :avocado: tags=shutdown:nowait
278 "e0df4425eb2cd9ea9a283e808037f805641c65d8fcecc8f6407d8f4f339561b4",
280 "e6ffd8813c8a335bc15728f2835f90539c84be7f8f5f691a8b01451b47fb4bd7"}
281 self
.common_tuxrun(csums
=sums
)
283 def test_armv5(self
):
285 :avocado: tags=arch:arm
286 :avocado: tags=cpu:arm926
287 :avocado: tags=machine:versatilepb
288 :avocado: tags=tuxboot:armv5
289 :avocado: tags=image:zImage
290 :avocado: tags=console:ttyAMA0
291 :avocado: tags=shutdown:nowait
293 sums
= { "rootfs.ext4.zst" :
294 "17177afa74e7294da0642861f08c88ca3c836764299a54bf6d1ce276cb9712a5",
296 "0bc0c0b0858cefd3c32b385c0d66d97142ded29472a496f4f490e42fc7615b25",
298 "c95af2f27647c12265d75e9df44c22ff5228c59855f54aaa70f41ec2842e3a4d" }
300 self
.common_tuxrun(csums
=sums
,
301 drive
="virtio-blk-pci",
302 dt
="versatile-pb.dtb")
304 def test_armv7(self
):
306 :avocado: tags=arch:arm
307 :avocado: tags=cpu:cortex-a15
308 :avocado: tags=machine:virt
309 :avocado: tags=tuxboot:armv7
310 :avocado: tags=image:zImage
311 :avocado: tags=console:ttyAMA0
312 :avocado: tags=shutdown:nowait
314 sums
= { "rootfs.ext4.zst" :
315 "ab1fbbeaddda1ffdd45c9405a28cd5370c20f23a7cbc809cc90dc9f243a8eb5a",
317 "4c7a22e9f15875bec06bd2a29d822496571eb297d4f22694099ffcdb19077572" }
319 self
.common_tuxrun(csums
=sums
)
321 def test_armv7be(self
):
323 :avocado: tags=arch:arm
324 :avocado: tags=cpu:cortex-a15
325 :avocado: tags=endian:big
326 :avocado: tags=machine:virt
327 :avocado: tags=tuxboot:armv7be
328 :avocado: tags=image:zImage
329 :avocado: tags=console:ttyAMA0
330 :avocado: tags=shutdown:nowait
332 sums
= {"rootfs.ext4.zst" :
333 "42ed46dd2d59986206c5b1f6cf35eab58fe3fd20c96b41aaa16b32f3f90a9835",
335 "7facc62082b57af12015b08f7fdbaf2f123ba07a478367853ae12b219afc9f2f" }
337 self
.common_tuxrun(csums
=sums
)
341 :avocado: tags=arch:i386
342 :avocado: tags=cpu:coreduo
343 :avocado: tags=machine:q35
344 :avocado: tags=tuxboot:i386
345 :avocado: tags=image:bzImage
346 :avocado: tags=shutdown:nowait
349 "a3e5b32a354729e65910f5a1ffcda7c14a6c12a55e8213fb86e277f1b76ed956",
351 "f15e66b2bf673a210ec2a4b2e744a80530b36289e04f5388aab812b97f69754a" }
353 self
.common_tuxrun(csums
=sums
, drive
="virtio-blk-pci")
355 @skip('https://gitlab.com/qemu-project/qemu/-/issues/1884')
356 def test_mips32(self
):
358 :avocado: tags=arch:mips
359 :avocado: tags=machine:malta
360 :avocado: tags=cpu:mips32r6-generic
361 :avocado: tags=endian:big
362 :avocado: tags=tuxboot:mips32
363 :avocado: tags=image:vmlinux
364 :avocado: tags=root:sda
365 :avocado: tags=shutdown:nowait
367 sums
= { "rootfs.ext4.zst" :
368 "fc3da0b4c2f38d74c6d705123bb0f633c76ed953128f9d0859378c328a6d11a0",
370 "bfd2172f8b17fb32970ca0c8c58f59c5a4ca38aa5855d920be3a69b5d16e52f0" }
372 self
.common_tuxrun(csums
=sums
, drive
="driver=ide-hd,bus=ide.0,unit=0")
374 @skip('https://gitlab.com/qemu-project/qemu/-/issues/1884')
375 def test_mips32el(self
):
377 :avocado: tags=arch:mipsel
378 :avocado: tags=machine:malta
379 :avocado: tags=cpu:mips32r6-generic
380 :avocado: tags=tuxboot:mips32el
381 :avocado: tags=image:vmlinux
382 :avocado: tags=root:sda
383 :avocado: tags=shutdown:nowait
385 sums
= { "rootfs.ext4.zst" :
386 "e799768e289fd69209c21f4dacffa11baea7543d5db101e8ce27e3bc2c41d90e",
388 "8573867c68a8443db8de6d08bb33fb291c189ca2ca671471d3973a3e712096a3" }
390 self
.common_tuxrun(csums
=sums
, drive
="driver=ide-hd,bus=ide.0,unit=0")
392 @skip('https://gitlab.com/qemu-project/qemu/-/issues/1884')
393 def test_mips64(self
):
395 :avocado: tags=arch:mips64
396 :avocado: tags=machine:malta
397 :avocado: tags=tuxboot:mips64
398 :avocado: tags=endian:big
399 :avocado: tags=image:vmlinux
400 :avocado: tags=root:sda
401 :avocado: tags=shutdown:nowait
403 sums
= { "rootfs.ext4.zst" :
404 "69d91eeb04df3d8d172922c6993bb37d4deeb6496def75d8580f6f9de3e431da",
406 "09010e51e4b8bcbbd2494786ffb48eca78f228e96e5c5438344b0eac4029dc61" }
408 self
.common_tuxrun(csums
=sums
, drive
="driver=ide-hd,bus=ide.0,unit=0")
410 @skip('https://gitlab.com/qemu-project/qemu/-/issues/1884')
411 def test_mips64el(self
):
413 :avocado: tags=arch:mips64el
414 :avocado: tags=machine:malta
415 :avocado: tags=tuxboot:mips64el
416 :avocado: tags=image:vmlinux
417 :avocado: tags=root:sda
418 :avocado: tags=shutdown:nowait
420 sums
= { "rootfs.ext4.zst" :
421 "fba585368f5915b1498ed081863474b2d7ec4e97cdd46d21bdcb2f9698f83de4",
423 "d4e08965e2155c4cccce7c5f34d18fe34c636cda2f2c9844387d614950155266" }
425 self
.common_tuxrun(csums
=sums
, drive
="driver=ide-hd,bus=ide.0,unit=0")
427 def test_ppc32(self
):
429 :avocado: tags=arch:ppc
430 :avocado: tags=machine:ppce500
431 :avocado: tags=cpu:e500mc
432 :avocado: tags=tuxboot:ppc32
433 :avocado: tags=image:uImage
434 :avocado: tags=shutdown:nowait
436 sums
= { "rootfs.ext4.zst" :
437 "8885b9d999cc24d679542a02e9b6aaf48f718f2050ece6b8347074b6ee41dd09",
439 "1a68f74b860fda022fb12e03c5efece8c2b8b590d96cca37a8481a3ae0b3f81f" }
441 self
.common_tuxrun(csums
=sums
, drive
="virtio-blk-pci")
443 def test_ppc64(self
):
445 :avocado: tags=arch:ppc64
446 :avocado: tags=machine:pseries
447 :avocado: tags=cpu:POWER10
448 :avocado: tags=endian:big
449 :avocado: tags=console:hvc0
450 :avocado: tags=tuxboot:ppc64
451 :avocado: tags=image:vmlinux
452 :avocado: tags=extradev:driver=spapr-vscsi
453 :avocado: tags=root:sda
455 sums
= { "rootfs.ext4.zst" :
456 "1d953e81a4379e537fc8e41e05a0a59d9b453eef97aa03d47866c6c45b00bdff",
458 "f22a9b9e924174a4c199f4c7e5d91a2339fcfe51c6eafd0907dc3e09b64ab728" }
459 self
.ppc64_common_tuxrun(sums
, prefix
='tuxrun_ppc64_')
461 def test_ppc64le(self
):
463 :avocado: tags=arch:ppc64
464 :avocado: tags=machine:pseries
465 :avocado: tags=cpu:POWER10
466 :avocado: tags=console:hvc0
467 :avocado: tags=tuxboot:ppc64le
468 :avocado: tags=image:vmlinux
469 :avocado: tags=extradev:driver=spapr-vscsi
470 :avocado: tags=root:sda
472 sums
= { "rootfs.ext4.zst" :
473 "b442678c93fb8abe1f7d3bfa20556488de6b475c22c8fed363f42cf81a0a3906",
475 "979eb61b445a010fb13e2b927126991f8ceef9c590fa2be0996c00e293e80cf2" }
476 self
.ppc64_common_tuxrun(sums
, prefix
='tuxrun_ppc64le_')
478 def test_riscv32(self
):
480 :avocado: tags=arch:riscv32
481 :avocado: tags=machine:virt
482 :avocado: tags=tuxboot:riscv32
485 "89599407d7334de629a40e7ad6503c73670359eb5f5ae9d686353a3d6deccbd5",
487 "f2ef28a0b77826f79d085d3e4aa686f1159b315eff9099a37046b18936676985",
489 "7168d296d0283238ea73cd5a775b3dd608e55e04c7b92b76ecce31bb13108cba" }
491 self
.common_tuxrun(csums
=sums
)
493 def test_riscv64(self
):
495 :avocado: tags=arch:riscv64
496 :avocado: tags=machine:virt
497 :avocado: tags=tuxboot:riscv64
500 "cd634badc65e52fb63465ec99e309c0de0369f0841b7d9486f9729e119bac25e",
502 "6e3373abcab4305fe151b564a4c71110d833c21f2c0a1753b7935459e36aedcf",
504 "b18e3a3bdf27be03da0b285e84cb71bf09eca071c3a087b42884b6982ed679eb" }
506 self
.common_tuxrun(csums
=sums
)
510 :avocado: tags=arch:s390x
511 :avocado: tags=endian:big
512 :avocado: tags=tuxboot:s390
513 :avocado: tags=image:bzImage
514 :avocado: tags=shutdown:nowait
517 "0414e98dd1c3dafff8496c9cd9c28a5f8d04553bb5ba37e906a812b48d442ef0",
519 "88c37c32276677f873a25ab9ec6247895b8e3e6f8259134de2a616080b8ab3fc" }
521 self
.common_tuxrun(csums
=sums
,
522 drive
="virtio-blk-ccw",
523 haltmsg
="Requesting system halt")
525 # Note: some segfaults caused by unaligned userspace access
526 @skipIf(os
.getenv('GITLAB_CI'), 'Skipping unstable test on GitLab')
529 :avocado: tags=arch:sh4
530 :avocado: tags=machine:r2d
531 :avocado: tags=cpu:sh7785
532 :avocado: tags=tuxboot:sh4
533 :avocado: tags=image:zImage
534 :avocado: tags=root:sda
535 :avocado: tags=console:ttySC1
537 sums
= { "rootfs.ext4.zst" :
538 "3592a7a3d5a641e8b9821449e77bc43c9904a56c30d45da0694349cfd86743fd",
540 "29d9b2aba604a0f53a5dc3b5d0f2b8e35d497de1129f8ee5139eb6fdf0db692f" }
542 # The test is currently too unstable to do much in userspace
543 # so we skip common_tuxrun and do a minimal boot and shutdown.
544 (kernel
, disk
, dtb
) = self
.fetch_tuxrun_assets(csums
=sums
)
546 # the console comes on the second serial port
547 self
.prepare_run(kernel
, disk
,
548 "driver=ide-hd,bus=ide.0,unit=0",
552 self
.wait_for_console_pattern("Welcome to TuxTest")
554 exec_command(self
, 'root')
556 exec_command_and_wait_for_pattern(self
, 'halt',
557 "reboot: System halted")
559 def test_sparc64(self
):
561 :avocado: tags=arch:sparc64
562 :avocado: tags=tuxboot:sparc64
563 :avocado: tags=image:vmlinux
564 :avocado: tags=root:sda
565 :avocado: tags=shutdown:nowait
568 sums
= { "rootfs.ext4.zst" :
569 "ad2f1dc436ab51583543d25d2c210cab478645d47078d30d129a66ab0e281d76",
571 "e34313e4325ff21deaa3d38a502aa09a373ef62b9bd4d7f8f29388b688225c55" }
573 self
.common_tuxrun(csums
=sums
, drive
="driver=ide-hd,bus=ide.0,unit=0")
575 def test_x86_64(self
):
577 :avocado: tags=arch:x86_64
578 :avocado: tags=machine:q35
579 :avocado: tags=cpu:Nehalem
580 :avocado: tags=tuxboot:x86_64
581 :avocado: tags=image:bzImage
582 :avocado: tags=root:sda
583 :avocado: tags=shutdown:nowait
586 "2bc7480a669ee9b6b82500a236aba0c54233debe98cb968268fa230f52f03461",
588 "b72ac729769b8f51c6dffb221113c9a063c774dbe1d66af30eb593c4e9999b4b" }
590 self
.common_tuxrun(csums
=sums
,
591 drive
="driver=ide-hd,bus=ide.0,unit=0")