QEMU-KVM内核虚拟化概述
本文翻译自https://www.linux-kvm.org/page/Memory
主要内容为qemu/kvm的内存虚拟化的架构描述(的梗概)。
这是官网十年前的一篇文章,细节大家不要细扣,大概了解内存虚拟化和EPT的相关架构就行。
guest修改页表对host的影响
由于Linux内核的layz-mode得到策略, qemu/kvm会为guest分配虚拟内存空间,但直到访问时,才真正分配物理空间。
以前(指使用shadow page table时),每当guest修改页表, 必然会影响host. host会确认2点:
- guest放到页表中的entry是有效的
- entry没有访问不被允许访问的memory
为什么会影响host呢? 有2方面的机制影响.
- 虚拟化硬件使用的页表集和guest使用的页表是分离的.首先guest在自己的页表上做了修改,然后host发现了这个修改,确认该修改并在硬件访问的真实页表中做修改.guest不能直接访问和操作真实页表.这就是SPT(shadow page table).
- VMX/AMD-v扩展允许当guest尝试设置指向base page table(CR3)的指针时, 就trap(发生异常).
shadow page table机制的缺点
SPT机制下,缺点在于:
- 每次访问页表都必须经历guest+host都访问的过程
- guest访问一次,host可能要访问25次,成本极高
- 确认和维护SPT成本非常高
EPT/NPT的引入
AMD和Intel提出了EPT/NPT来解决这些问题(SPT的缺点). EPT/NPT在硬件层面提供了一系列结构,能够直接将GPA转化成HPA,而不用经历每次访问页表都必须guest+host访问的过程.
问题在于, 如果host把我们使用的page table 交换出去了,我们必须更新EPT/NPT里面的结构.
解决办法是Linux称为mmu_notifier的东西. 在kernel释放或交换出去这些内存之前,kvm/qemu guest会收到host的意图通知. kvm/qemu guest会将即将被host使用的page从SPT或EPT结构中移除, 在guest做完移除工作之后, host就可以对这些page做它想做的操作了.
Fault-in path(产生page fault的处理路径)
- QEMU调用malloc()并且为该page分配虚拟地址空间,但是没有对应的物理空间.(也就是就分配了个名头)
- guest访问了它认为是一个物理地址的东西, 但是因为没有分配对应的物理空间, traps into host了
- host kernel看到了一个page fault, 对之前malloc()的区域调用do_page_fault()处理这个page fault,如果没什么问题,就分配一些memory给到该区域.
- host kernel 创建了pte_t来连接malloc()好的虚拟地址和分配的物理地址, 在pte_t中创建rmap entry, 把pte_t放到LRU等
- mmu_notifier和change_pte()被调用,允许kvm为新的page创建一个EPT entry
- 完成处理page fault, VMRESUME, guest继续运行
Swap-out path(当host 内存不够用时)
如果host面临memory压力,会发生什么情况呢?
上面提到的,之前分配给guest的物理page发现自己已经上了待退休名单, kernel决定该page下岗,接下来会发生:
- host kernel使用rmap结构找出该物理page被映射到哪个VMA(vm_area_struct)中去了
- host kernel先寻找与该VMA关联的mm_struct,然后再遍历Linux page tables,寻找该page的host hardware page table entry(pte_t).
- host kernel 将该page交换出去,并清除了pte_t, 但是,在释放该page之前:
- host kernle 调用了mmu_notifier invalidate_page(). 这俩东西寻找EPT结构中的该page的entry,然后移除掉.
- 下次访问该page时,就会到fault-in path中去.
逻辑链
某个时刻guest访问某物理地址(它认为的) ==》 Page Fault ==》 trap into host ==》 为产生page fault的地址分配实际空间(Fault-in path) ==》 回到guest继续运行... 运行了一段时间 ==》 host的内存不够用了,要收回之前分配给guest的内存 ==》 给guest一个意图通知 ==》 guest会意,将EPT中的映射删除 ==》 host收回之前分配的物理空间 ==> 某个时刻guest访问某物理地址(它认为的)
__EOF__

本文链接:https://www.cnblogs.com/haiyonghao/p/14440135.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角【推荐】一下。您的鼓励是博主的最大动力!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律