diff --git a/boot-qemu.sh b/boot-qemu.sh index f281648..77ceca4 100755 --- a/boot-qemu.sh +++ b/boot-qemu.sh @@ -168,7 +168,19 @@ function setup_qemu_args() { -machine "virt${HIGHMEM}" -no-reboot ) - QEMU=(qemu-system-arm) + # It is possible to boot ARMv7 kernels under KVM on AArch64 hosts, + # if it is supported. ARMv7 KVM support was ripped out of the + # kernel in 5.7 so we don't even bother checking. + if [[ "$(uname -m)" = "aarch64" && -e /dev/kvm ]] && ${KVM} && + "${BASE}"/utils/aarch64_32_bit_el1_supported; then + QEMU_ARCH_ARGS+=( + -cpu "host,aarch64=off" + -enable-kvm + ) + QEMU=(qemu-system-aarch64) + else + QEMU=(qemu-system-arm) + fi ;; arm64 | arm64be) diff --git a/utils/Makefile b/utils/Makefile new file mode 100644 index 0000000..888beb4 --- /dev/null +++ b/utils/Makefile @@ -0,0 +1,15 @@ +ifneq ($(shell uname -m),aarch64) +CROSS_COMPILE = aarch64-linux-gnu- +endif + +CC = $(CROSS_COMPILE)gcc +STRIP = $(CROSS_COMPILE)strip + +aarch64_32_bit_el1_supported: aarch64_32_bit_el1_supported.c + $(CC) -O2 -static -std=c17 -Wall -Wextra -Wpedantic -o $@ $^ + $(STRIP) -s $@ + +clean: + rm -fr aarch64_32_bit_el1_supported + +all: aarch64_32_bit_el1_supported diff --git a/utils/aarch64_32_bit_el1_supported b/utils/aarch64_32_bit_el1_supported new file mode 100755 index 0000000..f3bc160 Binary files /dev/null and b/utils/aarch64_32_bit_el1_supported differ diff --git a/utils/aarch64_32_bit_el1_supported.c b/utils/aarch64_32_bit_el1_supported.c new file mode 100644 index 0000000..60ea49e --- /dev/null +++ b/utils/aarch64_32_bit_el1_supported.c @@ -0,0 +1,31 @@ +#include /* errno for perror() */ +#include /* KVM_CHECK_EXTENSION, KVM_CAP_ARM_EL1_32BIT */ +#include /* open() */ +#include /* perror() */ +#include /* ioctl() */ +#include /* close() */ + +int main(void) +{ + int fd, ret; + + fd = open("/dev/kvm", O_RDWR); + if (fd < 0) { + perror("Failed to open /dev/kvm"); + return -errno; + } + + ret = ioctl(fd, KVM_CHECK_EXTENSION, KVM_CAP_ARM_EL1_32BIT); + if (ret < 0) { + perror("Error checking /dev/kvm for 32-bit EL1 support"); + ret = 0; + } + + close(fd); + + /* + * KVM_CHECK_EXTENSION returns 1 for supported, 0 for unsupported so + * invert it to match typical success/fail codes in programs. + */ + return !ret; +}