QEMU编译安装及Linux系统仿真

QEMU编译安装及Linux系统仿真

概述

QEMU是一个通用和开源计算机仿真器和虚拟机,支持:

  • 全系统仿真:在任何受支持的体系结构上运行任何计算机的操作系统;
  • 用户模式仿真:在任何受支持的体系结构上运行另一个 Linux/BSD 目标的程序;
  • 虚拟化:以接近本机的性能运行 KVM 和 Xen 虚拟机;

当用作仿真器时,QEMU可以在一台机器(如x86 PC)上运行为另一台机器(如ARM开发板)制作的操作系统和程序。

在进行嵌入式Linux系统学习时,QEMU一定程度上帮我们摆脱了硬件限制,前期的学习和验证都可以基于QEMU仿真器进行,让我们摆脱了因为没有开发板,无法进行学习的困扰。

本文记录了使用QEMU仿真Arm开发板的过程。

QEMU编译安装

系统自带的qemu版本过于老旧,需要下载源码进行编译安装。

源码下载:qemu-6.2.0

编译(Ubuntu18.04):

# 解压
tar xf qemu-6.2.0.tar.xz
mkdir -p build
cd build
# 编译配置, 可通过 ../qemu-6.2.0/configure --help 查看帮助信息
../qemu-6.2.0/configure --prefix=$HOME/.local --target-list=aarch64-softmmu,arm-softmmu,riscv32-softmmu,riscv64-softmmu,aarch64-linux-user,arm-linux-user,riscv32-linux-user,riscv64-linux-user --static
# 安装编译依赖: 如果提示还有其他依赖未安装, 通过 apt search 查看对应的依赖并安装
sudo apt-get install -y ninja-build libpixman-1-dev
# 编译
make && make install

验证QEMU:

# 如果没有将 $HOME/.local/bin 添加到环境变量, 则添加
export PATH=$HOME/.local/bin:$PATH

正常安装完成有如下产物:

qemu-bin

通过 qemu-system-arm --help 查看帮助信息,通过 qemu-system-arm -cpu help 可以查看支持的CPU,通过 qemu-system-arm -machine help 可以查看支持开发板。例如:

  • qemu-system-arm -machine help
Supported machines are:
... ...
mcimx6ul-evk         Freescale i.MX6UL Evaluation Kit (Cortex-A7)
... ...
vexpress-a9          ARM Versatile Express for Cortex-A9
... ...
  • qemu-system-aarch64 -machine help
Supported machines are:
... ...
raspi3b              Raspberry Pi 3B (revision 1.2)
... ...

准备根文件系统

制作过程见 使用BusyBox制作Linux根文件系统

制作根文件系统:

