QEMU仿真ARM64

QEMU(Quick Emulator)是一个开源的虚拟机监控器和仿真器,它允许在不同的硬件平台上执行虚拟机。QEMU的灵活性和广泛的支持使其成为虚拟化、仿真和跨平台开发的有力工具。它通常用于开发和测试新的操作系统内核、应用程序移植、虚拟化研究,以及需要在不同硬件架构上运行代码的场景。

比起使用开发板学习Linux内核移植,使用QEMU是一个省钱、方便、还能提升工具技能的方法。本文介绍使用QEMU搭建ARM64最小系统过程。
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权限。

介绍一下这个脚本的实现和功能:

编译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的功能。

posted @ 2024-06-14 16:47  小满的博客  阅读(60)  评论(0编辑  收藏  举报