学习和研究中前行,并在分享中提升自己

欢迎订阅阿里内推邮件



从kvm场景下guest访问的内存被swap出去之后说起

阅读次数: 256| 时间:2018年4月8日 19:35 | 标签:linux

熟悉linux内存管理的人同学应该都清楚,当物理机上的内存不足时会把非热点的page先换出到存储介质上,然后把物理页给其他进程使用。试想一下,在kvm场景下如果guest访问的内存被swap出去会发生什么样后果呢?先不着急讨论这个后果如何,我们先来复习一下guest内存map到物理内存的一个流程是什么样的。

guest 内存的映射流程

kvm平台下vm的内存是通过qemu分配的一段内存,qemu模拟了类似物理机器的内存条。而真正建立起gpa和hpa的maping关系,也就是EPT页表是在vm第一次访问内存的时候。我们通过下面一张图看看一下相关流程

首先,guest里面的相关进程访问某个虚拟地址时触发ept violation exit,实质上引起的是一个page fault的操作即 tdp_page_fault。然后,函数中会先把gpa转成对应的hva地址,然后通过hva去分配hpa即最终的物理地址(3,4两步)。找到hpa之后,通过direct_map来完成EPT页表的映射。至此,从gpa到hpa的完整映射流程已经走完。下次,当该进程再次访问这个页时直接通过EPT表来查询该真实的物理地址即可。当然,具体的细节就需要去翻相应的代码了。

guest所映射的host上物理内存被swap出去

正如上面所说如果host上的内存不足的时候,一些不常用的页就会被swap出去。而这些页很可能就已经跟guest gpa建立了map关系。当然,系统在将这些页swap出去时,就通知kvm mmu,kvm mmu 会将与这些要swap出去的页对应的EPT映射表drop掉。

那当进程再次访问这段内存时,触发流程如下:

1. VMEXIT
2. kvm_mmu_page_fault()
3. gfn_to_pfn
4. get_user_pages_fast()
    a.swap entry is found
    b.page swap-in process is initiated
    c.vcpu thread goes to sleep util page is swapped in
5. page is added EPT 

也就是说当有page被换出时,如果有进程访问这个地址时,那么该进程所在的vcpu就会sleep只到该地址所对应的内容再次被swap in之后才能继续运行。考虑到调度上的一些时延,势必会影响vm的vcpu的吞吐量。为了解决这个问题,提出了异步page fault也就是APF。

kvm mmu apf的方案

我们通过一张图看一下整个apf解决方案:

1. 进程访问被swap出去的内存页从而触发page fault,kvm mmu尝试apf方式。
2. 将具体的处理逻辑交给apf worker,然后通过注入 page not present的异常通知guest。
3. guest进入异常处理逻辑,将该进程block住,然后reschedule运行其他进程。
4. apf work完成page换进工作后通知guest,page页已经准备好。guest重新将block的进程调度进来,使该进程正常进行。

后记

  1. apf主要是通过pv方式来实现的,所以需要guest的支持(内核版本小于linux 2.6.36均不支持)。如果想要看相关代码,可以看看以下两个patch,主要是通过msr的方式来告诉后端是否支持apf。
   commit 631bc4878220932fe67fc46fc7cf7cccdb1ec597
Author: Gleb Natapov <gleb@redhat.com>
Date:   Thu Oct 14 11:22:52 2010 +0200

    KVM: Handle async PF in a guest.

    When async PF capability is detected hook up special page fault handler
    that will handle async page fault events and bypass other page faults to
    regular page fault handler. Also add async PF handling to nested SVM
    emulation. Async PF always generates exit to L1 where vcpu thread will
    be scheduled out until page is available.

    Acked-by: Rik van Riel <riel@redhat.com>
    Signed-off-by: Gleb Natapov <gleb@redhat.com>
    Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>

以及下面两个patch

commit fd10cde9294f73eeccbc16f3fec1ae6cde7b800c
Author: Gleb Natapov <gleb@redhat.com>
Date:   Thu Oct 14 11:22:51 2010 +0200

    KVM paravirt: Add async PF initialization to PV guest.

    Enable async PF in a guest if async PF capability is discovered.

    Acked-by: Rik van Riel <riel@redhat.com>
    Signed-off-by: Gleb Natapov <gleb@redhat.com>
    Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>    
commit 344d9588a9df06182684168be4f1408b55c7da3e
Author: Gleb Natapov <gleb@redhat.com>
Date:   Thu Oct 14 11:22:50 2010 +0200

    KVM: Add PV MSR to enable asynchronous page faults delivery.

    Guest enables async PF vcpu functionality using this MSR.

    Reviewed-by: Rik van Riel <riel@redhat.com>
    Signed-off-by: Gleb Natapov <gleb@redhat.com>
    Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>

kmod相关的修改可以看以下的patch

commit 7c90705bf2a373aa238661bdb6446f27299ef489
Author: Gleb Natapov <gleb@redhat.com>
Date:   Thu Oct 14 11:22:53 2010 +0200

    KVM: Inject asynchronous page fault into a PV guest if page is swapped out.

    Send async page fault to a PV guest if it accesses swapped out memory.
    Guest will choose another task to run upon receiving the fault.

    Allow async page fault injection only when guest is in user mode since
    otherwise guest may be in non-sleepable context and will not be able
    to reschedule.

    Vcpu will be halted if guest will fault on the same page again or if
    vcpu executes kernel code.