RFC-0224:使用者空間 J-Extension 指標遮蓋

RFC-0224:使用者空間 J-Extension 指標遮罩
狀態已接受
區域
  • 核心
說明

為了配合 RISC-V 指標遮罩擴充功能,需要進行的變更。

問題
Gerrit 變更
作者
審查人員
提交日期 (年-月-日)2023-03-09
審查日期 (年-月-日)2023-09-05

摘要

本文提出了在 Fuchsia 使用者空間中支援 RISC-V J 擴充指標遮罩功能所需的變更。

提振精神

RISC-V J 擴充功能旨在讓 RISC-V 成為傳統解譯或 JIT 編譯的語言,或需要大型執行階段程式庫或語言層級虛擬機器的語言的理想目標。包括但不限於 C#、Go、Haskell、Java、JavaScript、OCaml、PHP、Python、R、Ruby、Scala、Smalltalk 或 WebAssembly。J-extension 的一項重要功能是指標遮罩 (PM)。這是一項硬體功能,啟用後可讓 MMU 忽略記憶體存取作業中有效位址的前 N 位元。這與 ARMv8.0 CPU 上的 Top-Byte-Ignore (TBI) 功能非常相似。PM 的其中一個立即用途,是在使用者空間中啟用 Hardware-assisted AddressSanitizer (HWASan),其中標記會儲存在頂層位元組中,用於追蹤記憶體。

術語

本文件中使用的許多術語可從 RFC-0143:Userspace Top-Byte-Ignore 擴充。

Address:地址是 64 位元整數,代表使用者位址空間範圍內的位置。地址永遠不會標記。

Pointer:可解析的記憶體位置,可能有標記,也可能沒有標記。這相當於 RISC-V Base ISA 中定義的有效位址。

標記:指標的較高位元,通常用於中繼資料。RISC-V 指標遮罩可支援不同的標記大小。

Zjpm - 這是 J-extension 中指標遮罩功能的正式 ID。

設計

符合標記指標 ABI

Zjpm 會啟用標記的使用者空間指標。核心處理這些指標時,必須遵循 RFC-0143 中規定的相同規則。也就是:

  1. 核心會忽略從系統呼叫接收的使用者指標標記。

  2. 在接受位址的系統呼叫中傳遞標記指標會發生錯誤。

  3. 當核心接受標記指標時,無論是透過系統呼叫或錯誤,都會嘗試保留標記,以便使用者程式碼日後觀察。

  4. 核心本身不會產生標記指標。

  5. 比較使用者空間指標時,核心會忽略任何可能存在的標記。

此外,Zjpm 會由核心啟動選項控制。與 ARM TBI 類似,啟用 Zjpm 後,所有使用者空間程序都會啟用 Zjpm。

RISC-V 不會為寫入偵錯登錄的值提供語意意義,因此偵錯工具可以自由將標記值寫入偵錯登錄。針對檢查點等功能,系統會透過 mcontext6 註冊的 match 欄位控制指標比較作業,可控制是否要比對完全相符的標記值,或忽略標記,就像使用指標遮罩一樣。

將標記設為 8 位元 (適用於 Sv39 和 Sv48)

Zjpm 最直接的用途是啟用記憶體錯誤偵測工具,例如 RISC-V 上的 HWASan,這項工具會將中繼資料儲存在指標的頂層位元中。ARM TBI 僅支援 8 位元的標記大小。不過,Zjpm 的彈性更高,可讓系統忽略變數數量的頂層位元。這個位元數量可透過 CSR 登錄在不同模式下進行控制。

最簡單的方法就是遵循現有做法。ARM TBI 和 HWAsan 已使用 8 位元標記,但目前並沒有任何立即或可預見的需求,需要比 8 位元更大 (或更小) 的標記。

只有 Sv39 和 Sv48 支援 8 位元的標記大小。這是因為 Sv57 僅支援遮蓋前 7 位元。如果日後支援 Sv57,就需要重新檢視代碼大小。

實作

