发布日期:2022-09-17
QEMU、GCC 上游最近正式宣布支持龙架构,它是龙芯中科基于 MIPS 国产自主研发的指令集,也在某程度上受到 RISC-V 启发:
据说上游 Linux 内核至 5.19 起也初步支持龙架构(源:LoongArch CPU Support Merged For Linux 5.19 - But It Won’t Work For A Booting System Yet - Phoronix),可是很遗憾,这初步支持并不足以在龙架构上启动一个完整的 Linux 系统。
这代表着您即便没有购买龙芯 SoC 也可以透过 QEMU 用户空间模拟器 有限度地体验龙架构,这也正是本文章的焦点。
您必须熟悉 Linux 操作。本文章中的说明及命令适用于 Ubuntu 22.04。这并不代表您不能使用别的 Linux 发行版完成该文章所描述的操作,但您极有可能需要因应您的发行版调整您所输入的命令。本文章的作者将不会对您因误操作损坏系统承担任何责任。
为免对您日常使用的系统造成破坏,建议您在新建的 Ubuntu 22.04 虚拟机内进行相关操作。当然,如果您的操作系统不是 Linux(如 Windows、macOS)或您使用的 UOS 系统禁用了开发者模式,这或许是您唯一可行的选项。
因为 QEMU、GCC 也是最近才正式支持龙架构,所以您并不能透过 Ubuntu 默认的仓库直接下载安装相应的软件包。因此,我们需要获取并自行编译最新稳定版本 QEMU、GCC 的源代码。
下载 QEMU、GCC 前,我们先建好一些目录:
$ mkdir -p $HOME/opt/qemu $HOME/opt/cross $HOME/src
把工作目录设置为 $HOME/src
:
$ pushd $HOME/src
我们将把 QEMU 安装在 $HOME/opt/qemu
下,GCC 在 $HOME/opt/cross
下,把源代码存放在 $HOME/src
下。当然,您也可以选择别的目录。
参考文章:Hosts/Linux - QEMU、GCC Cross-Compiler - OSDev Wiki
截至 2022-09-17,最新的 QEMU 版本是 7.1.0,因此我们以 QEMU 7.1.0 为准。
更新仓库元数据:
$ sudo apt update
下载编译 QEMU 所需的依赖包:
$ sudo apt install -y build-essential \
git \
libglib2.0-dev \
libfdt-dev \
libpixman-1-dev \
zlib1g-dev \
ninja-build
从 QEMU 官方网站下载 7.1.0 版本源代码:
$ wget https://download.qemu.org/qemu-7.1.0.tar.xz
解压缩:
$ tar xvf qemu-7.1.0.tar.xz
创建一个编译用的新目录 build-qemu
:
$ mkdir build-qemu/
进去:
$ pushd build-qemu/
出口环境变量:
$ export PREFIX="$HOME/opt/qemu"
$ export TARGET_LIST="loongarch64-linux-user"
$ export PATH="$PREFIX/bin:$PATH"
配置 QEMU:
$ ../qemu-7.1.0/configure --prefix="$PREFIX" \
--target-list="$TARGET_LIST" \
--static
编译 QEMU:
$ make -j$(nproc)
安装 QEMU:
$ make install
现在来验证以下我们的安装:
$ which -- qemu-loongarch64 || \
echo qemu-loongarch64 is not in the PATH
看到类似 /home/dsleung/opt/qemu/bin/qemu-loongarch64
的输出为成功。倘若看到 qemu-loongarch64 is not in the PATH
,那代表失败了,请自行修正、重新编译安装 QEMU 哦 ~
倘若以后需要再编译 QEMU,大可留下源代码,但需要清理 build 文档:
$ make clean
离开 build 目录:
$ popd
为了以后能直接调用 qemu-loongarch64
,把 PATH
写进 profile 内:
$ echo "export PATH=\"\$HOME/opt/qemu/bin:\$PATH\"" >> ~/.profile
$ source ~/.profile
参考文章:GCC Cross-Compiler - OSDev Wiki、How to Build a GCC Cross-Compiler
更新仓库元数据:
$ sudo apt update
下载编译 GCC、Binutils、Glibc、Linux 所需的依赖包:
$ sudo apt install -y build-essential \
bison \
flex \
libgmp3-dev \
libmpc-dev \
libmpfr-dev \
texinfo
从官方网站下载 GCC、Binutils、Glibc、Linux 最新版本源代码 - 截至 2022-09-17,最新 GCC 版本为 12.2.0、Binutils 版本为 2.39、Glibc 版本为 2.36、Linux 版本为 6.0-rc5:
$ wget https://ftp.gnu.org/gnu/gcc/gcc-12.2.0/gcc-12.2.0.tar.xz
$ wget https://ftp.gnu.org/gnu/binutils/binutils-2.39.tar.xz
$ wget https://ftp.gnu.org/gnu/libc/glibc-2.36.tar.xz
$ wget https://git.kernel.org/torvalds/t/linux-6.0-rc5.tar.gz
解压缩:
$ tar xvf gcc-12.2.0.tar.xz
$ tar xvf binutils-2.39.tar.xz
$ tar xvf glibc-2.36.tar.xz
$ tar xvf linux-6.0-rc5.tar.gz
出口环境变量:
$ export PREFIX="$HOME/opt/cross"
$ export TARGET="loongarch64-linux-gnu"
$ export PATH="$PREFIX/bin:$PATH"
$ mkdir build-binutils/
$ pushd build-binutils/
$ ../binutils-2.39/configure --prefix="$PREFIX" \
--target="$TARGET" \
--disable-multilib
$ make -j$(nproc)
$ make install
$ make clean
$ popd
$ pushd linux-6.0-rc5/
$ make mrproper
$ make ARCH=loongarch INSTALL_HDR_PATH="$PREFIX/$TARGET" headers_install
$ popd
在安装 Linux 内核标头档前执行 make mrproper
能确保我们的 build 不会受遗留的 build 文档影响,相当于其他 Make 项目的 make clean
。
$ mkdir -p build-gcc/
$ pushd build-gcc/
$ ../gcc-12.2.0/configure --prefix="$PREFIX" \
--target="$TARGET" \
--enable-languages=c,c++ \
--disable-multilib
$ make -j$(nproc) all-gcc
$ make install-gcc
$ make clean
$ popd
$ mkdir -p build-glibc
$ pushd build-glibc/
$ ../glibc-2.36/configure --prefix="$PREFIX/$TARGET" \
--build=$MACHTYPE \
--host="$TARGET" \
--target="$TARGET" \
--with-headers="$PREFIX/$TARGET/include" \
--disable-multilib \
libc_cv_forced_unwind=yes
$ make install-bootstrap-headers=yes install-headers
$ make -j$(nproc) csu/subdir_lib
$ install csu/crt1.o csu/crti.o csu/crtn.o "$PREFIX/$TARGET/lib"
$ $TARGET-gcc -nostdlib \
-nostartfiles \
-shared \
-x c /dev/null \
-o "$PREFIX/$TARGET/lib/libc.so"
$ touch "$PREFIX/$TARGET/include/gnu/stubs.h"
$ popd
$ pushd build-gcc/
$ make -j$(nproc) all-target-libgcc
$ make install-target-libgcc
$ make clean
$ popd
$ pushd build-glibc/
$ make -j$(nproc)
$ make install
$ popd
$ pushd build-gcc/
$ make -j$(nproc)
$ make install
$ make clean
$ popd
$ which -- $TARGET-gcc || \
echo $TARGET-gcc is not in the PATH
把 $HOME/opt/cross/bin
加到 profile 的 PATH
:
$ echo "export PATH=\"\$HOME/opt/cross/bin:\$PATH\"" >> ~/.profile
$ source ~/.profile
要编译的都编译好了,可以离开 $HOME/src
:
$ popd
打开您最喜爱的文字编辑器(本人的为 Vim),写个 C 程序,并保存为 hello.c
:
#include
int main(void) {
printf("Hello LoongArch World!\n");
return 0;
}
使用交叉编译器编译:
$ loongarch64-linux-gnu-gcc -O2 --static hello.c -o hello
查看可执行文档 hello
的属性:
$ file hello
输出为:hello: ELF 64-bit LSB executable, LoongArch, version 1 (SYSV), statically linked, for GNU/Linux 5.19.0, with debug_info, not stripped
除非您电脑 CPU 架构为龙架构(当前绝大部分民用计算机为 x86_64
、ARM 架构),不然您不能直接运行该文档。幸好,我们能透过 qemu-loongarch64
间接运行该文档:
$ qemu-loongarch64 ./hello
输出为 Hello LoongArch World!
上游 QEMU、GCC 对龙架构的支持尚处于早期阶段,龙架构本身也如此。当龙架构及它的生态逐渐成熟,安装龙架构模拟器及交叉编译器将会大为简化,如 sudo apt install -y qemu-user-loongarch64 loongarch64-linux-gnu-binutils loongarch64-linux-gnu-gcc
。
或许在不太久的将来,随着龙架构向民用计算机普及化,我们或许不用再透过交叉编译及模拟器体验龙架构,而是在日常使用的台式机及笔记本电脑上直接体验龙架构。但在这一天的到来之前,我们还是有许多的办法探索龙架构,即便因为各种原因无法直接购买相关硬件。
其实我这篇文章原本打算编译上游的 Linux 6.0-rc5 内核及 BusyBox 1.35.0,并运行在 QEMU 龙架构系统模拟器 上,但上游 Linux 内核对龙架构的支持似乎还不够成熟,不能直接运行在龙架构上。
本文章到此为止吧,下次希望能透过 QEMU 龙架构系统模拟器继续探索龙架构并分享一些龙架构入门内核编程的心得。