| #!/usr/bin/env python3 |
| # |
| # VM testing aarch64 library |
| # |
| # Copyright 2020 Linaro |
| # |
| # Authors: |
| # Robert Foley <robert.foley@linaro.org> |
| # |
| # 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 = 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)) |