qemu 运行 riscv 内核失败记录

问题描述

之前搞嵌入式开发的时候研究过 riscv 架构,一直想用 qemu 跑这个架构
的内核来进一步理解操作系统中某些硬件相关的知识,就按照网上的帖子
尝试了下,结果没有搞出来。在这里我先记录下遇到的一些问题,以后抽
时间继续搞一下吧。

编译运行 busybox 程序的问题

编译器版本过高导致程序无法运行

交叉编译 busybox 程序后,运行 busybox 程序会报如下错误:

[longyu@debian-10:20:59:55] busybox-1.30.1 $ ./busybox
FATAL: kernel too old
已放弃

网上没有搜索到相关的链接,我怀疑是 gcc 版本问题。我使用
的 gcc 版本如下:

[root@debian-10:21:11:13] riscv64-linux #  riscv64--glibc--bleeding-edge-2020.08-1/bin/riscv64-linux-gcc -v
Using built-in specs.
COLLECT_GCC=/home/longyu/riscv64-linux/riscv64--glibc--bleeding-edge-2020.08-1/bin/riscv64-linux-gcc.br_real
COLLECT_LTO_WRAPPER=/home/longyu/riscv64-linux/riscv64--glibc--bleeding-edge-2020.08-1/bin/../libexec/gcc/riscv64-buildroot-linux-gnu/10.2.0/lto-wrapper
Target: riscv64-buildroot-linux-gnu
Configured with: ./configure --prefix=/opt/riscv64--glibc--bleeding-edge-2020.08-1 --sysconfdir=/opt/riscv64--glibc--bleeding-edge-2020.08-1/etc --enable-static --target=riscv64-buildroot-linux-gnu --with-sysroot=/opt/riscv64--glibc--bleeding-edge-2020.08-1/riscv64-buildroot-linux-gnu/sysroot --enable-__cxa_atexit --with-gnu-ld --disable-libssp --disable-multilib --disable-decimal-float --with-gmp=/opt/riscv64--glibc--bleeding-edge-2020.08-1 --with-mpc=/opt/riscv64--glibc--bleeding-edge-2020.08-1 --with-mpfr=/opt/riscv64--glibc--bleeding-edge-2020.08-1 --with-pkgversion='Buildroot 2020.08-14-ge5a2a90' --with-bugurl=http://bugs.buildroot.net/ --without-zstd --disable-libquadmath --disable-libquadmath-support --enable-tls --enable-threads --without-isl --without-cloog --with-arch=rv64imafd --with-abi=lp64 --enable-languages=c,c++,fortran --with-build-time-tools=/opt/riscv64--glibc--bleeding-edge-2020.08-1/riscv64-buildroot-linux-gnu/bin --enable-shared --disable-libgomp
Thread model: posix
Supported LTO compression algorithms: zlib
gcc version 10.2.0 (Buildroot 2020.08-14-ge5a2a90) 

这个版本非常新,可能有一些目前我的内核不支持的特性。为了排除
这个问题,我执行如下命令安装 debian 仓库中的 riscv64 gcc。

sudo apt-get install gcc-riscv64-linux-gnu

安装完成后重新编译后能够成功运行,测试过程如下:

[root@debian-10:21:09:57] busybox # file ./busybox
./busybox: ELF 64-bit LSB executable, UCB RISC-V, version 1 (SYSV), statically linked, for GNU/Linux 4.15.0, BuildID[sha1]=0c7958fe7fe545672b809d60984a195180dfdf3f, stripped
[root@debian-10:21:10:02] busybox # ./busybox ls
AUTHORS                 NOFORK_NOEXEC.lst       archival                debianutils             klibc-utils             networking              size_single_applets.sh
Config.in               NOFORK_NOEXEC.sh        busybox                 docs                    libbb                   printutils              sysklogd
INSTALL                 README                  busybox_unstripped      e2fsprogs               libpwdgrp               procps                  testsuite
LICENSE                 TODO                    busybox_unstripped.map  editors                 loginutils              qemu_multiarch_testing  util-linux
Makefile                TODO_unicode            busybox_unstripped.out  examples                mailutils               runit
Makefile.custom         applets                 configs                 findutils               make_single_applets.sh  scripts
Makefile.flags          applets_sh              console-tools           include                 miscutils               selinux
Makefile.help           arch                    coreutils               init                    modutils                shell

