QEMU仿真ARM64
QEMU(Quick Emulator)是一个开源的虚拟机监控器和仿真器,它允许在不同的硬件平台上执行虚拟机。QEMU的灵活性和广泛的支持使其成为虚拟化、仿真和跨平台开发的有力工具。它通常用于开发和测试新的操作系统内核、应用程序移植、虚拟化研究,以及需要在不同硬件架构上运行代码的场景。
比起使用开发板学习Linux内核移植,使用QEMU是一个省钱、方便、还能提升工具技能的方法。本文介绍使用QEMU搭建ARM64最小系统过程。
环境准备
宿主机:Ubuntu 22.04 (推荐不低于Ubuntu 20.04)
软件 | 版本 | 官网 |
---|---|---|
Linux Kernel | 6.0.9 | https://kernel.org |
BusyBox | 1.35.0 | https://busybox.net |
QEMU | 7.2.0-rc1 | https://www.qemu.org |
新建工作区,后续所有的源码都放在这个目录
mkdir source
交叉编译
安装gcc
sudo apt-get install gcc
sudo apt-get install g++
安装ARM64交叉编译工具
sudo apt-get install gcc-aarch64-linux-gnu
sudo apt-get install g++-aarch64-linux-gnu
交叉编译 Linux Kernel
获取内核代码并解压
wget https://cdn.kernel.org/pub/linux/kernel/v6.x/linux-6.0.9.tar.xz
tar xvf linux-6.0.9.tar.xz
配置.config
make CROSS_COMPILE=aarch64-linux-gnu- ARCH=arm64 O=build menuconfig -j16
如果有报错,大概率是缺少工具,按照报错提示安装对应工具即可。
选中RAM disk支持,注意一定要变成星号,并且将大小调整为64M:
Device Drivers > Block devices
<*> RAM block device support
(16) Default number of RAM disks (NEW)
(65536) Default RAM disk size (kbytes)
这里卖个关子,initrd和initramfs有什么区别?分别该怎么支持?
保存后,开始编译:
make CROSS_COMPILE=aarch64-linux-gnu- ARCH=arm64 O=build INSTALL_PATH=build/arch/$ARCH/boot -j16
file build/arch/arm64/boot/Image
编译过程中也可能因为缺少工具报错,安装即可。
本人AMD 6800H大概4min完成编译,AMD YES。
交叉编译 BusyBox
获取代码并解压
wget https://busybox.net/downloads/busybox-1.35.0.tar.bz2
tar xvf busybox-1.35.0.tar.bz2
配置.config
make CROSS_COMPILE=aarch64-linux-gnu- ARCH=arm64 menuconfig -j16
选中静态链接
Settings
[*] Build static binary (no shared libs)
执行编译
make CROSS_COMPILE=aarch64-linux-gnu- ARCH=arm64 install -j16
file _install/bin/busybox
制作根文件系统
两大编译完成后,还缺少根文件系统,在内核编译我们选择的是initrd方式的RamDisk,编写脚本自动化执行
#!/bin/bash
MOUNT_DIR=mnt
CURR_DIR=`pwd`
rm initrd.ext4
dd if=/dev/zero of=initrd.ext4 bs=1M count=64
mkfs.ext4 initrd.ext4
mkdir -p $MOUNT_DIR
mount initrd.ext4 $MOUNT_DIR
cp -arf busybox-1.35.0/_install/* $MOUNT_DIR
cd $MOUNT_DIR
mkdir -p etc dev mnt proc sys tmp mnt etc/init.d/
echo "proc /proc proc defaults 0 0" > etc/fstab
echo "tmpfs /tmp tmpfs defaults 0 0" >> etc/fstab
echo "sysfs /sys sysfs defaults 0 0" >> etc/fstab
echo "#!/bin/sh" > etc/init.d/rcS
echo "mount -a" >> etc/init.d/rcS
echo "mount -o remount,rw /" >> etc/init.d/rcS
echo "echo -e \"Welcome to ARM64 Linux\"" >> etc/init.d/rcS
chmod 755 etc/init.d/rcS
echo "::sysinit:/etc/init.d/rcS" > etc/inittab
echo "::respawn:-/bin/sh" >> etc/inittab
echo "::askfirst:-/bin/sh" >> etc/inittab
chmod 755 etc/inittab
cd dev
mknod console c 5 1
mknod null c 1 3
mknod tty1 c 4 1
cd $CURR_DIR
umount $MOUNT_DIR
echo "make initrd ok!"
保存后添加执行权限,执行时需要使用sudo权限。
介绍一下这个脚本的实现和功能:
- 使用 dd 和 initrd.ext4 制作一个空的64M的ext4格式的文件系统;
- mount这个文件系统,然后拷贝busybox编译的文件进去;
- 创建Linux的关键的标准层级目录 Filesystem Hierarchy Standard (FHS)
- 创建 /etc/fstab,这是mount自动挂载配置文件,可参考:mount命令及/etc/fstab文件详解
- 创建 /etc/init.d/rcS,这是文件系统的初始化脚本
- 创建 /etc/inittab,init进程会解析inittab文件
- 关于rcS和inittab可以参考嵌入式系统开发——文件系统中inittab文件、rcS文件、fstab文件、profile文件详解
编译QEMU
获取源码
wget https://download.qemu.org/qemu-7.2.0-rc1.tar.xz
tar xvf qemu-7.2.0-rc1.tar.xz
编译ARM64架构的QEMU
cd qemu-7.2.0-rc1
mkdir build
cd build
../configure --target-list=aarch64-softmmu
make -j16
file aarch64-softmmu/qemu-system-aarch64
编译过程可能会提示错误,按照提示安装相应依赖即可
这里提一下各个架构名称的联系和区别 arm vs AArch64 vs amd64 vs x86_64 vs x86:有什么区别? | Linux 中国 - 知乎 (zhihu.com)
查看QEMU支持的machine和cpu方法如下:
cd qemu-7.2.0-rc1/build/aarch64-softmmu
./qemu-system-aarch64 -M help # 查看支持的machine
./qemu-system-aarch64 -cpu help # 查看支持的CPU
可以看到支持包括ast-2600在内不少芯片
启动QEMU
前面的准备工作完成后,既可以启动虚拟机,编写脚本:
我们是ARM64位程序,选择cortex-a57架构
#!/bin/bash
source/qemu-7.2.0-rc1/build/aarch64-softmmu/qemu-system-aarch64 \
-nographic \
-M virt \
-cpu cortex-a57 \
-smp 2 \
-m 1G \
-kernel source/linux-6.0.9/build/arch/arm64/boot/Image \
-append "nokaslr root=/dev/ram init=/linuxrc console=ttyAMA0 console=ttyS0" \
-initrd source/initrd.ext4
运行后就可以看到正常启动进入console了
说明:上面append选项用来给内核传递命令行参数,nokaslr
表示关闭地址随机化,方便gdb调试内核。
QEMU官方文档:
Welcome to QEMU’s documentation! — QEMU documentation
停止qemu可以
ps -aux | grep qem
kill -9 PID
总结
以上介绍了最简单的QEMU使用,因为我们直接启动的内核还不涉及uboot,也没有虚拟化flash等周边资源,只是简单的基础框架搭建。后续计划添加Flash/Net等周边资源,使其更像一个完整的嵌入式开发系统,充分发挥QEMU的功能。