KVM影子页表

      2019年是崭新的一年,Linux kernel 5.0 低调发布了,给我的感觉就是,牛人不断在飞跃,我们也要策马奔腾赶紧追赶才有些许出路。

       内核子系统众多,我发现KVM是个非常有意思的子系统,对cpu,内核,IO的虚拟化玩的太溜了,一些技巧真是令人折服,简直就是一个超级魔法师,也可以成为"骗术”,而且还是里因外和。话不多说,进入主题。

       KVM虚拟化,对虚拟cpu很好理解,cpu采用两种模式,一种是root模式下的0 – 3特权级,另一种是非root模式下的0 - 3特权级别。在root模式下,cpu有真实的寄存器,一切都是真实,但是在非root模式下,cpu要使用的寄存器都放在与cpu绑定的一块物理内存上,绑定的过程有cpu新增的指令支持,当cpu收到中断,或者访问pio、mmio等会陷入到vmm(虚拟机监控机,在宿主端内核态特权级),,陷入以后vmm可以选择自己处理或者交给应用层处理。(此篇文章针对的是x86平台)

      但是对于内存的虚拟化就更麻烦了,一般的思路是,客户端虚拟地址经过客户端的页表转化为客户端的物理地址,然后把客户端的物理地址经过转换,变为宿主端的虚拟地址,kvm中有一个数据结构kvm_memory_slot记录了此映射关系,再经过页表的转换变为真实可用的物理地址。然而这样的转换路径也太长,影响了性能,kvm有了硬件的支持以后提出了影子页表的概念。

       影子页表简单来说就是,可以直接把客户端的虚拟地址映射成宿主端的物理地址。客户端想把客户端的页表基地址写入cr3寄存器的时候,由于读写cr3寄存器的指令都是特权指令,在读写 cr3的过程中都会陷入到VMM,VMM会首先截获到此指令。在客户端写cr3寄存器的时候,vmm首先保存好写入的值,然后填入的是主机端针对客户端生成的一张页表(也就是影子页表)的基地址,当客户端读cr3值的时候,vmm会把之前保存的cr3的值返回给客户端。

       这样做的目的是,在客户端内核态中虽然有一张页表,但是客户端在访问内存的时候,MMU不会走这张页表,MMU走的是以填入到cr3寄存器上的真实的值为基地址(这个值是vmm写的主机端的物理地址)的影子页表,经过影子页表找到真实的物理地址.影子页表时刻与客户端的页表保持同步。

      影子页表也有缺陷,KVM需要对客户端的每一个进程维护一张表,后面又有了EPT页表.暂且不谈。

KVM影子页表_第1张图片

你可能感兴趣的:(kvm)