可以看到编译出的 busybox 程序能够正常运行。

动态链接的程序无法运行

动态链接方式编译后,运行程序时会报如下错误:

/lib/ld-linux-riscv64-lp64d.so.1: No such file or directory

报错表明动态库加载器不存在,实际上它的路径并不在这个路径中,
它在如下路径中:

/usr/riscv64-linux-gnu/lib/ld-linux-riscv64-lp64d.so.1

编译器没有生成正确的动态库加载器路径,这是个问题。

qemu 编译的问题

执行 configure 的时候报了如下错误:

[longyu@debian-10:21:03:33] qemu $ ./configure --target-list=riscv64-softmmu
ERROR: glib-2.48 gthread-2.0 is required to compile QEMU

执行 apt-get install libglib2.0-dev命令能够解决这个问题,在这个
问题里它并不是要这个版本,而是需要安装相关的文件。安装完成后
如果还报相同的错误,以 root 权限再次执行看看。

解决了这个问题后,又报了一个 pixman 库不存在的错误,通过执
行如下命令解决:

sudo apt-get install libpixman-1-dev

然后以为应该没有问题了,结果发现 qemu 需要拉取某个子模块,
可能是网速太慢了,一直卡住不动

这个问题使用网上的方法没有生效,然后我通过设定一个 https 代理
来解决了,修改 git 配置文件前需要找到一个 https 代理地址与端口号

在 ~/.gitconfig 中添加如下内容:

[https]
	proxy=xx.xx.xx.xx:8080

设定后很快就成功拉取了,编译成功了,生成的 qemu-system-riscv64
文件位于 riscv64-softmmu 子目录中。

编译 riscv64-qemu 程序可以通过执行如下命令完成:

./configure --static --disable-system --target-list=riscv64-linux-user

编译完成后生成的 qemu-riscv64 文件位于 riscv64-linux-user 目录中。

加载内核遇到的问题

使用 qemu-system-riscv64 运行内核一直卡住不动,strace 看一直在
等待,不知道它在干嘛,网上搜了一圈也没有找到类似的问题,我觉
得可能是 qemu 的源码版本有些问题。

切换内核版本到 5.0 重新编译内核后也没啥用。

spike 模拟器的编译

这之后又从网上找到了一篇博客,看样子挺专业的。首先编译 spike 相
关程序,通过执行如下命令来完成:

$ git clone https://github.com/riscv/riscv-isa-sim.git
$ apt-get install device-tree-compiler
$ mkdir build
$ cd build
$ ../configure --prefix=$RISCV
$ make
$ make install

完成后会在 $RISCV/bin 中生成如下文件:

elf2hex  spike  spike-dasm  spike-log-parser  termios-xspike  xspike

同时在 $RISCV/lib 中生成了如下文件:

libcustomext.so  libdisasm.a  libfesvr.a  libsoftfloat.so  pkgconfig

这之后执行如下过程编译 bbl:

$ git clone https://github.com/riscv/riscv-pk.git
$ mkdir build
$ cd build
$ ../configure --prefix=$RISCV --host=riscv64-unknown-elf
$ make
$ make install

编译的时候遇到了如下报错:

gcc: error: unrecognized argument in option ‘-mcmodel=medany’
gcc: note: valid arguments to ‘-mcmodel=’ are: 32 kernel large medium small; did you mean ‘medium’?

尝试修改 Makefile 文件,去掉 -mcmodel 的设定后重新编译会有
新的报错。可能是源码有更新、gcc 版本不符合要求。

总结问题

经过几个小时的尝试,最终以失败告终。这里 qemu、gcc 的版本非常
值得怀疑,目前看来在 qemu 中运行 riscv linux 内核还是不太靠谱,
博客中说在 ubuntu 18.04 中测试的,我下了一个镜像安装了虚拟机后
发现也有相同的问题,暂时搞不动了,过段时间再搞搞吧,问题先记
录到这里。

你可能感兴趣的:(Linux,riscv,qemu,编译,busybox,编译)