本文将介绍VT-d Posted Interrupt的相关内容。首先会以一个例子介绍Posted interrupt的motivation;然后详细阐述涉及到的硬件和软件细节;接下来会介绍不同vCPU状态下的差异化处理;最后总结下本文。

阅读本文前,需先阅读以下文章:

  1. Intel SDM Chapter 29: APIC Virtualizaton & Virtual Interrupts
  2. Introduction to CPU-based Posted-interrupt
  3. VT-d Interrupt Remapping

1. terms

  • PI(Posted Interrupt)
  • hv(hypervisor)
  • VM(Virtual Machine)
  • IRTE(Interrupt Remapping Table Entry)
  • PID(Posted Interrupt Descriptor)
  • PIR( Posted Interrupt Requests)
  • ON(Outstanding Notification)
  • NV(Notification Vector)
  • ANV(Active Notification Vector)
  • WNV(Wake-up Notification Vector)
  • ple(pause loop exiting)

2. motivation

VT-d Interrupt Remapping demo usage中,如果目标vCPU正在运行,但是,当物理CPU接受到physical interrupt时,需发生VM-Exit,由hv为guest注入vector为30的virtual中断。

思考下:是否可以省去如下步骤:当物理CPU接受到physical interrupt时,需发生VM-Exit,由hv为guest注入vector为30的virtual中断。由硬件为正在运行的vCPU直接注入vector为30的virtual 中断(这样避免了一次VM-Exit),而这正是VT-d PI所能完成的功能。

3. details

3.1 CAP_REG的PI位

IOMMU通过Capability Register(CAP_REG)的PI位来报告interrupt posting capability。

3.2 IRTE

VT-d PI是VT-d Interrupt Remapping的一个扩展功能。根据Interrupt Remapping可知, 所有的Remapping格式中断请求都需要通过中断重映射表来投递, IRTE中的Mode域(IM)用来指定这个remappable中断请求是interrupt-remapping方式还是interrupt-posting方式。

如果IRTE的IM位为1,则VT-d硬件将会以PI的形式来解析该IRTE,如下图所示:

需要关注PI格式的IRTE的以下几个field:

  1. Posted Descriptor Address Low/High,该区域保存一个指向内存的指针,该指针指向的位置就是PID。
  2. Urgent位,该位用于表示该中断是否是紧急的,即是否需要目标CPU立即响应。
  3. Vector用于指定PID.PIR中哪个bit要置位。

3.3 PID

每个PID的大小为64 Byte,直接被硬件用来记录将要post的中断请求。其格式如下所示:

  1. Posted Interrupt Request (PIR)域,一共256 bit,每个bit对应一个中断向量,当VT-d硬件将中断请求post过来的时候,IRTE.Vector对应的bit将会被置起。
  2. Outstanding Notification (ON)域,表示该PID当前是否已经发出了一个Notification Event等待CPU的处理。

    • 当VT-d硬件将中断请求记录到PIR的时候,如果ON为0,并且允许立即发出一个Notification Event时,则将会将ON置起来,并且产生一个Notification Event;如果ON已经被置起来,则不会产生一个Notification Event。

    • ON的清零。

  3. Suppress Notification (SN)域,表示当PIR寄存器记录到non-urgent的中断时,是否不发出Notification Event,如果该位为1,则当PIR记录到non-urgent中断的时候,不发出Notification Event,并且不更改Outstanding Notification位的值。
  4. Notification Vector (NV)域,表示如果发出Notification Event时,具体的Vector值。
  5. Notification Destination (NDST)域,表示如果发出Notification Event时,要传递的物理CPU的LAPIC ID。

3.4 硬件上Posted Interrupt的处理过程

PST即IRTE中的Interrupt Mode位。

