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
)
161 def test_arm_virt(self
):
163 :avocado: tags=arch:arm
164 :avocado: tags=machine:virt
166 kernel_url
= ('https://archives.fedoraproject.org/pub/archive/fedora'
167 '/linux/releases/29/Everything/armhfp/os/images/pxeboot'
169 kernel_hash
= 'e9826d741b4fb04cadba8d4824d1ed3b7fb8b4d4'
170 kernel_path
= self
.fetch_asset(kernel_url
, asset_hash
=kernel_hash
)
172 kernel_command_line
= (self
.KERNEL_COMMON_COMMAND_LINE
+
174 console_pattern
= 'VFS: Cannot open root device'
176 self
.run_rr(kernel_path
, kernel_command_line
, console_pattern
, shift
=1)
178 @skipIf(os
.getenv('GITLAB_CI'), 'Running on GitLab')
179 def test_arm_cubieboard_initrd(self
):
181 :avocado: tags=arch:arm
182 :avocado: tags=machine:cubieboard
184 deb_url
= ('https://apt.armbian.com/pool/main/l/'
185 'linux-5.10.16-sunxi/linux-image-current-sunxi_21.02.2_armhf.deb')
186 deb_hash
= '9fa84beda245cabf0b4fa84cf6eaa7738ead1da0'
187 deb_path
= self
.fetch_asset(deb_url
, asset_hash
=deb_hash
)
188 kernel_path
= self
.extract_from_deb(deb_path
,
189 '/boot/vmlinuz-5.10.16-sunxi')
190 dtb_path
= '/usr/lib/linux-image-current-sunxi/sun4i-a10-cubieboard.dtb'
191 dtb_path
= self
.extract_from_deb(deb_path
, dtb_path
)
192 initrd_url
= ('https://github.com/groeck/linux-build-test/raw/'
193 '2eb0a73b5d5a28df3170c546ddaaa9757e1e0848/rootfs/'
194 'arm/rootfs-armv5.cpio.gz')
195 initrd_hash
= '2b50f1873e113523967806f4da2afe385462ff9b'
196 initrd_path_gz
= self
.fetch_asset(initrd_url
, asset_hash
=initrd_hash
)
197 initrd_path
= os
.path
.join(self
.workdir
, 'rootfs.cpio')
198 archive
.gzip_uncompress(initrd_path_gz
, initrd_path
)
200 kernel_command_line
= (self
.KERNEL_COMMON_COMMAND_LINE
+
201 'console=ttyS0,115200 '
204 console_pattern
= 'Boot successful.'
205 self
.run_rr(kernel_path
, kernel_command_line
, console_pattern
, shift
=1,
206 args
=('-dtb', dtb_path
,
207 '-initrd', initrd_path
,
210 def test_ppc64_pseries(self
):
212 :avocado: tags=arch:ppc64
213 :avocado: tags=machine:pseries
215 kernel_url
= ('https://archives.fedoraproject.org/pub/archive'
216 '/fedora-secondary/releases/29/Everything/ppc64le/os'
217 '/ppc/ppc64/vmlinuz')
218 kernel_hash
= '3fe04abfc852b66653b8c3c897a59a689270bc77'
219 kernel_path
= self
.fetch_asset(kernel_url
, asset_hash
=kernel_hash
)
221 kernel_command_line
= self
.KERNEL_COMMON_COMMAND_LINE
+ 'console=hvc0'
222 # icount is not good enough for PPC64 for complete boot yet
223 console_pattern
= 'Kernel command line: %s' % kernel_command_line
224 self
.run_rr(kernel_path
, kernel_command_line
, console_pattern
)
226 def test_m68k_q800(self
):
228 :avocado: tags=arch:m68k
229 :avocado: tags=machine:q800
231 deb_url
= ('https://snapshot.debian.org/archive/debian-ports'
232 '/20191021T083923Z/pool-m68k/main'
233 '/l/linux/kernel-image-5.3.0-1-m68k-di_5.3.7-1_m68k.udeb')
234 deb_hash
= '044954bb9be4160a3ce81f8bc1b5e856b75cccd1'
235 deb_path
= self
.fetch_asset(deb_url
, asset_hash
=deb_hash
)
236 kernel_path
= self
.extract_from_deb(deb_path
,
237 '/boot/vmlinux-5.3.0-1-m68k')
239 kernel_command_line
= (self
.KERNEL_COMMON_COMMAND_LINE
+
240 'console=ttyS0 vga=off')
241 console_pattern
= 'No filesystem could mount root'
242 self
.run_rr(kernel_path
, kernel_command_line
, console_pattern
)
244 def do_test_advcal_2018(self
, file_path
, kernel_name
, args
=None):
245 archive
.extract(file_path
, self
.workdir
)
247 for entry
in os
.scandir(self
.workdir
):
248 if entry
.name
.startswith('day') and entry
.is_dir():
249 kernel_path
= os
.path
.join(entry
.path
, kernel_name
)
252 kernel_command_line
= ''
253 console_pattern
= 'QEMU advent calendar'
254 self
.run_rr(kernel_path
, kernel_command_line
, console_pattern
,
257 def test_arm_vexpressa9(self
):
259 :avocado: tags=arch:arm
260 :avocado: tags=machine:vexpress-a9
262 tar_hash
= '32b7677ce8b6f1471fb0059865f451169934245b'
263 tar_url
= ('https://www.qemu-advent-calendar.org'
264 '/2018/download/day16.tar.xz')
265 file_path
= self
.fetch_asset(tar_url
, asset_hash
=tar_hash
)
266 dtb_path
= self
.workdir
+ '/day16/vexpress-v2p-ca9.dtb'
267 self
.do_test_advcal_2018(file_path
, 'winter.zImage',
268 args
=('-dtb', dtb_path
))
270 def test_m68k_mcf5208evb(self
):
272 :avocado: tags=arch:m68k
273 :avocado: tags=machine:mcf5208evb
275 tar_hash
= 'ac688fd00561a2b6ce1359f9ff6aa2b98c9a570c'
276 tar_url
= ('https://www.qemu-advent-calendar.org'
277 '/2018/download/day07.tar.xz')
278 file_path
= self
.fetch_asset(tar_url
, asset_hash
=tar_hash
)
279 self
.do_test_advcal_2018(file_path
, 'sanity-clause.elf')
281 @skip("Test currently broken") # Console stuck as of 5.2-rc1
282 def test_microblaze_s3adsp1800(self
):
284 :avocado: tags=arch:microblaze
285 :avocado: tags=machine:petalogix-s3adsp1800
287 tar_hash
= '08bf3e3bfb6b6c7ce1e54ab65d54e189f2caf13f'
288 tar_url
= ('https://www.qemu-advent-calendar.org'
289 '/2018/download/day17.tar.xz')
290 file_path
= self
.fetch_asset(tar_url
, asset_hash
=tar_hash
)
291 self
.do_test_advcal_2018(file_path
, 'ballerina.bin')
293 def test_ppc64_e500(self
):
295 :avocado: tags=arch:ppc64
296 :avocado: tags=machine:ppce500
297 :avocado: tags=cpu:e5500
299 tar_hash
= '6951d86d644b302898da2fd701739c9406527fe1'
300 tar_url
= ('https://www.qemu-advent-calendar.org'
301 '/2018/download/day19.tar.xz')
302 file_path
= self
.fetch_asset(tar_url
, asset_hash
=tar_hash
)
303 self
.do_test_advcal_2018(file_path
, 'uImage')
305 def test_ppc_g3beige(self
):
307 :avocado: tags=arch:ppc
308 :avocado: tags=machine:g3beige
310 tar_hash
= 'e0b872a5eb8fdc5bed19bd43ffe863900ebcedfc'
311 tar_url
= ('https://www.qemu-advent-calendar.org'
312 '/2018/download/day15.tar.xz')
313 file_path
= self
.fetch_asset(tar_url
, asset_hash
=tar_hash
)
314 self
.do_test_advcal_2018(file_path
, 'invaders.elf',
315 args
=('-M', 'graphics=off'))
317 def test_ppc_mac99(self
):
319 :avocado: tags=arch:ppc
320 :avocado: tags=machine:mac99
322 tar_hash
= 'e0b872a5eb8fdc5bed19bd43ffe863900ebcedfc'
323 tar_url
= ('https://www.qemu-advent-calendar.org'
324 '/2018/download/day15.tar.xz')
325 file_path
= self
.fetch_asset(tar_url
, asset_hash
=tar_hash
)
326 self
.do_test_advcal_2018(file_path
, 'invaders.elf',
327 args
=('-M', 'graphics=off'))
329 def test_sparc_ss20(self
):
331 :avocado: tags=arch:sparc
332 :avocado: tags=machine:SS-20
334 tar_hash
= 'b18550d5d61c7615d989a06edace051017726a9f'
335 tar_url
= ('https://www.qemu-advent-calendar.org'
336 '/2018/download/day11.tar.xz')
337 file_path
= self
.fetch_asset(tar_url
, asset_hash
=tar_hash
)
338 self
.do_test_advcal_2018(file_path
, 'zImage.elf')
340 def test_xtensa_lx60(self
):
342 :avocado: tags=arch:xtensa
343 :avocado: tags=machine:lx60
344 :avocado: tags=cpu:dc233c
346 tar_hash
= '49e88d9933742f0164b60839886c9739cb7a0d34'
347 tar_url
= ('https://www.qemu-advent-calendar.org'
348 '/2018/download/day02.tar.xz')
349 file_path
= self
.fetch_asset(tar_url
, asset_hash
=tar_hash
)
350 self
.do_test_advcal_2018(file_path
, 'santas-sleigh-ride.elf')
352 @skipUnless(os
.getenv('AVOCADO_TIMEOUT_EXPECTED'), 'Test might timeout')
353 class ReplayKernelSlow(ReplayKernelBase
):
354 # Override the timeout, because this kernel includes an inner
355 # loop which is executed with TB recompilings during replay,
356 # making it very slow.
359 def test_mips_malta_cpio(self
):
361 :avocado: tags=arch:mips
362 :avocado: tags=machine:malta
363 :avocado: tags=endian:big
364 :avocado: tags=slowness:high
366 deb_url
= ('http://snapshot.debian.org/archive/debian/'
367 '20160601T041800Z/pool/main/l/linux/'
368 'linux-image-4.5.0-2-4kc-malta_4.5.5-1_mips.deb')
369 deb_hash
= 'a3c84f3e88b54e06107d65a410d1d1e8e0f340f8'
370 deb_path
= self
.fetch_asset(deb_url
, asset_hash
=deb_hash
)
371 kernel_path
= self
.extract_from_deb(deb_path
,
372 '/boot/vmlinux-4.5.0-2-4kc-malta')
373 initrd_url
= ('https://github.com/groeck/linux-build-test/raw/'
374 '8584a59ed9e5eb5ee7ca91f6d74bbb06619205b8/rootfs/'
375 'mips/rootfs.cpio.gz')
376 initrd_hash
= 'bf806e17009360a866bf537f6de66590de349a99'
377 initrd_path_gz
= self
.fetch_asset(initrd_url
, asset_hash
=initrd_hash
)
378 initrd_path
= self
.workdir
+ "rootfs.cpio"
379 archive
.gzip_uncompress(initrd_path_gz
, initrd_path
)
381 kernel_command_line
= (self
.KERNEL_COMMON_COMMAND_LINE
+
382 'console=ttyS0 console=tty '
383 'rdinit=/sbin/init noreboot')
384 console_pattern
= 'Boot successful.'
385 self
.run_rr(kernel_path
, kernel_command_line
, console_pattern
, shift
=5,
386 args
=('-initrd', initrd_path
))
388 @skipUnless(os
.getenv('AVOCADO_ALLOW_UNTRUSTED_CODE'), 'untrusted code')
389 def test_mips64el_malta_5KEc_cpio(self
):
391 :avocado: tags=arch:mips64el
392 :avocado: tags=machine:malta
393 :avocado: tags=endian:little
394 :avocado: tags=slowness:high
395 :avocado: tags=cpu:5KEc
397 kernel_url
= ('https://github.com/philmd/qemu-testing-blob/'
398 'raw/9ad2df38/mips/malta/mips64el/'
399 'vmlinux-3.19.3.mtoman.20150408')
400 kernel_hash
= '00d1d268fb9f7d8beda1de6bebcc46e884d71754'
401 kernel_path
= self
.fetch_asset(kernel_url
, asset_hash
=kernel_hash
)
402 initrd_url
= ('https://github.com/groeck/linux-build-test/'
403 'raw/8584a59e/rootfs/'
404 'mipsel64/rootfs.mipsel64r1.cpio.gz')
405 initrd_hash
= '1dbb8a396e916847325284dbe2151167'
406 initrd_path_gz
= self
.fetch_asset(initrd_url
, algorithm
='md5',
407 asset_hash
=initrd_hash
)
408 initrd_path
= self
.workdir
+ "rootfs.cpio"
409 archive
.gzip_uncompress(initrd_path_gz
, initrd_path
)
411 kernel_command_line
= (self
.KERNEL_COMMON_COMMAND_LINE
+
412 'console=ttyS0 console=tty '
413 'rdinit=/sbin/init noreboot')
414 console_pattern
= 'Boot successful.'
415 self
.run_rr(kernel_path
, kernel_command_line
, console_pattern
, shift
=5,
416 args
=('-initrd', initrd_path
))
418 def do_test_mips_malta32el_nanomips(self
, kernel_path_xz
):
419 kernel_path
= self
.workdir
+ "kernel"
420 with lzma
.open(kernel_path_xz
, 'rb') as f_in
:
421 with
open(kernel_path
, 'wb') as f_out
:
422 shutil
.copyfileobj(f_in
, f_out
)
424 kernel_command_line
= (self
.KERNEL_COMMON_COMMAND_LINE
+
427 console_pattern
= 'Kernel command line: %s' % kernel_command_line
428 self
.run_rr(kernel_path
, kernel_command_line
, console_pattern
, shift
=5)
430 def test_mips_malta32el_nanomips_4k(self
):
432 :avocado: tags=arch:mipsel
433 :avocado: tags=machine:malta
434 :avocado: tags=endian:little
435 :avocado: tags=cpu:I7200
437 kernel_url
= ('https://mipsdistros.mips.com/LinuxDistro/nanomips/'
438 'kernels/v4.15.18-432-gb2eb9a8b07a1-20180627102142/'
439 'generic_nano32r6el_page4k.xz')
440 kernel_hash
= '477456aafd2a0f1ddc9482727f20fe9575565dd6'
441 kernel_path_xz
= self
.fetch_asset(kernel_url
, asset_hash
=kernel_hash
)
442 self
.do_test_mips_malta32el_nanomips(kernel_path_xz
)
444 def test_mips_malta32el_nanomips_16k_up(self
):
446 :avocado: tags=arch:mipsel
447 :avocado: tags=machine:malta
448 :avocado: tags=endian:little
449 :avocado: tags=cpu:I7200
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
463 :avocado: tags=cpu:I7200
465 kernel_url
= ('https://mipsdistros.mips.com/LinuxDistro/nanomips/'
466 'kernels/v4.15.18-432-gb2eb9a8b07a1-20180627102142/'
467 'generic_nano32r6el_page64k_dbg.xz')
468 kernel_hash
= '18d1c68f2e23429e266ca39ba5349ccd0aeb7180'
469 kernel_path_xz
= self
.fetch_asset(kernel_url
, asset_hash
=kernel_hash
)
470 self
.do_test_mips_malta32el_nanomips(kernel_path_xz
)