From 6d870a766c01ec6f22c9593a3a8b5d00e0026d9a Mon Sep 17 00:00:00 2001 From: Chen Wang Date: Wed, 6 Apr 2022 10:25:57 +0800 Subject: [PATCH] added article run qemu 2.12.0 --- articles/20220406-qemu-riscv-2.12.md | 118 +++++++++++++++++++++++++++ docs/howto-build-emu-riscv.md | 23 +++++- docs/zh/howto-build-emu-riscv.md | 19 ++++- 3 files changed, 155 insertions(+), 5 deletions(-) create mode 100644 articles/20220406-qemu-riscv-2.12.md diff --git a/articles/20220406-qemu-riscv-2.12.md b/articles/20220406-qemu-riscv-2.12.md new file mode 100644 index 0000000..bd55a3f --- /dev/null +++ b/articles/20220406-qemu-riscv-2.12.md @@ -0,0 +1,118 @@ +![](./diagrams/android-riscv.png) + +文章标题:**尝试运行第一个支持 RISC-V 的 QEMU 版本(v2.12.0)** + +- 作者:汪辰 +- 联系方式: / + +文章大纲 + + +- [1. 前言](#1-前言) +- [2. 下载和编译 QEMU](#2-下载和编译-qemu) +- [3. 构建文件系统](#3-构建文件系统) + + + +# 1. 前言 + +v2.12.0 是第一个加入对 RISC-V 支持的 QEMU 版本。研究这个版本上有关 RISC-V 的改动其实还是蛮有意义的。特别的地,最近在研究 android emulator,android emulator 的内部核心引擎其实也是基于 QEMU 开发的,而且很巧的是目前最新的 android emulator 所使用的 QEMU 正是基于 v2.12.0。虽然很可惜目前 android emulator 并没有升级其使用的 QEMU 版本的意思。 + +# 2. 下载和编译 QEMU + +具体搭建 QEMU 的构建环境这里就不多说了,感兴趣的可以参考 或者看一下这篇 ["在 QEMU 上运行 RISC-V 64 位版本的 Linux"](https://zhuanlan.zhihu.com/p/258394849)。 + +下载 2.12.0 的 QEMU 源码,解压后进入源码根目录,这里假设其绝对路径是 `${QEMU_2_12_0}`: + +``` +wget https://download.qemu.org/qemu-2.12.0.tar.xz +tar xJf qemu-2.12.0.tar.xz +cd ${QEMU_2_12_0} +``` + +开始编译 QEMU,这里我们采用最简单的方式,只编译 system 模式,以及 "IN-TREE" 方式,编译完成后,会在源码根目录下创建 `riscv64-softmmu` 目录,在该目录下会看到 `qemu-system-riscv64`: +``` +./configure --target-list=riscv64-softmmu && make +``` + +# 3. 构建文件系统 + +然后我们需要做一套系统,包括 bootloader(openspi) + linux kernel + rootfs + +参考 。我这里选择了 buildroot 方式。 + +去 下载当前最新版 `buildroot-2022.02.tar.gz`。解压后进入源码根目录 + +``` +make qemu_riscv64_virt_defconfig +``` +在继续 make 前通过运行 `make menuconfig` 做以下调整: + +- 如果在国内访问外网受限,可以将 download mirror 设置为国内,加快软件包下载速度 +- 通过菜单 Bootloaders ---> checkout "Include Linux as OpenSBI Payload", 勾选这个会自动勾选 “Install fw_payload image”。这一步很关键,因为我们要测试的 QEMU 2.12.0 中不支持 `-bios` 和 `-kernel` 分别加载 opensbi 和 linux 的方式,严格说是在 QEMU 4.1 之前都不支持以上分离的方式,在 4.1 之前只支持采用 "combined firmware and kernel" 的方式。 + +保存退出后执行 make 即可。构建成功后我们可以在源码根目录的 `output/images/` 下看到生成的所有我们需要的东西: +``` +buildroot-2022.02$ ls output/images/ -l +total 61308 +-rw-r--r-- 1 wangchen wangchen 99888 Mar 25 16:16 fw_dynamic.bin +-rw-r--r-- 1 wangchen wangchen 835168 Mar 25 16:16 fw_dynamic.elf +-rw-r--r-- 1 wangchen wangchen 99856 Mar 25 16:16 fw_jump.bin +-rw-r--r-- 1 wangchen wangchen 834672 Mar 25 16:16 fw_jump.elf +-rw-r--r-- 1 wangchen wangchen 21919240 Mar 25 16:16 fw_payload.bin +-rw-r--r-- 1 wangchen wangchen 20656936 Mar 25 16:16 fw_payload.elf +-rw-r--r-- 1 wangchen wangchen 19822080 Mar 25 16:16 Image +-rw-r--r-- 1 wangchen wangchen 62914560 Mar 25 21:29 rootfs.ext2 +-rw-r--r-- 1 wangchen wangchen 2652160 Mar 25 16:16 rootfs.tar +-rwxr-xr-x 1 wangchen wangchen 499 Mar 25 16:16 start-qemu.sh +``` + +其中 `fw_payload.elf` 就是我们需要的包含了 Linux 内核的 bootloader(openSBI),假设其绝对路径是 `${BUILDROOT_2022_02}/output/images/fw_payload.elf`。 + +`rootfs.ext2` 就是我们需要的文件系统了,假设其绝对路径是 `${BUILDROOT_2022_02}/output/images/rootfs.ext2`。 + +所以我们可以执行如下命令启动 qemu + +``` +cd ${QEMU_2_12_0}/riscv64-softmmu/ +./qemu-system-riscv64 \ + -M virt \ + -nographic \ + -kernel ${BUILDROOT_2022_02}/output/images/fw_payload.elf \ + -append "root=/dev/vda ro console=ttyS0" \ + -drive file=${BUILDROOT_2022_02}/output/images/rootfs.ext2,format=raw,id=hd0 \ + -device virtio-blk-device,drive=hd0 \ + -netdev user,id=net0 -device virtio-net-device,netdev=net0 +``` +进入控制台后,用户名 root,密码直接回车即可登录。注意这个版本还支持启动网络。 + +假如我们想通过 QEMU 启动自己定制的 Linux 内核(譬如 android 的 Linux 内核),一种办法是修改 Buildroot,但我现在不太想去折腾这个,因为我用 Buildroot 其实主要是图省事利用它做一个文件系统。 + +其实我们也可以自己搞定 bootloader + kernel 部分,具体方法就是自己编译制作 OpenSBI,然后把我们自己的内核作为 payload 塞进去就好了。 + +可以参考如下文档: + +- https://github.com/riscv-software-src/opensbi/blob/master/README.md +- https://github.com/riscv-software-src/opensbi/blob/master/docs/platform/qemu_virt.md + + +首先我们需要一个 riscv64 的 cross-toolchain,这里不赘述,做好后将 gcc 的路径加入 PATH。 + +然后下载 opensbi 源码,这里我们就用最新的 v1.0 的: +``` +git clone git@github.com:riscv-software-src/opensbi.git +cd opensbi +git checkout v1.0 -b v1.0 +``` + +然后执行如下 make,`FW_PAYLOAD_PATH` 设置为我们想塞入的 Linux 内核的 Image 文件路径 +``` +CROSS_COMPILE=riscv64-unknown-linux-gnu- make PLATFORM=generic FW_PAYLOAD_PATH=/path/to/your/Image +``` + +完成后就会在 `opensbi/build/platform/generic/firmware/` 下生成我们需要的 `fw_payload.elf` + + + + + diff --git a/docs/howto-build-emu-riscv.md b/docs/howto-build-emu-riscv.md index d8de545..ae60403 100644 --- a/docs/howto-build-emu-riscv.md +++ b/docs/howto-build-emu-riscv.md @@ -7,8 +7,8 @@ - [3. Install repo](#3-install-repo) - [4. Download source code](#4-download-source-code) - [5. Build](#5-build) - - [5.1. Incremental builds](#51-incremental-builds) - - [5.2. Speeding up builds with ‘ccache’](#52-speeding-up-builds-with-ccache) + - [5.1. Incremental builds](#51-incremental-builds) + - [5.2. Speeding up builds with ‘ccache’](#52-speeding-up-builds-with-ccache) - [6. Test with the generated AOSP system image](#6-test-with-the-generated-aosp-system-image) @@ -124,6 +124,8 @@ $ lunch sdk_phone_arm64-eng $ make -j8 ``` +`$AOSP` is the path to your aosp source tree. + Recommended build products are 'sdk_phone_arm64-eng ' or 'sdk_phone_x86_64-eng'. To boot the generated system image: @@ -136,9 +138,24 @@ $ objs/emulator ``` Note: +- The above command lines to start the emulator must be in the same terminal + session as the lunch command, otherwise an error will be reported. - If you want to launch emulator without GUI(headless mode), you can add `-no-window` option. - If you see error: "pulseaudio: Failed to initialize PA contextaudio: Could not init `pa' audio driver", you can add `-no-audio` option. - If you see error: "PCI bus not available for hda", you can add `-qemu -machine virt`. -- If you want to see kernel log in headless mode, you can add `-show-kernel` option. \ No newline at end of file +- If you want to see kernel log in headless mode, you can add `-show-kernel` option. + +To sum up, assuming that we have compiled and generated the aosp image of +`sdk_phone_arm64-eng`and emulator. When we want to run and test this aosp image +with our own compiled emulator, and use text mode (no GUI), you can enter the +following commands: +``` +$ cd $AOSP/ +$ . build/envsetup.sh +$ lunch sdk_phone_arm64-eng +$ cd /home/u/emu-master-dev/external/qemu +$ export ANDROID_BUILD_TOP=$AOSP +$ objs/emulator -no-window -show-kernel -no-audio -qemu -machine virt +``` \ No newline at end of file diff --git a/docs/zh/howto-build-emu-riscv.md b/docs/zh/howto-build-emu-riscv.md index 04c74d9..4aa12eb 100644 --- a/docs/zh/howto-build-emu-riscv.md +++ b/docs/zh/howto-build-emu-riscv.md @@ -9,8 +9,8 @@ - [3. 安装 repo](#3-安装-repo) - [4. 下载源码](#4-下载源码) - [5. 构建](#5-构建) - - [5.1. 增量构建](#51-增量构建) - - [5.2. 使用 “ccache” 加速构建](#52-使用-ccache-加速构建) + - [5.1. 增量构建](#51-增量构建) + - [5.2. 使用 “ccache” 加速构建](#52-使用-ccache-加速构建) - [6. 使用生成的 AOSP 系统映像进行测试](#6-使用生成的-aosp-系统映像进行测试) @@ -121,6 +121,8 @@ $ lunch sdk_phone_arm64-eng $ make -j8 ``` +`$AOSP` 是你 aosp 源码树的路径。 + 推荐选择的产品类型有 'sdk_phone_arm64-eng' 或者 'sdk_phone_x86_64-eng'。 利用我们自己构建的模拟器启动 AOSP 系统镜像的方法如下: @@ -133,8 +135,21 @@ $ objs/emulator ``` 注意: +- 以上启动 emulator 的命令行必须和 lunch 命令在一个终端会话中,否则会报错。 - 如果您想在没有图形界面的的模式(headless mode)下启动模拟器,您可以添加 `-no-window` 选项。 - 如果您看到错误:“pulseaudio: Failed to initialize PA contextaudio: Could not init 'pa' audio driver”,您可以添加 `-no-audio` 选项。 - 如果您看到错误:“PCI bus not available for hda”,您可以添加 `-qemu -machine virt`。 - 如果您想在 headless mode 下查看内核日志,可以添加 `-show-kernel` 选项。 + +综上所述,假设我们已经编译生成了 `sdk_phone_arm64-eng` 的 aosp image 和 emulator,现 +在我们想用自己编译的 emulator 运行测试一下这个 aosp image,,并且采用文本模式,不启动 +图形界面,可以输入如下命令: +``` +$ cd $AOSP/ +$ . build/envsetup.sh +$ lunch sdk_phone_arm64-eng +$ cd /home/u/emu-master-dev/external/qemu +$ export ANDROID_BUILD_TOP=$AOSP +$ objs/emulator -no-window -show-kernel -no-audio -qemu -machine virt +``` \ No newline at end of file -- Gitee