#!/usr/bin/env python3 # # VM testing aarch64 library # # Copyright 2020 Linaro # # Authors: # Robert Foley # # This code is licensed under the GPL version 2 or later. See # the COPYING file in the top-level directory. # import os import sys import subprocess import basevm from qemu.accel import kvm_available # This is the config needed for current version of QEMU. # This works for both kvm and tcg. CURRENT_CONFIG = { 'cpu' : "max", 'machine' : "virt,gic-version=max", } # The minimum minor version of QEMU we will support with aarch64 VMs is 3. # QEMU versions less than 3 have various issues running these VMs. QEMU_AARCH64_MIN_VERSION = 3 # The DEFAULT_CONFIG will default to a version of # parameters that works for backwards compatibility. DEFAULT_CONFIG = {'kvm' : {'cpu' : "host", 'machine' : "virt,gic-version=host"}, 'tcg' : {'cpu' : "cortex-a57", 'machine' : "virt"}, } def get_config_defaults(vmcls, default_config): """Fetch the configuration defaults for this VM, taking into consideration the defaults for aarch64 first, followed by the defaults for this VM.""" config = default_config config.update(aarch_get_config_defaults(vmcls)) return config def aarch_get_config_defaults(vmcls): """Set the defaults for current version of QEMU.""" config = CURRENT_CONFIG args, argv = basevm.parse_args(vmcls) qemu_path = basevm.get_qemu_path(vmcls.arch, args.build_path) qemu_version = basevm.get_qemu_version(qemu_path) if qemu_version < QEMU_AARCH64_MIN_VERSION: error = "\nThis major version of QEMU {} is to old for aarch64 VMs.\n"\ "The major version must be at least {}.\n"\ "To continue with the current build of QEMU, "\ "please restart with QEMU_LOCAL=1 .\n" print(error.format(qemu_version, QEMU_AARCH64_MIN_VERSION)) exit(1) if qemu_version == QEMU_AARCH64_MIN_VERSION: # We have an older version of QEMU, # set the config values for backwards compatibility. if kvm_available('aarch64'): config.update(DEFAULT_CONFIG['kvm']) else: config.update(DEFAULT_CONFIG['tcg']) return config def create_flash_images(flash_dir="./", efi_img=""): """Creates the appropriate pflash files for an aarch64 VM.""" flash0_path = get_flash_path(flash_dir, "flash0") flash1_path = get_flash_path(flash_dir, "flash1") fd_null = open(os.devnull, 'w') subprocess.check_call(["dd", "if=/dev/zero", "of={}".format(flash0_path), "bs=1M", "count=64"], stdout=fd_null, stderr=subprocess.STDOUT) # A reliable way to get the QEMU EFI image is via an installed package or # via the bios included with qemu. if not os.path.exists(efi_img): sys.stderr.write("*** efi argument is invalid ({})\n".format(efi_img)) sys.stderr.write("*** please check --efi-aarch64 argument or "\ "install qemu-efi-aarch64 package\n") exit(3) subprocess.check_call(["dd", "if={}".format(efi_img), "of={}".format(flash0_path), "conv=notrunc"], stdout=fd_null, stderr=subprocess.STDOUT) subprocess.check_call(["dd", "if=/dev/zero", "of={}".format(flash1_path), "bs=1M", "count=64"], stdout=fd_null, stderr=subprocess.STDOUT) fd_null.close() def get_pflash_args(flash_dir="./"): """Returns a string that can be used to boot qemu using the appropriate pflash files for aarch64.""" flash0_path = get_flash_path(flash_dir, "flash0") flash1_path = get_flash_path(flash_dir, "flash1") pflash_args_str = "-drive file={},format=raw,if=pflash "\ "-drive file={},format=raw,if=pflash" pflash_args = pflash_args_str.format(flash0_path, flash1_path) return pflash_args.split(" ") def get_flash_path(flash_dir, name): return os.path.join(flash_dir, "{}.img".format(name))