實作方式大多與 ARM TBI 的實作方式非常相似。只要在 upm CSR 中設定 uenable 位元,即可在 U 模式中啟用 Zjpm。您可以透過 upm 中的 ubits 位元欄位設定代碼大小。

現有的系統呼叫基礎結構應已設定為接受標記使用者空間指標,且標記大小固定。

ZX_FEATURE_KIND_ADDRESS_TAGGING 功能會提供額外標記 (例如 ZX_RISCV64_FEATURE_ADDRESS_TAGGING_ZJPM_8BIT),用於指出 Zjpm 已啟用以及代碼大小。ZX_RISCV64_FEATURE_ADDRESS_TAGGING_ZJPM_8BIT 表示前 8 位元已確實遮罩,但日後我們可能會新增其他標記,表示更多位元會遭到遮罩。舉例來說,我們可以新增 ZX_RISCV64_FEATURE_ADDRESS_TAGGING_ZJPM_16BIT 之類的項目,指出前 16 位元已遮罩,但 ZX_FEATURE_KIND_ADDRESS_TAGGING 也會設定 8 位元等效標記,確保檢查 8 位元標記的相容性程式碼可用於未來的系統。

Zjpm 也需要啟用 Zicsr 擴充功能,該擴充功能會提供修改 CSR 登錄器的指令。

成效

效能影響應該微乎其微,我們會使用現有的微型基準測試來驗證。

測試

用於測試 ARM TBI 的相同測試套件也應套用至 Zjpm。這些測試應不受啟用的位址標記模式影響。

缺點、替代方案和未知事項

Zjpm 比 ARM TBI 更具彈性,因此我們可以支援更多遮蔽選項。

目前似乎沒有任何實際硬體支援最新版本的 Zjpm,因此未明確說明核心如何發現硬體支援的內容。在我們瞭解硬體的實際限制條件之前,建議您採用此處提出的保守型單一功能一律開啟模式,因為這是最有可能獲得支援的模式。QEMU 應支援指標遮罩,並可透過「x-j」CPU 屬性啟用。

一律將標記設為其他靜態值

標記 ABI 可支援不同標記大小 (也就是說,我們不受限於 8 位元)。實際上,我們並不會使用太多虛擬位址的頂層位元。在 x86 上,我們實際上只使用底部 48 位元,但這只是我們目前鎖定的目標的假設,日後可能會有所變動。目前,標記大小的位元欄位長度為 5 位元,也就是說,指標的最高 31 位元可以忽略。這個欄位上方的位元剩餘部分為 WPRI,因此這個欄位日後可擴充至更大的值。

對於 HWASan 等工具,記憶體標記演算法不一定會依賴標記大小為 8 位元。將代碼大小增加到 16 位元,可大幅降低代碼比較作業出現偽陽性的機率,但這意味著需要將較大的代碼儲存到陰影記憶體,這不是很理想。目前 8 位元偽陽性機率也非常低。

將標記公開為可修改的值,供使用者空間使用

這個選項暗示一種向使用者公開指標遮罩功能的方法。也就是說,使用者可以 (1) 在執行階段啟用/停用指標遮罩,以及 (2) 變更標記大小。這可能不是理想做法,因為沒有立即需要這麼做,而且需要新增更多系統呼叫才能切換這些值。不過,標記 ABI 可讓您在日後支援這項功能。

指令擷取時的指標遮罩

Zjpm 的一項強大功能,是在指令擷取時啟用 PM,包括因直線執行、控制轉移 (例如分支和直接/間接跳躍以及 uret/sret/mret) 而導致的單調遞增 PC。此提案僅概述資料指標的指標遮罩規則,但日後仍可探索這項選項。

與其他理想硬體功能互動

Zjpm 只會導入指標遮罩功能。其他實用功能 (例如標記檢查或沙箱強制執行) 可能會在需要 Zjpm 的軟體或未來硬體擴充功能中實作。舉例來說,ARM MTE 就是依附 TBI 的類似功能。

草稿變更

目前 Zjpm 仍是草案提案,但我們希望能為 RVA23 進行驗證,以便 HWASan 正式支援。我們會更新這份文件,以便因應規格中的任何重大變更。