RISC-V Toolchain And QEMU9.0源码编译
RISC-V Toolchain源码构建
RISC-V是一个基于精简指令集原则的开源指令集架构,目前随着越来越多的开发者参与到RISC-V社区的开发中,RISC-V的热度逐年高涨。如何构建一个属于自己的RISC-V GNU交叉编译工具链用来使用就显得十分有必要了。
源码获取
RISC-V的源码地址有两种方式获取:
- 第一种则是放置在
GITHUB
上的仓库riscv-gnu-toolchain中,比较推荐网络状况良好的读者使用。 - 第二种则是放置在
GITEE
上的镜像仓库riscv-gnu-toolchain,比较推荐网络状况不是那么良好的读者使用。
在这里,我便以第一种方式进行演示。如果读者在进入GITHUB或GITEE
镜像网页进行克隆时,应该能够注意到README
中的构建提示:--recursive
,但是需要注意的是,这是不需要的选项;或者说,构建RISC-V工具链不强制需要。
如果读者选择--recursive
,那么请您至少预留40G的磁盘空间,谨防磁盘爆炸。
git clone https://github.com/riscv-collab/riscv-gnu-toolchain
依赖获取
对于不同版本的系统,需要的安装的依赖有些许差异。
我当前的版本是Ubuntu22.04 LTS,当然,我也会将其他主流发行版本的依赖配置给出。
对于Ubuntu而言:
sudo apt-get install autoconf automake autotools-dev curl python3 python3-pip libmpc-dev libmpfr-dev libgmp-dev gawk build-essential bison flex texinfo gperf libtool patchutils bc zlib1g-dev libexpat-dev ninja-build git cmake libglib2.0-dev libslirp-dev
对于RPM系(Fedora、CentOS和RHEL OS)而言:
sudo yum install autoconf automake python3 libmpc-devel mpfr-devel gmp-devel gawk bison flex texinfo patchutils gcc gcc-c++ zlib-devel expat-devel libslirp-devel
对于Arch系:
sudo pacman -Syyu autoconf automake curl python3 libmpc mpfr gmp gawk base-devel bison flex texinfo gperf libtool patchutils bc zlib expat libslirp
编译
目前我的环境为:Ubuntu22.04 LTS
,为了编译时不会报错,我选择了一个较为稳定的版本:2024.04.12
,并且只下载了部分模块:
cd riscv-gnu-toolchain
git checkout 2024.04.12
git submodule init gcc gdb musl binutils
git submodule update --remote gcc gdb musl binutils
对于一般需求而言,我们通常只需要构建Linux
或Multilib
即可,如果需要构建Newlib
,其大致流程和前两种几乎一致。
在选择其他功能前,我们需要设置一下riscv-gnu-toolchain
将要安装的位置,通过--prefix
来进行设置:
--prefix=PREFIX install architecture-independent files in PREFIX [/usr/local]
在构建Linux
时,有两种版本和一些小的组件可以选择:rv32
和rv64
这两种版本。同时这两种版本对应的一些小组件,使用--with-arch
和--with-abi
进行选择。
--with-arch
支持的有必须的(i)
、(a)tomics
、(m)ultiplication and division
、(f)loat
、(d)ouble
、 or(g)eneral
for MAFD.--with-abi
支持的有ilp32
,ilp32d
,ilp32f
,lp64
,lp64f
,lp64d
.
--with-arch=rv64imafdc Sets the base RISC-V ISA, defaults to rv64imafdc
--with-abi=lp64d Sets the base RISC-V ABI, defaults to lp64d
通常而言,遵循默认设置或如下设置即可(如有特殊需求,则需要自行添加):
./configure --prefix=/opt/riscv --with-arch=rv32gc --with-abi=ilp32d # 构建RV32(选择其中一个即可)
./configure --prefix=/opt/riscv --with-arch=rv64gc --with-abi=lp64d # 构建RV64
sudo make linux -j(nproc)
在构建Multilib
时,参数几乎一致,直接运行即可:
./configure --prefix=/opt/riscv --enable-multilib
sudo make linux -j(nproc)
sudo make musl -j(nproc)
至此,构建就结束了。
测试
riscv64-unknown-linux-gnu-gcc --print-multi-lib
.;
lib32/ilp32;@march=rv32imac@mabi=ilp32
lib32/ilp32d;@march=rv32imafdc@mabi=ilp32d
lib64/lp64;@march=rv64imac@mabi=lp64
lib64/lp64d;@march=rv64imafdc@mabi=lp64d
riscv64-unknown-linux-gnu-g++ --print-multi-lib
.;
lib32/ilp32;@march=rv32imac@mabi=ilp32
lib32/ilp32d;@march=rv32imafdc@mabi=ilp32d
lib64/lp64;@march=rv64imac@mabi=lp64
lib64/lp64d;@march=rv64imafdc@mabi=lp64d
QEMU9.0源码编译
QEMU(Quick Emulator)是一款免费开源模拟器,其与Bochs,PearPC类似,但拥有高速(配合KVM)、跨平台的特性。
QEMU是一个托管的虚拟机,它使用动态二进制转换技术来模拟处理器,并且提供多种硬件和外设模型,这使它能够运行多种未修改的客户机操作系统,能与KVM配合以接近本地速度运行虚拟机(接近真实电脑的速度)。
源码获取
源码获取依旧有两种方式:
- QEMU官网直接下载
- 通过
wget
在终端上下载(推荐)
wget https://download.qemu.org/qemu-9.0.0.tar.xz
tar xvJf qemu-9.0.0.tar.xz
依赖获取
当前我的环境为Ubuntu22.04 LTS
,其他发行版可以在构建时通过报错下载所缺少的依赖。
sudo apt install autoconf automake autotools-dev curl libmpc-dev libmpfr-dev libgmp-dev \
gawk build-essential bison flex texinfo gperf libtool patchutils bc \
zlib1g-dev libexpat-dev git \
libglib2.0-dev libfdt-dev libpixman-1-dev \
libncurses5-dev libncursesw5-dev
编译
新版本的(Qemu9.0.0)的编译时直接全部架构编译安装。
--target-list=LIST set target list (default: build all)
Available targets: aarch64-linux-user
aarch64_be-linux-user alpha-linux-user
arm-linux-user armeb-linux-user cris-linux-user
hexagon-linux-user hppa-linux-user i386-linux-user
loongarch64-linux-user m68k-linux-user
microblaze-linux-user microblazeel-linux-user
mips-linux-user mips64-linux-user
mips64el-linux-user mipsel-linux-user
mipsn32-linux-user mipsn32el-linux-user
nios2-linux-user or1k-linux-user ppc-linux-user
ppc64-linux-user ppc64le-linux-user
riscv32-linux-user riscv64-linux-user
s390x-linux-user sh4-linux-user sh4eb-linux-user
sparc-linux-user sparc32plus-linux-user
sparc64-linux-user x86_64-linux-user
xtensa-linux-user xtensaeb-linux-user
aarch64-softmmu alpha-softmmu arm-softmmu
avr-softmmu cris-softmmu hppa-softmmu i386-softmmu
loongarch64-softmmu m68k-softmmu microblaze-softmmu
microblazeel-softmmu mips-softmmu mips64-softmmu
mips64el-softmmu mipsel-softmmu nios2-softmmu
or1k-softmmu ppc-softmmu ppc64-softmmu
riscv32-softmmu riscv64-softmmu rx-softmmu
s390x-softmmu sh4-softmmu sh4eb-softmmu
sparc-softmmu sparc64-softmmu tricore-softmmu
x86_64-softmmu xtensa-softmmu xtensaeb-softmmu
因此,我们可以做出选择:
./configure --prefix=/opt/qemu --target-list=riscv64-softmmu,riscv64-linux-user
make -j $(nproc)
sudo make install
测试
qemu-riscv64 -version
qemu-riscv64 version 9.0.0
qemu-system-riscv64 -version
QEMU emulator version 9.0.0
QEMU部分参数解析
基于阶段一和阶段二中使用的qemu命令做出简要解释:
- -m 或 —m:指定虚拟机的内存大小。例如,-m 2G 表示分配2GB的内存给虚拟机。
- -smp:指定虚拟机的处理器数量和拓扑结构。例如,-smp 4 表示使用4个处理器。
- -cpu:指定虚拟机使用的CPU型号或架构。例如,-cpu host 表示使用宿主机的CPU。
- -device:指定虚拟机添加和配置虚拟设备。例如,-device virtio-net表示添加一个VirtIO网络设备。
- -bios:指定虚拟机的BIOS文件。例如,-bios /usr/lib/riscv64-linux-gnu/opensbi/generic/fw_jump.elf
- -kernel:指定要用作虚拟机内核的镜像文件。例如,-kernel /usr/lib/u-boot/qemu-riscv64_smode/uboot.elf
- -virtfs:-virtfs [tag|mount_tag][,driver[,mount_options]], 用于配置虚拟文件系统,virtfs允许将主机文件系统的目录或文件与虚拟机进行共享,以便虚拟机可以访问和操作这些文件
- -hda 或 -drive:指定虚拟机的硬盘镜像文件或设备。例如,-hda disk.img 表示使用名为 disk.img 的硬盘镜像文件作为虚拟机的主硬盘。
- -cdrom:指定虚拟机的光驱设备,可以用于加载ISO镜像文件。例如,-cdrom os.iso 表示使用名为 os.iso 的ISO镜像文件作为光驱。
- -boot:指定虚拟机的启动顺序。例如,-boot c 表示从硬盘启动,-boot d 表示从光驱启动。
- -net:配置虚拟机的网络设置。例如,-net nic 表示为虚拟机添加一个网络适配器,-net user 表示使用用户模式网络栈。
- -vnc:启用VNC远程访问功能。例如,-vnc :1 表示在端口5901上启动VNC服务器。
- -usb:启用虚拟机的USB支持。例如,-usb 表示启用USB控制器。
- -snapshot:启用快照模式,允许创建和恢复虚拟机的快照。 -monitor:启动一个与虚拟机交互的监控控制台。例如,-monitor stdio 表示将监控控制台输出重定向到标准输入/输出。
- -nographic:参数用于在无图形化界面的模式下运行虚拟机
- -name:为虚拟机指定一个名称
qemu-system-riscv64 \
-machine 'virt' \
-cpu 'rv64' \
-m 1G \
-device virtio-blk-device,drive=hd \
-drive file=qcow2镜像路径,if=none,id=hd \
-virtfs local,id=lee,path=实验工程路径,mount_tag=lee,security_model=passthrough \
-bios /usr/lib/riscv64-linux-gnu/opensbi/generic/fw_jump.elf \
-kernel /usr/lib/u-boot/qemu-riscv64_smode/uboot.elf \
-object rng-random,filename=/dev/urandom,id=rng \
-device virtio-rng-device,rng=rng \
-nographic \
-append "root=LABEL=rootfs console=ttyS0"