目录
1 引言
本章节中使用qemu的原因是:我们构建的rootfs,需要有平台验证,而qemu是一个非常好的模拟器。
2 qemu简介
qemu”是一个广泛使用的开源计算机模拟器和虚拟机。"
当作为模拟器时,可以在一种架构(如x86 PC)下运行另一种架构(如ARM)下的操作系统和程序。通过使用动态转换,它可以获得非常好的性能。
作为虚拟机时,QEMU可以使用其他虚拟机管理程序(如 Xen 或 KVM)来使用CPU扩展(HVM)进行虚拟化,通过在主机CPU上直接执行客户机代码来获得接近于宿主机的性能。
3 工具安装
ubuntu20.04源提供相对比较高的QEMU版本,可以选择命令行直接安装。
sudo apt-get install qemu qemu-system qemu-user
安装完成后,可以通过Tab键补全检查安装好的qemu 工具:"qemu-system-"
root@test:# qemu-
qemu-img qemu-system-cris qemu-system-mips64 qemu-system-ppc64le qemu-system-tricore
qemu-io qemu-system-hppa qemu-system-mips64el qemu-system-riscv32 qemu-system-unicore32
qemu-make-debian-root qemu-system-i386 qemu-system-mipsel qemu-system-riscv64 qemu-system-x86_64
qemu-nbd qemu-system-lm32 qemu-system-moxie qemu-system-s390x qemu-system-xtensa
qemu-pr-helper qemu-system-m68k qemu-system-nios2 qemu-system-sh4 qemu-system-xtensaeb
qemu-system-aarch64 qemu-system-microblaze qemu-system-or1k qemu-system-sh4eb
qemu-system-alpha qemu-system-microblazeel qemu-system-ppc qemu-system-sparc
qemu-system-arm qemu-system-mips qemu-system-ppc64 qemu-system-sparc64
qemu-system-arm用来模拟 32 位的 Arm cpu,比如 Arm9 /Arm11、 Cortex-A7/A9/A15 。
qemu-system-aarch64来模拟 64 位的 Arm cpu,比如 Arm Cortex A53,A57。
4 环境准备
4.1 cross-toochain安装
安装32位编译器,用于编译32位的kernel,u-boot。
sudo apt-get install gcc-arm-linux-gnueabi
安装64位编译器,用于编译64位的kernel,u-boot。
sudo apt-get install gcc-aarch64-linux-gnu
4.2 kernel编译
github上拉去太慢,使用如下地址,通过wget来获取。
https://mirror.bjtu.edu.cn/kernel/linux/kernel/v5.x/
wget https://mirror.bjtu.edu.cn/kernel/linux/kernel/v5.x/linux-5.10.tar.xz
4.2.1 编译32位kernel
这里我们使用 vexpress-a9 这款开发板。vexpress-a9 是 Arm 公司自己设计的一款 4 核 Cortex-A9 开发板,U-Boot、Linux Kernel 和 QEMU 对这款开发板都做了完整的支持。当然,如果想搭其它开发板,也不难,只要qemu和内核对它有成熟的支持就够了。
生成vexpress开发板子的config文件:
make CROSS_COMPILE=arm-linux-gnueabihf- ARCH=arm vexpress_defconfig
编译内核:
make CROSS_COMPILE=arm-linux-gnueabihf- ARCH=arm
生成的内核镱像位于arch/arm/boot/zImage.。
4.2.2 编译64位kernel
编译命令:
make ARCH=arm64 defconfig CROSS_COMPILE=aarch64-linux-gnu-
# 如果需要调整配置选项,则使用menuconfig
make ARCH=arm64 menuconfig CROSS_COMPILE=aarch64-linux-gnu-
make ARCH=arm64 Image -j8 CROSS_COMPILE=aarch64-linux-gnu-
生成的内核镱像位于arch/arm64/boot/Image.。
4.3 u-boot编译
4.3.1 使用32位工具
github上拉去太慢,使用如下地址,通过wget来获取。
https://ftp.denx.de/pub/u-boot/
wget https://ftp.denx.de/pub/u-boot/u-boot-2020.10.tar.bz2
下载完后,可以看到 configs 目录下有针对这款开发板的配置文件。ca9x4表示cortexA9架构,4核心。
vexpress_ca9x4_defconfig
编译:
make vexpress_ca9x4_defconfig
make CROSS_COMPILE=arm-linux-gnueabihf- all
最终编译生成 elf 格式的可执行文件 u-boot 和纯二进制文件u-boot.bin,其中 QEMU 可以启动的为 elf 格式的可执行文件 u-boot 。
4.3.2 使用64位工具
4.4 rootfs构建
5 仿真运行
5.1 u-boot加载kernel
5.1.1 单独启动u-boot
sudo qemu-system-arm -M vexpress-a9 -m 512M -kernel where_is_directory/u-boot -nographic
5.1.2 单独启动kernel
qemu-system-arm -M vexpress-a9 -m 512M -kernel /kernel_direcotry/arch/arm/boot/zImage -dtb /kernel_direcotry/arch/arm/boot/dts/vexpress-v2p-ca9.dtb -nographic -append "console=ttyAMA0"
qemu命令的参数:
-M vexpress-a9 模拟vexpress-a9单板。
-m 512M 单板运行物理内存512M
-kernel /path/to/kernel/dir/arch/arm/boot/zImage 告诉qemu单板运行内核镜像路径
-nographic 不使用图形化界面,只使用串口
-append "console=ttyAMA0" 内核启动参数,这里告诉内核vexpress单板运行,串口设备是那个tty。
5.1.3 u-boot加载kernel
1)QEMU 可以模拟 sd 卡等外设。我们就把编译好的固件放在一个模块的 sdcard 上,让 QEMU 从这张模拟的 sd 卡上启动 Linux 系统:
制作 sd 卡镜像,并将它格式化成 fat 格式:
dd if=/dev/zero of=sd.img bs=4096 count=4096
mkfs.ext4 sd.img
把编译好的 kernel zImage 和 dtb 文件拷贝到 sd.img 中:
sudo mount sd.img mnt/ -o loop,rw
sudo cp kernel_directory/arch/arm/boot/zImage /mnt/
sudo cp kernel_directory/arch/arm/boot/dts/vexpress-v2p-ca9.dtb /mnt/
sudo umount /mnt
2)启动 QEMU
sudo qemu-system-arm -M vexpress-a9 -m 512M -kernel uboot_directory/u-boot -nographic -sd sd.img
-kernel 指定 QEMU 启动时首先执行的程序,我们这里指定为前面编译好的 u-boot 可以执行文件,通过u-boot去加载kernel。
上图所示u-boot 已经顺利启动并进入命令行模式,下面我们来启动 Linux Kernel
3)首先通过 ext4load 命令把 sd.img 里面的 zImage 和 dtb 文件读到开发板的内存中:
ext4load mmc 0:0 0x60008000 zImage
ext4load mmc 0:0 0x62008000 vexpress-v2p-ca9.dtb
注意:如果失败,请重复几次。
4)通过 bootz 命令启动 Linux Kernel:
bootz 0x60008000 - 0x62008000
注意事项: 0x60008000 0x62008000是怎么确认的这个地址?
1. 通过 “textofs” 查看Linux kernel zImage 执行地址对应的内存偏移地址,为:0x00008000
root@test:/home/work/qemu_test/linux-5.10# grep -nr "textofs" ./
./arch/arm/Makefile:141:textofs-y := 0x00008000
./arch/arm/Makefile:143:textofs-$(CONFIG_PM_H1940) := 0x00108000
./arch/arm/Makefile:145:textofs-$(CONFIG_ARCH_REALTEK) := 0x00108000
./arch/arm/Makefile:148:textofs-$(CONFIG_SA1111) := 0x00208000
2. u-boot 命令行中输入bdinfo命令,可以查到这块开发板内存的起始地址。
=> bdinfo
boot_params = 0x60002000
DRAM bank = 0x00000000
-> start = 0x60000000
-> size = 0x20000000
从上图中可以看到这块开发板的内存实际地址为 0x60000000,所以对应内核的起始地址为:0x60008000。dtb 的加载地址没有特别的要求,一般注意和 Linux Kernel Image 避开,不要重叠即可;
5.2 kernel加载rootfs
注意事项
1)你可以使用-M ?参数来获取该qemu版本支持的所有单板
root@test:/home/work/qemu_test# qemu-system-arm -M ?
Supported machines are:
akita Sharp SL-C1000 (Akita) PDA (PXA270)
ast2500-evb Aspeed AST2500 EVB (ARM1176)
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
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)
midway Calxeda Midway (ECX-2000)
mps2-an385 ARM MPS2 with AN385 FPGA image for Cortex-M3
mps2-an511 ARM MPS2 with AN511 DesignStart FPGA image for Cortex-M3
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
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)
smdkc210 Samsung SMDKC210 board (Exynos4210)
spitz Sharp SL-C3000 (Spitz) PDA (PXA270)
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 QEMU 2.11 ARM Virtual Machine (alias of virt-2.11)
virt-2.11 QEMU 2.11 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
xilinx-zynq-a9 Xilinx Zynq Platform Baseboard for Cortex-A9
z2 Zipit Z2 (PXA27x)
2)可以通过参数 -machine help
来查看QEMU支持的设备模块
root@test:/home/work/qemu_test# qemu-system-arm -machine help
Supported machines are:
akita Sharp SL-C1000 (Akita) PDA (PXA270)
ast2500-evb Aspeed AST2500 EVB (ARM1176)
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
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)
midway Calxeda Midway (ECX-2000)
mps2-an385 ARM MPS2 with AN385 FPGA image for Cortex-M3
mps2-an511 ARM MPS2 with AN511 DesignStart FPGA image for Cortex-M3
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
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)
smdkc210 Samsung SMDKC210 board (Exynos4210)
spitz Sharp SL-C3000 (Spitz) PDA (PXA270)
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 QEMU 2.11 ARM Virtual Machine (alias of virt-2.11)
virt-2.11 QEMU 2.11 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
xilinx-zynq-a9 Xilinx Zynq Platform Baseboard for Cortex-A9
z2 Zipit Z2 (PXA27x)
3)退出qemu的状态
先按一下:ctrl+A,然后再按X
参考
https://wiki.archlinux.org/title/QEMU_(%E7%AE%80%E4%BD%93%E4%B8%AD%E6%96%87)