2020-07-01 15:56:21 +02:00
|
|
|
#!/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
|
2021-05-27 23:16:53 +02:00
|
|
|
from qemu.utils import kvm_available
|
2020-07-01 15:56:21 +02:00
|
|
|
|
|
|
|
# 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
|
2020-07-01 15:56:26 +02:00
|
|
|
args = basevm.parse_args(vmcls)
|
2020-07-01 15:56:21 +02:00
|
|
|
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))
|