注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

路雷米的博客

人生最难的就是在热爱和生计之间做选择, 愿每个人这一生 既对得起梦想又担得责任

 
 
 

日志

 
 

【KVM新概念】 - Paravirtualized End-of-Interrupt Indication (PV-EOI)  

2015-10-26 14:36:02|  分类: VT-related |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |

[http://www.netfoucs.com/article/luo_brian/4555.html]

背景

X86 PC体系架构中的中断控制器,早先是8259A,现在更普遍使用的是APIC,他们处理中断的流程遵循如下流程:

    1. 外部设备产生一个中断,如果该中断没有被屏蔽掉,中断控制器将IRR寄存器中相应的位置1,表示收到中断,但是还未提交给CPU处理;
    2. 中断控制器将该中断提交给CPU,CPU收到中断请求后,会应答中断控制器;
    3. 中断控制器收到CPU的中断应答后,将IRR寄存器中相应的位清0,并将ISR寄存器相应的位置1,表示CPU正在处理该中断;
    4. 当该中断的处理程序结束以前,需要将中断控制器的EOI寄存器对应的位置1, 表示CPU完成了对该中断的处理;
    5. 中断控制器收到EOI后,ISR寄存器中相应的位清0,允许下次中断;

在虚拟化场景中,该流程至少会导致两次VM Exit: 第一次是VMM截获到设备中断的时候,通知客户机退出,将这个中断注入到客户机中;另外一次是当客户机操作系统处理完该中断后,写中断控制器的EOI寄存器,这是个MMIO操作,也会导致客户机退出。在一个外部IO比较频繁的场景中,外部中断会导致大量的VM Exit, 影响客户机的整体性能。

 

原理

PV-EOI其实就是通过半虚拟化的办法来优化上述的VM Exit影响,virtio也是使用这个思想来优化网络和磁盘;就EOI的优化来说,其思想本质上很简单:

    1. 客户机和VMM协商,首先确定双方是否都能支持PV-EOI特性,如果成功,则进一步协商一块2 bytes的内存区间作为双方处理EOI的共享缓存;
    2. 在VMM向客户机注入中断之前,会把缓存的最低位置1,表示客户机不需要通过写EOI寄存器;
    3. 客户机在写EOI之前,如果发现该位被设置,则将该位清0;VMM轮询这个标志位,当检查到清0后,会更新模拟中断控制器中的EOI寄存器;如果客户机发现该位未被设置,则继续使用MMIO或者MSR写EOI寄存器;

从上面的流程可以看出,原来写EOI寄存器的操作在PV-EOI之后变成了写共享内存的操作,从而避免了写MMIO导致的VM Exit。

 

需要注意的是,为了保证客户机和VMM同时处理共享内存的性能和可靠性,目前KVM的PV-EOF方案采用了如下的优化措施:

    1. VMM保障仅会在客户机VCPU的上下文中更改共享内存中的最低位,从而避免了客户机采用任何锁机制来与VMM进行同步;
    2. 客户机必须使用原子的test_and_clear操作来更改共享内存中的最低位,这是因为VMM在任何时候都有可能设置或者清除该位;

效果

同时使用了PV-EOI的客户机和KVM, 会明显的减少VM Exit的数量,从下面的统计可以看出,同样压力下,VM Exit的数量减少了接近一半:

 

Performance counter stats for 'sleep 1s': 47,357 kvm:kvm_entry [99.98%] 0 kvm:kvm_hypercall [99.98%] 0 kvm:kvm_hv_hypercall [99.98%] 5,001 kvm:kvm_pio [99.98%] 0 kvm:kvm_cpuid [99.98%] 22,124 kvm:kvm_apic [99.98%] 49,849 kvm:kvm_exit [99.98%] 21,115 kvm:kvm_inj_virq [99.98%] 0 kvm:kvm_inj_exception [99.98%] 0 kvm:kvm_page_fault [99.98%] 22,937 kvm:kvm_msr [99.98%] 0 kvm:kvm_cr [99.98%] 0 kvm:kvm_pic_set_irq [99.98%] 0 kvm:kvm_apic_ipi [99.98%] 22,207 kvm:kvm_apic_accept_irq [99.98%] 22,421 kvm:kvm_eoi [99.98%] 0 kvm:kvm_pv_eoi [99.99%] 0 kvm:kvm_nested_vmrun [99.99%] 0 kvm:kvm_nested_intercepts [99.99%] 0 kvm:kvm_nested_vmexit [99.99%] 0 kvm:kvm_nested_vmexit_inject [99.99%] 0 kvm:kvm_nested_intr_vmexit [99.99%] 0 kvm:kvm_invlpga [99.99%] 0 kvm:kvm_skinit [99.99%] 57 kvm:kvm_emulate_insn [99.99%] 0 kvm:vcpu_match_mmio [99.99%] 0 kvm:kvm_userspace_exit [99.99%] 2 kvm:kvm_set_irq [99.99%] 2 kvm:kvm_ioapic_set_irq [99.99%] 23,609 kvm:kvm_msi_set_irq [99.99%] 1 kvm:kvm_ack_irq [99.99%] 131 kvm:kvm_mmio [99.99%] 226 kvm:kvm_fpu [100.00%] 0 kvm:kvm_age_page [100.00%] 0 kvm:kvm_try_async_get_page [100.00%] 0 kvm:kvm_async_pf_doublefault [100.00%] 0 kvm:kvm_async_pf_not_present [100.00%] 0 kvm:kvm_async_pf_ready [100.00%] 0 kvm:kvm_async_pf_completed 1.002100578 seconds time elapsed After: Performance counter stats for 'sleep 1s': 28,354 kvm:kvm_entry [99.98%] 0 kvm:kvm_hypercall [99.98%] 0 kvm:kvm_hv_hypercall [99.98%] 1,347 kvm:kvm_pio [99.98%] 0 kvm:kvm_cpuid [99.98%] 1,931 kvm:kvm_apic [99.98%] 29,595 kvm:kvm_exit [99.98%] 24,884 kvm:kvm_inj_virq [99.98%] 0 kvm:kvm_inj_exception [99.98%] 0 kvm:kvm_page_fault [99.98%] 1,986 kvm:kvm_msr [99.98%] 0 kvm:kvm_cr [99.98%] 0 kvm:kvm_pic_set_irq [99.98%] 0 kvm:kvm_apic_ipi [99.99%] 25,953 kvm:kvm_apic_accept_irq [99.99%] 26,132 kvm:kvm_eoi [99.99%] 26,593 kvm:kvm_pv_eoi [99.99%] 0 kvm:kvm_nested_vmrun [99.99%] 0 kvm:kvm_nested_intercepts [99.99%] 0 kvm:kvm_nested_vmexit [99.99%] 0 kvm:kvm_nested_vmexit_inject [99.99%] 0 kvm:kvm_nested_intr_vmexit [99.99%] 0 kvm:kvm_invlpga [99.99%] 0 kvm:kvm_skinit [99.99%] 284 kvm:kvm_emulate_insn [99.99%] 68 kvm:vcpu_match_mmio [99.99%] 68 kvm:kvm_userspace_exit [99.99%] 2 kvm:kvm_set_irq [99.99%] 2 kvm:kvm_ioapic_set_irq [99.99%] 28,288 kvm:kvm_msi_set_irq [99.99%] 1 kvm:kvm_ack_irq [99.99%] 131 kvm:kvm_mmio [100.00%] 588 kvm:kvm_fpu [100.00%] 0 kvm:kvm_age_page [100.00%] 0 kvm:kvm_try_async_get_page [100.00%] 0 kvm:kvm_async_pf_doublefault [100.00%] 0 kvm:kvm_async_pf_not_present [100.00%] 0 kvm:kvm_async_pf_ready [100.00%] 0 kvm:kvm_async_pf_completed 1.002039622 seconds time elapsed 


支持

  • Linux 3.6RC1以上的版本开始支持PV-EOI,也就是说PV-EOI需要客户机和主机都是Linux 3.6以上版本;
  • Qemu-1.2开始支持PV-EOI,在1.3中I默认开启PV-EOI, 可以通过-cpu kvm64,+kvm_pv_eoi来开启或者关闭该功能;
  • libvirt可以通过<apic eoi="on/off"/>来开启或者关闭PV-EOI;
  • RHEL从6.4版本开始支持PV-EOI, 详情参看下面参考资料4中的PV-EOI章节
  • Windows客户机不支持PV-EOI,理论上也应该可以支持,但是目前没有相应的驱动;
  评论这张
 
阅读(287)| 评论(0)
推荐 转载

历史上的今天

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2018