大约在今年五六月份(kernel 5.7),arm kernel社区的maintainer Marc Zyngier移除了对arm32 kvm的支持,也就是在kernel 5.7
以后不能在arm32的host上创建kvm虚拟机。但是在arm64的host上还是可以创建arm32 kvm虚拟机的,本文就介绍一下如何在arm64的host上创建arm32虚机。
arm64的host最容易获得的是树莓派,最好在树莓派4上安装64位的ubuntu。本文以树莓派4-ubuntui系统为例。
创建虚机需要的原料:kernel,initrd,rootfs,命令行参数,前三个可以从ubuntu提供的arm32镜像中获得。
这是一个硬盘的完整镜像,也许可以直接用它来创建虚机,但是我还不会,我这里只介绍使用-kernel的方式启动虚机。首先就是从这个镜像里面取出,kernel和initrd。这个方法可能不止一种,我有一种比较可靠的方法,就是比较麻烦。将这个镜像作为非启动盘挂在一个可以启动的arm64的虚机里面,利用9p文件系统将kernel和initrd取出来。如果你要自己编译kernel,把他的config也取出来。arm64的虚拟机启动方法可以看这个链接:https://blog.csdn.net/wujianyongw4/article/details/90289208,挂载9p文件系统再加上
-fsdev local,security_model=passthrough,id=fsdev0,path=/tmp/share -device virtio-9p-pci,id=fs0,fsdev=fsdev0,mount_tag=hostshare
再看看:https://www.linux-kvm.org/page/9p_virtio怎么用。
外挂arm32 image参照原硬盘的挂载方式即可。根据我的经验需要将非启动盘的命令写在启动盘命令之上。
进入arm64vm之后mount 9p,lsblk查看arm32镜像,再将arm32的镜像mount起来,从其中的boot目录下找到kernel和initrd,最好将config也取出来备用。,然后复制到9p的目录下,这时从host的9p挂载目录下就可以得到所有的东西了。
假设你已经把kernel,initrd取出来了,启动命令行如下:
qemu-system-aarch64 \
-cpu host,aarch64=off -smp 1 \
-M virt,kernel_irqchip=on,accel=kvm,gic-version=host \
-nographic \
-m 1024M,maxmem=4096M,slots=2 \
-monitor unix:qemu-monitor-socket,server,nowait \
-drive if=none,file=bionic-server-cloudimg-armhf.img,id=hd1 \
-device virtio-blk-device,drive=hd1 \
-netdev user,id=user0 -device virtio-net-device,netdev=user0 \
-fsdev local,security_model=passthrough,id=fsdev0,path=9pshare \
-device virtio-9p-pci,id=fs0,fsdev=fsdev0,mount_tag=hostshare \
-append "root=/dev/vda1 earlycon console=ttyAMA0 loglevel=8" \
-nodefaults -serial mon:stdio \
-kernel vmlinuz-4.15.0-115-generic-lpae \
-initrd initrd.img-4.15.0-115-generic-lpae \
这个命令行的关键就是那句“aarch64=off”,这句话开启了arm64 kvm的32位模式。
---------------------------------------------分割线-------------------------------------------------------------
如果你想自己编译kernel接着往下看。
如果你想自己编译kernel,比如你在一台x86机器上编译,需要做的就是安装工具链,下载源码,编译。
装工具链很简单,apt install gcc-arm-linux-gnueabi就行了。
下源码:
git clone git://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next |
编译:
cp config(ubuntu-arm32) .config
ARCH=arm make menuconfig
export ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- && make -j4 && make modules_install -j4
关键的部分来了,我没有make install去产生initrd,需要手动创建initrd,把上面得到的initrd解压出来,用刚刚编译出来的module替换,然后打包压缩。原因是make install会将本地的文件系统里的命令来制作initrd(我在arm64机器上测试是这样的)
解压initrd的命令:
1. mv initrd.img initrd.gz && gunzip initrd.img.gz
2. cpio -idmv < initrd.img
rm -r lib/modules/xxx
cp -a /lib/modules/yyy lib/modules/
打包压缩:
find . | cpio -o -H newc | gzip > ../initrd.img
试试看吧。