VMX – block by NMI和 NMI unblockinig due to IRET 之间的关系

相关SDM章节: 27.2.3- Information About NMI Unblocking Due to IRET

最近收到同事发来的一个问题,即:

VMCS 中的 Guest Interruptibility State field 的 bit3-Blocking by NMI 和 VM-exit Interrupt-information field 或 VM-exit qualification field 中 的 bit12,也就是NMI unblocking due to IRET 之间的关系是什么?VMM在调度Guest期间对这里的”bit12″的利用方式是怎样的?

硬件逻辑

通过查阅 SDM,可以获得以下信息:

  1. IRET指令的执行可能会导致 vmexit,vmexit 的原因可能为:faults,EPT violation,page-modification log-full events,或者 SPP-related events.

  2. 如果在IRET执行时,NMI处于被block状态,即 Guest Interruptibililty State 的 bit3-Blocking by NMI 为1。那么IRET的执行会导致NMI被解除block,也就是将 Blocking by NMI从1设置为0. 即使 IRET 本身导致了fault 或 vmexit,unblock 的硬件行为不会发生变化。

  3. 1中所述的所有 vmexit,都会在 VM-exit Interrupt-information field / VM-exit qualification 的 bit12 提供 NMI unblocking due to IRET 信息,指示本次vmexit 是由 IRET 导致,并且 IRET unblock 了NMI,也就是 IRET 指令的执行导致了 Guest Interruptibility field 的 bit3 Blocking by NMI 从1 变为了0.

    但是,NMI unblocking due to IRET 还需要其它条件辅助才能成立。

    • “NMI-exiting” control 为0,或 “virtual NMIs” control 为1
    • vmexit 没有写 IDT-vectoring information field 的 valid bit 为 1
    • vmexit 不是由 #DF(double fault) 异常导致的

    在这三个条件同时成立的情况下,IRET 导致的 vmexit 会 Unblock NMI,也就是将 NMI unblocking due to IRET 写1.

    • 如果 IRET 指令的一部分为memory access,”virtual NMIs” control 为0,NMI 在IRET指令执行之前就已经被block 了,那么 NMI unblocking due to IRET 会被写1.
    • 如果 IRET 指令的一部分为memory access,”virtual NMIs” control 为1,且 virtual-NMI 在IRET指令执行之前就已经被 block了,那么 NMI unblocking due to IRET 也会被写1.
  4. IRET也可能会导致 APIC-access vmexit,EPT misconfigrations,但这类 vmexit 不会携带 NMI unblocking due to IRET 信息。

具体的逻辑如下图所示,红色部分会最终将 NMI unblocking due to IRET 信息存储到 VM-exit Interrupt-information field 中。绿色部分最终会将 NMI unblocking due to IRET 存储到 VM-exit qualification field 中。

软件逻辑

  • 每次 vmexit 时

软件逻辑很简单,在每次 vmexit 时,均会查看上图中菱形框中的条件是否满足,如果满足,就直接对Guest Interruptibility state 的 bit3,也就是 Blocking by NMI 写1,以在下次 vmentry 之前屏蔽掉 NMI。这里隐含着一个软件逻辑:由于 IRET 导致的 vmexit 会修改 Blocking by NMI,但这是不合理的,因此需要在由 IRET 导致的 vmexit 产生后,重新修改Blocking by NMI,使其能够正常block NMI。

另一方面,如果菱形框中的条件不满足,就正常读取 Blocking by NMI 的值确定是否需要对 NMI 进行屏蔽。

  • 处理 EPT violation vmexit 或 PML_FULL vmexit 时

逻辑与每次 vmexit时相同。但这里读取的NMI unblocking due to IRET 信息来自vmexit qualification,而不是 每次 vmexit时的 vmexit interrupt information。

总结

Guest 执行 IRET 会导致本来处于”Blocking NMI”的Guest环境变为”not Blocking NMI”,这是硬件逻辑的不合理之处,软件应该在检测到由 IRET 导致的 unblock NMI 动作之后,在root mode 对 NMI 重新 block。