1 # Record/replay test that boots a Linux kernel
3 # Copyright (c) 2020 ISP RAS
6 # Pavel Dovgalyuk <Pavel.Dovgaluk@ispras.ru>
8 # This work is licensed under the terms of the GNU GPL, version 2 or
9 # later. See the COPYING file in the top-level directory.
17 from avocado
import skip
18 from avocado
import skipIf
19 from avocado
import skipUnless
20 from avocado_qemu
import wait_for_console_pattern
21 from avocado
.utils
import archive
22 from avocado
.utils
import process
23 from boot_linux_console
import LinuxKernelTest
25 class ReplayKernelBase(LinuxKernelTest
):
27 Boots a Linux kernel in record mode and checks that the console
28 is operational and the kernel command line is properly passed
29 from QEMU to the kernel.
30 Then replays the same scenario and verifies, that QEMU correctly
35 KERNEL_COMMON_COMMAND_LINE
= 'printk.time=1 panic=-1 '
37 def run_vm(self
, kernel_path
, kernel_command_line
, console_pattern
,
38 record
, shift
, args
, replay_path
):
39 logger
= logging
.getLogger('replay')
40 start_time
= time
.time()
44 logger
.info('recording the execution...')
47 logger
.info('replaying the execution...')
49 vm
.add_args('-icount', 'shift=%s,rr=%s,rrfile=%s' %
50 (shift
, mode
, replay_path
),
51 '-kernel', kernel_path
,
52 '-append', kernel_command_line
,
58 self
.wait_for_console_pattern(console_pattern
, vm
)
61 logger
.info('finished the recording with log size %s bytes'
62 % os
.path
.getsize(replay_path
))
65 logger
.info('successfully finished the replay')
66 elapsed
= time
.time() - start_time
67 logger
.info('elapsed time %.2f sec' % elapsed
)
70 def run_rr(self
, kernel_path
, kernel_command_line
, console_pattern
,
72 replay_path
= os
.path
.join(self
.workdir
, 'replay.bin')
73 t1
= self
.run_vm(kernel_path
, kernel_command_line
, console_pattern
,
74 True, shift
, args
, replay_path
)
75 t2
= self
.run_vm(kernel_path
, kernel_command_line
, console_pattern
,
76 False, shift
, args
, replay_path
)
77 logger
= logging
.getLogger('replay')
78 logger
.info('replay overhead {:.2%}'.format(t2
/ t1
- 1))
80 class ReplayKernelNormal(ReplayKernelBase
):
81 @skipIf(os
.getenv('GITLAB_CI'), 'Running on GitLab')
82 def test_x86_64_pc(self
):
84 :avocado: tags=arch:x86_64
85 :avocado: tags=machine:pc
87 kernel_url
= ('https://archives.fedoraproject.org/pub/archive/fedora'
88 '/linux/releases/29/Everything/x86_64/os/images/pxeboot'
90 kernel_hash
= '23bebd2680757891cf7adedb033532163a792495'
91 kernel_path
= self
.fetch_asset(kernel_url
, asset_hash
=kernel_hash
)
93 kernel_command_line
= self
.KERNEL_COMMON_COMMAND_LINE
+ 'console=ttyS0'
94 console_pattern
= 'VFS: Cannot open root device'
96 self
.run_rr(kernel_path
, kernel_command_line
, console_pattern
, shift
=5)
98 def test_mips_malta(self
):
100 :avocado: tags=arch:mips
101 :avocado: tags=machine:malta
102 :avocado: tags=endian:big
104 deb_url
= ('http://snapshot.debian.org/archive/debian/'
105 '20130217T032700Z/pool/main/l/linux-2.6/'
106 'linux-image-2.6.32-5-4kc-malta_2.6.32-48_mips.deb')
107 deb_hash
= 'a8cfc28ad8f45f54811fc6cf74fc43ffcfe0ba04'
108 deb_path
= self
.fetch_asset(deb_url
, asset_hash
=deb_hash
)
109 kernel_path
= self
.extract_from_deb(deb_path
,
110 '/boot/vmlinux-2.6.32-5-4kc-malta')
111 kernel_command_line
= self
.KERNEL_COMMON_COMMAND_LINE
+ 'console=ttyS0'
112 console_pattern
= 'Kernel command line: %s' % kernel_command_line
114 self
.run_rr(kernel_path
, kernel_command_line
, console_pattern
, shift
=5)
116 def test_mips64el_malta(self
):
118 This test requires the ar tool to extract "data.tar.gz" from
121 The kernel can be rebuilt using this Debian kernel source [1] and
122 following the instructions on [2].
124 [1] http://snapshot.debian.org/package/linux-2.6/2.6.32-48/
125 #linux-source-2.6.32_2.6.32-48
126 [2] https://kernel-team.pages.debian.net/kernel-handbook/
127 ch-common-tasks.html#s-common-official
129 :avocado: tags=arch:mips64el
130 :avocado: tags=machine:malta
132 deb_url
= ('http://snapshot.debian.org/archive/debian/'
133 '20130217T032700Z/pool/main/l/linux-2.6/'
134 'linux-image-2.6.32-5-5kc-malta_2.6.32-48_mipsel.deb')
135 deb_hash
= '1aaec92083bf22fda31e0d27fa8d9a388e5fc3d5'
136 deb_path
= self
.fetch_asset(deb_url
, asset_hash
=deb_hash
)
137 kernel_path
= self
.extract_from_deb(deb_path
,
138 '/boot/vmlinux-2.6.32-5-5kc-malta')
139 kernel_command_line
= self
.KERNEL_COMMON_COMMAND_LINE
+ 'console=ttyS0'
140 console_pattern
= 'Kernel command line: %s' % kernel_command_line
141 self
.run_rr(kernel_path
, kernel_command_line
, console_pattern
, shift
=5)
143 def test_aarch64_virt(self
):
145 :avocado: tags=arch:aarch64
146 :avocado: tags=machine:virt
147 :avocado: tags=cpu:cortex-a53
149 kernel_url
= ('https://archives.fedoraproject.org/pub/archive/fedora'
150 '/linux/releases/29/Everything/aarch64/os/images/pxeboot'
152 kernel_hash
= '8c73e469fc6ea06a58dc83a628fc695b693b8493'
153 kernel_path
= self
.fetch_asset(kernel_url
, asset_hash
=kernel_hash
)
155 kernel_command_line
= (self
.KERNEL_COMMON_COMMAND_LINE
+
157 console_pattern
= 'VFS: Cannot open root device'
159 self
.run_rr(kernel_path
, kernel_command_line
, console_pattern
,
160 args
=('-cpu', 'cortex-a53'))
162 def test_arm_virt(self
):
164 :avocado: tags=arch:arm
165 :avocado: tags=machine:virt
167 kernel_url
= ('https://archives.fedoraproject.org/pub/archive/fedora'
168 '/linux/releases/29/Everything/armhfp/os/images/pxeboot'
170 kernel_hash
= 'e9826d741b4fb04cadba8d4824d1ed3b7fb8b4d4'
171 kernel_path
= self
.fetch_asset(kernel_url
, asset_hash
=kernel_hash
)
173 kernel_command_line
= (self
.KERNEL_COMMON_COMMAND_LINE
+
175 console_pattern
= 'VFS: Cannot open root device'
177 self
.run_rr(kernel_path
, kernel_command_line
, console_pattern
, shift
=1)
179 @skipIf(os
.getenv('GITLAB_CI'), 'Running on GitLab')
180 def test_arm_cubieboard_initrd(self
):
182 :avocado: tags=arch:arm
183 :avocado: tags=machine:cubieboard
185 deb_url
= ('https://apt.armbian.com/pool/main/l/'
186 'linux-5.10.16-sunxi/linux-image-current-sunxi_21.02.2_armhf.deb')
187 deb_hash
= '9fa84beda245cabf0b4fa84cf6eaa7738ead1da0'
188 deb_path
= self
.fetch_asset(deb_url
, asset_hash
=deb_hash
)
189 kernel_path
= self
.extract_from_deb(deb_path
,
190 '/boot/vmlinuz-5.10.16-sunxi')
191 dtb_path
= '/usr/lib/linux-image-current-sunxi/sun4i-a10-cubieboard.dtb'
192 dtb_path
= self
.extract_from_deb(deb_path
, dtb_path
)
193 initrd_url
= ('https://github.com/groeck/linux-build-test/raw/'
194 '2eb0a73b5d5a28df3170c546ddaaa9757e1e0848/rootfs/'
195 'arm/rootfs-armv5.cpio.gz')
196 initrd_hash
= '2b50f1873e113523967806f4da2afe385462ff9b'
197 initrd_path_gz
= self
.fetch_asset(initrd_url
, asset_hash
=initrd_hash
)
198 initrd_path
= os
.path
.join(self
.workdir
, 'rootfs.cpio')
199 archive
.gzip_uncompress(initrd_path_gz
, initrd_path
)
201 kernel_command_line
= (self
.KERNEL_COMMON_COMMAND_LINE
+
202 'console=ttyS0,115200 '
205 console_pattern
= 'Boot successful.'
206 self
.run_rr(kernel_path
, kernel_command_line
, console_pattern
, shift
=1,
207 args
=('-dtb', dtb_path
,
208 '-initrd', initrd_path
,
211 def test_ppc64_pseries(self
):
213 :avocado: tags=arch:ppc64
214 :avocado: tags=machine:pseries
216 kernel_url
= ('https://archives.fedoraproject.org/pub/archive'
217 '/fedora-secondary/releases/29/Everything/ppc64le/os'
218 '/ppc/ppc64/vmlinuz')
219 kernel_hash
= '3fe04abfc852b66653b8c3c897a59a689270bc77'
220 kernel_path
= self
.fetch_asset(kernel_url
, asset_hash
=kernel_hash
)
222 kernel_command_line
= self
.KERNEL_COMMON_COMMAND_LINE
+ 'console=hvc0'
223 # icount is not good enough for PPC64 for complete boot yet
224 console_pattern
= 'Kernel command line: %s' % kernel_command_line
225 self
.run_rr(kernel_path
, kernel_command_line
, console_pattern
)
227 def test_m68k_q800(self
):
229 :avocado: tags=arch:m68k
230 :avocado: tags=machine:q800
232 deb_url
= ('https://snapshot.debian.org/archive/debian-ports'
233 '/20191021T083923Z/pool-m68k/main'
234 '/l/linux/kernel-image-5.3.0-1-m68k-di_5.3.7-1_m68k.udeb')
235 deb_hash
= '044954bb9be4160a3ce81f8bc1b5e856b75cccd1'
236 deb_path
= self
.fetch_asset(deb_url
, asset_hash
=deb_hash
)
237 kernel_path
= self
.extract_from_deb(deb_path
,
238 '/boot/vmlinux-5.3.0-1-m68k')
240 kernel_command_line
= (self
.KERNEL_COMMON_COMMAND_LINE
+
241 'console=ttyS0 vga=off')
242 console_pattern
= 'No filesystem could mount root'
243 self
.run_rr(kernel_path
, kernel_command_line
, console_pattern
)
245 def do_test_advcal_2018(self
, file_path
, kernel_name
, args
=None):
246 archive
.extract(file_path
, self
.workdir
)
248 for entry
in os
.scandir(self
.workdir
):
249 if entry
.name
.startswith('day') and entry
.is_dir():
250 kernel_path
= os
.path
.join(entry
.path
, kernel_name
)
253 kernel_command_line
= ''
254 console_pattern
= 'QEMU advent calendar'
255 self
.run_rr(kernel_path
, kernel_command_line
, console_pattern
,
258 def test_arm_vexpressa9(self
):
260 :avocado: tags=arch:arm
261 :avocado: tags=machine:vexpress-a9
263 tar_hash
= '32b7677ce8b6f1471fb0059865f451169934245b'
264 tar_url
= ('https://www.qemu-advent-calendar.org'
265 '/2018/download/day16.tar.xz')
266 file_path
= self
.fetch_asset(tar_url
, asset_hash
=tar_hash
)
267 dtb_path
= self
.workdir
+ '/day16/vexpress-v2p-ca9.dtb'
268 self
.do_test_advcal_2018(file_path
, 'winter.zImage',
269 args
=('-dtb', dtb_path
))
271 def test_m68k_mcf5208evb(self
):
273 :avocado: tags=arch:m68k
274 :avocado: tags=machine:mcf5208evb
276 tar_hash
= 'ac688fd00561a2b6ce1359f9ff6aa2b98c9a570c'
277 tar_url
= ('https://www.qemu-advent-calendar.org'
278 '/2018/download/day07.tar.xz')
279 file_path
= self
.fetch_asset(tar_url
, asset_hash
=tar_hash
)
280 self
.do_test_advcal_2018(file_path
, 'sanity-clause.elf')
282 @skip("Test currently broken") # Console stuck as of 5.2-rc1
283 def test_microblaze_s3adsp1800(self
):
285 :avocado: tags=arch:microblaze
286 :avocado: tags=machine:petalogix-s3adsp1800
288 tar_hash
= '08bf3e3bfb6b6c7ce1e54ab65d54e189f2caf13f'
289 tar_url
= ('https://www.qemu-advent-calendar.org'
290 '/2018/download/day17.tar.xz')
291 file_path
= self
.fetch_asset(tar_url
, asset_hash
=tar_hash
)
292 self
.do_test_advcal_2018(file_path
, 'ballerina.bin')
294 def test_ppc64_e500(self
):
296 :avocado: tags=arch:ppc64
297 :avocado: tags=machine:ppce500
298 :avocado: tags=cpu:e5500
300 tar_hash
= '6951d86d644b302898da2fd701739c9406527fe1'
301 tar_url
= ('https://www.qemu-advent-calendar.org'
302 '/2018/download/day19.tar.xz')
303 file_path
= self
.fetch_asset(tar_url
, asset_hash
=tar_hash
)
304 self
.do_test_advcal_2018(file_path
, 'uImage', ('-cpu', 'e5500'))
306 def test_ppc_g3beige(self
):
308 :avocado: tags=arch:ppc
309 :avocado: tags=machine:g3beige
311 tar_hash
= 'e0b872a5eb8fdc5bed19bd43ffe863900ebcedfc'
312 tar_url
= ('https://www.qemu-advent-calendar.org'
313 '/2018/download/day15.tar.xz')
314 file_path
= self
.fetch_asset(tar_url
, asset_hash
=tar_hash
)
315 self
.do_test_advcal_2018(file_path
, 'invaders.elf',
316 args
=('-M', 'graphics=off'))
318 def test_ppc_mac99(self
):
320 :avocado: tags=arch:ppc
321 :avocado: tags=machine:mac99
323 tar_hash
= 'e0b872a5eb8fdc5bed19bd43ffe863900ebcedfc'
324 tar_url
= ('https://www.qemu-advent-calendar.org'
325 '/2018/download/day15.tar.xz')
326 file_path
= self
.fetch_asset(tar_url
, asset_hash
=tar_hash
)
327 self
.do_test_advcal_2018(file_path
, 'invaders.elf',
328 args
=('-M', 'graphics=off'))
330 def test_sparc_ss20(self
):
332 :avocado: tags=arch:sparc
333 :avocado: tags=machine:SS-20
335 tar_hash
= 'b18550d5d61c7615d989a06edace051017726a9f'
336 tar_url
= ('https://www.qemu-advent-calendar.org'
337 '/2018/download/day11.tar.xz')
338 file_path
= self
.fetch_asset(tar_url
, asset_hash
=tar_hash
)
339 self
.do_test_advcal_2018(file_path
, 'zImage.elf')
341 def test_xtensa_lx60(self
):
343 :avocado: tags=arch:xtensa
344 :avocado: tags=machine:lx60
345 :avocado: tags=cpu:dc233c
347 tar_hash
= '49e88d9933742f0164b60839886c9739cb7a0d34'
348 tar_url
= ('https://www.qemu-advent-calendar.org'
349 '/2018/download/day02.tar.xz')
350 file_path
= self
.fetch_asset(tar_url
, asset_hash
=tar_hash
)
351 self
.do_test_advcal_2018(file_path
, 'santas-sleigh-ride.elf',
352 args
=('-cpu', 'dc233c'))
354 @skipUnless(os
.getenv('AVOCADO_TIMEOUT_EXPECTED'), 'Test might timeout')
355 class ReplayKernelSlow(ReplayKernelBase
):
356 # Override the timeout, because this kernel includes an inner
357 # loop which is executed with TB recompilings during replay,
358 # making it very slow.
361 def test_mips_malta_cpio(self
):
363 :avocado: tags=arch:mips
364 :avocado: tags=machine:malta
365 :avocado: tags=endian:big
366 :avocado: tags=slowness:high
368 deb_url
= ('http://snapshot.debian.org/archive/debian/'
369 '20160601T041800Z/pool/main/l/linux/'
370 'linux-image-4.5.0-2-4kc-malta_4.5.5-1_mips.deb')
371 deb_hash
= 'a3c84f3e88b54e06107d65a410d1d1e8e0f340f8'
372 deb_path
= self
.fetch_asset(deb_url
, asset_hash
=deb_hash
)
373 kernel_path
= self
.extract_from_deb(deb_path
,
374 '/boot/vmlinux-4.5.0-2-4kc-malta')
375 initrd_url
= ('https://github.com/groeck/linux-build-test/raw/'
376 '8584a59ed9e5eb5ee7ca91f6d74bbb06619205b8/rootfs/'
377 'mips/rootfs.cpio.gz')
378 initrd_hash
= 'bf806e17009360a866bf537f6de66590de349a99'
379 initrd_path_gz
= self
.fetch_asset(initrd_url
, asset_hash
=initrd_hash
)
380 initrd_path
= self
.workdir
+ "rootfs.cpio"
381 archive
.gzip_uncompress(initrd_path_gz
, initrd_path
)
383 kernel_command_line
= (self
.KERNEL_COMMON_COMMAND_LINE
+
384 'console=ttyS0 console=tty '
385 'rdinit=/sbin/init noreboot')
386 console_pattern
= 'Boot successful.'
387 self
.run_rr(kernel_path
, kernel_command_line
, console_pattern
, shift
=5,
388 args
=('-initrd', initrd_path
))
390 @skipUnless(os
.getenv('AVOCADO_ALLOW_UNTRUSTED_CODE'), 'untrusted code')
391 def test_mips64el_malta_5KEc_cpio(self
):
393 :avocado: tags=arch:mips64el
394 :avocado: tags=machine:malta
395 :avocado: tags=endian:little
396 :avocado: tags=slowness:high
398 kernel_url
= ('https://github.com/philmd/qemu-testing-blob/'
399 'raw/9ad2df38/mips/malta/mips64el/'
400 'vmlinux-3.19.3.mtoman.20150408')
401 kernel_hash
= '00d1d268fb9f7d8beda1de6bebcc46e884d71754'
402 kernel_path
= self
.fetch_asset(kernel_url
, asset_hash
=kernel_hash
)
403 initrd_url
= ('https://github.com/groeck/linux-build-test/'
404 'raw/8584a59e/rootfs/'
405 'mipsel64/rootfs.mipsel64r1.cpio.gz')
406 initrd_hash
= '1dbb8a396e916847325284dbe2151167'
407 initrd_path_gz
= self
.fetch_asset(initrd_url
, algorithm
='md5',
408 asset_hash
=initrd_hash
)
409 initrd_path
= self
.workdir
+ "rootfs.cpio"
410 archive
.gzip_uncompress(initrd_path_gz
, initrd_path
)
412 kernel_command_line
= (self
.KERNEL_COMMON_COMMAND_LINE
+
413 'console=ttyS0 console=tty '
414 'rdinit=/sbin/init noreboot')
415 console_pattern
= 'Boot successful.'
416 self
.run_rr(kernel_path
, kernel_command_line
, console_pattern
, shift
=5,
417 args
=('-initrd', initrd_path
, '-cpu', '5KEc'))
419 def do_test_mips_malta32el_nanomips(self
, kernel_path_xz
):
420 kernel_path
= self
.workdir
+ "kernel"
421 with lzma
.open(kernel_path_xz
, 'rb') as f_in
:
422 with
open(kernel_path
, 'wb') as f_out
:
423 shutil
.copyfileobj(f_in
, f_out
)
425 kernel_command_line
= (self
.KERNEL_COMMON_COMMAND_LINE
+
428 console_pattern
= 'Kernel command line: %s' % kernel_command_line
429 self
.run_rr(kernel_path
, kernel_command_line
, console_pattern
, shift
=5,
430 args
=('-cpu', 'I7200'))
432 def test_mips_malta32el_nanomips_4k(self
):
434 :avocado: tags=arch:mipsel
435 :avocado: tags=machine:malta
436 :avocado: tags=endian:little
438 kernel_url
= ('https://mipsdistros.mips.com/LinuxDistro/nanomips/'
439 'kernels/v4.15.18-432-gb2eb9a8b07a1-20180627102142/'
440 'generic_nano32r6el_page4k.xz')
441 kernel_hash
= '477456aafd2a0f1ddc9482727f20fe9575565dd6'
442 kernel_path_xz
= self
.fetch_asset(kernel_url
, asset_hash
=kernel_hash
)
443 self
.do_test_mips_malta32el_nanomips(kernel_path_xz
)
445 def test_mips_malta32el_nanomips_16k_up(self
):
447 :avocado: tags=arch:mipsel
448 :avocado: tags=machine:malta
449 :avocado: tags=endian:little
451 kernel_url
= ('https://mipsdistros.mips.com/LinuxDistro/nanomips/'
452 'kernels/v4.15.18-432-gb2eb9a8b07a1-20180627102142/'
453 'generic_nano32r6el_page16k_up.xz')
454 kernel_hash
= 'e882868f944c71c816e832e2303b7874d044a7bc'
455 kernel_path_xz
= self
.fetch_asset(kernel_url
, asset_hash
=kernel_hash
)
456 self
.do_test_mips_malta32el_nanomips(kernel_path_xz
)
458 def test_mips_malta32el_nanomips_64k_dbg(self
):
460 :avocado: tags=arch:mipsel
461 :avocado: tags=machine:malta
462 :avocado: tags=endian:little
464 kernel_url
= ('https://mipsdistros.mips.com/LinuxDistro/nanomips/'
465 'kernels/v4.15.18-432-gb2eb9a8b07a1-20180627102142/'
466 'generic_nano32r6el_page64k_dbg.xz')
467 kernel_hash
= '18d1c68f2e23429e266ca39ba5349ccd0aeb7180'
468 kernel_path_xz
= self
.fetch_asset(kernel_url
, asset_hash
=kernel_hash
)
469 self
.do_test_mips_malta32el_nanomips(kernel_path_xz
)