Message ID | 20200529203458.1038-9-robert.foley@linaro.org (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | tests/vm: Add support for aarch64 VMs | expand |
Hi Robert, On 5/29/20 10:34 PM, Robert Foley wrote: > ubuntu.aarch64 provides a script to create an Ubuntu 18.04 VM. > Another new file is also added aarch64vm.py, which is a module with > common methods used by aarch64 VMs, such as how to create the > flash images. > > Signed-off-by: Robert Foley <robert.foley@linaro.org> > Reviewed-by: Peter Puhov <peter.puhov@linaro.org> > --- > configure | 20 +++++++ > tests/vm/Makefile.include | 11 ++++ > tests/vm/aarch64vm.py | 106 ++++++++++++++++++++++++++++++++++++++ > tests/vm/basevm.py | 12 +++++ > tests/vm/ubuntu.aarch64 | 68 ++++++++++++++++++++++++ > 5 files changed, 217 insertions(+) > create mode 100644 tests/vm/aarch64vm.py > create mode 100755 tests/vm/ubuntu.aarch64 > > diff --git a/configure b/configure > index d82de47fdd..8a286e75a5 100755 > --- a/configure > +++ b/configure > @@ -411,6 +411,7 @@ prefix="/usr/local" > mandir="\${prefix}/share/man" > datadir="\${prefix}/share" > firmwarepath="\${prefix}/share/qemu-firmware" > +efi_aarch64="" > qemu_docdir="\${prefix}/share/doc/qemu" > bindir="\${prefix}/bin" > libdir="\${prefix}/lib" > @@ -1099,6 +1100,8 @@ for opt do > ;; > --firmwarepath=*) firmwarepath="$optarg" > ;; > + --efi-aarch64=*) efi_aarch64="$optarg" > + ;; > --host=*|--build=*|\ > --disable-dependency-tracking|\ > --sbindir=*|--sharedstatedir=*|\ > @@ -1753,6 +1756,7 @@ Advanced options (experts only): > --sysconfdir=PATH install config in PATH$confsuffix > --localstatedir=PATH install local state in PATH (set at runtime on win32) > --firmwarepath=PATH search PATH for firmware files > + --efi-aarch64=PATH PATH of efi file to use for aarch64 VMs. > --with-confsuffix=SUFFIX suffix for QEMU data inside datadir/libdir/sysconfdir [$confsuffix] > --with-pkgversion=VERS use specified string as sub-version of the package > --enable-debug enable common debug build options > @@ -3548,6 +3552,20 @@ EOF > fi > fi > > +############################################ > +# efi-aarch64 probe > +# Check for efi files needed by aarch64 VMs. > +# By default we will use the efi included with QEMU. > +# Allow user to override the path for efi also. > +if ! test -f "$efi_aarch64"; then > + if test -f $source_path/pc-bios/edk2-aaarch64-code.fd.bz2; then > + # valid after build > + efi_aarch64=$PWD/pc-bios/edk2-aarch64-code.fd > + else > + efi_aarch64="" > + fi > +fi > + > ########################################## > # libcap-ng library probe > if test "$cap_ng" != "no" ; then > @@ -6604,6 +6622,7 @@ if test "$docs" != "no"; then > echo "sphinx-build $sphinx_build" > fi > echo "genisoimage $genisoimage" > +echo "efi_aarch64 $efi_aarch64" > echo "python_yaml $python_yaml" > echo "slirp support $slirp $(echo_version $slirp $slirp_version)" > if test "$slirp" != "no" ; then > @@ -7667,6 +7686,7 @@ echo "PYTHON=$python" >> $config_host_mak > echo "SPHINX_BUILD=$sphinx_build" >> $config_host_mak > echo "SPHINX_WERROR=$sphinx_werror" >> $config_host_mak > echo "GENISOIMAGE=$genisoimage" >> $config_host_mak > +echo "EFI_AARCH64=$efi_aarch64" >> $config_host_mak > echo "PYTHON_YAML=$python_yaml" >> $config_host_mak > echo "CC=$cc" >> $config_host_mak > if $iasl -h > /dev/null 2>&1; then > diff --git a/tests/vm/Makefile.include b/tests/vm/Makefile.include > index f6c3892bb2..cc71e6ed0a 100644 > --- a/tests/vm/Makefile.include > +++ b/tests/vm/Makefile.include > @@ -5,6 +5,9 @@ > IMAGES := freebsd netbsd openbsd centos fedora > ifneq ($(GENISOIMAGE),) > IMAGES += ubuntu.i386 centos > +ifneq ($(EFI_AARCH64),) > +IMAGES += ubuntu.aarch64 > +endif > endif > > IMAGES_DIR := $(HOME)/.cache/qemu-vm/images > @@ -23,6 +26,11 @@ vm-help vm-test: > ifneq ($(GENISOIMAGE),) > @echo " vm-build-centos - Build QEMU in CentOS VM, with Docker" > @echo " vm-build-ubuntu.i386 - Build QEMU in ubuntu i386 VM" > +ifneq ($(EFI_AARCH64),) > + @echo " vm-build-ubuntu.aarch64 - Build QEMU in ubuntu aarch64 VM" > +else > + @echo " (install qemu-efi-aarch64 to build centos/ubuntu aarch64 images.)" I'm not sure your test is working well, I have qemu-efi-aarch64 installed and it not automatically discovered. # apt install qemu-efi-aarch64 qemu-efi-aarch64 is already the newest version (0~20191122.bd85bf54-2ubuntu3). Hint: I'm using out-of-tree builds. > +endif > else > @echo " (install genisoimage to build centos/ubuntu images)" > endif > @@ -65,6 +73,7 @@ $(IMAGES_DIR)/%.img: $(SRC_PATH)/tests/vm/% \ > $(if $(V)$(DEBUG), --debug) \ > $(if $(GENISOIMAGE),--genisoimage $(GENISOIMAGE)) \ > $(if $(QEMU_LOCAL),--build-path $(BUILD_DIR)) \ > + $(if $(EFI_AARCH64),--efi-aarch64 $(EFI_AARCH64)) \ > --image "$@" \ > --force \ > --build-image $@, \ > @@ -80,6 +89,7 @@ vm-build-%: $(IMAGES_DIR)/%.img > $(if $(J),--jobs $(J)) \ > $(if $(V),--verbose) \ > $(if $(QEMU_LOCAL),--build-path $(BUILD_DIR)) \ > + $(if $(EFI_AARCH64),--efi-aarch64 $(EFI_AARCH64)) \ > --image "$<" \ > $(if $(BUILD_TARGET),--build-target $(BUILD_TARGET)) \ > --snapshot \ > @@ -102,6 +112,7 @@ vm-boot-ssh-%: $(IMAGES_DIR)/%.img > $(if $(J),--jobs $(J)) \ > $(if $(V)$(DEBUG), --debug) \ > $(if $(QEMU_LOCAL),--build-path $(BUILD_DIR)) \ > + $(if $(EFI_AARCH64),--efi-aarch64 $(EFI_AARCH64)) \ > --image "$<" \ > --interactive \ > false, \ > diff --git a/tests/vm/aarch64vm.py b/tests/vm/aarch64vm.py > new file mode 100644 > index 0000000000..bb04cb19c9 > --- /dev/null > +++ b/tests/vm/aarch64vm.py > @@ -0,0 +1,106 @@ > +#!/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, 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)) > diff --git a/tests/vm/basevm.py b/tests/vm/basevm.py > index 1aab9e3a24..f406a20466 100644 > --- a/tests/vm/basevm.py > +++ b/tests/vm/basevm.py > @@ -92,6 +92,7 @@ class BaseVM(object): > self._guest = None > self._genisoimage = args.genisoimage > self._build_path = args.build_path > + self._efi_aarch64 = args.efi_aarch64 > # Allow input config to override defaults. > self._config = DEFAULT_CONFIG.copy() > if config != None: > @@ -496,6 +497,14 @@ def get_qemu_path(arch, build_path=None): > qemu_path = "qemu-system-" + arch > return qemu_path > > +def get_qemu_version(qemu_path): > + """Get the version number from the current QEMU, > + and return the major number.""" > + output = subprocess.check_output([qemu_path, '--version']) > + version_line = output.decode("utf-8") > + version_num = re.split(' |\(', version_line)[3].split('.')[0] > + return int(version_num) > + > def parse_config(config, args): > """ Parse yaml config and populate our config structure. > The yaml config allows the user to override the > @@ -573,6 +582,9 @@ def parse_args(vmcls): > parser.add_option("--build-path", default=None, > help="Path of build directory, "\ > "for using build tree QEMU binary. ") > + parser.add_option("--efi-aarch64", > + default="/usr/share/qemu-efi-aarch64/QEMU_EFI.fd", > + help="Path to efi image for aarch64 VMs.") > parser.disable_interspersed_args() > return parser.parse_args() > > diff --git a/tests/vm/ubuntu.aarch64 b/tests/vm/ubuntu.aarch64 > new file mode 100755 > index 0000000000..6f903c029c > --- /dev/null > +++ b/tests/vm/ubuntu.aarch64 > @@ -0,0 +1,68 @@ > +#!/usr/bin/env python3 > +# > +# Ubuntu aarch64 image > +# > +# Copyright 2020 Linaro > +# > +# Authors: > +# Robert Foley <robert.foley@linaro.org> > +# Originally based on ubuntu.i386 Fam Zheng <famz@redhat.com> > +# > +# This code is licensed under the GPL version 2 or later. See > +# the COPYING file in the top-level directory. > +# > + > +import sys > +import basevm > +import aarch64vm > +import ubuntuvm > + > +DEFAULT_CONFIG = { > + 'cpu' : "cortex-a57", > + 'machine' : "virt,gic-version=3", > + 'install_cmds' : "apt-get update,"\ > + "apt-get build-dep -y --arch-only qemu,"\ > + "apt-get install -y libfdt-dev flex bison pkg-config", > + # We increase beyond the default time since during boot > + # it can take some time (many seconds) to log into the VM > + # especially using softmmu. > + 'ssh_timeout' : 60, > +} > + > +class UbuntuAarch64VM(ubuntuvm.UbuntuVM): > + name = "ubuntu.aarch64" > + arch = "aarch64" > + image_name = "ubuntu-18.04-server-cloudimg-arm64.img" > + image_link = "https://cloud-images.ubuntu.com/releases/18.04/release/" + image_name > + image_sha256="0fdcba761965735a8a903d8b88df8e47f156f48715c00508e4315c506d7d3cb1" > + BUILD_SCRIPT = """ > + set -e; > + cd $(mktemp -d); > + sudo chmod a+r /dev/vdb; > + tar --checkpoint=.10 -xf /dev/vdb; > + ./configure {configure_opts}; > + make --output-sync {target} -j{jobs} {verbose}; > + """ > + def boot(self, img, extra_args=None): > + aarch64vm.create_flash_images(self._tmpdir, self._efi_aarch64) > + default_args = aarch64vm.get_pflash_args(self._tmpdir) > + if extra_args: > + extra_args.extend(default_args) > + else: > + extra_args = default_args > + # We always add these performance tweaks > + # because without them, we boot so slowly that we > + # can time out finding the boot efi device. > + if '-smp' not in extra_args and \ > + '-smp' not in self._config['extra_args'] and \ > + '-smp' not in self._args: > + # Only add if not already there to give caller option to change it. > + extra_args.extend(["-smp", "8"]) > + > + # We have overridden boot() since aarch64 has additional parameters. > + # Call down to the base class method. > + super(UbuntuAarch64VM, self).boot(img, extra_args=extra_args) > + > +if __name__ == "__main__": > + defaults = aarch64vm.get_config_defaults(UbuntuAarch64VM, DEFAULT_CONFIG) > + sys.exit(basevm.main(UbuntuAarch64VM, defaults)) >
Philippe Mathieu-Daudé <philmd@redhat.com> writes: > Hi Robert, > > On 5/29/20 10:34 PM, Robert Foley wrote: <snip> >> diff --git a/configure b/configure >> index d82de47fdd..8a286e75a5 100755 >> --- a/configure >> +++ b/configure >> @@ -411,6 +411,7 @@ prefix="/usr/local" >> mandir="\${prefix}/share/man" >> datadir="\${prefix}/share" >> firmwarepath="\${prefix}/share/qemu-firmware" >> +efi_aarch64="" >> qemu_docdir="\${prefix}/share/doc/qemu" >> bindir="\${prefix}/bin" >> libdir="\${prefix}/lib" >> @@ -1099,6 +1100,8 @@ for opt do >> ;; >> --firmwarepath=*) firmwarepath="$optarg" >> ;; >> + --efi-aarch64=*) efi_aarch64="$optarg" >> + ;; >> --host=*|--build=*|\ >> --disable-dependency-tracking|\ >> --sbindir=*|--sharedstatedir=*|\ >> @@ -1753,6 +1756,7 @@ Advanced options (experts only): >> --sysconfdir=PATH install config in PATH$confsuffix >> --localstatedir=PATH install local state in PATH (set at runtime on win32) >> --firmwarepath=PATH search PATH for firmware files >> + --efi-aarch64=PATH PATH of efi file to use for aarch64 VMs. >> --with-confsuffix=SUFFIX suffix for QEMU data inside datadir/libdir/sysconfdir [$confsuffix] >> --with-pkgversion=VERS use specified string as sub-version of the package >> --enable-debug enable common debug build options >> @@ -3548,6 +3552,20 @@ EOF >> fi >> fi >> >> +############################################ >> +# efi-aarch64 probe >> +# Check for efi files needed by aarch64 VMs. >> +# By default we will use the efi included with QEMU. >> +# Allow user to override the path for efi also. >> +if ! test -f "$efi_aarch64"; then >> + if test -f $source_path/pc-bios/edk2-aaarch64-code.fd.bz2; then >> + # valid after build >> + efi_aarch64=$PWD/pc-bios/edk2-aarch64-code.fd >> + else >> + efi_aarch64="" >> + fi >> +fi >> + <snip> >> >> IMAGES_DIR := $(HOME)/.cache/qemu-vm/images >> @@ -23,6 +26,11 @@ vm-help vm-test: >> ifneq ($(GENISOIMAGE),) >> @echo " vm-build-centos - Build QEMU in CentOS VM, with Docker" >> @echo " vm-build-ubuntu.i386 - Build QEMU in ubuntu i386 VM" >> +ifneq ($(EFI_AARCH64),) >> + @echo " vm-build-ubuntu.aarch64 - Build QEMU in ubuntu aarch64 VM" >> +else >> + @echo " (install qemu-efi-aarch64 to build centos/ubuntu aarch64 images.)" > > I'm not sure your test is working well, I have qemu-efi-aarch64 > installed and it not automatically discovered. > > # apt install qemu-efi-aarch64 > qemu-efi-aarch64 is already the newest version > (0~20191122.bd85bf54-2ubuntu3). > > Hint: I'm using out-of-tree builds. I think efi_aarch64="" needs to be the default path, which can then be overridden by the command line or finally fall back to the built in image.
On Sun, 31 May 2020 at 06:54, Alex Bennée <alex.bennee@linaro.org> wrote: > > > Philippe Mathieu-Daudé <philmd@redhat.com> writes: > > > Hi Robert, > > > > On 5/29/20 10:34 PM, Robert Foley wrote: > <snip> > >> diff --git a/configure b/configure > >> index d82de47fdd..8a286e75a5 100755 > >> --- a/configure > >> +++ b/configure > >> @@ -411,6 +411,7 @@ prefix="/usr/local" > >> mandir="\${prefix}/share/man" > >> datadir="\${prefix}/share" > >> firmwarepath="\${prefix}/share/qemu-firmware" > >> +efi_aarch64="" > >> qemu_docdir="\${prefix}/share/doc/qemu" > >> bindir="\${prefix}/bin" > >> libdir="\${prefix}/lib" > >> @@ -1099,6 +1100,8 @@ for opt do > >> ;; > >> --firmwarepath=*) firmwarepath="$optarg" > >> ;; > >> + --efi-aarch64=*) efi_aarch64="$optarg" > >> + ;; > >> --host=*|--build=*|\ > >> --disable-dependency-tracking|\ > >> --sbindir=*|--sharedstatedir=*|\ > >> @@ -1753,6 +1756,7 @@ Advanced options (experts only): > >> --sysconfdir=PATH install config in PATH$confsuffix > >> --localstatedir=PATH install local state in PATH (set at runtime on win32) > >> --firmwarepath=PATH search PATH for firmware files > >> + --efi-aarch64=PATH PATH of efi file to use for aarch64 VMs. > >> --with-confsuffix=SUFFIX suffix for QEMU data inside datadir/libdir/sysconfdir [$confsuffix] > >> --with-pkgversion=VERS use specified string as sub-version of the package > >> --enable-debug enable common debug build options > >> @@ -3548,6 +3552,20 @@ EOF > >> fi > >> fi > >> > >> +############################################ > >> +# efi-aarch64 probe > >> +# Check for efi files needed by aarch64 VMs. > >> +# By default we will use the efi included with QEMU. > >> +# Allow user to override the path for efi also. > >> +if ! test -f "$efi_aarch64"; then > >> + if test -f $source_path/pc-bios/edk2-aaarch64-code.fd.bz2; then > >> + # valid after build > >> + efi_aarch64=$PWD/pc-bios/edk2-aarch64-code.fd > >> + else > >> + efi_aarch64="" > >> + fi > >> +fi > >> + > <snip> > >> > >> IMAGES_DIR := $(HOME)/.cache/qemu-vm/images > >> @@ -23,6 +26,11 @@ vm-help vm-test: > >> ifneq ($(GENISOIMAGE),) > >> @echo " vm-build-centos - Build QEMU in CentOS VM, with Docker" > >> @echo " vm-build-ubuntu.i386 - Build QEMU in ubuntu i386 VM" > >> +ifneq ($(EFI_AARCH64),) > >> + @echo " vm-build-ubuntu.aarch64 - Build QEMU in ubuntu aarch64 VM" > >> +else > >> + @echo " (install qemu-efi-aarch64 to build centos/ubuntu aarch64 images.)" > > > > I'm not sure your test is working well, I have qemu-efi-aarch64 > > installed and it not automatically discovered. > > > > # apt install qemu-efi-aarch64 > > qemu-efi-aarch64 is already the newest version > > (0~20191122.bd85bf54-2ubuntu3). > > > > Hint: I'm using out-of-tree builds. > > I think efi_aarch64="" needs to be the default path, which can then be > overridden by the command line or finally fall back to the built in > image. I think what we are saying here is that if we want to use the qemu-efi-aarch64 package's image we should override it on the command line via --efi-aarch64. Seems like the text above needs adjustment to something like: > +ifneq ($(EFI_AARCH64),) > + @echo " vm-build-ubuntu.aarch64 - Build QEMU in ubuntu aarch64 VM" > +else @echo " to build centos/ubuntu aarch64 images use configure --efi-aarch64" Thanks & Regards, -Rob > > -- > Alex Bennée
diff --git a/configure b/configure index d82de47fdd..8a286e75a5 100755 --- a/configure +++ b/configure @@ -411,6 +411,7 @@ prefix="/usr/local" mandir="\${prefix}/share/man" datadir="\${prefix}/share" firmwarepath="\${prefix}/share/qemu-firmware" +efi_aarch64="" qemu_docdir="\${prefix}/share/doc/qemu" bindir="\${prefix}/bin" libdir="\${prefix}/lib" @@ -1099,6 +1100,8 @@ for opt do ;; --firmwarepath=*) firmwarepath="$optarg" ;; + --efi-aarch64=*) efi_aarch64="$optarg" + ;; --host=*|--build=*|\ --disable-dependency-tracking|\ --sbindir=*|--sharedstatedir=*|\ @@ -1753,6 +1756,7 @@ Advanced options (experts only): --sysconfdir=PATH install config in PATH$confsuffix --localstatedir=PATH install local state in PATH (set at runtime on win32) --firmwarepath=PATH search PATH for firmware files + --efi-aarch64=PATH PATH of efi file to use for aarch64 VMs. --with-confsuffix=SUFFIX suffix for QEMU data inside datadir/libdir/sysconfdir [$confsuffix] --with-pkgversion=VERS use specified string as sub-version of the package --enable-debug enable common debug build options @@ -3548,6 +3552,20 @@ EOF fi fi +############################################ +# efi-aarch64 probe +# Check for efi files needed by aarch64 VMs. +# By default we will use the efi included with QEMU. +# Allow user to override the path for efi also. +if ! test -f "$efi_aarch64"; then + if test -f $source_path/pc-bios/edk2-aaarch64-code.fd.bz2; then + # valid after build + efi_aarch64=$PWD/pc-bios/edk2-aarch64-code.fd + else + efi_aarch64="" + fi +fi + ########################################## # libcap-ng library probe if test "$cap_ng" != "no" ; then @@ -6604,6 +6622,7 @@ if test "$docs" != "no"; then echo "sphinx-build $sphinx_build" fi echo "genisoimage $genisoimage" +echo "efi_aarch64 $efi_aarch64" echo "python_yaml $python_yaml" echo "slirp support $slirp $(echo_version $slirp $slirp_version)" if test "$slirp" != "no" ; then @@ -7667,6 +7686,7 @@ echo "PYTHON=$python" >> $config_host_mak echo "SPHINX_BUILD=$sphinx_build" >> $config_host_mak echo "SPHINX_WERROR=$sphinx_werror" >> $config_host_mak echo "GENISOIMAGE=$genisoimage" >> $config_host_mak +echo "EFI_AARCH64=$efi_aarch64" >> $config_host_mak echo "PYTHON_YAML=$python_yaml" >> $config_host_mak echo "CC=$cc" >> $config_host_mak if $iasl -h > /dev/null 2>&1; then diff --git a/tests/vm/Makefile.include b/tests/vm/Makefile.include index f6c3892bb2..cc71e6ed0a 100644 --- a/tests/vm/Makefile.include +++ b/tests/vm/Makefile.include @@ -5,6 +5,9 @@ IMAGES := freebsd netbsd openbsd centos fedora ifneq ($(GENISOIMAGE),) IMAGES += ubuntu.i386 centos +ifneq ($(EFI_AARCH64),) +IMAGES += ubuntu.aarch64 +endif endif IMAGES_DIR := $(HOME)/.cache/qemu-vm/images @@ -23,6 +26,11 @@ vm-help vm-test: ifneq ($(GENISOIMAGE),) @echo " vm-build-centos - Build QEMU in CentOS VM, with Docker" @echo " vm-build-ubuntu.i386 - Build QEMU in ubuntu i386 VM" +ifneq ($(EFI_AARCH64),) + @echo " vm-build-ubuntu.aarch64 - Build QEMU in ubuntu aarch64 VM" +else + @echo " (install qemu-efi-aarch64 to build centos/ubuntu aarch64 images.)" +endif else @echo " (install genisoimage to build centos/ubuntu images)" endif @@ -65,6 +73,7 @@ $(IMAGES_DIR)/%.img: $(SRC_PATH)/tests/vm/% \ $(if $(V)$(DEBUG), --debug) \ $(if $(GENISOIMAGE),--genisoimage $(GENISOIMAGE)) \ $(if $(QEMU_LOCAL),--build-path $(BUILD_DIR)) \ + $(if $(EFI_AARCH64),--efi-aarch64 $(EFI_AARCH64)) \ --image "$@" \ --force \ --build-image $@, \ @@ -80,6 +89,7 @@ vm-build-%: $(IMAGES_DIR)/%.img $(if $(J),--jobs $(J)) \ $(if $(V),--verbose) \ $(if $(QEMU_LOCAL),--build-path $(BUILD_DIR)) \ + $(if $(EFI_AARCH64),--efi-aarch64 $(EFI_AARCH64)) \ --image "$<" \ $(if $(BUILD_TARGET),--build-target $(BUILD_TARGET)) \ --snapshot \ @@ -102,6 +112,7 @@ vm-boot-ssh-%: $(IMAGES_DIR)/%.img $(if $(J),--jobs $(J)) \ $(if $(V)$(DEBUG), --debug) \ $(if $(QEMU_LOCAL),--build-path $(BUILD_DIR)) \ + $(if $(EFI_AARCH64),--efi-aarch64 $(EFI_AARCH64)) \ --image "$<" \ --interactive \ false, \ diff --git a/tests/vm/aarch64vm.py b/tests/vm/aarch64vm.py new file mode 100644 index 0000000000..bb04cb19c9 --- /dev/null +++ b/tests/vm/aarch64vm.py @@ -0,0 +1,106 @@ +#!/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, 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)) diff --git a/tests/vm/basevm.py b/tests/vm/basevm.py index 1aab9e3a24..f406a20466 100644 --- a/tests/vm/basevm.py +++ b/tests/vm/basevm.py @@ -92,6 +92,7 @@ class BaseVM(object): self._guest = None self._genisoimage = args.genisoimage self._build_path = args.build_path + self._efi_aarch64 = args.efi_aarch64 # Allow input config to override defaults. self._config = DEFAULT_CONFIG.copy() if config != None: @@ -496,6 +497,14 @@ def get_qemu_path(arch, build_path=None): qemu_path = "qemu-system-" + arch return qemu_path +def get_qemu_version(qemu_path): + """Get the version number from the current QEMU, + and return the major number.""" + output = subprocess.check_output([qemu_path, '--version']) + version_line = output.decode("utf-8") + version_num = re.split(' |\(', version_line)[3].split('.')[0] + return int(version_num) + def parse_config(config, args): """ Parse yaml config and populate our config structure. The yaml config allows the user to override the @@ -573,6 +582,9 @@ def parse_args(vmcls): parser.add_option("--build-path", default=None, help="Path of build directory, "\ "for using build tree QEMU binary. ") + parser.add_option("--efi-aarch64", + default="/usr/share/qemu-efi-aarch64/QEMU_EFI.fd", + help="Path to efi image for aarch64 VMs.") parser.disable_interspersed_args() return parser.parse_args() diff --git a/tests/vm/ubuntu.aarch64 b/tests/vm/ubuntu.aarch64 new file mode 100755 index 0000000000..6f903c029c --- /dev/null +++ b/tests/vm/ubuntu.aarch64 @@ -0,0 +1,68 @@ +#!/usr/bin/env python3 +# +# Ubuntu aarch64 image +# +# Copyright 2020 Linaro +# +# Authors: +# Robert Foley <robert.foley@linaro.org> +# Originally based on ubuntu.i386 Fam Zheng <famz@redhat.com> +# +# This code is licensed under the GPL version 2 or later. See +# the COPYING file in the top-level directory. +# + +import sys +import basevm +import aarch64vm +import ubuntuvm + +DEFAULT_CONFIG = { + 'cpu' : "cortex-a57", + 'machine' : "virt,gic-version=3", + 'install_cmds' : "apt-get update,"\ + "apt-get build-dep -y --arch-only qemu,"\ + "apt-get install -y libfdt-dev flex bison pkg-config", + # We increase beyond the default time since during boot + # it can take some time (many seconds) to log into the VM + # especially using softmmu. + 'ssh_timeout' : 60, +} + +class UbuntuAarch64VM(ubuntuvm.UbuntuVM): + name = "ubuntu.aarch64" + arch = "aarch64" + image_name = "ubuntu-18.04-server-cloudimg-arm64.img" + image_link = "https://cloud-images.ubuntu.com/releases/18.04/release/" + image_name + image_sha256="0fdcba761965735a8a903d8b88df8e47f156f48715c00508e4315c506d7d3cb1" + BUILD_SCRIPT = """ + set -e; + cd $(mktemp -d); + sudo chmod a+r /dev/vdb; + tar --checkpoint=.10 -xf /dev/vdb; + ./configure {configure_opts}; + make --output-sync {target} -j{jobs} {verbose}; + """ + def boot(self, img, extra_args=None): + aarch64vm.create_flash_images(self._tmpdir, self._efi_aarch64) + default_args = aarch64vm.get_pflash_args(self._tmpdir) + if extra_args: + extra_args.extend(default_args) + else: + extra_args = default_args + # We always add these performance tweaks + # because without them, we boot so slowly that we + # can time out finding the boot efi device. + if '-smp' not in extra_args and \ + '-smp' not in self._config['extra_args'] and \ + '-smp' not in self._args: + # Only add if not already there to give caller option to change it. + extra_args.extend(["-smp", "8"]) + + # We have overridden boot() since aarch64 has additional parameters. + # Call down to the base class method. + super(UbuntuAarch64VM, self).boot(img, extra_args=extra_args) + +if __name__ == "__main__": + defaults = aarch64vm.get_config_defaults(UbuntuAarch64VM, DEFAULT_CONFIG) + sys.exit(basevm.main(UbuntuAarch64VM, defaults))