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