From 867976c2befc21009f7f5d24872218eae4a273e1 Mon Sep 17 00:00:00 2001 From: Nathan Chancellor Date: Fri, 9 Dec 2022 14:38:01 -0700 Subject: [PATCH] boot-qemu.py: Simplify can_use_kvm() The existing check for '/dev/kvm' is not strong enough, as it is possible that '/dev/kvm' exists but the user does not have sufficient permissions to access it, which will result in QEMU immediately refusing to start. This can be quite frustrating when doing a sequence of builds non-interactively, as the results will be tainted due to the initial startup failure. Switch to os.access(), which allows us to make sure '/dev/kvm' is writeable with the current permissions. At the same time, clean up this function. If '/dev/kvm' is accessible, it implies hardware virtualization support, so we can ditch the '/proc/cpuinfo' check for x86. Refactor the 32-bit EL1 check for aarch64 to its own function, which allows us to compact the aarch64 section signficantly. Signed-off-by: Nathan Chancellor --- boot-qemu.py | 72 +++++++++++++++++++++++++++------------------------- 1 file changed, 37 insertions(+), 35 deletions(-) diff --git a/boot-qemu.py b/boot-qemu.py index 046ee65..3bb8e14 100755 --- a/boot-qemu.py +++ b/boot-qemu.py @@ -93,53 +93,55 @@ def parse_arguments(): return parser.parse_args() +def arm64_have_el1_32(): + """ + Calls 'aarch64_32_bit_el1_supported' to see if 32-bit EL1 is supported on + the current machine. + + Returns: + True if 32-bit EL1 is supported, false if not + """ + try: + subprocess.run(base_folder.joinpath('utils', + 'aarch64_32_bit_el1_supported'), + check=True) + except subprocess.CalledProcessError: + return False + return True + + def can_use_kvm(can_test_for_kvm, guest_arch): """ Checks that KVM can be used for faster VMs based on: * User's request * Whether or not '--no-kvm' was used - * '/dev/kvm' is available - * The guest architecture - * Only 'arm'/'arm32_v7', 'arm64', 'arm64be', 'x86', and 'x86_64' - are supported with KVM - * Availability of hardware virtualization support - * aarch64 may not support accelerated 32-bit guests - * i386 and x86_64 need the virtualization extensions in - '/proc/cpuinfo' + * '/dev/kvm' is readable and writable by the current user + * Implies hardware virtualization support + * The host architecture relative to guest architecture + * aarch64 always supports accelerated aarch64 guests, may support + accelerated aarch32 guests + * x86_64 always supports accelerated 64-bit and 32-bit x86 guests Parameters: - user_kvm_opt_out (bool): False if user passed in '--no-kvm', True if not + can_test_for_vm (bool): False if user passed in '--no-kvm', True if not guest_arch (str): The guest architecture being run. Returns: True if KVM can be used based on the above parameters, False if not. """ - if can_test_for_kvm: - # /dev/kvm must exist to use KVM with QEMU - if Path("/dev/kvm").exists(): - host_arch = platform.machine() - - if host_arch == "aarch64": - # If /dev/kvm exists on aarch64, KVM is supported for aarch64 guests - if "arm64" in guest_arch: - return True - # 32-bit EL1 is not always supported, test for it first - if guest_arch in ("arm", "arm32_v7"): - check_32_bit_el1 = base_folder.joinpath( - "utils", "aarch64_32_bit_el1_supported") - try: - subprocess.run([check_32_bit_el1], check=True) - except subprocess.CalledSubprocessError: - return False - return True - - if host_arch == "x86_64" and "x86" in guest_arch: - # Check /proc/cpuinfo for whether or not the machine supports hardware virtualization - cpuinfo = Path("/proc/cpuinfo").read_text(encoding='utf-8') - # SVM is AMD, VMX is Intel - return cpuinfo.count("svm") > 0 or cpuinfo.count("vmx") > 0 - - # We could not prove that we could use KVM safely so don't try + # /dev/kvm must be readable and writeable to use KVM with QEMU + if can_test_for_kvm and os.access('/dev/kvm', os.R_OK | os.W_OK): + host_arch = platform.machine() + + if host_arch == "aarch64": + if guest_arch in ('arm', 'arm32_v7'): + return arm64_have_el1_32() + return "arm64" in guest_arch + + if host_arch == "x86_64": + return "x86" in guest_arch + + # If we could not prove that we can use KVM safely, don't try return False