专栏首页虚拟化笔记IOMMU(五)-interrupt remmaping
原创

IOMMU(五)-interrupt remmaping

惠伟:IOMMU(四)-dma remapping​zhuanlan.zhihu.com

MSI

通过DMA写物理地址0x0FEE_XXXX来产生中断,PCI config space中有MSI Address和Data寄存器,驱动配置这两个寄存器,Address寄存器中有Destination ID,表示Local APIC ID,Address寄存器所有字段组合起来就是x0FEE_XXXX,Data寄存器有vector号,表示中断号。

如果request-without-PASID,不进行DMA remapping,并且目的地址是0x0FEE_xxxxh就是中断。如果request-with-PASID,DMA转换后地址是0x0FEE_xxxxh就报错。如果request-with-PASID,转换前的地址是0x0FEE_xxxxh正常转换,但如果转换模式是passthrough就报错。

no interrupt remapping

物理中断一般情况下不能直接投递到虚拟机中,只能先到物理机上,物理机再通过event inject机制把中断投递到虚拟机中。那么vt-d物理中断先由哪个物理CPU处理呢?当然最好是虚拟机运行在哪个物理CPU,物理中断就由那个物理CPU处理,物理中断来了,虚拟机正好由于external interrupt exiting出来,物理CPU处理物理中断,然后重新进入虚拟机时正好把中断注入。假如物理中断到了其它物理CPU,接收到外部中断的物理CPU需要给虚拟机所在的物理CPU发送一个IPI中断,把虚拟机exit出来,再进入虚拟机进行中断注入。KVM要拦截guest对passthrough pci设备MSI addr和data寄存器的读写,然后host分配一个p_vector,外设中断来了,VMM把p_vector转换成v_vector,再把v_vector注入给虚拟机。

interrupt remapping

MSI Address和Data中不再包含destination id和vector,换成handle和subhandle。

handle和subhandle算出interrupt_index

if (address.SHV == 0) {
interrupt_index = address.handle;
} else {
interrupt_index = (address.handle + data.subhandle);
}

再根据interrupt_index查Interrupt Remap Table,查到的Entry中有Destination ID和vector。

那interrupt remapping有什么好处:

  • 中断隔离和迁移

passthrough设备1给虚拟1,虚拟机1运行在物理CPU1,passthrough外设2给虚拟机2,虚拟机2运行在物理CPU2上,外设1产生的中断最好不要给了物理CPU2,外设2产生的中断最好不要给了物理CPU1。虚拟CPU从一个物理CPU迁移到另一个物理CPU,设备产生的中断需要投递到新的物理CPU上。有interrupt remapping效率更高,原来需要更新设备的MSI Address和Data寄存器,现在只需要更新中断重映射表。

  • 支持的中断更多

原来MSI Data vector只有8位,用了interrupt remapping,vector存在放IRTE中,IRTE表的索引放置在MSI Address和Data寄存器中,索引值可以很大。

代码分析

初始化硬件,准备数据和注册函数。

start_kernel
  └─x86_late_time_init
      └─apic_intr_mode_init
          ├─default_setup_apic_routing
          |   └─enable_IR_x2apic
          |       ├─irq_remapping_prepare
          |       |    └─intel_prepare_irq_remapping
          |       |          └─intel_setup_irq_remapping
          |       └─irq_remapping_enable
          |            └─intel_enable_irq_remapping
          └─apic_bsp_setup
              └─irq_remap_enable_fault_handling
                  └─enable_drhd_fault_handling

linux中断处理子系统有两个很重要的概念就是irq_chip和irq_domain,IOMMU为了支持interrupt remapping也增加了这两个东西。

static struct irq_chip intel_ir_chip = {
	.name			= "INTEL-IR",
	.irq_ack		= apic_ack_irq,
	.irq_set_affinity	= intel_ir_set_affinity,
	.irq_compose_msi_msg	= intel_ir_compose_msi_msg,
	.irq_set_vcpu_affinity	= intel_ir_set_vcpu_affinity,
};
static const struct irq_domain_ops intel_ir_domain_ops = {
	.select = intel_irq_remapping_select,
	.alloc = intel_irq_remapping_alloc,
	.free = intel_irq_remapping_free,
	.activate = intel_irq_remapping_activate,
	.deactivate = intel_irq_remapping_deactivate,
};

最重要的函数就是intel_ir_set_vcpu_affinity,irq_set_vcpu_affinity调用到它,irq_set_vcpu_affinity函数的第一参数是物理中断号,另一个参数是vcpu_info,kvm中函数update_pi_irte调用到这个函数,虽然函数名字有pi(post interrupt),但硬件不支持post interrupt的情况也可以搞定,kvm调用irq_set_vcpu_affinity时参数vcpu_info设置为空即可,这样IOMMU中IRTE只支持interrupt remaping不支持post interrupt。

update_pi_irte
  └─irq_set_vcpu_affinity
       └─intel_ir_set_vcpu_affinity
             └─modify_irte

kvm的物理中断号来自于vfio,vfio_msi_set_vector_signal向系统申请物理中断号,传递给kvm,当外设触发中断后,IOMMU先处理,再给vcpu所有的物理cpu发起一个物理中断,物理cpu从not-root exit出来,vfio的vfio_msihandler进行中断处理,通过eventfd给kvm一个信号,kvm更新VMCS中虚拟中断字段,物理cpu重新enter non-root模式把虚拟中断中断注入。

原创声明,本文系作者授权云+社区发表,未经许可,不得转载。

如有侵权,请联系 yunjia_community@tencent.com 删除。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • IOMMU(六)-post interrupt

    惠伟:IOMMU(五)-interrupt remmaping​zhuanlan.zhihu.com

    惠伟
  • 图说ARM架构知识

    ARM架构分为系统架构、安全架构、CPU架构。 ? CPU架构主要是指系统架构上的芯片实现。 安全架构主要是指PSA,前面介绍过。请参考: ARM公司PSA平台...

    安智客
  • x86中断和中断虚拟化

    网上有很多写中断虚拟化的博客,讲qemu/kvm是怎么模拟中断的,贴了大段大段的代码,看起来很吃力,对于一个虚拟化新手来说太困难太困难,我这儿写点简单的,讲讲中...

    惠伟
  • Dynamic DMA mapping Guide

    这是一篇指导驱动工程师如何使用DMA API的文档,为了方便理解,文档中给出了伪代码的例程。另外一篇文档dma-api.txt给出了相关API的简明描述,有兴趣...

    Linux阅码场
  • 倒计时:《Linux的任督二脉》之《内存管理》在线课程

    理解硬件访问内存的原理,MMU和页表;澄清Linux内核ZONE,buddy,slab管理;澄清用户空间malloc与内核关系,Lazy分配机制;澄清进程的内存...

    Linux阅码场
  • 优惠今天结束:《Linux的任督二脉》之《内存管理》在线课程

    理解硬件访问内存的原理,MMU和页表;澄清Linux内核ZONE,buddy,slab管理;澄清用户空间malloc与内核关系,Lazy分配机制;澄清进程的内存...

    Linux阅码场
  • Docker desktop 与VWare 冲突解决方案

    问题描述: docker desktop 和vware 这俩个工具无法同时使用,如果需要单独使用vware,需要做一些配置才行不然会报错。 报错内容为: V...

    happlyfox
  • 【STM32】EXTI---外部中断/事件控制器

    AXYZdong
  • Java停止线程的四种方法

    线程调用interrupt()方法后,在线程的run方法中判断当前对象的interrupted()状态,如果是中断状态则抛出异常,达到中断线程的效果。 ...

    凡人飞

扫码关注云+社区

领取腾讯云代金券