一、VFIO 热迁移之状态机

前言

VFIO 的热迁移技术是一个相对来说比较新的特性,它相较于 vdpa 是可以直通到虚拟机内部,这样会有着更好的性能,但也存在一个问题就是通用性差一点,如不是标准的 virtio 设备,那么就需要在虚拟机里面安装专属的设备驱动,这在云厂商来说是一个极大的挑战,但是对于一些非网络设备如 GPU、RDMA 等设备追求性能优先的设备有着极大的优势,同时 virtio 协议已经支持这一特性,我们就借着 virtio-net 设备好好的来理解一下这个技术,同时也梳理一下,实现该方案,我们需要做什么,如放在 RDMA、SNIC等卡上,逻辑和软件需要做什么具体的事情。

迁移整体框架图

这个图主要是在热迁移时候,QEMU 的函数调用路径和 kernel 驱动里面的一些状态机变化,主要涉及到源虚拟机和目的虚拟机

sequenceDiagram
    participant Source QEMU
    participant Dest QEMU
    participant Source VFIO
    participant Dest VFIO

    Note over Source QEMU, Dest QEMU: 初始状态: VM 在源端运行

    rect rgba(200, 255, 200, 0.3)
        Note over Source QEMU, Source VFIO: 阶段 1: 迁移设置与预拷贝 (Pre-copy)
        Source QEMU->>Source VFIO: .save_setup()
        Note right of Source VFIO: 设备状态: _RUNNING -> _PRE_COPY
        Source QEMU->>Dest QEMU: 迁移设置握手
        Note over Dest QEMU, Dest VFIO: VFIO设备状态已为 _STOP (由VM状态变化触发)
        Dest QEMU->>Dest VFIO: .load_setup()
        Note right of Dest VFIO: 设备状态: _STOP -> _RESUMING

        loop 迭代预拷贝
            Source QEMU->>Source VFIO: .save_live_iterate()
            Source VFIO-->>Source QEMU: 预拷贝数据块
            Source QEMU->>Dest QEMU: 传输数据块
            Dest QEMU->>Dest VFIO: .load_state_buffer() (存储数据)
            Note right of Dest VFIO: 设备状态: _RESUMING (累积状态中)
        end
        Note over Source QEMU, Source VFIO: 预拷贝持续直到数据收敛...
    end

    rect rgba(255, 228, 181, 0.4)
        Note over Source QEMU, Source VFIO: 阶段 2: 切换 (Stop and Copy)
        Source QEMU->>Source QEMU: 暂停 vCPUs
        Note over Source QEMU, Source VFIO: 进入 P2P 静默状态
        Source QEMU->>Source VFIO: 转换到 P2P 静默状态
        Note right of Source VFIO: 设备状态: _PRE_COPY -> _PRE_COPY_P2P

        Note over Source QEMU, Source VFIO: 进入停止并拷贝状态
        Source QEMU->>Source VFIO: .save_live_complete_precopy()
        Note right of Source VFIO: 设备状态: _PRE_COPY_P2P -> _STOP_COPY
        Source VFIO-->>Source QEMU: 最终设备状态数据
        Source QEMU->>Dest QEMU: 传输最终状态数据
    end

    rect rgba(173, 216, 230, 0.4)
        Note over Dest QEMU, Dest VFIO: 阶段 3: 恢复与运行
        Dest QEMU->>Dest VFIO: .load_state() / .load_state_buffer()
        Note right of Dest VFIO: 加载最终状态. 设备状态: _RESUMING (持续加载)
        Dest QEMU->>Dest VFIO: .load_cleanup()
        Dest QEMU->>Dest QEMU: 恢复 vCPUs
        Note over Dest QEMU, Dest VFIO: VM状态变为RUNNING,触发VFIO设备状态转换
        Dest VFIO-->>Dest VFIO: (vmstate_change_prepare 被调用)
        Note right of Dest VFIO: 设备状态: _RESUMING -> _RUNNING_P2P
        Dest VFIO-->>Dest VFIO: (vmstate_change 被调用)
        Note right of Dest VFIO: 设备状态: _RUNNING_P2P -> _RUNNING
        Note over Dest QEMU, Dest VFIO: VM 现在在目标端运行
    end

    rect rgba(211, 211, 211, 0.5)
        Note over Source QEMU, Source VFIO: 阶段 4: 清理
        Source QEMU->>Source VFIO: .cleanup()
        Note right of Source VFIO: 设备状态: _STOP_COPY -> _STOP
    end                                                                     

原虚拟机

stateDiagram-v2                                                 
    direction LR                                                
    [*] --> _RUNNING: 正常运行                                  
    _RUNNING --> _PRE_COPY: migrate_init() / .save_setup()                                                        
    _PRE_COPY --> _PRE_COPY: .save_live_iterate()                                                                  
    _PRE_COPY --> _PRE_COPY_P2P: vCPUs 停止 / P2P 静默                                                                                                                            
    _PRE_COPY_P2P --> _STOP_COPY: .save_live_complete_precopy()                                                   
    _STOP_COPY --> _STOP: 迁移完成 / .cleanup()                                                                  
    _STOP --> [*]: 清理完成                                     

目的虚拟机

 stateDiagram-v2                                              
     direction LR                                             
     [*] --> _STOP: 接收迁移 / .load_setup()                                                                
     _STOP --> _RESUMING: .load_state() / .load_state_buffer()                                              
     _RESUMING --> _RUNNING_P2P: .load_cleanup() / vCPUs 启动                                                          
     _RUNNING_P2P --> _RUNNING: 转换到完全运行状态                                                               
     _RUNNING --> [*]: 正常运行                               

总结

1、通过上面三个图,我们大概了解了在热迁移 QEMU 的一些行为,主要是状态机的变化,但还是比较浅显的
2、虽然很清晰了状态机的变化,但是这些命令是如何下发下来的,virtio 设备又需要做什么适配、DMA 的脏页是如何记录的、原虚拟机的设备vring 状态在目的虚拟机是如何恢复的..etc,都需要我们一一了解

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