当VT-d硬件接收到其旗下I/O设备传递过来的中断请求时,会先查看自己的中断重定向功能是否打开,如果没有打开则,直接上传给LAPIC。如果中断重定向功能打开,则会查看中断请求的格式,如果是不可重定向格式,则直接将中断请求提交给LAPIC。如果是可重定向的格式,则会根据算法计算Interrupt_Index值,对中断重定向表进行索引找到相应的IRTE。然后,查看IRTE中的Interrupt Mode,如果为0,则该IRTE的格式为Remapped Format,即立即根据IRTE的信息产生一个新的中断请求,提交到LAPIC。如果Interrupt Mode为1,则表示该IRTE的格式为Posted Format,根据IRTE中提供的PID的地址,在内存中找到相应PID,并根据其ON、URG和SN的设置判断是否需要立即产生一个Notification Event,如果不需要,则只是将该中断信息记录到PID.PIR中,等待hv的后续处理(会在vCPU is ready-to-run or halted when Notification Event happen中介绍)。如果需要立即产生一个Notification Event,则根据PID(会提供目标APIC ID、vector、传输模式和触发模式等信息)产生一个Notification Event,同时将ON置位。

硬件在对PID进行修改的时候,要保证该修改是原子操作,即对PID的读取、修改和写入必须是原子操作,并且在写入之后,要保证相应内存在各个cache agent之间的一致性,即所有的CPU应该立马能够看到该内存修改。

3.5 the relationship with CPU-based Posted-interrupt

CPU-based Posted-interrupt需要与IOMMU协同工作才能实现VT-d Posted Interrupt feature。

有三点需要注意:

  1. enable APICv
  2. 设置VMCS的posted-interrupt descriptor,这正是IRTE中Posted Descriptor Address Low/High所设置的值。
  3. 设置VMCS的posted-interrupt notification vector为ANV(下节会详细介绍)。


4. 不同vCPU状态下的差异化处理

4.1 Background

在vCPU调度的过程中,vCPU会有如下三种状态:

  1. 当vCPU被scheduler选中来运行的时候,此时vCPU的状态为’active’。
  2. 当vCPU被抢占(Preempted),例如时间片到期了,此时vCPU的状态为’ready-to-run’。
  3. 当vCPU执行了hlt指令或者触发了ple,hv也会干预进来将vCPU给block出来,此时vCPU状态为’halted ‘。

4.2 ANV and WNV

hv需要为每个vCPU分配物理中断vector:
第一个称作Active Notification Vector(ANV),该Vector对应到vCPU的状态为active时,Notification Event所使用的中断vector(需要设置VMCS的posted-interrupt notification vector为ANV)。

第二个称作Wake-up Notification Vector(WNV),该Vector对应到目标vCPU不在当前物理CPU上执行时,由于Urgent被置起来产生的Notification Event所使用的中断Vector。

在active状态下,PID.NV的值就是ANV。在ready-to-run或者halted状态下,PID.NV的值就是WNV。这里的ANV和WNV可以是同一个值。

hv需要保证的是:运行在同一个pCPU上的所有vCPU的PID.NV值不同。

详情可参考:ACRN posted interrupt

4.3 vCPU Scheduling

只需理解状态转换,对于‘NV’的设置是hv specific的,无需深究。

4.4 vCPU is active when Notification Event happen

guest在Non-Root下就能直接处理此中断,而不需要hv的参与。

详细步骤请参考:Posted Interrupt

4.5 vCPU is ready-to-run or halted when Notification Event happen

WNV的handler:

如果vCPU的state为halted,则需要先将vCPU的状态设置为ready-to-run。

handler会调度vCPU。

扫描PID.PIR,检测是否有处于pending状态的posted interrupt请求;如果有处于pending状态的posted interrupt请求,hv会在LAPIC上生成一个vector号为ANV的self-IPI(注意:在还未真正enter guest之前,当前物理CPU处于关中断状态)。 当进入Non-Root模式时,物理IRR寄存器中的ANV位会被置上,硬件(CPU)会处理posted interrupt。该中断的处理类似于vCPU处于active状态时,接收到了ANV的中断请求,vCPU可以直接对其进行处理,不需要hv的参与。

5. summary

VT-d PI advantages

  • External interrupts from direct-assigned devices are delivered to guest running in non-root mode directly
  • Improve Interrupt virtualization efficiency, e.g. Less VM-Exits.
  • Simplify interrupt migration
    • 更新PID.NDST
    • 如果per-PCPU的IDT向量管理不一样,还需要更新PCPU IDT的vector
  • Consume less physical interrupts

参考资料:

  1. fangying:VT-d Posted Interrupt
  2. 河马 Intel VT-d(4)- Interrupt Posting
  3. Feng Wu:VT-d Posted Interrupts
  4. Hardware passthrough