VMX - block by NMI和 NMI unblockinig due to IRET 之間的關係

EwanHai發表於2021-02-08

相關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。

相關文章