1# Functional test that boots a various Linux systems and checks the 2# console output. 3# 4# Copyright (c) 2022 Linaro Ltd. 5# 6# Author: 7# Alex Bennée <alex.bennee@linaro.org> 8# 9# SPDX-License-Identifier: GPL-2.0-or-later 10 11import time 12import os 13import logging 14 15from avocado_qemu import QemuSystemTest 16from avocado_qemu import wait_for_console_pattern 17from avocado_qemu import exec_command 18from avocado_qemu import BUILD_DIR 19from avocado.utils import process 20from avocado.utils.path import find_command 21 22class Aarch64VirtMachine(QemuSystemTest): 23 KERNEL_COMMON_COMMAND_LINE = 'printk.time=0 ' 24 timeout = 360 25 26 def wait_for_console_pattern(self, success_message, vm=None): 27 wait_for_console_pattern(self, success_message, 28 failure_message='Kernel panic - not syncing', 29 vm=vm) 30 31 # This tests the whole boot chain from EFI to Userspace 32 # We only boot a whole OS for the current top level CPU and GIC 33 # Other test profiles should use more minimal boots 34 def test_alpine_virt_tcg_gic_max(self): 35 """ 36 :avocado: tags=arch:aarch64 37 :avocado: tags=machine:virt 38 :avocado: tags=accel:tcg 39 """ 40 iso_url = ('https://dl-cdn.alpinelinux.org/' 41 'alpine/v3.16/releases/aarch64/' 42 'alpine-virt-3.16.3-aarch64.iso') 43 44 # Alpine use sha256 so I recalculated this myself 45 iso_sha1 = '0683bc089486d55c91bf6607d5ecb93925769bc0' 46 iso_path = self.fetch_asset(iso_url, asset_hash=iso_sha1) 47 48 self.vm.set_console() 49 kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE + 50 'console=ttyAMA0') 51 self.require_accelerator("tcg") 52 53 self.vm.add_args("-accel", "tcg") 54 self.vm.add_args("-cpu", "max,pauth-impdef=on") 55 self.vm.add_args("-machine", 56 "virt,acpi=on," 57 "virtualization=on," 58 "mte=on," 59 "gic-version=max,iommu=smmuv3") 60 self.vm.add_args("-smp", "2", "-m", "1024") 61 self.vm.add_args('-bios', os.path.join(BUILD_DIR, 'pc-bios', 62 'edk2-aarch64-code.fd')) 63 self.vm.add_args("-drive", f"file={iso_path},format=raw") 64 self.vm.add_args('-device', 'virtio-rng-pci,rng=rng0') 65 self.vm.add_args('-object', 'rng-random,id=rng0,filename=/dev/urandom') 66 67 self.vm.launch() 68 self.wait_for_console_pattern('Welcome to Alpine Linux 3.16') 69 70 71 def common_aarch64_virt(self, machine): 72 """ 73 Common code to launch basic virt machine with kernel+initrd 74 and a scratch disk. 75 """ 76 logger = logging.getLogger('aarch64_virt') 77 78 kernel_url = ('https://fileserver.linaro.org/s/' 79 'z6B2ARM7DQT3HWN/download') 80 kernel_hash = 'ed11daab50c151dde0e1e9c9cb8b2d9bd3215347' 81 kernel_path = self.fetch_asset(kernel_url, asset_hash=kernel_hash) 82 83 self.vm.set_console() 84 kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE + 85 'console=ttyAMA0') 86 self.require_accelerator("tcg") 87 self.vm.add_args('-cpu', 'max,pauth-impdef=on', 88 '-machine', machine, 89 '-accel', 'tcg', 90 '-kernel', kernel_path, 91 '-append', kernel_command_line) 92 93 # A RNG offers an easy way to generate a few IRQs 94 self.vm.add_args('-device', 'virtio-rng-pci,rng=rng0') 95 self.vm.add_args('-object', 96 'rng-random,id=rng0,filename=/dev/urandom') 97 98 # Also add a scratch block device 99 logger.info('creating scratch qcow2 image') 100 image_path = os.path.join(self.workdir, 'scratch.qcow2') 101 qemu_img = os.path.join(BUILD_DIR, 'qemu-img') 102 if not os.path.exists(qemu_img): 103 qemu_img = find_command('qemu-img', False) 104 if qemu_img is False: 105 self.cancel('Could not find "qemu-img", which is required to ' 106 'create the temporary qcow2 image') 107 cmd = '%s create -f qcow2 %s 8M' % (qemu_img, image_path) 108 process.run(cmd) 109 110 # Add the device 111 self.vm.add_args('-blockdev', 112 f"driver=qcow2,file.driver=file,file.filename={image_path},node-name=scratch") 113 self.vm.add_args('-device', 114 'virtio-blk-device,drive=scratch') 115 116 self.vm.launch() 117 self.wait_for_console_pattern('Welcome to Buildroot') 118 time.sleep(0.1) 119 exec_command(self, 'root') 120 time.sleep(0.1) 121 exec_command(self, 'dd if=/dev/hwrng of=/dev/vda bs=512 count=4') 122 time.sleep(0.1) 123 exec_command(self, 'md5sum /dev/vda') 124 time.sleep(0.1) 125 exec_command(self, 'cat /proc/interrupts') 126 time.sleep(0.1) 127 exec_command(self, 'cat /proc/self/maps') 128 time.sleep(0.1) 129 130 def test_aarch64_virt_gicv3(self): 131 """ 132 :avocado: tags=arch:aarch64 133 :avocado: tags=machine:virt 134 :avocado: tags=accel:tcg 135 :avocado: tags=cpu:max 136 """ 137 self.common_aarch64_virt("virt,gic_version=3") 138 139 def test_aarch64_virt_gicv2(self): 140 """ 141 :avocado: tags=arch:aarch64 142 :avocado: tags=machine:virt 143 :avocado: tags=accel:tcg 144 :avocado: tags=cpu:max 145 """ 146 self.common_aarch64_virt("virt,gic-version=2") 147