03 内存脏页与异步 PF 机制与实现详解
1. dirty_ring.c — 脏页环
依赖:CONFIG_HAVE_KVM_DIRTY_RING(ARM64 可选 HAVE_KVM_DIRTY_RING_ACQ_REL,弱序架构需额外内存序语义)。
动机:传统 KVM_GET_DIRTY_LOG bitmap 在大内存 VM 上 扩展性差;脏页环提供 per-vCPU 环形缓冲区,用户态增量拉取脏 GPA。
要点:
kvm_dirty_ring_used/soft_limit/full控制背压;kvm_reset_dirty_gfn清除 dirty 标记;kvm_cpu_dirty_log_size()为 weak,架构可扩展保留项数。
RK3588:作 host 跑大内存 Android VM 时,若启用 dirty ring 可降低 migration/live snapshot 开销;需 QEMU 与内核 同时支持。
2. pfncache.c — PFN 缓存
依赖:CONFIG_HAVE_KVM_PFNCACHE。
缓存 GFN→PFN 解析结果,加速 MMIO/缺页路径中重复查找。架构通过 Kconfig 声明能力;与 ARM Stage-2 页表协作在 arch 层消费。
3. async_pf.c — 异步 Page Fault
依赖:CONFIG_KVM_ASYNC_PF(x86 为主;ARM 支持情况视配置)。
流程概念:
- Guest 触发缺页 exit;
- 架构可投递 异步 PF 工作项
async_pf_execute; - 在 host
mm中 fault-in 页面后kvm_async_pf_completion唤醒 guest。
1 | static void async_pf_execute(struct work_struct *work) |
降低 KVM_RUN 线程阻塞;对 内存大、换页频繁 的 VM 有益。
4. coalesced_mmio.c — MMIO 合并
依赖:CONFIG_KVM_MMIO(ARM64 KVM select)。
问题:高频 MMIO(如 virtio 环)每次写都 VM exit 开销大。
做法:在 专用页(KVM_GET_VCPU_MMAP_SIZE 含一页)维护 ring buffer,批量提交 MMIO 写,减少 exit 次数。
头文件 coalesced_mmio.h 定义环格式;kvm_main 在 MMIO bus 上注册 coalesced zone。
5. kvm_mm.h
公共 MM 辅助声明,供 dirty_ring、kvm_main 共享,非独立功能模块。
6. 与 kvm_main 内存路径关系
| 机制 | 触发场景 |
|---|---|
| mmu_notifier | host 换出/释放 guest RAM 页 |
| dirty ring / dirty log | 迁移、增量备份 |
| async pf | guest 缺页 |
| coalesced mmio | 批量设备寄存器写 |
ARM64 guest RAM 映射实现在 arch/arm64/kvm/mmu.c(Stage-2 IPA)。
7. RK3588 实践
| 场景 | 建议 |
|---|---|
| 桌面/服务器式 VM 迁移 | 评估 dirty ring + QEMU 新版本 |
| 嵌入式轻量 VM | 常关闭,简化路径 |
| virtio 性能 | coalesced mmio + ioeventfd(见 02 文档) |
8. 小结
virt/kvm 中内存相关文件侧重 性能与可扩展性;页表与 Stage-2 仍在 arch。RK3588 host 调优 virtio/MMIO 时 coalesced_mmio 与 eventfd 通常比 dirty ring 更常触及。
正在加载留言…