xref: /openbmc/qemu/tests/functional/replay_kernel.py (revision ee376948ebd9cf74b4456a7422e5073a72e4486a)
1a2fe7bb7SThomas Huth# Record/replay test that boots a Linux kernel
2a2fe7bb7SThomas Huth#
3a2fe7bb7SThomas Huth# Copyright (c) 2020 ISP RAS
4a2fe7bb7SThomas Huth#
5a2fe7bb7SThomas Huth# Author:
6a2fe7bb7SThomas Huth#  Pavel Dovgalyuk <Pavel.Dovgaluk@ispras.ru>
7a2fe7bb7SThomas Huth#
8a2fe7bb7SThomas Huth# This work is licensed under the terms of the GNU GPL, version 2 or
9a2fe7bb7SThomas Huth# later.  See the COPYING file in the top-level directory.
10a2fe7bb7SThomas Huth
11a2fe7bb7SThomas Huthimport os
12a2fe7bb7SThomas Huthimport logging
13a2fe7bb7SThomas Huthimport time
14a2fe7bb7SThomas Huthimport subprocess
15a2fe7bb7SThomas Huth
16a2fe7bb7SThomas Huthfrom qemu_test.linuxkernel import LinuxKernelTest
17a2fe7bb7SThomas Huth
18a2fe7bb7SThomas Huthclass ReplayKernelBase(LinuxKernelTest):
19a2fe7bb7SThomas Huth    """
20a2fe7bb7SThomas Huth    Boots a Linux kernel in record mode and checks that the console
21a2fe7bb7SThomas Huth    is operational and the kernel command line is properly passed
22a2fe7bb7SThomas Huth    from QEMU to the kernel.
23a2fe7bb7SThomas Huth    Then replays the same scenario and verifies, that QEMU correctly
24a2fe7bb7SThomas Huth    terminates.
25a2fe7bb7SThomas Huth    """
26a2fe7bb7SThomas Huth
27a2fe7bb7SThomas Huth    timeout = 180
28a2fe7bb7SThomas Huth    REPLAY_KERNEL_COMMAND_LINE = 'printk.time=1 panic=-1 '
29a2fe7bb7SThomas Huth
30a2fe7bb7SThomas Huth    def run_vm(self, kernel_path, kernel_command_line, console_pattern,
31a2fe7bb7SThomas Huth               record, shift, args, replay_path):
32a2fe7bb7SThomas Huth        # icount requires TCG to be available
33a2fe7bb7SThomas Huth        self.require_accelerator('tcg')
34a2fe7bb7SThomas Huth
35a2fe7bb7SThomas Huth        logger = logging.getLogger('replay')
36a2fe7bb7SThomas Huth        start_time = time.time()
37*006453f4SThomas Huth        vm = self.get_vm(name='recording' if record else 'replay')
38a2fe7bb7SThomas Huth        vm.set_console()
39a2fe7bb7SThomas Huth        if record:
40a2fe7bb7SThomas Huth            logger.info('recording the execution...')
41a2fe7bb7SThomas Huth            mode = 'record'
42a2fe7bb7SThomas Huth        else:
43a2fe7bb7SThomas Huth            logger.info('replaying the execution...')
44a2fe7bb7SThomas Huth            mode = 'replay'
45a2fe7bb7SThomas Huth        vm.add_args('-icount', 'shift=%s,rr=%s,rrfile=%s' %
46a2fe7bb7SThomas Huth                    (shift, mode, replay_path),
47a2fe7bb7SThomas Huth                    '-kernel', kernel_path,
48a2fe7bb7SThomas Huth                    '-append', kernel_command_line,
49a2fe7bb7SThomas Huth                    '-net', 'none',
50a2fe7bb7SThomas Huth                    '-no-reboot')
51a2fe7bb7SThomas Huth        if args:
52a2fe7bb7SThomas Huth            vm.add_args(*args)
53a2fe7bb7SThomas Huth        vm.launch()
54a2fe7bb7SThomas Huth        self.wait_for_console_pattern(console_pattern, vm)
55a2fe7bb7SThomas Huth        if record:
56a2fe7bb7SThomas Huth            vm.shutdown()
57a2fe7bb7SThomas Huth            logger.info('finished the recording with log size %s bytes'
58a2fe7bb7SThomas Huth                        % os.path.getsize(replay_path))
59a2fe7bb7SThomas Huth            self.run_replay_dump(replay_path)
60a2fe7bb7SThomas Huth            logger.info('successfully tested replay-dump.py')
61a2fe7bb7SThomas Huth        else:
62a2fe7bb7SThomas Huth            vm.wait()
63a2fe7bb7SThomas Huth            logger.info('successfully finished the replay')
64a2fe7bb7SThomas Huth        elapsed = time.time() - start_time
65a2fe7bb7SThomas Huth        logger.info('elapsed time %.2f sec' % elapsed)
66a2fe7bb7SThomas Huth        return elapsed
67a2fe7bb7SThomas Huth
68a2fe7bb7SThomas Huth    def run_replay_dump(self, replay_path):
69a2fe7bb7SThomas Huth        try:
70a2fe7bb7SThomas Huth            subprocess.check_call(["./scripts/replay-dump.py",
71a2fe7bb7SThomas Huth                                   "-f", replay_path],
72a2fe7bb7SThomas Huth                                  stdout=subprocess.DEVNULL)
73a2fe7bb7SThomas Huth        except subprocess.CalledProcessError:
74a2fe7bb7SThomas Huth            self.fail('replay-dump.py failed')
75a2fe7bb7SThomas Huth
76a2fe7bb7SThomas Huth    def run_rr(self, kernel_path, kernel_command_line, console_pattern,
77a2fe7bb7SThomas Huth               shift=7, args=None):
78a2fe7bb7SThomas Huth        replay_path = os.path.join(self.workdir, 'replay.bin')
79a2fe7bb7SThomas Huth        t1 = self.run_vm(kernel_path, kernel_command_line, console_pattern,
80a2fe7bb7SThomas Huth                         True, shift, args, replay_path)
81a2fe7bb7SThomas Huth        t2 = self.run_vm(kernel_path, kernel_command_line, console_pattern,
82a2fe7bb7SThomas Huth                         False, shift, args, replay_path)
83a2fe7bb7SThomas Huth        logger = logging.getLogger('replay')
84a2fe7bb7SThomas Huth        logger.info('replay overhead {:.2%}'.format(t2 / t1 - 1))
85