Skip to content

Commit

Permalink
boot-qemu.sh: Support booting ARMv7 kernels under KVM on AArch64 hosts
Browse files Browse the repository at this point in the history
It is possible to use KVM on AArch64 hosts to boot ARMv7 kernels, which
can result in a significant amount of speed up. On a Raspberry Pi 4:

Benchmark 1: boot-qemu.sh
  Time (mean ± σ):      3.879 s ±  0.041 s    [User: 1.389 s, System: 0.405 s]
  Range (min … max):    3.839 s …  3.982 s    20 runs

Benchmark 2: boot-qemu.sh --no-kvm
  Time (mean ± σ):     17.997 s ±  0.091 s    [User: 15.614 s, System: 0.422 s]
  Range (min … max):   17.850 s … 18.200 s    20 runs

Summary
  'boot-qemu.sh' ran
    4.64 ± 0.05 times faster than 'boot-qemu.sh --no-kvm'

However, the host must support 32-bit EL1, which is not always true so
we need to add a small C program to check for it before using
'aarch64=off' + '-enable-kvm'. This has no detectable overhead on a
system that does not support it.

Benchmark 1: boot-qemu.sh (with check)
  Time (mean ± σ):      6.148 s ±  0.027 s    [User: 3.944 s, System: 0.219 s]
  Range (min … max):    6.098 s …  6.193 s    20 runs

Benchmark 2: boot-qemu.sh (without check)
  Time (mean ± σ):      6.137 s ±  0.029 s    [User: 3.981 s, System: 0.170 s]
  Range (min … max):    6.079 s …  6.208 s    20 runs

Summary
  'boot-utils-ro' ran
    1.00 ± 0.01 times faster than 'boot-utils'

Link: https://fedoraproject.org/wiki/Architectures/AArch64/Booting_a_32-Bit_QEMU_image
Signed-off-by: Nathan Chancellor <[email protected]>
  • Loading branch information
nathanchance committed Jan 13, 2022
1 parent 6cfa159 commit ad66a0d
Show file tree
Hide file tree
Showing 4 changed files with 59 additions and 1 deletion.
14 changes: 13 additions & 1 deletion boot-qemu.sh
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
15 changes: 15 additions & 0 deletions utils/Makefile
Original file line number Diff line number Diff line change
@@ -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
Binary file added utils/aarch64_32_bit_el1_supported
Binary file not shown.
31 changes: 31 additions & 0 deletions utils/aarch64_32_bit_el1_supported.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
#include <errno.h> /* errno for perror() */
#include <linux/kvm.h> /* KVM_CHECK_EXTENSION, KVM_CAP_ARM_EL1_32BIT */
#include <fcntl.h> /* open() */
#include <stdio.h> /* perror() */
#include <sys/ioctl.h> /* ioctl() */
#include <unistd.h> /* 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;
}

0 comments on commit ad66a0d

Please sign in to comment.