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
, skipUnless
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 def test_mips32(self
):
357 :avocado: tags=arch:mips
358 :avocado: tags=machine:malta
359 :avocado: tags=cpu:mips32r6-generic
360 :avocado: tags=endian:big
361 :avocado: tags=tuxboot:mips32
362 :avocado: tags=image:vmlinux
363 :avocado: tags=root:sda
364 :avocado: tags=shutdown:nowait
366 sums
= { "rootfs.ext4.zst" :
367 "fc3da0b4c2f38d74c6d705123bb0f633c76ed953128f9d0859378c328a6d11a0",
369 "bfd2172f8b17fb32970ca0c8c58f59c5a4ca38aa5855d920be3a69b5d16e52f0" }
371 self
.common_tuxrun(csums
=sums
, drive
="driver=ide-hd,bus=ide.0,unit=0")
373 def test_mips32el(self
):
375 :avocado: tags=arch:mipsel
376 :avocado: tags=machine:malta
377 :avocado: tags=cpu:mips32r6-generic
378 :avocado: tags=tuxboot:mips32el
379 :avocado: tags=image:vmlinux
380 :avocado: tags=root:sda
381 :avocado: tags=shutdown:nowait
383 sums
= { "rootfs.ext4.zst" :
384 "e799768e289fd69209c21f4dacffa11baea7543d5db101e8ce27e3bc2c41d90e",
386 "8573867c68a8443db8de6d08bb33fb291c189ca2ca671471d3973a3e712096a3" }
388 self
.common_tuxrun(csums
=sums
, drive
="driver=ide-hd,bus=ide.0,unit=0")
390 def test_mips64(self
):
392 :avocado: tags=arch:mips64
393 :avocado: tags=machine:malta
394 :avocado: tags=tuxboot:mips64
395 :avocado: tags=endian:big
396 :avocado: tags=image:vmlinux
397 :avocado: tags=root:sda
398 :avocado: tags=shutdown:nowait
400 sums
= { "rootfs.ext4.zst" :
401 "69d91eeb04df3d8d172922c6993bb37d4deeb6496def75d8580f6f9de3e431da",
403 "09010e51e4b8bcbbd2494786ffb48eca78f228e96e5c5438344b0eac4029dc61" }
405 self
.common_tuxrun(csums
=sums
, drive
="driver=ide-hd,bus=ide.0,unit=0")
407 def test_mips64el(self
):
409 :avocado: tags=arch:mips64el
410 :avocado: tags=machine:malta
411 :avocado: tags=tuxboot:mips64el
412 :avocado: tags=image:vmlinux
413 :avocado: tags=root:sda
414 :avocado: tags=shutdown:nowait
416 sums
= { "rootfs.ext4.zst" :
417 "fba585368f5915b1498ed081863474b2d7ec4e97cdd46d21bdcb2f9698f83de4",
419 "d4e08965e2155c4cccce7c5f34d18fe34c636cda2f2c9844387d614950155266" }
421 self
.common_tuxrun(csums
=sums
, drive
="driver=ide-hd,bus=ide.0,unit=0")
423 def test_ppc32(self
):
425 :avocado: tags=arch:ppc
426 :avocado: tags=machine:ppce500
427 :avocado: tags=cpu:e500mc
428 :avocado: tags=tuxboot:ppc32
429 :avocado: tags=image:uImage
430 :avocado: tags=shutdown:nowait
432 sums
= { "rootfs.ext4.zst" :
433 "8885b9d999cc24d679542a02e9b6aaf48f718f2050ece6b8347074b6ee41dd09",
435 "1a68f74b860fda022fb12e03c5efece8c2b8b590d96cca37a8481a3ae0b3f81f" }
437 self
.common_tuxrun(csums
=sums
, drive
="virtio-blk-pci")
439 def test_ppc64(self
):
441 :avocado: tags=arch:ppc64
442 :avocado: tags=machine:pseries
443 :avocado: tags=cpu:POWER10
444 :avocado: tags=endian:big
445 :avocado: tags=console:hvc0
446 :avocado: tags=tuxboot:ppc64
447 :avocado: tags=image:vmlinux
448 :avocado: tags=extradev:driver=spapr-vscsi
449 :avocado: tags=root:sda
451 sums
= { "rootfs.ext4.zst" :
452 "1d953e81a4379e537fc8e41e05a0a59d9b453eef97aa03d47866c6c45b00bdff",
454 "f22a9b9e924174a4c199f4c7e5d91a2339fcfe51c6eafd0907dc3e09b64ab728" }
455 self
.ppc64_common_tuxrun(sums
, prefix
='tuxrun_ppc64_')
457 def test_ppc64le(self
):
459 :avocado: tags=arch:ppc64
460 :avocado: tags=machine:pseries
461 :avocado: tags=cpu:POWER10
462 :avocado: tags=console:hvc0
463 :avocado: tags=tuxboot:ppc64le
464 :avocado: tags=image:vmlinux
465 :avocado: tags=extradev:driver=spapr-vscsi
466 :avocado: tags=root:sda
468 sums
= { "rootfs.ext4.zst" :
469 "b442678c93fb8abe1f7d3bfa20556488de6b475c22c8fed363f42cf81a0a3906",
471 "979eb61b445a010fb13e2b927126991f8ceef9c590fa2be0996c00e293e80cf2" }
472 self
.ppc64_common_tuxrun(sums
, prefix
='tuxrun_ppc64le_')
474 def test_riscv32(self
):
476 :avocado: tags=arch:riscv32
477 :avocado: tags=machine:virt
478 :avocado: tags=tuxboot:riscv32
481 "89599407d7334de629a40e7ad6503c73670359eb5f5ae9d686353a3d6deccbd5",
483 "f2ef28a0b77826f79d085d3e4aa686f1159b315eff9099a37046b18936676985",
485 "7168d296d0283238ea73cd5a775b3dd608e55e04c7b92b76ecce31bb13108cba" }
487 self
.common_tuxrun(csums
=sums
)
489 def test_riscv64(self
):
491 :avocado: tags=arch:riscv64
492 :avocado: tags=machine:virt
493 :avocado: tags=tuxboot:riscv64
496 "cd634badc65e52fb63465ec99e309c0de0369f0841b7d9486f9729e119bac25e",
498 "6e3373abcab4305fe151b564a4c71110d833c21f2c0a1753b7935459e36aedcf",
500 "b18e3a3bdf27be03da0b285e84cb71bf09eca071c3a087b42884b6982ed679eb" }
502 self
.common_tuxrun(csums
=sums
)
504 def test_riscv32_maxcpu(self
):
506 :avocado: tags=arch:riscv32
507 :avocado: tags=machine:virt
508 :avocado: tags=cpu:max
509 :avocado: tags=tuxboot:riscv32
512 "89599407d7334de629a40e7ad6503c73670359eb5f5ae9d686353a3d6deccbd5",
514 "f2ef28a0b77826f79d085d3e4aa686f1159b315eff9099a37046b18936676985",
516 "7168d296d0283238ea73cd5a775b3dd608e55e04c7b92b76ecce31bb13108cba" }
518 self
.common_tuxrun(csums
=sums
)
520 def test_riscv64_maxcpu(self
):
522 :avocado: tags=arch:riscv64
523 :avocado: tags=machine:virt
524 :avocado: tags=cpu:max
525 :avocado: tags=tuxboot:riscv64
528 "cd634badc65e52fb63465ec99e309c0de0369f0841b7d9486f9729e119bac25e",
530 "6e3373abcab4305fe151b564a4c71110d833c21f2c0a1753b7935459e36aedcf",
532 "b18e3a3bdf27be03da0b285e84cb71bf09eca071c3a087b42884b6982ed679eb" }
534 self
.common_tuxrun(csums
=sums
)
538 :avocado: tags=arch:s390x
539 :avocado: tags=endian:big
540 :avocado: tags=tuxboot:s390
541 :avocado: tags=image:bzImage
542 :avocado: tags=shutdown:nowait
545 "0414e98dd1c3dafff8496c9cd9c28a5f8d04553bb5ba37e906a812b48d442ef0",
547 "88c37c32276677f873a25ab9ec6247895b8e3e6f8259134de2a616080b8ab3fc" }
549 self
.common_tuxrun(csums
=sums
,
550 drive
="virtio-blk-ccw",
551 haltmsg
="Requesting system halt")
553 # Note: some segfaults caused by unaligned userspace access
554 @skipUnless(os
.getenv('QEMU_TEST_FLAKY_TESTS'), 'Test is unstable on GitLab')
557 :avocado: tags=arch:sh4
558 :avocado: tags=machine:r2d
559 :avocado: tags=cpu:sh7785
560 :avocado: tags=tuxboot:sh4
561 :avocado: tags=image:zImage
562 :avocado: tags=root:sda
563 :avocado: tags=console:ttySC1
566 sums
= { "rootfs.ext4.zst" :
567 "3592a7a3d5a641e8b9821449e77bc43c9904a56c30d45da0694349cfd86743fd",
569 "29d9b2aba604a0f53a5dc3b5d0f2b8e35d497de1129f8ee5139eb6fdf0db692f" }
571 # The test is currently too unstable to do much in userspace
572 # so we skip common_tuxrun and do a minimal boot and shutdown.
573 (kernel
, disk
, dtb
) = self
.fetch_tuxrun_assets(csums
=sums
)
575 # the console comes on the second serial port
576 self
.prepare_run(kernel
, disk
,
577 "driver=ide-hd,bus=ide.0,unit=0",
581 self
.wait_for_console_pattern("Welcome to TuxTest")
583 exec_command(self
, 'root')
585 exec_command_and_wait_for_pattern(self
, 'halt',
586 "reboot: System halted")
588 def test_sparc64(self
):
590 :avocado: tags=arch:sparc64
591 :avocado: tags=tuxboot:sparc64
592 :avocado: tags=image:vmlinux
593 :avocado: tags=root:sda
594 :avocado: tags=shutdown:nowait
597 sums
= { "rootfs.ext4.zst" :
598 "ad2f1dc436ab51583543d25d2c210cab478645d47078d30d129a66ab0e281d76",
600 "e34313e4325ff21deaa3d38a502aa09a373ef62b9bd4d7f8f29388b688225c55" }
602 self
.common_tuxrun(csums
=sums
, drive
="driver=ide-hd,bus=ide.0,unit=0")
604 def test_x86_64(self
):
606 :avocado: tags=arch:x86_64
607 :avocado: tags=machine:q35
608 :avocado: tags=cpu:Nehalem
609 :avocado: tags=tuxboot:x86_64
610 :avocado: tags=image:bzImage
611 :avocado: tags=root:sda
612 :avocado: tags=shutdown:nowait
615 "2bc7480a669ee9b6b82500a236aba0c54233debe98cb968268fa230f52f03461",
617 "b72ac729769b8f51c6dffb221113c9a063c774dbe1d66af30eb593c4e9999b4b" }
619 self
.common_tuxrun(csums
=sums
,
620 drive
="driver=ide-hd,bus=ide.0,unit=0")