Table of contents
foreword
This article introduces the use of qemu to simulate the ARM-64bit development board ( there is another article for ARM-32bit ), and starts the ARM64 Linux kernel. The general idea is:
- Install the qemu-system-aarch64 (ARM-64bit) simulator;
- Install aarch64-linux-gnu (ARM-64bit) cross compiler;
- Cross-compile the linux source code to get the ARM64 Linux kernel image;
- Cross-compile busybox source code, use busybox to make initramfs;
- Finally, use qemu-system-aarch64 to enable the ARM64 Linux kernel;
My environment:
- Host hardware platform: x86_64
- Host operating system: Ubuntu 20.04 (Linux 5.4.0-139-generic)
- QEMU version: qemu-4.2.1
- Experimental kernel: linux-5.19
- busybox version: busybox-1.35.0
Pre-knowledge
virt development board
As of the time of this manuscript, QEMU has simulated more than 70 hardware development boards, please refer to Arm System emulator . But there are so few QEMU emulators for ARM-64bit that virt is the only choice. Virt supports PCI, virtio, newer ARM CPU, and large-capacity memory. Unfortunately, it does not support graphical interfaces. If you don't know what hardware development board to choose, choose virt.
For more detailed content, please refer to:
Why the “virt”board?
Installing Debian on QEMU’s 32-bit ARM “virt”board
Installing Debian on QEMU’s 64-bit ARM “virt”board
Introduction to ARM Processor Family
There are many families of ARM processors, which are 32bit and which are 64bit, please refer to:
List_of_ARM_processors
Many manufacturers use ARM cores to design SOC chips. There are many listed here. You can refer to:
List_of_products_using_ARM_processors
Install qemu-system-aarch64
Install:
$ sudo apt install qemu-system-arm
The qemu-system-arm version of ARM-32bit and the qemu-system-aarch64 version of ARM-64bit will be installed at the same time, check the version number:
$ qemu-system-aarch64 --version
QEMU emulator version 4.2.1 (Debian 1:4.2-3ubuntu6.24)
Copyright (c) 2003-2019 Fabrice Bellard and the QEMU Project developers
Check the ARM kernel development board supported by qemu. This article chooses the virt development board:
$ qemu-system-aarch64 -M help
Supported machines are:
akita Sharp SL-C1000 (Akita) PDA (PXA270)
ast2500-evb Aspeed AST2500 EVB (ARM1176)
ast2600-evb Aspeed AST2600 EVB (Cortex A7)
borzoi Sharp SL-C3100 (Borzoi) PDA (PXA270)
canon-a1100 Canon PowerShot A1100 IS
cheetah Palm Tungsten|E aka. Cheetah PDA (OMAP310)
collie Sharp SL-5500 (Collie) PDA (SA-1110)
connex Gumstix Connex (PXA255)
cubieboard cubietech cubieboard (Cortex-A8)
emcraft-sf2 SmartFusion2 SOM kit from Emcraft (M2S010)
highbank Calxeda Highbank (ECX-1000)
imx25-pdk ARM i.MX25 PDK board (ARM926)
integratorcp ARM Integrator/CP (ARM926EJ-S)
kzm ARM KZM Emulation Baseboard (ARM1136)
lm3s6965evb Stellaris LM3S6965EVB
lm3s811evb Stellaris LM3S811EVB
mainstone Mainstone II (PXA27x)
mcimx6ul-evk Freescale i.MX6UL Evaluation Kit (Cortex A7)
mcimx7d-sabre Freescale i.MX7 DUAL SABRE (Cortex A7)
microbit BBC micro:bit
midway Calxeda Midway (ECX-2000)
mps2-an385 ARM MPS2 with AN385 FPGA image for Cortex-M3
mps2-an505 ARM MPS2 with AN505 FPGA image for Cortex-M33
mps2-an511 ARM MPS2 with AN511 DesignStart FPGA image for Cortex-M3
mps2-an521 ARM MPS2 with AN521 FPGA image for dual Cortex-M33
musca-a ARM Musca-A board (dual Cortex-M33)
musca-b1 ARM Musca-B1 board (dual Cortex-M33)
musicpal Marvell 88w8618 / MusicPal (ARM926EJ-S)
n800 Nokia N800 tablet aka. RX-34 (OMAP2420)
n810 Nokia N810 tablet aka. RX-44 (OMAP2420)
netduino2 Netduino 2 Machine
none empty machine
nuri Samsung NURI board (Exynos4210)
palmetto-bmc OpenPOWER Palmetto BMC (ARM926EJ-S)
raspi2 Raspberry Pi 2
raspi3 Raspberry Pi 3
realview-eb ARM RealView Emulation Baseboard (ARM926EJ-S)
realview-eb-mpcore ARM RealView Emulation Baseboard (ARM11MPCore)
realview-pb-a8 ARM RealView Platform Baseboard for Cortex-A8
realview-pbx-a9 ARM RealView Platform Baseboard Explore for Cortex-A9
romulus-bmc OpenPOWER Romulus BMC (ARM1176)
sabrelite Freescale i.MX6 Quad SABRE Lite Board (Cortex A9)
sbsa-ref QEMU 'SBSA Reference' ARM Virtual Machine
smdkc210 Samsung SMDKC210 board (Exynos4210)
spitz Sharp SL-C3000 (Spitz) PDA (PXA270)
swift-bmc OpenPOWER Swift BMC (ARM1176)
sx1 Siemens SX1 (OMAP310) V2
sx1-v1 Siemens SX1 (OMAP310) V1
terrier Sharp SL-C3200 (Terrier) PDA (PXA270)
tosa Sharp SL-6000 (Tosa) PDA (PXA255)
verdex Gumstix Verdex (PXA270)
versatileab ARM Versatile/AB (ARM926EJ-S)
versatilepb ARM Versatile/PB (ARM926EJ-S)
vexpress-a15 ARM Versatile Express for Cortex-A15
vexpress-a9 ARM Versatile Express for Cortex-A9
virt-2.10 QEMU 2.10 ARM Virtual Machine
virt-2.11 QEMU 2.11 ARM Virtual Machine
virt-2.12 QEMU 2.12 ARM Virtual Machine
virt-2.6 QEMU 2.6 ARM Virtual Machine
virt-2.7 QEMU 2.7 ARM Virtual Machine
virt-2.8 QEMU 2.8 ARM Virtual Machine
virt-2.9 QEMU 2.9 ARM Virtual Machine
virt-3.0 QEMU 3.0 ARM Virtual Machine
virt-3.1 QEMU 3.1 ARM Virtual Machine
virt-4.0 QEMU 4.0 ARM Virtual Machine
virt-4.1 QEMU 4.1 ARM Virtual Machine
virt QEMU 4.2 ARM Virtual Machine (alias of virt-4.2)
virt-4.2 QEMU 4.2 ARM Virtual Machine
witherspoon-bmc OpenPOWER Witherspoon BMC (ARM1176)
xilinx-zynq-a9 Xilinx Zynq Platform Baseboard for Cortex-A9
xlnx-versal-virt Xilinx Versal Virtual development board
xlnx-zcu102 Xilinx ZynqMP ZCU102 board with 4xA53s and 2xR5Fs based on the value of smp
z2 Zipit Z2 (PXA27x)
Look at the list of CPUs supported by the virt development board. This article takes the 64-bit cortex-a57 as an example:
$ qemu-system-aarch64 -M virt --cpu help
Available CPUs:
arm1026
arm1136
arm1136-r2
arm1176
arm11mpcore
arm926
arm946
cortex-a15
cortex-a53
cortex-a57
cortex-a7
cortex-a72
cortex-a8
cortex-a9
cortex-m0
cortex-m3
cortex-m33
cortex-m4
cortex-r5
cortex-r5f
max
pxa250
pxa255
pxa260
pxa261
pxa262
pxa270-a0
pxa270-a1
pxa270
pxa270-b0
pxa270-b1
pxa270-c0
pxa270-c5
sa1100
sa1110
ti925t
Install cross-compilation tools
We are developing under the X86 platform, the target platform is the arm architecture, and the cross-compilation tool chain needs to be installed. The cross compilers for arm-linux mainly include:
- arm-linux-gnueabi and arm-linux-gnueabihf for ARM-32bit.
- aarch64-linux-gnu for ARM-64bit.
For the differences between the versions of the cross compiler, please refer to " The Differences Between the Versions of the Arm Series Cross Compilers ".
Install the aarch64-linux-gnu version of ARM-64bit:
$ sudo apt install gcc-aarch64-linux-gnu
View version:
$ aarch64-linux-gnu-gcc --version
aarch64-linux-gnu-gcc (Ubuntu 9.4.0-1ubuntu1~20.04.1) 9.4.0
Copyright (C) 2019 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
Cross compile ARM64 Linux kernel
Download the source code:
$ mkdir ~/kvm-arm
$ cd ~/kvm-arm/
$ wget https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/snapshot/linux-5.19.tar.gz
$ tar -xf linux-5.19.tar.gz
$ cd linux-5.19/
$ make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- O=build defconfig
$ make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- O=build -j8
illustrate:
- ARCH: Specify the target CPU architecture;
- CROSS_COMPILE: Specify a cross compiler;
- O=build: O is the abbreviation of Out, which means that the compiled output files are placed in the build directory, not mixed with the source code, and the source code is kept clean.
- Only defconfig configuration is optional during make, because there is one and only defconfig in the linux-5.19/arch/arm64/configs/ directory.
Check the original kernel file vmlinux compiled by the kernel, which is the ARM 64-bit version.
$ file build/vmlinux
build/vmlinux: ELF 64-bit LSB shared object, ARM aarch64, version 1 (SYSV), statically linked, BuildID[sha1]=f2a5fd51bd2d59f90b7b26b8926f5afdeab60f36, not stripped
vmlinux cannot directly boot the Linux system. It can boot the Linux system from the Image file (uncompressed version) or Image.gz (compressed version). The kernel image used below is Image:
$ file build/arch/arm64/boot/Image
build/arch/arm64/boot/Image: MS-DOS executable PE32+ executable (EFI application) Aarch64 (stripped to external PDB), for MS Windows
$ file build/arch/arm64/boot/Image.gz
build/arch/arm64/boot/Image.gz: gzip compressed data, max compression, from Unix, original size modulo 2^32 36112896
Cross compile ARM64 Busybox
$ mkdir ~/kvm-arm
$ cd ~/kvm-arm/
$ wget https://busybox.net/downloads/busybox-1.35.0.tar.bz2
$ tar -xf busybox-1.35.0.tar.bz2
$ cd busybox-1.35.0/
$ export ARCH=arm64
$ export CROSS_COMPILE=aarch64-linux-gnu-
$ make menuconfig
# 修改配置,选中如下项目,静态编译
# Settings –> Build Options –> [*] Build static binary(no share libs)
# 反选如下项目,否则后续qemu执行会提示 /bin/sh:can't access tty;job control turned off
# Shells ---> [ ] Job control
$ make -j `nproc`
$ make install
After installation, it will be installed to the _install/ directory of the source code directory by default:
$ ls _install/
bin linuxrc sbin usr
The most important thing is _install/bin/busybox, the others are link files.
$ file _install/bin/busybox
_install/bin/busybox: ELF 64-bit LSB executable, ARM aarch64, version 1 (GNU/Linux), statically linked, BuildID[sha1]=3768162c347859f16ab4f0b01a48fb8c0502774d, for GNU/Linux 3.7.0, stripped
If the following prompts appear during compilation, ignore them:
Trying libraries: m resolv rt
Library m is needed, can't exclude it (yet)
Library resolv is needed, can't exclude it (yet)
Library rt is not needed, excluding it
Library m is needed, can't exclude it (yet)
Library resolv is needed, can't exclude it (yet)
Final link with: m resolv
Use busybox to make initramfs
Use busybox to quickly make initramfs.
Create the inti startup script in the virtual rootfs and give it executable permissions:
$ cd ~/kvm-arm/busybox-1.35.0/_install/
$ mkdir proc sys dev tmp
$ touch init
$ chmod +x init
Script content:
#!/bin/sh
# 挂载一些必要的文件系统
mount -t proc none /proc
mount -t sysfs none /sys
mount -t tmpfs none /tmp
mount -t devtmpfs none /dev
echo
echo "Hello 64-bit ARM Linux"
# 显示开机消耗时间
echo "This boot took $(cut -d' ' -f1 /proc/uptime) seconds"
echo
# 停留在控制台
exec /bin/sh
Make the initramfs file, which is a file packaged by cpio and compressed by gzip. It is a memory file system in cpio format.
$ find . -print0 | cpio --null -ov --format=newc | gzip -9 > ../initramfs.cpio.gz
Boot ARM64 Linux Kernel Using QEMU
ARM Linux kernel image and initramfs are ready, you can use QEMU to start the linux kernel.
Start QEMU in the character interface mode, and log output to the console at the same time:
$ qemu-system-aarch64 \
-M virt \
-cpu cortex-a57 \
-smp 8 \
-m 8G \
-kernel ./linux-5.19/build/arch/arm64/boot/Image \
-initrd ./busybox-1.35.0/initramfs.cpio.gz \
-nographic \
-append "init=/init console=ttyAMA0"
QEMU parameter description (for more, please refer to: Standard options ):
- -M: Specifies the simulated development board, which can be viewed through qemu-system-aarch64 M help. As of the time of writing, only virt supports 64-bit ARM.
- -cpu: Specify the simulated cpu, which can be viewed through qemu-system-aarch64 -M virt --cpu help, here select cortex-a57.
- -smp: Specify the number of cpu cores, you can use the nproc command to check after startup.
- -m: Specify the memory size, virt can support large memory, you can use the free -h command to check after startup.
- -kernel: Specifies the kernel image to start;
- -initrd: Specify the memory file system to start;
- -append: The startup parameters passed to the kernel; you can use the cat /proc/cmdline command to check after startup.
- -nographic: start the character interface (do not start the graphical interface), redirect the output to the host command line, and use it in combination with the parameter console=ttyAMA0;
9 Reference