一、参考资料
安装
# 查询 qemu 包 apt list | grep qemu # 查询已安装的 qemu 包 apt list --installed | grep qemu # 查询 qemu 版本 qemu-img -V # 安装 sudo apt-get install qemu-system sudo apt-get install qemu-system-arm qemu-system-x86 qemu-system-mips qemu-utils apt-get install qemu # 编译安装 git clone git://git.qemu.org/qemu.git cd qemu git submodule init git submodule update --recursive apt install libglib2.0 libglib2.0-dev apt install autoconf automake libtool ./configure make make install
wget https://download.qemu.org/qemu-8.2.0.tar.xz tar xvJf qemu-8.2.0.tar.xz cd qemu-8.2.0 ./configure make
Linux 内核调试 二:ubuntu20.04安装qemu
Linux 内核调试 三:《QEMU ARM guest support》翻译
Linux 内核调试 四:qemu-system-arm功能选项整理
Linux 内核调试 六:qemu-system-arm仿真vexpress-a9
Linux 内核调试 八:qemu使用initramfs文件系统
基于qemu-riscv从0开始构建嵌入式linux系统ch0.引言
基于qemu-riscv从0开始构建嵌入式linux系统ch1. 搭建qemu环境
基于qemu-riscv从0开始构建嵌入式linux系统ch2. 添加qemu仿真板——Quard-Star板
基于qemu-riscv从0开始构建嵌入式linux系统ch3. 添加中断控制器、串口、pflash支持
使用者模式与系统模式
命令
Linux 内核调试 四:qemu-system-arm功能选项整理
# 使用RAM文件系统: qemu-system-riscv64 -M virt -m 256M -nographic \ -kernel images/Image \ -device virtio-rng-pci \ -initrd images/rootfs.cpio \ -device virtio-blk-device,drive=hd0 \ -drive file=images/rootfs.ext4,format=raw,id=hd0 \ -append "root=/dev/ram rw console=ttyS0" \ -device virtio-net-device,netdev=net0 \ -netdev user,id=net0,host=10.0.2.1,hostfwd=tcp::5555-:22 # 或者使用块设备文件系统: qemu-system-riscv64 -M virt -m 256M -nographic \ -kernel images/Image \ -device virtio-rng-pci \ -initrd images/rootfs.cpio \ -device virtio-blk-device,drive=hd0 \ -drive file=images/rootfs.ext4,format=raw,id=hd0 \ -append "root=/dev/vda rw console=ttyS0" \ -device virtio-net-device,netdev=net0 \ -netdev user,id=net0,host=10.0.2.1,hostfwd=tcp::5555-:22
以上两个命令只有 -append 选项中的 root 参数不同。
riscv64 默认打开了 9P 文件系统(CONFIG_NET_9P 等选项默认打开),可以通过9P文件系统实现host和guest共享文件夹。增加以下qemu启动选项:
-fsdev local,id=test_dev,path=./images,security_model=none -device virtio-9p-pci,fsdev=test_dev,mount_tag=dev9p
如果是自己编译的qemu,如果不支持9P文件系统,需要打开–enable-virtfs选项重新编译qemu。
进入guest系统后,通过mount加载9p文件系统,即可直接访问host的文件夹:
mount -t 9p dev9p /mnt
其中:
-kernel:指定Linux内核镜像。
-initrd images/rootfs.cpio:指定根文件系统镜像(无压缩的.cpio或者压缩后.cpio.xz),用于通过 RAM 文件系统系统启动。这个是可选的,跟 -append 选项指定的命令行参数 root 有关,如果 root 参数为 root=/dev/ram ,表示使用 RAM 文件系统,此时要给出 -initrd 选项。使用 RAM 文件系统启动,可以确保每次系统启动都使用同样的镜像,因为在系统中做的任何修改在系统退出时都不会被保存。如果要保存系统中的修改,一个方法是可以使用块设备/硬盘镜像启动,另一个方法是可以在系统启动后挂着一个硬盘镜像,将所有修改保存在该硬盘上。
-device/-drive:指定一个块设备/硬盘,该设备对应 /dev/vda 文件。如果要使用该设备作为根文件系统,可以修改 -append 选项中的 root 参数为 root=/dev/vda ,这种情况下,在系统中的修改会被保存在 -drive 选项中 file 指定的镜像文件中。如果该设备不是根文件系统,则可以在进入系统后使用 mount 命令(例如 mount /dev/vad /mnt )加载该文件系统,用于保存系统中的修改。
-device/-netdev:给虚拟机配置一个网卡,对应 Buildroot 构建时配置的通过 DHCP 自动分配 IP 地址的 eth0 网卡。其中 host=10.0.2.1 是 qemu user 类型网络的默认网段 10.0.2.0/24 的一个地址,分配给 host 使用,guest 通过 dhcp 获取从该网段获取 ip 地址。hostfwd=tcp::5555-:22 是将 host 的 5555 端口的数据都转发到 guest 的 22 端口(ssh),host 可以通过该端口 ssh 登录到 guest 。
上面的示例使用 user 类型网卡,只能 host 连接 guest 。也可以使用 tap 类型网卡,使用 -device virtio-net-device,netdev=tap0 -netdev tap,id=tap0 或者 -net tap -net nic 选项(可以使用多次,创建多个网卡),需要注意的是,tap 类型网卡需要 root 权限启动 qemu 。使用 tap 类型网卡,在 guest 和 host 都会创建 tap 类型的网卡,guest 的 tap 网卡自动配置了 ip 地址,host 的没有配置,可以给它配置同一个网段的 ip ,例如 sudo ip addr add 169.254.62.132/16 dev tap0 ,就可以双向互相 ping 通了。
-append:内核启动参数,可以使用 man bootparam 了解更多,更准确的,则要看对应内核版本的源码。
-fsdev/-device:指定 9P 文件系统选项,开启 host 和 guest 共享文件夹功能。其中 path 指定 host 文件夹路径,mount_tag 指定在 guest 加载 9P 文件系统时,mount 的设备名称,即 mount 命令的 device 参数。
注意:
不同架构 qemu 命令参数和内核参数会有些差别,特别是内核参数,例如 console 在 riscv 和 x86_64 架构下是 ttyS0 ,在 arm 和 aarch64 架构下则是 ttyAMA0 ,arm 架构还需要指定 dtb 。复制其他架构的 qemu 命令来使用时需要注意这点,否则可能看起来像 qemu 挂死的样子。
在 Ubuntu 上安装和使用 Qemu | Linux 中国
ARM
QEMU运行ARM64(Aarch64)Debian系Linux
Qemu模拟ARM64使用GDB调试linux kernel
qemu-system-aarch64 -M virt -cpu cortex-a53 -nographic -smp 1 -kernel Image -append "rootwait root=/dev/vda console=ttyAMA0" -netdev user,id=eth0 -device virtio-net-device,netdev=eth0 -drive file=rootfs.ext4,if=none,format=raw,id=hd0 -device virtio-blk-device,drive=hd0 -nographic
~/repo/qemu/build/aarch64-softmmu/qemu-system-aarch64 -machine virt,kernel_irqchip=on,gic-version=3 -cpu cortex-a57 \ -m 2G \ -bios ~/QEMU_EFI.fd \ -kernel ~/repo/linux/arch/arm64/boot/Image \ -initrd ~/repo/buildroot.git/output/images/rootfs.cpio.gz \ -monitor telnet:127.0.0.1:4444,server,nowait \ -append "console=ttyAMA0 root=/dev/ram rdinit=/init acpi=on" \ -nographic \
Raspbian
# 树莓派镜像地址: # https://downloads.raspberrypi.org/raspbian_lite/images/raspbian_lite-2019-09-30/ # 2019-09-26-raspbian-buster-lite.zip # 2019-09-26-raspbian-buster-lite.zip ==> 2019-09-26-raspbian-buster-lite.img # 去官网下载img: # http://downloads.raspberrypi.org/raspbian_lite/images/ //精简版的镜像目录不含GUI # http://downloads.raspberrypi.org/raspbian_full/images/ //完整版的镜像目录含GUI # 建议选择 2019-09-26版镜像在2019-09-30目录下面,下载img文件就可以。其他版本有的试了,但是不可用,强烈建议选择下面推荐的这两个版本的镜像,如想尝试新版可等待这个版本模拟成功后再去尝试新版。版本详解如下: # 2019-09-26-raspbian-buster-lite.img —— 树莓派精简版镜像,没有GUI,实际上只用到里面的配置、驱动、根文件系统,(模拟1代时里面的 Linux内核、设备树不使用,使用第一步下载的内核和设备树) # 2020-05-27-raspios-buster-full-armhf.img —— 树莓派完整版镜像,有GUI画面,实际上只用到里面的配置、驱动、根文件系统,(模拟1代时里面的 Linux内核、设备树不使用,使用第一步下载的内核和设备树) file 2018-06-27-raspbian-stretch.img # output: # 2018-06-27-raspbian-stretch.img: DOS/MBR boot sector; partition 1 : ID=0xc, start-CHS (0x0,130,3), end-CHS (0x6,4,22), startsector 8192, 88472 sectors; partition 2 : ID=0x83, start-CHS (0x6,30,25), end-CHS (0x24a,106,32), startsector 98304, 9322496 sectors # 1、从镜像拷贝出启动qemu所需的内核文件和设备树引导文件 # 从file命令的输出中,将 partition 1 'startsector'的值乘以512,并使用这个数字作为下面mount命令中的偏移值.(8192 x 512) $ sudo mount 2018-06-27-raspbian-stretch.img -o offset=4194304 /mnt # 从 /mnt 目录把镜像里的文件拷贝出来 $ sudo umount 2018-06-27-raspbian-stretch.img /mnt # 其中kernel.img与kernel7.img,kernel8.img就是启动qemu所需的内核,*.dtd文件是设备树引导文件,对应树莓派的cpu及版本,其中kernel.img内核文件对应设备为: # kernel.img 对应 RPi 1B, 1A, A+, B+, 2B(第一版) Z, Z (摄像头版本), ZW, CM1 # kernel7.img 对应 RPi2B2, RPi3B, CM3 and CM3L. # kernel8.img 对应 RPi3B, CM3 and CM3L, RPi4B, # qemu-system-arm 支持Raspberry Pi 2(2B)设备,所以对应该设备我们使用kernel7.img以及对应2B的bcm2709-rpi-2-b.dtb文件。 # qemu-system-aarch64 支持Raspberry Pi 3(3B)设备,所以对应该设备我们使用kernel8.img以及对应3B的bcm2710-rpi-3-b.dtb文件。 # 2、将交叉编译好的执行程序放入镜像 # 从file命令的输出中,将 partition 2 'startsector'的值乘以512,并使用这个数字作为下面mount命令中的偏移值.(98304 x 512) $ sudo mount 2018-06-27-raspbian-stretch.img -o offset=50331648 /mnt # 将你交叉编译好的执行程序放入该目录下 $ sudo umount 2018-06-27-raspbian-stretch.img /mnt # 3、如果镜像空间不足需要给镜像扩容 ?? $ qemu-img resize 2018-06-27-raspbian-stretch.img 4G # 三、运行虚拟机 # armV7: qemu-system-arm -M raspi2 -kernel kernel7.img -sd 2018-06-27-raspbian-stretch.img -append "rw earlyprintk loglevel=8 console=ttyAMA0,115200 dwc_otg.lpm_enable=0 root=/dev/mmcblk0p2 rootwait" -dtb bcm2709-rpi-2-b.dtb -nographic # armV8: qemu-system-aarch64 -M raspi3 -kernel kernel8.img -sd 2020-08-20-raspios-buster-arm64-lite.img -append "rw earlyprintk loglevel=8 console=ttyAMA0,115200 dwc_otg.lpm_enable=0 root=/dev/mmcblk0p2 rootwait" -dtb bcm2710-rpi-3-b.dtb -nographic qemu-system-aarch64 -M raspi3b -kernel kernel8.img -sd 2019-09-26-raspbian-buster-lite.img -append "rw earlyprintk loglevel=8 console=ttyAMA0,115200 dwc_otg.lpm_enable=0 root=/dev/mmcblk0p2 rootwait" -dtb bcm2710-rpi-3-b.dtb -nographic # 命令参数: # -M raspi2 模拟raspi2单板,你可以使用-M ?参数来获取该qemu版本支持的所有单板 # -m 512M 单板运行物理内存512M # -kernel /path/to/kernel/dir/arch/arm/boot/zImage 告诉qemu单板运行内核镜像路径 # -nographic 不使用图形化界面,只使用串口 # -append "console=ttyAMA0" 内核启动参数,这里告诉内核vexpress单板运行,串口设备是哪个tty # 如果搭建其它单板,需要注意内核启动参数的console=参数值,同样地,可从生成的.config文件中找到 # 树莓派默认用户名密码:(pi/raspberry) # qemu退出的方式:官方文档给出的是 ctrl + A 和 X,需要注意ctrl 与 A同时按住抬起后再按X,不要三个键同时按~
qemu-system-aarch64 -M raspi3 -cpu cortex-a53 -m 1024 -kernel kernel8.img -dtb bcm2710-rpi-3-b.dtb -sd openEuler-20.03-LTS-SP1-raspi-aarch64.img -net user,hostfwd=tcp::6022-:22 -append "rw earlyprintk loglevl=8 console=ttyAMA0,115200 dwc_otg.lpm_enable=0 root=/dev/mmcblk0p3 rootwait panic=1" -no-reboot -nographic
Board
基于Qemu搭建imx6l模拟开发板环境+添加驱动+驱动测试
【嵌入式Linux驱动入门】一、基于QEMU的IMX6ULL虚拟开发环境搭建
不用买硬件,1s体验鸿蒙系统!(IMX6ULL QEMU运行鸿蒙系统)
Android
如何运行编好的Android程序,在模拟器上运行编译好的android
export ANDROID_PRODUCT_OUT=~/android/out/target/product/generic ANDROID_PRODUCT_OUT_BIN=~/android/out/host/linux-x86/bin export PATH=${PATH}:${ANDROID_PRODUCT_OUT_BIN}:${ANDROID_PRODUCT_OUT} emulator emulator -system system.img -data userdata.img -ramdisk ramdisk.img
二、QEMU调试参数
cmdline:nokaslr (禁用内核地址空间布局随机)
-S 在开始时阻塞 CPU 执行
-s 开启 GDB 服务器,端口 1234
-gdb tcp::1234 开启 GDB 服务器,端口可以自己指定
qemu-system-x86_64 \ -kernel bzImage \ -initrd initramfs.img \ -m 1G \ -nographic \ -append "earlyprintk=serial,ttyS0 console=ttyS0 nokaslr" \ -S \ -gdb tcp::1234
三、QEMU 命令
CTAL + A,然后按 x 键
四、buildroot