29.8. 靈活返回和事件傳遞 (FRED)

29.8.1. 概述

FRED 架構定義了簡單的新過渡,可以改變特權級別(環過渡)。FRED 架構的設計目標如下:

  1. 透過以更低延遲的過渡替換透過中斷描述符表 (IDT 事件傳遞) 的事件傳遞和透過 IRET 指令的事件返回,從而提高整體效能和響應時間。

  2. 透過確保事件傳遞建立完整的管理程式上下文,並且事件返回建立完整的使用者上下文,從而提高軟體的健壯性。

FRED 架構定義的新過渡是 FRED 事件傳遞,以及用於從事件返回的兩個 FRED 返回指令。FRED 事件傳遞可以實現從環 3 到環 0 的過渡,但它也用於傳遞環 0 的事件。一個 FRED 指令 (ERETU) 實現從環 0 到環 3 的返回,而另一個指令 (ERETS) 返回時保持在環 0 中。總的來說,FRED 事件傳遞和 FRED 返回指令就是 FRED 過渡。

除了這些過渡之外,FRED 架構還定義了一個新的指令 (LKGS),用於管理 GS 段暫存器的狀態。LKGS 指令可以被不使用新的 FRED 過渡的 64 位作業系統使用。

此外,FRED 架構易於擴充套件,以適應未來的 CPU 架構。

29.8.2. 基於軟體的事件分發

FRED 在事件處理方面與 IDT 的運作方式不同。FRED 不是根據事件向量直接將事件分發到其處理程式,而是要求軟體根據事件的型別和向量將其分發到其處理程式。因此,必須實現一個事件分發框架,以促進事件到處理程式的分發過程。FRED 事件分發框架在事件傳遞後接管控制,並採用兩級分發。

第一級分發基於事件型別,第二級分發基於事件向量。

29.8.3. 完整的管理程式/使用者上下文

FRED 事件傳遞在事件傳遞和返回時自動儲存和恢復完整的管理程式/使用者上下文。因此,它避免了由於 %cr2 和/或 %dr6 導致的瞬態狀態問題,並且不再需要處理由半生不熟的條目狀態導致的所有難看的角落情況。

FRED 允許使用新的事件返回指令 ERETS/ERETU 顯式取消阻塞 NMI,從而避免了 IRET 無條件取消阻塞 NMI 造成的混亂,例如,當在 NMI 處理期間發生異常時。

FRED 總是恢復 %rsp 的完整值,因此啟用 FRED 後不再需要 ESPFIX。

29.8.4. LKGS

LKGS 的行為類似於 MOV 到 GS 指令,只是它將基地址載入到 IA32_KERNEL_GS_BASE MSR 中,而不是 GS 段的描述符快取中。使用 LKGS,最終避免了篡改核心 GS,也就是說,作業系統始終可以使用自己的 GS 基地址執行。

由於來自環 3 的 FRED 事件傳遞和 ERETU 都交換了 GS 基地址的值和 IA32_KERNEL_GS_BASE MSR 的值,加上 LKGS 指令的引入,因此啟用 FRED 後不再需要 SWAPGS 指令,因此被禁止 (#UD)。

29.8.5. 堆疊級別

引入了 4 個堆疊級別 0~3 來代替用於事件處理的不可重入 IST,並且每個堆疊級別都應配置為使用專用堆疊。

當前堆疊級別可以在 FRED 事件傳遞時保持不變或升高。如果保持不變,CPU 將繼續使用當前事件堆疊。如果升高,CPU 將切換到由新堆疊級別的 MSR 指定的新事件堆疊,即 MSR_IA32_FRED_RSP[123]。

只有執行 FRED 返回指令 ERET[US] 才能降低當前堆疊級別,從而導致 CPU 切換回之前的事件傳遞提升堆疊級別之前所在的堆疊。