virt-report虚拟化社区动态

vhost-vDPA:队列配置、硬件数据路径与迁移

本文由 OpenAI Codex (GPT-6-Astra) 辅助编写。

一、vDPA 的 virtio 接口与队列卸载

高报文率虚拟机常把大量宿主 CPU 时间花在队列解析、缓冲区访问和网络转发上。vhost-net 把处理放进宿主内核,vhost-user 允许独立进程接管;如果设备本身能够消费 virtio 队列,还可以进一步减少软件参与。vDPA 为这类设备提供框架:数据路径遵循 virtio,设备的配置方式可以由厂商驱动转换。

本文以 QEMU 中的 vhost-vDPA 网络后端为主线,先看组件分工,再追踪直接模式下的一次发送,随后展开队列、DMA 地址和通知配置,最后说明 Shadow Virtqueue 怎样参与迁移。vDPA 框架支持硬件和软件实现;本文的发送例子使用硬件,迁移部分再引入 QEMU 中转的影子队列。

源码版本:QEMU 10.2.0、Linux 6.18。

二、客户机、QEMU 与宿主 vDPA 驱动的分工

客户机仍看到 virtio-net PCI 设备,并使用标准驱动协商特性、建立 RX/TX 队列。QEMU 提供客户机可见的 PCI 和 virtio 控制接口,打开 /dev/vhost-vdpa-N;宿主的 vhost_vdpa 驱动把 vhost 用户接口转换为 vDPA 配置操作,具体设备驱动再把这些操作落到硬件或软件实现。

组件所在位置主要责任
客户机 virtio-net 驱动客户机内核准备缓冲区、发布请求、回收完成
QEMU 前端与 vhost-vDPA 后端宿主用户态 QEMU 进程设备能力、队列配置、内存映射及生命周期协调
vhost_vdpa宿主内核接收 ioctl / IOTLB 更新,连接队列与通知
vDPA 设备驱动与实现宿主驱动及对应硬件或软件后端设置真实队列、处理请求、报告完成
vhost-vDPA 的配置路径与直接数据路径
控制配置经过 QEMU、vhost_vdpa 与设备驱动;直接模式的硬件设备访问已映射的队列与数据缓冲区。虚线表示控制,实线表示请求数据及完成。
控制配置经过 QEMU、vhost_vdpa 与设备驱动;直接模式的硬件设备访问已映射的队列与数据缓冲区。虚线表示控制,实线表示请求数据及完成。 打开原图
Mermaid 源码
flowchart TB
    accTitle: vhost-vDPA 控制配置与直接硬件数据路径
    accDescr: 客户机使用 virtio 驱动。QEMU 通过 vhost_vdpa 内核接口和设备驱动配置队列、DMA 映射与通知,硬件在授权映射内直接访问客户机队列和报文。
    G["客户机 virtio-net 驱动"]
    R["客户机 RAM<br/>virtqueue + 报文缓冲区"]
    Q["QEMU<br/>PCI / virtio 控制接口"]
    V["宿主 vhost_vdpa<br/>队列 / IOTLB / 通知"]
    D["vDPA 设备驱动<br/>厂商配置适配"]
    H["硬件 vDPA 数据面"]
    N["外部网络"]
    G -->|"发布与回收"| R
    G -.->|"协商 / 配置"| Q
    Q -.->|"ioctl / IOTLB 更新"| V
    V -.->|"vDPA 配置操作"| D
    D -.-> H
    H <-->|"经过 DMA 地址映射<br/>读取请求 / 写回完成"| R
    H <--> N

vhost-vDPA 与 vhost-user 的宿主接口不同:前者使用内核字符设备和 vDPA 驱动框架,后者通过 Unix socket 协议与用户态进程交接资源。VFIO 直通通常让客户机控制实际设备接口并加载该设备的驱动;vDPA 则维持客户机 virtio 数据接口,由宿主驱动适配控制操作。SR-IOV 可以为某些实现提供硬件功能划分,但不是所有 vDPA 的必备条件。QEMU vhost-vDPA 定义

三、发送请求的硬件数据路径

设 TX 队列已配置完成,客户机准备报文 P1。本例采用硬件 vDPA、直接队列访问、合法 DMA 映射,先不启用数据队列的 Shadow Virtqueue。

  1. 发布。客户机写网络头、报文和描述符链,再发布 available 进度。
  2. 通知。若设备需要通知,驱动写门铃;已经配置好的 kick/通知路径让设备检查队列。
  3. 读取。设备按 IOVA 映射访问描述符和数据缓冲区,执行网络发送所需的处理。
  4. 完成。当缓冲区可以归还时,设备更新 used,并按客户机通知配置触发完成路径。
  5. 回收。客户机读 used,解除对应映射或引用,回收描述符及数据缓冲区。

