news 2026/8/1 10:05:57

[Virtualization](九):QEMU virt machine 与 Device Tree

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
[Virtualization](九):QEMU virt machine 与 Device Tree

第八篇讨论了 SBI 在 RISC-V Guest 中如何被虚拟化。本篇回到 QEMU:-machine virt到底如何把 RAM、CPU、UART、virtio、interrupt controller 和 device tree 组织成 Guest Linux 眼中的一台 RISC-V 机器?

1. 本篇要回答的问题

启动 RISC-V Linux guest 时,我们经常写:

qemu-system-riscv64\-machinevirt\-m1G\-smp4\-nographic\-kernelImage\-append"console=ttyS0"

其中-machine virt不是一句泛泛的“虚拟机器”,而是 QEMU 里一个具体的 RISC-V machine model。

它要回答的问题是:

Guest Linux 启动时看到的那台 RISC-V 机器,是 QEMU 如何描述、摆放和交付的?

2. machine model 是什么

QEMU 不是只模拟 CPU。

它要提供一整台机器的外观:

  • RAM
  • CPU hart
  • interrupt controller
  • timer
  • UART
  • virtio-mmio 设备
  • flash/ROM
  • firmware
  • kernel/initrd 放置位置
  • device tree

这些对象加起来,才构成 Guest Linux 能启动的“平台”。

可以把 QEMU machine model 理解成一张虚拟硬件原理图。

真实板卡靠硬件手册描述设备,QEMUvirtmachine 靠代码和 device tree 描述设备。

3.virtmachine 的基本布局

QEMU RISC-Vvirtmachine 通常会定义一套固定或可配置的地址布局。

简化模型:

Guest physical address space 0x00000000 +-------------------+ | ROM / firmware | +-------------------+ | CLINT / AIA | +-------------------+ | PLIC / interrupt | +-------------------+ | UART | +-------------------+ | virtio-mmio | +-------------------+ 0x80000000 | RAM | | kernel / initrd | | device tree | +-------------------+

实际地址会随 QEMU 版本和配置变化,但思路不变:

QEMU 把一组设备放进 guest physical address space,再告诉 Guest Linux 这些设备在哪里。

4. CPU hart 如何创建

RISC-V 多核里常说 hart。

-smp 4会让 QEMU 创建多个 guest hart。

每个 hart 对 Guest Linux 来说像一个 CPU。

在 KVM 模式下,hart 通常对应 vCPU。

Guest hart 0 <-> KVM vCPU 0 <-> QEMU vCPU thread 0 Guest hart 1 <-> KVM vCPU 1 <-> QEMU vCPU thread 1 Guest hart 2 <-> KVM vCPU 2 <-> QEMU vCPU thread 2 Guest hart 3 <-> KVM vCPU 3 <-> QEMU vCPU thread 3

Device tree 中的 CPU 节点会告诉 Guest Linux 有哪些 hart、hart id 是什么、支持哪些 ISA 扩展。

5. RAM 如何交给 Guest

-m 1G告诉 QEMU 给 guest 准备 1GB RAM。

QEMU 会创建对应 memory region,并把它放到virtmachine 的 RAM 地址范围中。

在 KVM 模式下,QEMU 还会把这段内存注册给 KVM,成为 memory slot。

QEMU memory region | | if KVM: KVM_SET_USER_MEMORY_REGION v KVM memory slot | v Guest RAM in GPA space

Guest Linux 最终通过 device tree 的memory节点知道 RAM 起点和大小。

6. Firmware、kernel 和 initrd

RISC-V Linux 启动通常涉及 firmware/SBI,例如 OpenSBI。

QEMU 需要安排:

  • firmware 从哪里开始执行
  • kernel Image 放在哪里
  • initrd 放在哪里
  • device tree 放在哪里
  • 启动参数如何传给 kernel

简化启动交接:

reset vector | v firmware / SBI | | pass hart id and DTB address v Linux kernel entry

Guest Linux 不需要知道 QEMU 内部如何加载文件。

它只需要在启动入口拿到符合 RISC-V boot protocol 的参数。

7. UART 与-nographic

-nographic常常和console=ttyS0一起使用。

QEMUvirtmachine 会提供一个 UART 设备。

Guest Linux 通过 device tree 发现 UART,然后把 console 输出到这个设备。

Guest printk | v Guest UART driver | | MMIO access v QEMU UART device model | v host terminal

这就是为什么串口配置正确时,guest kernel log 会出现在当前终端中。

如果早期日志依赖earlycon=sbi,则可能走 SBI console 路径,而不是完整 UART driver。

8. virtio-mmio 设备窗口

QEMUvirtmachine 常使用 virtio-mmio 给 guest 提供虚拟设备。

每个 virtio-mmio 设备会占用一段 MMIO 地址。

Guest Linux 通过 device tree 发现这些设备,然后加载 virtio driver。

例如 virtio block:

DTB virtio-mmio node | v Guest virtio-mmio driver | v Guest virtio-blk driver | v QEMU virtio-blk device model

因此 device tree 里的 virtio-mmio 节点是 guest driver 和 QEMU device model 对上的关键。

9. interrupt controller

Guest 设备需要中断。

QEMUvirtmachine 会为 guest 提供中断控制器模型。

