QEMU 训练营 2026 专业阶段总结¶
主要贡献者
- 作者:@yyxt-xwy
背景介绍¶
未来想往 Linux 方向发展,通过学长了解到 qemu 训练营,想通过学习多了解一些底层知识,提升自己的能力
专业阶段¶
本次专业阶段我选择 GPU 方向基础实验,实验需要在 QEMU 内实现一款自定义 GPGPU PCI 虚拟设备,完整支持寄存器 MMIO 访问、VRAM 显存读写、Host-Device DMA 数据搬运、Kernel 程
序加载启动,以及轻量化 SIMT 并行指令执行引擎。
1. PCI 与 MMIO 设备建模
GPGPU 设备以标准 PCI 设备形式挂载到 QEMU 总线。设备初始化阶段完成 PCI 配置空间、BAR 内存空间注册,并绑定对应的 MMIO 读写回调函数。上层测试程序通过qpci_io_readl、qpci_io_writel完成寄存器交互,因此设备模型必须精准处理每一次 MMIO 读写操作。
设备内部维护一套完整控制寄存器组,覆盖设备运行状态、执行控制命令、Kernel 配置参数、DMA 描述符、VRAM 访问窗口等模块。 - MMIO 写:修改设备运行状态,例如写入 Kernel 入口、Grid/Block 线程维度、启动指令、DMA 传输参数; - MMIO 读:向外暴露设备当前状态、计算结果、错误标识。
- VRAM 与 DMA 建模 VRAM 作为设备私有显存,用于存放 Kernel 二进制指令、输入输出数据、线程运行参数。数据有两种写入途径:直接 MMIO 映射访问,或是通过 DMA 批量搬运。
DMA 模块模拟宿主机与虚拟 GPU 间高速数据传输:QTest 测试程序配置传输源地址、目标地址、数据长度与传输方向后,写入控制寄存器触发 DMA 流程;设备模型解析 DMA 描述符完成内存拷贝,传输结束后更新状态标志位。
- Kernel 完整启动执行流程 程序运行标准流程:测试程序先将 Kernel 指令与运算数据写入 VRAM,再通过 MMIO 配置 Kernel 入口、线程规模、Grid/Block 维度等寄存器,最后写入启动指令触发计算。
设备收到启动命令后进入核心执行函数:
该函数基于当前设备状态 GPGPUState 创建独立线程上下文,循环读取 VRAM 内 RV32 指令逐条解释执行,运算完成后将结果回写 VRAM。- 简化 SIMT 并行执行模型 这部分实现了一个简化的 SIMT 执行引擎。每个线程拥有自己的寄存器状态和程序计数器,设备会按照测试要求模拟多个线程执行同一段 kernel 代码。 执行核心需要支持基础的 RV32 指令,包括算术运算、访存、分支跳转以及部分浮点操作。对于每条指令,执行函数会从 VRAM 中取指,解析 opcode、rd、rs1、rs2、立即数等字段,然后更新对应线程的寄存器或内存。 其中,线程号、block 信息等内置变量通过寄存器或特殊方式传递给 kernel,使测试中的向量加法、访存、分支等场景能够正常运行。
总结¶
由于个人时间问题,仅完成基础实验部分,进阶实验暂未做完。通过 GPU 基础实验,我对 QEMU 中 PCI 设备建模、BAR/MMIO 访问、设备内部状态维护、DMA 模拟等有了初步理解。