dd if=/dev/zero of=rootfs.ext4 bs=1M count=64
mkfs.ext4 rootfs.ext4
sudo mount rootfs.ext4 /mnt/
sudo cp -af rootfs/* /mnt/

sudo mknod /mnt/dev/null    c 1 3
sudo mknod /mnt/dev/tty1    c 4 1
sudo mknod /mnt/dev/tty2    c 4 2
sudo mknod /mnt/dev/tty3    c 4 3
sudo mknod /mnt/dev/tty4    c 4 4
sudo mknod /mnt/dev/tty5    c 4 5
sudo mknod /mnt/dev/console c 5 1

sudo umount /mnt

产物 rootfs.ext4 存放在 $HOME 目录下,后续会使用到。

Linux内核编译

环境准备

源码下载:

git clone https://source.codeaurora.org/external/imx/linux-imx
git checkout rel_imx_4.9.88_2.0.0_ga # 这是一个tag

此时仓库状态:HEAD detached at rel_imx_4.9.88_2.0.0_ga。tag 相当于是一个快照,不能更改它的代码,如果要在该tag的基础上做修改,可以基于该tag开新的分支(git checkout -b $branch_name $tag_name)。

export ARCH=arm
export CROSS_COMPILE=arm-linux-gnueabihf-
export PATH=/opt/gcc-linaro-7.5.0-2019.12-x86_64_arm-linux-gnueabihf/bin:$PATH

本文的目标是在imx6ull上运行,在此之前,先按大多数教程试用和验证一下 QEMU编译安装 小节生成的qemu程序。

vexpress

编译内核:

make vexpress_defconfig
# 直接编会链接不过, 需要 make menuconfig 到 > Device Drivers > Input device support 打开 Polled input device skeleton
make -j4

第一次尝试:

qemu-system-arm -nographic -machine vexpress-a9 -m 512M -kernel arch/arm/boot/zImage -dtb arch/arm/boot/dts/vexpress-v2p-ca9.dtb -append "console=ttyAMA0 loglevel=8"

此时报错:

---[ end Kernel panic - not syncing: VFS: Unable to mount root fs on unknown-block(0,0)

原因是没有指定根文件系统。

第二次尝试:

qemu-system-arm -nographic -machine vexpress-a9 -m 512M -kernel arch/arm/boot/zImage -dtb arch/arm/boot/dts/vexpress-v2p-ca9.dtb -append "console=ttyAMA0 root=/dev/mmcblk0 rootfstype=ext4 loglevel=8" -drive file=~/rootfs.ext4,format=raw,id=sdcard -device sd-card,drive=sdcard

此时能正常进入系统:

Booting Linux on physical CPU 0x0
Linux version 4.9.88+ (***@ubuntu18.04) (gcc version 7.5.0 (Linaro GCC 7.5-2019.12) ) #2 SMP Sun Aug 28 07:50:20 CST 2022
CPU: ARMv7 Processor [410fc090] revision 0 (ARMv7), cr=10c53c7d
CPU: PIPT / VIPT nonaliasing data cache, VIPT nonaliasing instruction cache
OF: fdt:Machine model: V2P-CA9

... ...

EXT4-fs (mmcblk0): mounted filesystem with ordered data mode. Opts: (null)
VFS: Mounted root (ext4 filesystem) readonly on device 179:0.
Freeing unused kernel memory: 1024K
random: crng init done

Please press Enter to activate this console. 

Processing /etc/profile... Done

/ # 

Ctrl+a x 退出QEMU仿真。

imx6ull

选择合适的编译配置(imx_v7_defconfig):

在这里插入图片描述

编译内核:

make distclean
make imx_v7_defconfig
make -j4

第一次尝试(需要修改 machinedtbappend 参数):

qemu-system-arm -nographic -machine mcimx6ul-evk -m 512M -kernel arch/arm/boot/zImage -dtb arch/arm/boot/dts/imx6ull-14x14-evk.dtb -append "console=ttymxc0,115200 root=/dev/mmcblk0 rootfstype=ext4 loglevel=8" -drive file=~/rootfs.ext4,format=raw,id=sdcard -device sd-card,drive=sdcard

现象:没有任何打印,QEMU没有起来。

【尝试1】:修改打印等级和打印端口:

  • 进入> Kernel hacking > printk and dmesg options
  • 使能 Show timing information on printks,将 Default message log level (1-7) 修改为 7
  • 使能 Kernel low-level debugging functions,将 Kernel low-level debugging port 修改为 i.MX6UL Debug UART(作用点);

重新编译运行,现象:

Uncompressing Linux... done, booting the kernel.

然后卡住。

【尝试2】:使用gdb查看运行到什么地方:

  • 进入 > Kernel hacking > Compile-time checks and compiler options
  • 使能 Compile the kernel with debug info,使能 Provide GDB scripts for kernel debugging

重新编译,QEMU带调试参数(-S -s)运行,新建窗口进行GDB调试:

qemu-system-arm -nographic -machine mcimx6ul-evk -m 512M -kernel arch/arm/boot/zImage -dtb arch/arm/boot/dts/imx6ull-14x14-evk.dtb -append "console=ttymxc0,115200 root=/dev/mmcblk0 rootfstype=ext4 loglevel=8" -drive file=~/rootfs.ext4,format=raw,id=sdcard -device sd-card,drive=sdcard -S -s

在另一个窗口使用 arm-linux-gnueabihf-gdb vmlinux 调试:

(gdb) target remote :1234
Remote debugging using :1234
0x80000000 in ?? ()
(gdb) b start_kernel 
Breakpoint 1 at 0x80e008d0: file init/main.c, line 486.
(gdb) c
Continuing.

Breakpoint 1, start_kernel () at init/main.c:486
486             set_task_stack_end_magic(&init_task);
(gdb) n

一路回车,发现重新会执行到:pr_notice("%s", linux_banner);pr_notice("Kernel command line: %s\n", boot_command_line); ,按理应该有打印,但QEMU仿真窗口仍然没有新的打印出现,初步猜测是打印相关的编译配置和设备树没有配对。

此处问题定位卡住很长时间,暂时先使用现成的方案,后续计划进行解决。

【尝试3】:更换编译配置和设备树:

替换 百问网 用于QEMU仿真的编译配置和设备树,并进行适配:

100ask_imx6ull_qemu_defconfig –> arch/arm/configs/imx6ull_qemu_defconfig

100ask_imx6ull_qemu.dts –> arch/arm/boot/dts/imx6ull-qemu.dts

diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
index a27f48966938..5d5aa6ee73b5 100644
--- a/arch/arm/boot/dts/Makefile
+++ b/arch/arm/boot/dts/Makefile
@@ -524,6 +524,7 @@ dtb-$(CONFIG_SOC_IMX6ULL) += \
        imx6ull-14x14-ddr3-arm2-uart2.dtb \
        imx6ull-14x14-ddr3-arm2-usb.dtb \
        imx6ull-14x14-ddr3-arm2-wm8958.dtb \
+       imx6ull-qemu.dtb \
        imx6ull-14x14-evk.dtb \
        imx6ull-14x14-evk-btwifi.dtb \
        imx6ull-14x14-evk-btwifi-oob.dtb \
diff --git a/arch/arm/boot/dts/imx6ull-qemu.dts b/arch/arm/boot/dts/imx6ull-qemu.dts
index 9782aeb1bfef..d83bdafd71bd 100644
--- a/arch/arm/boot/dts/imx6ull-qemu.dts
+++ b/arch/arm/boot/dts/imx6ull-qemu.dts
@@ -133,10 +133,6 @@
        assigned-clock-rates = <786432000>;
 };
 
-&qemu_net {
-       status = "okay";
-};
-
 &fec1 {
        pinctrl-names = "default";
        pinctrl-0 = <&pinctrl_enet1>;

继续编译验证:

make distclean
make imx6ull_qemu_defconfig
make -j4
qemu-system-arm -nographic -machine mcimx6ul-evk -m 512M -kernel arch/arm/boot/zImage -dtb arch/arm/boot/dts/imx6ull-qemu.dtb -append "console=ttymxc0,115200 root=/dev/mmcblk0 rootfstype=ext4 loglevel=8" -drive file=~/rootfs.ext4,format=raw,id=sdcard -device sd-card,drive=sdcard

查看启动日志:

[    1.176928] mmc1: host does not support reading read-only switch, assuming write-enable
[    1.186928] mmc1: new high speed SD card at address 4567
[    1.206928] mmcblk1: mmc1:4567 QEMU! 64.0 MiB 
... ...
[    1.427380] Kernel panic - not syncing: VFS: Unable to mount root fs on unknown-block(0,0)
[    1.433212] ---[ end Kernel panic - not syncing: VFS: Unable to mount root fs on unknown-block(0,0)

修改 append 参数,继续仿真:

qemu-system-arm -nographic -machine mcimx6ul-evk -m 512M -kernel arch/arm/boot/zImage -dtb arch/arm/boot/dts/imx6ull-qemu.dtb -append "console=ttymxc0,115200 root=/dev/mmcblk1 rootfstype=ext4 loglevel=8" -drive file=~/rootfs.ext4,format=raw,id=sdcard -device sd-card,drive=sdcard

此时能正常进入系统:

Uncompressing Linux... done, booting the kernel.
[    0.000000] Booting Linux on physical CPU 0x0
[    0.000000] Linux version 4.9.88-04763-g5e23f9d61147-dirty (***@ubuntu18.04) (gcc version 7.5.0 (Linaro GCC 7.5-2019.12) ) #1 SMP PREEMPT Sun Aug 28 10:35:52 CST 2022
[    0.000000] CPU: ARMv7 Processor [410fc075] revision 5 (ARMv7), cr=30c53c7d

... ...

[    2.659779] EXT4-fs (mmcblk1): mounted filesystem with ordered data mode. Opts: (null)
[    2.669779] VFS: Mounted root (ext4 filesystem) readonly on device 179:0.
[    2.688896] devtmpfs: mounted
[    2.769778] Freeing unused kernel memory: 2048K

Please press Enter to activate this console. 

Processing /etc/profile... Done

/ # 

到此,本次仿真基本结束,接下来可以根据需要修改内核源码,脱离硬件限制,愉快地开始学习Linux内核吧 ^_^

后续计划

  1. Visual Studio Code + GDB + QEMU 图形化调试Linux内核done
  2. IMX6ULL QEMU仿真编译配置和设备树研究;
  • 1
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
QEMU是一个开源的虚拟机监视器和模拟器,可以用于模拟多种硬件平台,包括ARM。以下是使用300字回答如何编译安装QEMU用于ARM模拟的步骤: 首先,需要下载QEMU的源代码。可以从官方网站或Git仓库获取最新版本的源代码。 接下来,需要确保系统安装了必要的编译工具和依赖项。这些依赖项包括GCC编译器、make工具和C库等。可以使用包管理器来安装它们,例如在Debian或Ubuntu上可以使用apt-get命令。 然后,进入QEMU源代码目录,开始进行配置和编译。可以使用以下命令进行配置: $ ./configure --target-list=arm-softmmu --prefix=/usr/local 这将配置QEMU来模拟ARM处理器,并将安装目录设定为/usr/local。 完成配置后,可以使用以下命令开始编译安装QEMU: $ make $ sudo make install 这将对QEMU进行编译,并将其安装在指定的目录中。可能需要等待一段时间,具体时间取决于系统的性能和网络连接速度。 编译安装完成后,可以通过运行以下命令来验证QEMU是否正常工作: $ qemu-system-arm --version 如果成功安装,应该会显示QEMU的版本信息。 现在,您可以使用QEMU来模拟ARM处理器并运行ARM二进制文件。例如,可以使用以下命令来运行一个ARM可执行文件: $ qemu-system-arm -cpu cortex-a53 -machine virt -nographic -kernel path/to/kernel.img 以上是在300字中回答如何编译安装QEMU用于ARM模拟的简要步骤。实际过程可能因系统环境和配置而有所不同,建议查阅QEMU的官方文档以获取更详细的指导。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值