ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

QEMU VFIO 设备实时迁移完全指南:pre-copy、P2P 静止态与 multifd 状态传输

QEMU VFIO 设备实时迁移完全指南:pre-copy、P2P 静止态与 multifd 状态传输 虚拟化硬件仿真【免费下载链接】qemuOfficial QEMU mirror. Please see https://www.qemu.org/contribute/ for how to submit changes to QEMU. Pull Requests are disabled. Please only use release tarballs from the QEMU website.项目地址https://gitcode.com/gh_mirrors/qe/qemu点击查看免费下载VFIO 设备迁移是 QEMU 虚拟机迁移中最复杂也最关键的环节之一它要求源主机保存 guest 使用的直通设备如 GPU、网卡、NVMe 控制器的全部内部状态并在目标主机上精确恢复。本文以 docs/devel/migration/vfio.rst 为骨架结合 QEMU 源码hw/vfio/migration.c、hw/vfio/pci.c与内核 uAPI 头文件linux-headers/linux/vfio.h系统讲解 VFIO 迁移的两阶段模型、设备状态机、脏页跟踪机制、多设备 P2P 协同、以及 QEMU 10.0 引入的 multifd 状态传输方案。读完本文你将掌握 VFIO 迁移的完整工作原理、QEMU 侧设备 hook 的实现逻辑以及x-pre-copy-dirty-page-tracking、x-migration-multifd-transfer等关键属性的实际用途与默认行为。VFIO 设备迁移概述两阶段模型虚拟机迁移的本质是把源主机上每个设备的状态保存下来再在目标主机上恢复。对于 VFIO 直通设备这一过程由 QEMU 的 VFIO 迁移模块与内核 vendor driver 协同完成。从整体上看VFIO 设备迁移由两个阶段组成可选的 pre-copy预拷贝阶段迭代式进行允许 guest 在设备状态向目标端传输的同时继续运行从而显著缩短 VM 的总停机时间stop-and-copy停止拷贝阶段暂停 guest 与设备一次性拷贝剩余状态直到数据收敛为 0。Pre-copy 阶段非常适合迁移状态数据量巨大的 VFIO 设备——它把大量数据的传输提前到停机之前完成。设备通过在内核VFIO_DEVICE_FEATURE_MIGRATIONioctl 的返回 flags 中上报VFIO_MIGRATION_PRE_COPY标志见 linux-headers/linux/vfio.h来选择加入opt-inpre-copy 支持。从源码角度看hw/vfio/migration.c 中定义了与数据量相关的两个关键常量能帮助我们理解设备状态规模的范围/* VFIO 设备迁移量小则几 KB大则可达数 GB该值需覆盖最坏情况 */ #define VFIO_MIG_STOP_COPY_SIZE (100 * GiB) /* 基于 mlx5 设备迁移总迁移量通常数百 MB实测确定的默认数据缓冲大小 */ #define VFIO_MIG_DEFAULT_DATA_BUFFER_SIZE (1 * MiB)这些注释说明不同 vendor driver 的迁移状态大小差异巨大QEMU 因此采用了迭代 缓冲的通用设计。进一步降低停机时间switchover-ack 与 initial bytes当设备支持 pre-copy 时还可以通过开启switchover-ack 迁移能力migration capability进一步压缩停机时间。其原理建立在 VFIO 迁移 uAPI 对initial bytes初始字节的定义之上uAPI 将 pre-copy 数据流划分为 initial bytes 与 dirty bytes 两类官方建议在停止源 VM 之前应先把 initial bytes 发送到目标端并完成加载开启 switchover-ack 后QEMU 会保证这一建议被强制满足因此可以进一步减少停机时间。以 mlx5 设备为例initial bytes 中保存的是元数据用于在目标端触发耗时的资源预分配。尽管 initial bytes 体积小、发送耗时可忽略但目标端加载它们可能花费大量时间。如果这段预分配被推迟到停机窗口内完成会显著拉长 downtime而 switchover-ack 保证预分配在停机前就已就绪。VFIO_PRECOPY_INFO_REINITinitial bytes 的重置语义initial bytes 最初被定义为单调递减从非零初始值随读取逐渐归零。但存在一些场景需要在 pre-copy 期间传输新的initial bytes 数据块例如设备发生重配置。为此uAPI 提供了VFIO_PRECOPY_INFO_REINIT输出标志定义于 linux-headers/linux/vfio.h支持该特性的设备可以报告一个全新的 initial_bytes 值不受之前任何上报值的约束此时 QEMU 会重新请求一次 switchover ACK确保新的 initial bytes 在切换switch over前已加载到目标端。内核头文件对该语义有更详细的说明见 linux-headers/linux/vfio.h 中VFIO_MIG_GET_PRECOPY_INFOioctl 的注释该 ioctl 仅在 pre-copy 状态有效返回的vfio_precopy_info结构包含initial_bytes、dirty_bytes与flags三个字段其中initial_bytes从非零值开始、随数据被读出而减少dirty_bytes则从零开始、随设备内部状态变更而增减。内核还建议只有当initial_bytes归零后才应离开 PRE_COPY 进入 STOP_COPY过早切换只会让迁移更慢。多设备 P2P 迁移与 P2P 静止状态当一台 guest 同时直通多个设备、且设备之间存在P2PPeer-to-PeerDMA 事务例如 GPU 与 RDMA 网卡之间的直接数据交换时逐个停止/启动设备会破坏事务的原子性。为此VFIO 迁移 uAPI 定义了中间态的 P2P 静止状态P2P quiescent state处于 P2P 静止状态时设备不能发起新的 P2P DMA 事务但可以响应到达的 P2P 事务设备进入该状态时所有未完成的 P2P 事务保证已经完成迁移时所有支持 P2P 迁移的设备先统一进入 P2P 静止状态然后才被停止或启动。这样做的原因很直观对多个设备的停止/启动并非原子地一次性完成先让所有设备进入静止态可以保证任何一台设备停、启的瞬间不会与其他设备发生半中断的 P2P 事务从而在 P2P 层面保证迁移安全。对应的设备迁移状态见 linux-headers/linux/vfio.h 的vfio_device_mig_state枚举enum vfio_device_mig_state { VFIO_DEVICE_STATE_ERROR 0, VFIO_DEVICE_STATE_STOP 1, VFIO_DEVICE_STATE_RUNNING 2, VFIO_DEVICE_STATE_STOP_COPY 3, VFIO_DEVICE_STATE_RESUMING 4, VFIO_DEVICE_STATE_RUNNING_P2P 5, VFIO_DEVICE_STATE_PRE_COPY 6, VFIO_DEVICE_STATE_PRE_COPY_P2P 7, VFIO_DEVICE_STATE_NR, };由此派生出两条迁移准入规则单设备迁移无论是否支持 P2P 迁移均被允许多设备迁移仅当所有设备都支持 P2P 迁移时才被允许。QEMU 侧的迭代式设备 hook 实现VFIO 迁移模块通过注册SaveVMHandlers迁移回调集合接入 QEMU 主迁移框架各 hook 的注册见 hw/vfio/migration.c。下表汇总了文档描述的每个 hook 及其职责Hook职责非 multifd 模式行为multifd 模式行为save_setup在源端建立迁移设置 pre-copy 状态同左load_setup在目标端将设备置为_RESUMING状态设置 RESUming同左save_query_pending上报 vendor driver 尚未保存的剩余数据量汇报 pending 数据同左is_active_iterate指示save_live_iterate仅在 pre-copy 状态激活判断是否处于 pre-copy同左save_live_iterate迭代读取 pre-copy 阶段数据从设备读取数据同左switchover_start切换switch over开始时被调用NOP启动线程将 multifd 收到的数据按序重组并加载进设备save_state保存设备 config space保存 config space仅发送一个虚拟的 EOS 标记save_complete完成 stop-and-copy 拷贝置_STOP_COPY并迭代拷贝至数据为 0仅发送虚拟 EOS 标记save_complete_precopy_threadstop-and-copy 阶段的线程处理NOP置_STOP_COPY迭代读取并排队交给 multifd 传输最后连 config space 一起入队load_state加载主迁移通道传来的 config 段与数据段加载同左load_state_buffer加载经 multifd 通道到达的设备状态与 config不使用加载 multifd 缓冲save_cleanup/load_cleanup迁移相关清理清理同左从实现细节看hw/vfio/migration.c 中vfio_migration_set_state()是贯穿所有 hook 的核心状态切换函数hw/vfio/migration.c它通过VFIO_DEVICE_FEATURE_SET | VFIO_DEVICE_FEATURE_MIG_DEVICE_STATE组合 flags 下发 ioctl把vfio_device_feature_mig_state中的目标状态写入内核若切换失败则尝试把设备恢复到recover_state恢复失败则回退到VFIO_DEVICE_RESET重置设备并把状态置回_RUNNING。该函数还会处理状态切换成功后返回的data_fd迁移数据文件描述符后续的迭代读写都基于这个 fd 进行。状态变更的驱动机制除显式的 hook 调用外VFIO 迁移代码还依赖两类 change handler 来驱动状态机VM state change handler当 VM 状态在运行 ↔ 不运行之间切换时同步切换 VFIO 设备状态Migration state change handler当迁移状态发生特定变化时触发设备状态迁移例如迁移失败或取消时把设备状态恢复回_RUNNING。这两条联动路径保证了 VFIO 设备状态始终与 VM/迁移全局状态保持一致也是失败自动恢复语义的实现基础。系统内存脏页跟踪VFIO 迁移必须把设备 DMA 写入的系统内存页标记为脏才能保证目标端内存一致性。QEMU 通过 memory listener 回调接入脏页跟踪log_global_start/log_global_stop通知 VFIO 脏页跟踪模块启动/停止跟踪log_sync从脏页跟踪模块查询脏页 bitmap并把被 VFIO 设备 DMA 过的系统内存页标记为脏bitmap按 container 粒度查询。目前脏页跟踪有两条实现路径设备脏页跟踪Device dirty tracking由设备自身记录并上报其 DMA。仅当设备具备跟踪自身 DMA 的能力时才可用。能力的探测、跟踪的启停以及 bitmap 的同步都通过 DMA logging uAPI 完成具体结构见 linux-headers/linux/vfio.h 的vfio_device_feature_dma_logging_control与 linux-headers/linux/vfio.h 的vfio_device_feature_dma_logging_report及其注释VFIO IOMMU 模块由 IOMMU 完成脏页跟踪。但文档明确指出目前 IOMMU 尚无脏页跟踪支持因此所有页都会被永久标记为脏除非设备驱动通过外部 API 钉住pin页面——此时仅这些钉住的页面被永久标记为脏。如果上述两种方式都不可用则 QEMU 将所有页永久标记为脏即最保守的全量拷贝。pre-copy 阶段的脏页跟踪与 opt-out 属性默认情况下脏页在 pre-copy 与 stop-and-copy 两个阶段都会被跟踪即标记为脏的页会在两个阶段都拷贝到目标端。在 pre-copy 阶段持续发现脏页能帮助 QEMU预测能否达成预期的停机时间预算如果 pre-copy 期间脏页持续出现QEMU 就会预判 stop-and-copy 阶段同样会持续产生脏页从而相应调整对 downtime 的估计。QEMU 为每个设备提供了独立的 opt-out 属性x-pre-copy-dirty-page-tracking设为 off 后pre-copy 阶段不再查询脏页 bitmap所有脏页将只在 stop-and-copy 阶段拷贝。该属性在 hw/vfio/pci.c 中定义DEFINE_PROP_ON_OFF_AUTO(x-pre-copy-dirty-page-tracking, VFIOPCIDevice, vbasedev.pre_copy_dirty_page_tracking, ON_OFF_AUTO_ON),它支持on/off/auto三态默认值为 on即默认在 pre-copy 阶段也跟踪脏页。命令行用法示例-device vfio-pci,host0000:65:00.0,x-pre-copy-dirty-page-trackingoff启用 vIOMMU 时的脏页跟踪当 guest 使用 vIOMMU 时情况有所不同pre-copy 阶段IO 虚拟地址IOVA范围可能被 unmap。此时 unmap ioctl 会返回该范围内的脏页QEMU 把对应的 guest 物理页标记为脏stop-and-copy 阶段改用 IOMMU notifier 获取已映射页面的回调然后针对这些已映射范围从 VFIO IOMMU 模块拉取脏页 bitmap限制如果启用了 vIOMMU 的同时启用了设备脏页跟踪则实时迁移会被阻止live migration will be blocked。实时迁移过程中的状态流转文档用两个状态机图完整刻画了 VFIO 设备在实时迁移中的状态变化。括号内的三元组依次表示(VM 状态, 迁移状态, VFIO 设备状态)。以下内容直接继承自文档原文适用于同时支持 pre-copy 与 P2P 的设备不支持这两者的设备流程类似只是跳过相应状态。保存路径源端QEMU normal running state (RUNNING, _NONE, _RUNNING) | migrate_init spawns migration_thread Migration thread then calls each devices .save_setup() (RUNNING, _SETUP, _PRE_COPY) | (RUNNING, _ACTIVE, _PRE_COPY) If device is active, get pending_bytes by .state_pending_{estimate,exact}() If total pending_bytes threshold_size, call .save_live_iterate() Data of VFIO device for pre-copy phase is copied Iterate till total pending bytes converge and are less than threshold | On migration completion, the vCPUs and the VFIO device are stopped The VFIO device is first put in P2P quiescent state (FINISH_MIGRATE, _ACTIVE, _PRE_COPY_P2P) | Then the VFIO device is put in _STOP_COPY state (FINISH_MIGRATE, _ACTIVE, _STOP_COPY) .save_complete() is called for each active device For the VFIO device: in the non-multifd mode iterate in .save_complete() until pending data is 0 In the multifd mode this iteration is done in .save_complete_precopy_thread() instead. | (POSTMIGRATE, _COMPLETED, _STOP_COPY) Migraton thread schedules cleanup bottom half and exits | .save_cleanup() is called (POSTMIGRATE, _COMPLETED, _STOP)关键点解读迁移线程migration thread由migrate_init派生随后逐个调用每个设备的.save_setup()pre-copy 的迭代收敛由state_pending_{estimate,exact}()提供的 pending 字节数与threshold_size阈值共同驱动停机时刻设备先进入 P2P 静止态_PRE_COPY_P2P再进入_STOP_COPY非 multifd 模式下迭代发生在save_complete()内部multifd 模式下则转移给save_complete_precopy_thread()线程完成。恢复路径目标端Incoming migration calls .load_setup() for each device (RESTORE_VM, _ACTIVE, _STOP) | For each device, .load_state() is called for that device section data transmitted via the main migration channel. For data transmitted via multifd channels .load_state_buffer() is called instead. (RESTORE_VM, _ACTIVE, _RESUMING) | At the end, .load_cleanup() is called for each device and vCPUs are started The VFIO device is first put in P2P quiescent state (RUNNING, _ACTIVE, _RUNNING_P2P) | (RUNNING, _NONE, _RUNNING)恢复路径的要点目标端通过.load_setup()把设备置于_RESUMING状态主迁移通道的数据段由.load_state()加载multifd 通道到达的数据则由.load_state_buffer()加载vCPU 启动前设备同样先进入 P2P 静止态_RUNNING_P2P再回到_RUNNING保证与源端停止顺序对称的 P2P 安全性。Postcopy当前不支持Postcopy后拷贝迁移目前不支持 VFIO 设备。这意味着 VFIO 设备只能走 pre-copy stop-and-copy 的同步路径不能把设备状态推迟到目标端 VM 启动后再传输。对于包含 VFIO 直通设备的迁移配置QEMU 迁移框架会相应拒绝 postcopy 能力相关约束可结合 docs/devel/migration/postcopy.rst 对照理解。Multifd 状态传输QEMU 10.0 起的低停机方案从QEMU 10.0起VFIO 设备的_STOP_COPY状态可以通过multifd 通道传输相关实现见 hw/vfio/migration-multifd.c。这一能力带来两个直接收益降低停机时间——尤其在多 VFIO 设备或单个设备迁移状态很大的场景下多通道并行传输明显压缩 stop-and-copy 窗口并行化——置_STOP_COPY状态与保存 config space 的操作被放到独立线程中执行即前述save_complete_precopy_thread。multifd VFIO 状态传输由 VFIO 设备属性x-migration-multifd-transfer控制属性定义于 hw/vfio/pci.cDEFINE_PROP(x-migration-multifd-transfer, VFIOPCIDevice, vbasedev.migration_multifd_transfer, vfio_pci_migration_multifd_transfer_prop, OnOffAuto, .set_default true, .defval.i ON_OFF_AUTO_AUTO),它支持on/off/auto三态默认值为 AUTO——即在其余配置支持的前提下自动尝试使用 multifd 通道传输 VFIO 设备状态。安全性与限流属性由于目标端 QEMU 需要按序加载设备状态缓冲因此必须把先到达的缓冲排队直到可以被加载进设备。一个潜在风险是恶意的源 QEMU 理论上可诱导目标端无限分配内存用于缓冲在途buffers-in-flight数据。为此 QEMU 提供属性x-migration-max-queued-buffers-size定义于 hw/vfio/pci.cDEFINE_PROP_SIZE(x-migration-max-queued-buffers-size, VFIOPCIDevice, vbasedev.migration_max_queued_buffers_size, UINT64_MAX),该属性用于限制目标端排队中的 VFIO 设备状态缓冲总大小。但文档也明确指出默认取舍默认值为UINT64_MAX即限制被禁用。原因是在大多数 VFIO 实时迁移场景中恶意源导致目标 OOM并非现实威胁而合理取值又高度依赖具体部署因此默认放开、由管理员按需收紧。平台相关的加载顺序部分主机平台例如ARM64要求 VFIO 设备 config 只能在所有可迭代iterable数据加载完毕之后、于非可迭代数据的加载阶段再加载。这种加载顺序的互锁行为由属性x-migration-load-config-after-iter控制定义于 hw/vfio/pci.cDEFINE_PROP_ON_OFF_AUTO(x-migration-load-config-after-iter, VFIOPCIDevice, vbasedev.migration_load_config_after_iter, ON_OFF_AUTO_AUTO),默认值同样为AUTO仅在确实需要该约束的平台如 ARM64上启用config 延后加载。小结与实战速查VFIO 设备迁移在 QEMU 中是一条完整、精细的工程链路两阶段模型pre-copy / stop-and-copy解决大数据量迁移的停机问题switchover-ack 与VFIO_PRECOPY_INFO_REINIT解决 initial bytes 的送达保证与重配置场景P2P 静止态保证多设备迁移的原子安全脏页跟踪设备自跟踪 / IOMMU 模块 / 全量兜底保证内存一致性multifd 通道则在 QEMU 10.0 起提供更低的停机窗口。实战配置速查-device vfio-pci,...属性均可在 hw/vfio/pci.c 的属性表中找到属性取值默认用途x-pre-copy-dirty-page-trackingon/off/autoon是否在 pre-copy 阶段查询脏页 bitmapoff 则脏页仅在 stop-and-copy 拷贝x-migration-multifd-transferon/off/autoauto是否经 multifd 通道传输_STOP_COPY状态x-migration-max-queued-buffers-size字节数UINT64_MAX禁用限制目标端排队中的 VFIO 状态缓冲总大小x-migration-load-config-after-iteron/off/autoauto是否在可迭代数据全部加载后才加载设备 configARM64 等平台必需migration-eventsboolfalse是否发送 VFIO 迁移 QAPI 事件见 hw/vfio/migration.c需要深入底层时uAPI 的权威说明位于内核头文件 linux-headers/linux/vfio.hvfio_device_mig_state结构注释详述了完整的设备状态机与各状态转换vfio_device_feature_dma_logging_control/vfio_device_feature_dma_logging_report注释则解释了设备脏页跟踪的完整 uAPI。QEMU 侧的实现主入口是 hw/vfio/migration.cmultifd 路径见 hw/vfio/migration-multifd.c。如果你正在部署 GPU/RDMA 直通环境的实时迁移或计划调优大规模 VFIO 迁移的停机时间以上机制与属性就是最直接的入手点。赞分享虚拟化硬件仿真【免费下载链接】qemuOfficial QEMU mirror. Please see https://www.qemu.org/contribute/ for how to submit changes to QEMU. Pull Requests are disabled. Please only use release tarballs from the QEMU website.项目地址https://gitcode.com/gh_mirrors/qe/qemu点击查看免费下载相关推荐RuView 复现审计 WiFlow-STDWiFi 姿态模型的 0.08% 翻车、重训回血与 30 倍瘦身实测RuView 复现审计 WiFlow STDWiFi 姿态模型的 0.08% 翻车、重训回血与 30 倍瘦身实测 WiFlow STD 是 2026 年一篇宣虚拟化硬件仿真Cloud Hypervisor 在线迁移Live Migration完全指南UNIX Socket、TCP、TLS 加密与 VFIO 设备迁移Cloud Hypervisor 在线迁移Live Migration完全指南UNIX Socket、TCP、TLS 加密与 VFIO 设备迁移 Clou云原生From 与 Intocomprehensive-rust 中类型转换 trait 的完整实战指南From 与 Intocomprehensive rust 中类型转换 trait 的完整实战指南 本文以 Google Android 团队的 Rust 课虚拟化硬件仿真上一篇终极指南shadPS4智能游戏历史记录与快速继续功能详解下一篇Triton中间表示TTIR、TTGIR和LLVM IR的多层设计创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表