1#!/usr/bin/env python3 2# 3# VM testing aarch64 library 4# 5# Copyright 2020 Linaro 6# 7# Authors: 8# Robert Foley <robert.foley@linaro.org> 9# 10# This code is licensed under the GPL version 2 or later. See 11# the COPYING file in the top-level directory. 12# 13import os 14import sys 15import subprocess 16import basevm 17from qemu.utils import kvm_available 18 19# This is the config needed for current version of QEMU. 20# This works for both kvm and tcg. 21CURRENT_CONFIG = { 22 'cpu' : "max", 23 'machine' : "virt,gic-version=max", 24} 25 26# The minimum minor version of QEMU we will support with aarch64 VMs is 3. 27# QEMU versions less than 3 have various issues running these VMs. 28QEMU_AARCH64_MIN_VERSION = 3 29 30# The DEFAULT_CONFIG will default to a version of 31# parameters that works for backwards compatibility. 32DEFAULT_CONFIG = {'kvm' : {'cpu' : "host", 33 'machine' : "virt,gic-version=host"}, 34 'tcg' : {'cpu' : "cortex-a57", 35 'machine' : "virt"}, 36} 37 38def get_config_defaults(vmcls, default_config): 39 """Fetch the configuration defaults for this VM, 40 taking into consideration the defaults for 41 aarch64 first, followed by the defaults for this VM.""" 42 config = default_config 43 config.update(aarch_get_config_defaults(vmcls)) 44 return config 45 46def aarch_get_config_defaults(vmcls): 47 """Set the defaults for current version of QEMU.""" 48 config = CURRENT_CONFIG 49 args = basevm.parse_args(vmcls) 50 qemu_path = basevm.get_qemu_path(vmcls.arch, args.build_path) 51 qemu_version = basevm.get_qemu_version(qemu_path) 52 if qemu_version < QEMU_AARCH64_MIN_VERSION: 53 error = "\nThis major version of QEMU {} is to old for aarch64 VMs.\n"\ 54 "The major version must be at least {}.\n"\ 55 "To continue with the current build of QEMU, "\ 56 "please restart with QEMU_LOCAL=1 .\n" 57 print(error.format(qemu_version, QEMU_AARCH64_MIN_VERSION)) 58 exit(1) 59 if qemu_version == QEMU_AARCH64_MIN_VERSION: 60 # We have an older version of QEMU, 61 # set the config values for backwards compatibility. 62 if kvm_available('aarch64'): 63 config.update(DEFAULT_CONFIG['kvm']) 64 else: 65 config.update(DEFAULT_CONFIG['tcg']) 66 return config 67 68def create_flash_images(flash_dir="./", efi_img=""): 69 """Creates the appropriate pflash files 70 for an aarch64 VM.""" 71 flash0_path = get_flash_path(flash_dir, "flash0") 72 flash1_path = get_flash_path(flash_dir, "flash1") 73 fd_null = open(os.devnull, 'w') 74 subprocess.check_call(["dd", "if=/dev/zero", "of={}".format(flash0_path), 75 "bs=1M", "count=64"], 76 stdout=fd_null, stderr=subprocess.STDOUT) 77 # A reliable way to get the QEMU EFI image is via an installed package or 78 # via the bios included with qemu. 79 if not os.path.exists(efi_img): 80 sys.stderr.write("*** efi argument is invalid ({})\n".format(efi_img)) 81 sys.stderr.write("*** please check --efi-aarch64 argument or "\ 82 "install qemu-efi-aarch64 package\n") 83 exit(3) 84 subprocess.check_call(["dd", "if={}".format(efi_img), 85 "of={}".format(flash0_path), 86 "conv=notrunc"], 87 stdout=fd_null, stderr=subprocess.STDOUT) 88 subprocess.check_call(["dd", "if=/dev/zero", 89 "of={}".format(flash1_path), 90 "bs=1M", "count=64"], 91 stdout=fd_null, stderr=subprocess.STDOUT) 92 fd_null.close() 93 94def get_pflash_args(flash_dir="./"): 95 """Returns a string that can be used to 96 boot qemu using the appropriate pflash files 97 for aarch64.""" 98 flash0_path = get_flash_path(flash_dir, "flash0") 99 flash1_path = get_flash_path(flash_dir, "flash1") 100 pflash_args_str = "-drive file={},format=raw,if=pflash "\ 101 "-drive file={},format=raw,if=pflash" 102 pflash_args = pflash_args_str.format(flash0_path, flash1_path) 103 return pflash_args.split(" ") 104 105def get_flash_path(flash_dir, name): 106 return os.path.join(flash_dir, "{}.img".format(name)) 107