不同配置可能涉及:

  • PLIC
  • AIA
  • IMSIC
  • ACLINT/CLINT 相关组件

Device tree 会告诉 Guest Linux 中断控制器是什么、设备 interrupt line 如何连接。

virtio device completes request | v virtual interrupt controller | v Guest Linux interrupt handler

中断控制器是 QEMU machine model、KVM interrupt injection 和 guest driver 之间的交汇点。

10. Device Tree 是硬件契约

RISC-V Linux 依赖 DTB 认识硬件。

QEMUvirtmachine 创建完虚拟硬件后,会生成一份 device tree,交给 guest。

DTB 通常包含:

  • /memory
  • /cpus
  • /chosen
  • interrupt controller 节点
  • UART 节点
  • virtio-mmio 节点
  • reserved-memory
  • initrd 起止地址
  • bootargs

可以把 DTB 理解成 QEMU 写给 Guest Linux 的硬件说明书。

11.chosen节点

chosen节点常包含启动参数。

例如:

chosen { bootargs = "console=ttyS0 earlycon=sbi"; linux,initrd-start = <...>; linux,initrd-end = <...>; };

-append里的内容通常会进入 bootargs。

-initrd对应的地址范围也会通过 DTB 告诉 guest。

Guest Linux 早期启动解析 DTB 后,就能知道 command line 和 initrd 位置。

12. dumpdtb:观察 QEMU 生成了什么

理解virtmachine 最实用的方法之一是 dump DTB。

qemu-system-riscv64\-machinevirt,dumpdtb=virt.dtb\-nographic\-kernelImage

然后反编译:

dtc-Idtb-Odts virt.dtb>virt.dts

通过virt.dts可以直接看到 QEMU 告诉 guest 的硬件布局。

这比只读文字描述更可靠。

13. QEMU 源码阅读入口

本篇对应的 QEMU 源码入口:

  • hw/riscv/virt.c:RISC-V virt machine 主体
  • target/riscv/:CPU model、ISA、CSR、TCG/KVM 相关架构代码
  • target/riscv/kvm/:RISC-V KVM accelerator 相关
  • hw/intc/:中断控制器模型
  • hw/char/:UART 等字符设备
  • hw/virtio/:virtio 框架
  • hw/block/virtio-blk.c:virtio block

阅读问题:

  • virtmachine 在哪里注册?
  • RAM base 和 device base 在哪里定义?
  • CPU hart 在哪里创建?
  • DTB 在哪里生成和填充?
  • virtio-mmio 设备如何挂到地址空间?
  • interrupt line 如何连接?

14. 本篇小结

这一篇把 QEMUvirtmachine 和 Device Tree 放在一起看。

第一,-machine virt是一个具体的 RISC-V 虚拟平台模型。

第二,QEMU 负责创建 RAM、CPU hart、UART、virtio、中断控制器等虚拟硬件。

第三,Device Tree 是 QEMU 和 Guest Linux 之间的硬件契约。

第四,Guest Linux 通过 DTB 发现内存、CPU、中断控制器和设备。

第五,读hw/riscv/virt.c时应该同时观察设备创建和 DTB 生成。

可以把本篇压缩成一句话:

QEMUvirtmachine 负责把虚拟硬件拼出来,Device Tree 负责把这台 RISC-V 机器说明白,Guest Linux 则根据这份说明书完成启动和驱动绑定。

15. 下一篇预告:virtio 与 vhost

下一篇进入 I/O 路径。

会讨论:

  • virtio 为什么适合虚拟化
  • virtqueue 的基本结构
  • virtio-mmio 和 virtio-pci
  • virtio-blk、virtio-net 的请求路径
  • QEMU device model 与 host backend
  • vhost-kernel 和 vhost-user 如何减少 QEMU 数据面开销
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/8/1 10:00:20

C语言斐波那契数列实现:从迭代递归到算法优化实战

1. 项目概述&#xff1a;从“Hello World”到第一个算法挑战 如果你刚学完C语言的“Hello World”&#xff0c;正愁不知道下一步该写点什么来巩固基础&#xff0c;那么“求斐波那契数列的前20个数”这个项目&#xff0c;绝对是你从语法学习迈向算法思维的第一块绝佳跳板。它不像…

作者头像 李华
网站建设 2026/8/1 9:59:57

HART协议详解:07 HART故障诊断与维修工程

第七季 HART故障诊断与维修工程 ——从通信失败到设备根因定位:建立从现象到本质的工程诊断能力 各位工业现场的工程师朋友们,大家好! 经过前六季的学习,我们已经完成了HART从认知、通信、协议、Command到设备内部数据流的完整体系构建。 现在,我们进入最实战、最具价…

作者头像 李华
网站建设 2026/8/1 9:56:44

工程网络与关键路径法详解:从基础概念到实战应用

1. 项目概述&#xff1a;从一道题看透工程网络的核心价值 如果你正在学习软件工程&#xff0c;或者准备相关的考试&#xff0c;那么“工程网络”这个词对你来说一定不陌生。它听起来有点抽象&#xff0c;像是课本里那些带着圆圈和箭头的复杂图表。但说实话&#xff0c;我第一次…

作者头像 李华