相關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,可以獲得以下資訊:
-
IRET
指令的執行可能會導致 vmexit,vmexit 的原因可能為:faults,EPT violation,page-modification log-full events,或者 SPP-related events. -
如果在
IRET
執行時,NMI處於被block狀態
,即 Guest Interruptibililty State 的 bit3-Blocking by NMI 為1。那麼IRET的執行會導致NMI被解除block,也就是將 Blocking by NMI從1設定為0. 即使 IRET 本身導致了fault 或 vmexit,unblock 的硬體行為
不會發生變化。 -
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.
-
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。