Skip to content

Commit ad66a0d

Browse files
committed
boot-qemu.sh: Support booting ARMv7 kernels under KVM on AArch64 hosts
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]>
1 parent 6cfa159 commit ad66a0d

File tree

4 files changed

+59
-1
lines changed

4 files changed

+59
-1
lines changed

boot-qemu.sh

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,19 @@ function setup_qemu_args() {
168168
-machine "virt${HIGHMEM}"
169169
-no-reboot
170170
)
171-
QEMU=(qemu-system-arm)
171+
# It is possible to boot ARMv7 kernels under KVM on AArch64 hosts,
172+
# if it is supported. ARMv7 KVM support was ripped out of the
173+
# kernel in 5.7 so we don't even bother checking.
174+
if [[ "$(uname -m)" = "aarch64" && -e /dev/kvm ]] && ${KVM} &&
175+
"${BASE}"/utils/aarch64_32_bit_el1_supported; then
176+
QEMU_ARCH_ARGS+=(
177+
-cpu "host,aarch64=off"
178+
-enable-kvm
179+
)
180+
QEMU=(qemu-system-aarch64)
181+
else
182+
QEMU=(qemu-system-arm)
183+
fi
172184
;;
173185

174186
arm64 | arm64be)

utils/Makefile

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
ifneq ($(shell uname -m),aarch64)
2+
CROSS_COMPILE = aarch64-linux-gnu-
3+
endif
4+
5+
CC = $(CROSS_COMPILE)gcc
6+
STRIP = $(CROSS_COMPILE)strip
7+
8+
aarch64_32_bit_el1_supported: aarch64_32_bit_el1_supported.c
9+
$(CC) -O2 -static -std=c17 -Wall -Wextra -Wpedantic -o $@ $^
10+
$(STRIP) -s $@
11+
12+
clean:
13+
rm -fr aarch64_32_bit_el1_supported
14+
15+
all: aarch64_32_bit_el1_supported

utils/aarch64_32_bit_el1_supported

510 KB
Binary file not shown.

utils/aarch64_32_bit_el1_supported.c

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
#include <errno.h> /* errno for perror() */
2+
#include <linux/kvm.h> /* KVM_CHECK_EXTENSION, KVM_CAP_ARM_EL1_32BIT */
3+
#include <fcntl.h> /* open() */
4+
#include <stdio.h> /* perror() */
5+
#include <sys/ioctl.h> /* ioctl() */
6+
#include <unistd.h> /* close() */
7+
8+
int main(void)
9+
{
10+
int fd, ret;
11+
12+
fd = open("/dev/kvm", O_RDWR);
13+
if (fd < 0) {
14+
perror("Failed to open /dev/kvm");
15+
return -errno;
16+
}
17+
18+
ret = ioctl(fd, KVM_CHECK_EXTENSION, KVM_CAP_ARM_EL1_32BIT);
19+
if (ret < 0) {
20+
perror("Error checking /dev/kvm for 32-bit EL1 support");
21+
ret = 0;
22+
}
23+
24+
close(fd);
25+
26+
/*
27+
* KVM_CHECK_EXTENSION returns 1 for supported, 0 for unsupported so
28+
* invert it to match typical success/fail codes in programs.
29+
*/
30+
return !ret;
31+
}

0 commit comments

Comments
 (0)