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

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

為配合 RISC-V 指標遮蓋擴充功能而需要變更。

問題
變更
  • 817252
作者
審查人員
提交日期 (年/月)2023-03-09
審查日期 (年/月)2023 年 9 月 5 日

摘要

本文件建議進行必要變更,以支援 Fuchsia 使用者空間中的 RISC-V J-extension 指標遮蓋功能。

提振精神

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

術語

本文件使用的大部分術語都可以從 RFC-0143: Userspace Top-Byte-Ignore 擴充。

地址 - 地址是 64 位元整數,代表使用者位址空間邊界內的位置。地址絕不會標記。

Pointer - 可參照記憶體的位置,不一定有標記。這相當於 RISC-V BaseISA 中所定義的有效地址。

標記 - 指標的上位元,通常用於中繼資料。RISC-V 指標遮蓋支援不同的代碼大小。

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

設計

符合標記指標 ABI 規定

Zjpm 會啟用已標記的使用者空間指標。核心處理這些指標時,必須遵守 RFC-0143 中指定的規則。如下所示:

  1. 核心將忽略從 syscall 接收的使用者指標上的標記。

  2. 在接受地址的系統呼叫上傳送標記的指標會有誤。

  3. 當核心接受標記的指標時,無論是透過系統呼叫或錯誤,核心都會嘗試將標記保留至使用者程式碼之後可能觀察到的情況。

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

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

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

RISC-V 不會對寫入偵錯登錄的值提供語意含義,因此偵錯工具可以自由將標記值寫入偵錯註冊。對於觀察點之類的功能,您可以透過 mcontext6 註冊的 match 欄位控制指標比較,而該欄位可控制為完全相符標記的值,也可以像使用指標遮蓋一樣忽略標記。

將代碼設為 8 位元 (適用於 Sv39 和 Sv48)

Zjpm 最立即的用途是啟用記憶體錯誤偵測工具,例如 RISC-V 上的 HWASan,這類工具需要將中繼資料儲存至指標頂端位元。ARM TBI 僅支援 8 位元的標記大小。不過,Zjpm 則具有較高的彈性,可忽略記憶體存取次數不變的頂端位元。這個位元數可透過 CSR 註冊表在不同模式下控制。

最簡單的方法就是配合現在的需求。ARM TBI 和 HPSan

只有 Sv39 和 Sv48 支援 8 位元的代碼大小。這是因為 Sv57 僅支援遮蓋前 7 位元的內容。假如日後支援 Sv57,則必須重新查看代碼大小。

實作

許多實作方式都與 ARM TBI 的實作非常類似。只要在 upm CSR 中設定 uenable 位元,即可在 U-mode 中啟用 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 的一項強大功能是啟用指令擷取的強大功能,包括使用直線執行、控制轉移 (例如分支和直接/間接跳躍) 和 uret/sret/mret 單向電腦產生的指標。本提案僅概述指標上的指標遮蓋規則,但未來還有機會探索這個選項。

與其他理想的硬體功能互動

Zjpm 只會導入指標遮蓋功能。其他實用功能 (例如代碼檢查或沙箱強制執行) 可在需要 Zjpm 的軟體或日後的硬體擴充功能中實作。以 TBI 為基礎的 ARM MTE 就是一個類似功能。

對草稿所做的變更

Zjpm 目前仍為草擬提案,但想要看到 RVA23 經過批准,HWASan 能夠正式支援這項提案。我們會配合規格中的重大變更更新本文件。