997 字
5 分钟
QEMU 热迁移
🏗️ QEMU 热迁移的分层架构设计
📋 分层结构
┌─────────────────────────────────────┐
│ 通用迁移层 (migration/) │ ← 您之前看到的代码
│ - 传输协议管理 │
│ - 调度和流控 │
│ - 错误处理 │
└─────────────────────────────────────┘
↕️ VMState接口
┌─────────────────────────────────────┐
│ 架构特定层 (target/*/machine.c) │ ← 架构相关处理
│ - CPU寄存器状态 │
│ - 架构特定控制状态 │
│ - 特殊功能寄存器 │
└─────────────────────────────────────┘
🎯 架构相关处理的关键组件
1️⃣ VMState 描述符(每个架构都有)
RISC-V 架构示例:
const VMStateDescription vmstate_riscv_cpu = {
.name = "cpu",
.version_id = 10,
.minimum_version_id = 10,
.post_load = riscv_cpu_post_load,
.fields = (const VMStateField[]) {
VMSTATE_UINTTL_ARRAY(env.gpr, RISCVCPU, 32), // 32个通用寄存器
VMSTATE_UINT64_ARRAY(env.fpr, RISCVCPU, 32), // 32个浮点寄存器
VMSTATE_UINTTL(env.pc, RISCVCPU), // 程序计数器
VMSTATE_UINT64(env.mstatus, RISCVCPU), // 机器状态寄存器
VMSTATE_UINT64(env.mip, RISCVCPU), // 中断挂起寄存器
VMSTATE_UINT64(env.mie, RISCVCPU), // 中断使能寄存器
// ... 更多RISC-V特定状态
}
};
x86 架构示例:
const VMStateDescription vmstate_x86_cpu = {
.name = "cpu",
.version_id = 12,
.minimum_version_id = 11,
.pre_save = cpu_pre_save,
.post_load = cpu_post_load,
.fields = (const VMStateField[]) {
VMSTATE_UINTTL_ARRAY(env.regs, X86CPU, CPU_NB_REGS), // 通用寄存器
VMSTATE_UINTTL(env.eip, X86CPU), // 指令指针
VMSTATE_UINTTL(env.eflags, X86CPU), // 标志寄存器
VMSTATE_SEGMENT_ARRAY(env.segs, X86CPU, 6), // 段寄存器
VMSTATE_UINTTL(env.cr[0], X86CPU), // 控制寄存器
// ... 更多x86特定状态(FPU、SSE、AVX等)
}
};
2️⃣ 架构状态注册机制
// 在CPU创建时(cpu-target.c)
if (qdev_get_vmsd(DEVICE(cpu)) == NULL) {
vmstate_register(NULL, cpu->cpu_index, &vmstate_cpu_common, cpu); // 通用CPU状态
}
if (cpu->cc->sysemu_ops->legacy_vmsd != NULL) {
vmstate_register(NULL, cpu->cpu_index, cpu->cc->sysemu_ops->legacy_vmsd, cpu); // 架构特定状态
}
3️⃣ CPU 状态同步
// 在关键迁移点调用
void cpu_synchronize_all_states(void)
{
CPUState *cpu;
CPU_FOREACH(cpu) {
cpu_synchronize_state(cpu); // 同步每个CPU的架构特定状态
}
}
🔄 架构相关代码的调用时机
📍 在迁移流程中的关键调用点
// 1. 迁移设置阶段 - migration_thread()
qemu_savevm_state_setup(s->to_dst_file);
↓
QTAILQ_FOREACH(se, &savevm_state.handlers, entry) {
// 遍历所有注册的VMState处理器,包括每个CPU的架构特定状态
vmstate_save(f, se, ms->vmdesc); // ← 架构特定代码在这里被调用
}
// 2. 迁移完成阶段 - migration_completion_precopy()
cpu_synchronize_all_states(); // ← 同步所有CPU的架构状态
qemu_savevm_state_complete_precopy(s->to_dst_file, false, s->block_inactive);
↓
// 保存所有架构特定的CPU状态
🎯 实际的架构差异处理
不同架构保存的状态完全不同:
架构 | 特有状态示例 |
---|---|
RISC-V | 特权级寄存器、PMP 配置、Vector 扩展状态 |
x 86 | 段寄存器、FPU、SSE/AVX、控制寄存器 |
ARM | 协处理器寄存器、NEON 状态、安全扩展 |
PowerPC | SPR 寄存器、AltiVec、Book 3 S 特定状态 |
架构特定的后处理:
// RISC-V架构的迁移后处理
static int pmp_post_load(void *opaque, int version_id)
{
RISCVCPU *cpu = opaque;
CPURISCVState *env = &cpu->env;
// 重新计算PMP规则
for (i = 0; i < MAX_RISCV_PMPS; i++) {
pmp_update_rule_addr(env, i); // RISC-V特有的PMP处理
}
pmp_update_rule_nums(env);
return 0;
}
🔍 为什么您之前没看到架构相关代码?
📂 代码组织策略
- 抽象层分离: 迁移框架 (
migration/
) 专注于传输机制 - 插件化设计: 架构特定代码通过 VMState 接口插入
- 统一调用: 通过
qemu_savevm_state_*
系列函数统一调用
🔗 关键连接点
// 在migration_thread中的关键调用
qemu_savevm_state_setup(s->to_dst_file); // 设置阶段:注册所有VMState
qemu_savevm_state_iterate(s->to_dst_file); // 迭代阶段:保存可迭代状态
cpu_synchronize_all_states(); // 同步阶段:确保架构状态一致
qemu_savevm_state_complete_precopy(); // 完成阶段:保存所有架构状态
🎯 实际架构相关工作
✅ 每次迁移都会处理的架构特定内容:
- CPU 寄存器: 通用寄存器、特殊寄存器、控制寄存器
- 浮点状态: FPU、SIMD、向量寄存器状态
- 特权状态: 特权级别、内存管理、中断状态
- 扩展功能: 架构特定的扩展(如 x 86 的 AVX、ARM 的 NEON 等)
- 系统寄存器: CSR、MSR、协处理器寄存器等
🔧 架构适配机制
- 编译时适配: 每个架构编译进对应的 machine. c
- 运行时注册: CPU 创建时自动注册其 VMState 描述符
- 统一接口: 通过 VMState 框架提供统一的保存/恢复接口
这种设计使得通用迁移代码可以处理所有架构,而架构特定细节则由对应的 target 代码负责!
[1 tool called]