OpenEuler RISC-V 25.09(社区创新版本)已支持 RVA23S64 Profile,为适配 RISC-V Server Platform Reference Spec(下文简称 RVSP-REF) 做好了充足的准备。
介于目前没有成熟的 RISC-V 服务器硬件平台支持完整的 RVA23S64 Profile,因此我们尝试先通过 QEMU 来搭建一个符合 RVSP-REF 规范的 Machine,来帮助 OpenEuler 进行软件栈左移开发。
本文会介绍一下 RISC-V 服务器参考平台规范,然后带大家简单梳理一下当前 QEMU RVSP-REF 的进展,最后说明如何在 QEMU rvsp-ref Machine 上启动 OpenEuler 25.09。
RISC-V 服务器参考平台规范介绍
RVSP-REF Spec 1.0 概要
服务器和我们平时用的电脑不一样,需要常年稳定运行,对可靠性、安全性、性能都要求更高(比如数据中心的服务器不能随便死机,还要防黑客偷数据)。因此,RVSP-REF Spec 定义了一套标准化的硬件能力和接口,使操作系统、虚拟机监控程序等可移植系统软件能够依赖这些能力,实现单一二进制镜像兼容。这个规范适用于通用服务器系统(如 Web 服务器、数据库服务器等),强调高可靠性(RAS)、安全性、性能和服务质量(QoS)等服务器级需求。
2025 年 3 月份 RVSP-REF Spec 1.0 定稿,同年 5 月份,QEMU 上游更新了 rvsp-ref board 补丁(PATCH v3),增加了对 RVA23 的支持以及 iommu 设备。
一个完整的 RISC-V 服务器平台,至少要包含四部分:
-
完善的 SoC 硬件支持:提供硬件接口(如 CPU 核满足 RVA23S64、定时器、高级中断控制器、PCIe 根端口等)。
-
标准化的平台固件:基于 UEFI 和 ACPI 标准,提供启动和运行时服务。
-
丰富的管理接口:通过基板管理控制器(BMC)支持带内(in-band)和带外(out-of-band)管理(如 MCTP、PLDM、IPMI、Redfish)。
-
多种安全模型:支持安全启动、调试授权、机密计算等。
硬件模块规范介绍
我们来看一些和 RISC-V 体系结构比较相关的硬件模块规范:
1.时钟与定时器
-
时间计数器(time CSR) 必须以至少 100 MHz 的频率递增,单位纳秒。
-
必须保持跨 CPU 核低功耗状态的计时连续性(系统级休眠状态除外)。
如果考虑性能,规范强烈推荐支持 Sstc 扩展,它通过引入stimecmp和vstimecmp寄存器,为监管者和虚拟机提供了高效的计时器中断机制,是提升系统(尤其是虚拟化环境)性能的关键特性。
2. 中断控制器
-
必须支持 RISC-V 高级中断架构(AIA)。
-
外部中断必须通过 消息信号中断(MSI) 传递。
-
IMSIC 需支持 S-mode 中断文件,并至少支持 5 个 VS-mode 中断文件(用于虚拟化)。
-
若 SoC 使用线中断,需通过 APLIC 转换为 MSI。
值得一提的是,RISC-V 的 AIA(高级中断架构)相比传统的 PLIC(平台级中断控制器)在中断处理机制、性能、虚拟化支持等方面带来了显著的提升。
AIA 通过引入消息信号中断(MSI)、增强的优先级管理和对虚拟化的原生支持,从 PLIC 那种集中、静态的中断管理方式,转向了分布式、基于消息、且深度支持虚拟化的现代架构,为高性能计算和服务器场景提供了更现代、更高效的解决方案。
所以在 RVSP-REF Spec 1.0 中,强制要求使用 AIA,这对于将 RISC-V 推向数据中心、高性能计算和需要强实时性的应用领域至关重要。
3. 输入输出内存管理单元(IOMMU)
-
所有 DMA 设备(包括 PCIe 设备和非 PCIe 设备)必须受 IOMMU 管理。
-
必须支持 RISC-V IOMMU 规范,包括地址转换、PASID(20 位宽度)、ATS(地址转换服务)等。
-
推荐支持硬件性能监控(HPM)和错误注入功能。
-
复位后默认关闭 DMA,以增强安全性。
4. PCIe 子系统
-
根复合体(Root Complex) 必须符合 PCIe 6.0 标准。
-
ECAM 配置空间 必须支持非缓存、强序访问,并确保写操作的完成语义。
-
内存映射空间 需支持 32 位和 64 位 BAR,并定义访问错误处理规则(如返回全 1 数据)。
-
必须支持 ACS(访问控制服务)、AER(高级错误报告)、DPC(下游端口遏制) 等可靠性功能。
-
可选支持 PTM(精确时间测量) 和 SR-IOV 虚拟化。
5. 可靠性、可用性与可服务性(RAS)
-
推荐使用 ECC 内存、数据毒化(Data Poisoning) 和 定期内存巡检。
-
应支持 RISC-V RERI(错误记录接口),实现错误日志持久化(跨复位保留)。
-
需区分可纠正错误(CE)、非致命错误(UED)和致命错误(UEC)的处理策略。
值得补充的是,RISC-V RERI(RAS Error Record Register Interface)是 RISC-V 体系架构中一项重要的 可靠性、可用性与可维护性 规范,它为标准化的错误报告和日志记录提供了硬件接口,在高端应用如数据中心服务器中,RAS 特性是必不可少的。
6. 服务质量(QoS)
- 要求 SoC 提供资源管理机制(如缓存、内存带宽分配),以减少应用间性能干扰。
7. 性能监控
- CPU 核和 IOMMU 应支持硬件性能计数器(至少 40 位宽),用于优化分析。
8. 安全性
-
通过 IOMMU 隔离设备 DMA 访问。
-
支持 T2GPA 模式(防止设备滥用 ATS)。
-
可选集成 SPDM、TDISP 等可信 I/O 协议。
QEMU RVSP-REF 进展
QEMU rvsp-ref Machine 目前包含的组件如下:
- Based on riscv virt machine type
- A new memory map as close as virt machine as possible
- A new virt CPU type rvsp-ref-cpu for server platform compliance
- AIA
- PCIe AHCI
- PCIe NIC
- No virtio device
- No fw_cfg device
- No ACPI table provided
- Only minimal device tree nodes
PS:服务器平台规范要求 BRS-I(参见 FIRM_010)。BRS-I 需要 ACPI,甚至还需要一些特定的 ACPI 表,例如 PPTT(参见 BRS 规范第 6 章)。不过,我认为我们的思路应该是在这里生成一个设备树(DT),然后让 edk2 从该设备树生成 ACPI 表。
QEMU 已经支持了 RVA23S64,但是对于服务器规范还缺少一些规范,比如 sdext,之前我在论坛做过这个规范的分享:探讨 The RISC-V Debug Specification 的实现(笔者已经和上游做了沟通,后续会补全这个扩展的实现,并贡献到 QEMU 上游)。
在 QEMU rvsp-ref Machine 上启动 OpenEuler
下载 QEMU
目前 rvsp-ref 的补丁还游离在主线之外(因为缺少 sdext 扩展),因此笔者基于 riscv-to-apply.next 添加了一些必要的组件和 bugfix,可以在这里下载到源码:
git clone -b riscv-server-platform git@github.com:zevorn/qemu.git
截至当前文章撰写时的提交历史如下:
commit 07b4e4467a94e8e538b272e5a3135d16cc98ab03 (HEAD -> riscv-server-platform, origin/riscv-server-platform)
Author: Chao Liu <chao.liu.riscv@isrc.iscas.ac.cn>
Date: Sat Nov 1 19:04:41 2025 +0800
hw/riscv: update rvsp-ref default cpu type to cpu-max
temp patch for support openEuler 25.09
Signed-off-by: Chao Liu <chao.liu.riscv@isrc.iscas.ac.cn>
然后使用如下命令编译:
./configure --target-list=riscv64-softmmu && make -j$(nproc)
验证是否编译成功:
./build/qemu-system-riscv64 -M ?
Supported machines are:
amd-microblaze-v-generic AMD Microblaze-V generic platform
microchip-icicle-kit Microchip PolarFire SoC Icicle Kit
none empty machine
rvsp-ref RISC-V Server SoC Reference board # 这是我们需要的
shakti_c RISC-V Board compatible with Shakti SDK
sifive_e RISC-V Board compatible with SiFive E SDK
sifive_u RISC-V Board compatible with SiFive U SDK
spike RISC-V Spike board (default)
virt RISC-V VirtIO board
xiangshan-kunminghu RISC-V Board compatible with the Xiangshan Kunminghu FPGA prototype platform
更新镜像
这里我们以 OpenEuler 25.09 为例,可以参考 使用qemu启动openeuler-24.03-LTS-SP2 - openEuler - RISC-V 开发者社区,先从 virt 启动,我们需要修改一点东西来支持 rvsp-ref Machine。
主要是修改一下 grub.cfg:
vim /boot/efi/EFI/openEuler/grub.cfg
找到这部分:
linux /vmlinuz-6.6.0-102.0.0.5.oe2509.riscv64 root=UUID=c6dd218d-fc09--4066-bc5d-b20a8eb9da7a ro
...
将 ro 改为 rw 即可(后续我们会做优化,避免直接修改 openEuler 镜像)。
更新启动脚本
新建一个启动脚本,命令如下:
#!/usr/bin/env bash
# The script is created for starting a riscv64 qemu virtual machine with specific parameters.
RESTORE=$(echo -en '\001\033[0m\002')
YELLOW=$(echo -en '\001\033[00;33m\002')
## Configuration
vcpu=8
memory=8
drive="$(ls *.qcow2)"
fw1="RISCV_VIRT_CODE.fd"
fw2="RISCV_VIRT_VARS.fd"
ssh_port=12055
cmd="/home/zevorn/qemu/build/qemu-system-riscv64 \
-nographic -machine rvsp-ref,pflash0=pflash0,pflash1=pflash1 \
-smp "$vcpu" -m "$memory"G \
-blockdev node-name=pflash0,driver=file,read-only=on,filename="$fw1" \
-blockdev node-name=pflash1,driver=file,filename="$fw2" \
-object rng-random,filename=/dev/urandom,id=rng0 \
-drive file=$drive,format=qcow2,id=virtio-drive,if=none \
-device virtio-blk-pci,drive=virtio-drive,id=virtio-blk-0"
echo ${YELLOW}:: Starting VM...${RESTORE}
echo ${YELLOW}:: Using following configuration${RESTORE}
echo ""
echo ${YELLOW}vCPU Cores: "$vcpu"${RESTORE}
echo ${YELLOW}Memory: "$memory"G${RESTORE}
echo ${YELLOW}Disk: "$drive"${RESTORE}
echo ${YELLOW}SSH Port: "$ssh_port"${RESTORE}
echo ""
echo ${YELLOW}:: NOTE: Make sure ONLY ONE .qcow2 file is${RESTORE}
echo ${YELLOW}in the current directory${RESTORE}
echo ""
echo ${YELLOW}:: Tip: Try setting DNS manually if QEMU user network doesn\'t work well. ${RESTORE}
echo ${YELLOW}:: HOWTO -\> https://serverfault.com/a/810639 ${RESTORE}
echo ""
echo ${YELLOW}:: Tip: If \'ping\' reports permission error, try reinstalling \'iputils\'. ${RESTORE}
echo ${YELLOW}:: HOWTO -\> \'sudo dnf reinstall iputils\' ${RESTORE}
echo ""
sleep 2
eval $cmd
然后执行这个脚本,可以直接启动:
chmod +x ./start_rvsp-ref_vm.sh
./start_rvsp-ref_vm.sh
下面截取一些关键输出:
OpenSBI v1.7
____ _____ ____ _____
/ __ \ / ____| _ \_ _|
| | | |_ __ ___ _ __ | (___ | |_) || |
| | | | '_ \ / _ \ '_ \ \___ \| _ < | |
| |__| | |_) | __/ | | |____) | |_) || |_
\____/| .__/ \___|_| |_|_____/|____/_____|
| |
|_|
Platform Name : riscv-rvsp-ref,qemu # 这里显示 rvsp-ref
Platform Features : medeleg
Platform HART Count : 8
Platform IPI Device : aia-imsic # 使用的是 aia 高级中断
Platform Timer Device : aclint-mtimer @ 10000000Hz
Platform Console Device : uart8250
Platform HSM Device : ---
Platform PMU Device : ---
Platform Reboot Device : syscon-reboot
Platform Shutdown Device : syscon-poweroff
Platform Suspend Device : ---
Platform CPPC Device : ---
Firmware Base : 0x80000000
Firmware Size : 403 KB
Firmware RW Offset : 0x40000
Firmware RW Size : 147 KB
Firmware Heap Offset : 0x54000
Firmware Heap Size : 67 KB (total), 4 KB (reserved), 13 KB (used), 49 KB (free)
Firmware Scratch Size : 4096 B (total), 1400 B (used), 2696 B (free)
Runtime SBI Version : 3.0
Standard SBI Extensions : time,rfnc,ipi,base,hsm,srst,pmu,dbcn,fwft,legacy,dbtr,sse
Experimental SBI Extensions : none
Domain0 Name : root
Domain0 Boot HART : 1
Domain0 HARTs : 0*,1*,2*,3*,4*,5*,6*,7*
Domain0 Region00 : 0x0000000000100000-0x0000000000100fff M: (I,R,W) S/U: (R,W)
Domain0 Region01 : 0x0000000010000000-0x0000000010000fff M: (I,R,W) S/U: (R,W)
Domain0 Region02 : 0x0000000002000000-0x0000000002007fff M: (I,R,W) S/U: ()
Domain0 Region03 : 0x000000000c000000-0x000000000c007fff M: (I,R,W) S/U: ()
Domain0 Region04 : 0x0000000024000000-0x0000000024007fff M: (I,R,W) S/U: ()
Domain0 Region05 : 0x0000000080000000-0x000000008003ffff M: (R,X) S/U: ()
Domain0 Region06 : 0x0000000080040000-0x000000008007ffff M: (R,W) S/U: ()
Domain0 Region07 : 0x0000000000000000-0xffffffffffffffff M: () S/U: (R,W,X)
Domain0 Next Address : 0x0000000020000000
Domain0 Next Arg1 : 0x000000027fe00000
Domain0 Next Mode : S-mode
Domain0 SysReset : yes
Domain0 SysSuspend : yes
...
# 成功登录系统以后,可以打印一下信息:
[root@localhost ~]# fastfetch
`.cc.`
``.cccccccc..`
`.cccccccccccccccc.`
``.cccccccccccccccccccccc.``
`..cccccccccccccccccccccccccccc..`
`.ccccccccccccccc/++/ccccccccccccccccc.`
.cccccccccccccccmNMMNdo+oso+ccccccccccc.
.cccccccccc/++odms+//+mMMMMm/:+syso/cccc
.cccccccccyNNMMMs:::/::+o+/:cdMMMMMmcccc root@localhost
.ccccccc:+NmdyyhNNmNNNd:ccccc:oyyyo:cccc --------------
.ccc:ohdmMs:cccc+mNMNmyccccccccccccccccc OS: openEuler 25.09 riscv64
.cc/NMMMMMo////:c:///:cccccccccccccccccc Host: riscv-rvsp-ref,qemu
.cc:syysyNMNNNMNyccccccccccccccccccccccc Kernel: Linux 6.6.0-102.0.0.5.oe2509.riscv64
.cccccccc+MMMMMNyc:/+++/cccccccccccccccc Uptime: 56 mins
.cccccccccohhhs/comMMMMNhccccccccccccccc Packages: 306 (rpm)
.ccccccccccccccc:MMMMMMMM/cccccccccccccc Shell: bash 5.2.37
.ccccccccccccccccsNNNNNd+cccccccccccccc. Cursor: Adwaita
`..cccccccccccccccc/+/:cccccccccccccc..` Terminal: vt220
``.cccccccccccccccccccccccccccc.`` CPU: rv64gcvh (8)
`.cccccccccccccccccccccc.` Memory: 277.14 MiB / 7.50 GiB
``.cccccccccccccc.`` Swap: Disabled
`.cccccccc.` Disk (/): 1.32 GiB / 37.11 GiB
`....` Local IP (eth0): 10.0.2.15/24
Locale: en_US.UTF-8