直接模式由设备访问队列与报文,省去了 QEMU 普通软件收发路径的逐包解析和复制。网络处理、DMA、IOMMU 转换和通知仍消耗资源,其他环节的复制取决于设备、驱动及工作模式。设备发布 TX used 后,客户机可回收本地缓冲区;远端应用接收由网络协议确认。

设备失联、映射错误或队列停止时,要先确认设备不会继续访问旧内存,再释放队列和缓冲区。只关闭客户机驱动或停止发新请求,不足以证明之前的 DMA 已结束。可恢复状态、队列暂停、设备复位和资源释放之间必须有明确的完成边界。

四、队列启动前,需要建立三类关系

1. 能力协商与设备状态

QEMU 读取设备与后端能力,结合前端配置向客户机提供可用特性,再设置协商结果。split/packed、队列数、卸载功能、控制队列等都影响后续处理。客户机设置 DRIVER_OK 前,特性和队列必须准备好;迁移目标也要能维持客户机已经看到的接口。

2. 队列与通知:设备从哪里开始处理

配置包含队列大小、描述符/可用/完成地址和消费进度,以及 kick、call 文件描述符。常见控制操作包括 VHOST_SET_VRING_NUM、VHOST_SET_VRING_ADDR、VHOST_SET_VRING_BASE 和 VHOST_VDPA_SET_VRING_ENABLE。内核 vDPA 配置层再调用设备的队列设置方法。

kick 方向是客户机到队列消费者,call 方向是设备完成到客户机。常规路径可以连接 KVM ioeventfd / irqfd;部分配置还允许映射设备通知区域以缩短 doorbell 路径。具体是否绕过某个软件环节取决于设备和平台能力,不能把所有 vDPA 都画成完全没有宿主参与。

3. 地址与权限:设备看到的 IOVA 对应哪段 RAM

队列里写着地址,但硬件不能拿 QEMU 进程的虚拟地址直接发起 DMA。QEMU 通过 IOTLB 更新传递设备地址范围、长度、宿主用户地址和访问权限,宿主后端据此建立设备可用的映射。配置客户机 IOMMU 时,还要把映射变化与失效同步给后端。

VHOST_IOTLB_UPDATE
  iova : 设备使用的地址起点
  size : 映射长度
  uaddr: QEMU 进程中相应 RAM 的地址
  perm : 只读或读写权限
  asid : 已支持时区分设备地址空间

解除对应访问:VHOST_IOTLB_INVALIDATE

没有客户机 IOMMU 时,设备地址可以按 GPA 建立映射;有客户机 IOMMU 或影子队列时,IOVA 与 GPA 未必相等。地址转换、页固定和 DMA 隔离还涉及宿主 IOMMU 与具体驱动,不等于发送一条 UPDATE 就自动满足全部安全条件。QEMU 10.2 的 vhost-vDPA 初始化还会限制客户机 RAM discard,以配合固定内存的要求。映射更新与失效、初始化与内存生命周期约束

五、Shadow Virtqueue 与设备写入跟踪

热迁移必须知道客户机 RAM 哪些位置被修改。KVM 脏页日志主要观察客户机 CPU 对内存的写入,硬件 DMA 的修改还需要设备日志或其他协作。直接访问客户机队列的设备若不能提供所需追踪能力,迁移层就无法仅靠 CPU 脏页信息得到完整结果。

Shadow Virtqueue 在 QEMU 中增加一套面向后端的影子队列。客户机仍发布原队列;QEMU 取出请求、转换或登记相应地址,再把描述符转交到影子队列。设备消费影子队列并写回其 used,QEMU 根据关联找回客户机请求,完成内存访问记账、发布客户机 used,再通知客户机。

从直接队列访问切到影子队列转发
Shadow Virtqueue 中转描述符和完成,数据缓冲区仍可映射为同一份客户机 RAM。QEMU 因而能参与可写缓冲区的脏页记账,但增加了队列解析和事件处理。
Shadow Virtqueue 中转描述符和完成,数据缓冲区仍可映射为同一份客户机 RAM。QEMU 因而能参与可写缓冲区的脏页记账,但增加了队列解析和事件处理。 打开原图
Mermaid 源码
sequenceDiagram
    accTitle: vDPA Shadow Virtqueue 的描述符和完成转发
    accDescr: QEMU 从客户机原队列取请求,建立地址关联并放入影子队列;设备使用影子队列并访问映射后的数据缓冲区。QEMU 收到完成后向客户机回写并参与脏页记账。
    participant G as 客户机 virtqueue
    participant Q as QEMU SVQ
    participant S as 影子 virtqueue
    participant H as vDPA 设备
    participant B as 客户机数据缓冲区
    G->>Q: 发布请求,按需 kick
    Q->>Q: 保存原请求关联,翻译 DMA 地址
    Q->>S: 写入影子描述符并发布
    S->>H: 设备读取影子队列
    H->>B: 在授权映射中读写数据
    H->>S: 写影子 used 并通知
    S->>Q: 取得完成 ID / len
    Q->>Q: 校验关联,回收影子描述符
    Q->>G: 发布客户机 used,完成写入记账
    Note over Q,B: 数据区可映射为同一份 RAM;描述符中转不等于复制所有报文

例如一个 RX 请求允许设备写入客户机缓冲区 B。直接模式下,硬件可以写 B 和客户机 used,QEMU 未必看到每次变化;SVQ 模式把对应完成先交给 QEMU,QEMU 根据原请求的可写区域完成记账,再向客户机发布 used。迁移还必须停止和收尾在途访问,最终同步这些变化,不能只在某一时刻扫描 CPU 脏页位图。

数据队列中,QEMU 转发描述符和完成记录,维护影子请求与客户机请求的关联;普通数据缓冲区仍可映射到同一份客户机 RAM。控制队列还可能使用独立的影子缓冲区,由 QEMU 检查或重放 MAC、队列数量、过滤等配置命令。两类队列因此有不同的缓冲区安排。

QEMU 10.2 的网络后端在预拷贝准备阶段可停启后端,将数据队列切换为 SVQ;失败回退时再恢复相应模式。x-svq 也允许从开始就启用实验性的影子队列。一次切换依次停止处理、读取队列进度、重配映射并恢复访问,原有请求状态随这些步骤交接。迁移事件与数据队列切换、请求转发

六、能记录脏页,还要解决状态与兼容性

SVQ 提供软件协作办法,但一个设备能否迁移,还取决于暂停与恢复能力、特性集、队列状态、控制命令状态,以及目的端支持情况。QEMU 对 SVQ 支持的特性进行验证,并会设置迁移阻止原因。启用了 vDPA 或 x-svq,不足以推导“任意硬件之间都能迁移”。

需要保留的状态遗漏时的后果应核对什么
客户机已协商特性与队列布局目的端按不同格式解释相同内存源/目的能力交集及运行中的既定选择
在途请求与队列进度请求重复执行或被跳过停止完成、消费位置、恢复位置
设备写入 RAM目的端拿到旧数据或旧完成记录DMA 脏页追踪或 SVQ 记账,以及停机后的最终同步
MAC、过滤、队列等控制状态接口可见但收发行为不同状态保存、受支持命令与目的端重放
目的端 DMA 映射与网络连接设备访问无效地址或报文不能交付新宿主映射、路由和外部网络接入

具体排错时,先查看 QEMU 的迁移阻止原因,再核对后端能力、映射错误和队列停启日志。吞吐下降若只在迁移期间出现,也应检查数据队列是否已经切到 SVQ,以及 QEMU 线程是否成为新的瓶颈。性能变化可能是为了获得迁移可见性而付出的代价,需要与迁移窗口一起评价。

七、源码:配置、映射与完成转发

源码跟踪内容
QEMU net/vhost-vdpa.c网络队列与控制队列、SVQ 特性检查、迁移阶段切换
QEMU hw/virtio/vhost-vdpa.cvhost ioctl、IOTLB UPDATE/INVALIDATE、队列启动、暂停与映射
QEMU vhost-shadow-virtqueue.c客户机队列 pop、影子描述符、完成 ID 关联与回写
Linux drivers/vhost/vdpa.c用户接口到 vDPA 配置及地址映射的转换
Linux include/linux/vdpa.h设备驱动实现的配置操作和能力约定

SVQ 的完成路径先从后端 used 取回关联的 VirtQueueElement,检查 ID 和有效链,再调用 virtqueue_fill/flush 向客户机发布完成。设备写出的 ID 必须引用已提交的影子请求;来自设备的完成元数据仍需要验证,不能直接当作可信内存索引。

八、从软件后端到硬件数据面,再补齐可迁移性

vhost 系列的发展把“客户机使用什么接口”与“宿主哪里执行请求”逐渐分开。vhost-net 减少 QEMU 用户态往返,vhost-user 允许专用进程和轮询框架,vDPA 则进一步允许具有 virtio 数据面能力的设备接手。保留标准客户机驱动降低了客户机适配负担,但宿主仍要负责具体硬件的配置、内存隔离与生命周期。

直接硬件访问缩短正常路径,却让软件更难观察在途请求和 DMA 写入。2022 年的 QEMU SVQ 讨论把影子队列作为迁移脏页追踪的协作方案,后续实现可在迁移阶段切换,平时继续使用较短的数据路径。它用额外 CPU 和状态管理换取迁移可见性,并没有消除设备特性限制。SVQ 初期设计讨论

vDPA 也支持软件实现;VDUSE 提供用户态数据面与内核控制、隔离之间的接口,支持的设备类型和能力取决于版本。后端选择需要同时考虑正常吞吐、CPU 开销、尾延迟、迁移降速和故障恢复。直接模式与 SVQ 的对比尤其要标明测试处于正常运行还是迁移阶段。

九、参考资料