特權層二進制接口規範標準(0.3版)
特權層二進制接口規範標準 0.3版 作者:RISC-V Unix工作組 2021年6月8日 譯者:洛佳 |
1.0.0版 |
簡介
[編輯]本標準描述了RISC-V架構的特權層二進制接口。它使用平台或虛擬化軟件特有的功能,定義一組抽象接口,以便於在不同的RISC-V實現下移植特權層軟件和虛擬化的特權層軟件。特權層接口的設計遵守了RISC-V的設計哲學,即它必須實現較少的核心功能,以模塊化方式提供更多可選的功能擴展。
特權層接口的模塊化擴展是可選的,但它必須被完整地實現。如果「探測特權層接口模塊函數」認為一個擴展是可用的,它的所有功能必須與「獲取特權層接口規範版本號函數」得到的版本相符合。
提供特權層接口的軟件被稱作特權層接口的實現。特權層接口的實現可以是機器模式下運行的固件,也可以是宿主特權態下運行的虛擬化監視軟件。
特權層接口標準並未規定發現硬件的方法。特權層軟件必須輔助使用其它的規範標準,來完成特定平台下發現硬件的流程。
二進制編碼
[編輯]所有的特權層接口函數具有相同的二進制編碼,它反映了不同的特權層接口擴展。特權層接口的調用約定描述如下:
- 使用ECALL指令來轉移指令流的控制權,而不是使用CALL指令;
- a7寄存器用於保存擴展編號;
- a6寄存器用於保存函數編號;
- 除了a0和a1外,所有其餘的寄存器上下文都應當被特權層接口實現保護;
- 特權層接口函數的返回值有兩個,分別保存到a0和a1寄存器。其中,a0寄存器返回錯誤編號。返回值的描述和下表是相同的。
寄存器 | 名稱 | 類型 |
---|---|---|
a0 | 錯誤編號 | usize |
a1 | 函數的返回值 | usize |
所有的擴展編號和函數編號都是32位的整數。傳入擴展編號和函數編號,應當符合上述的調用約定。
返回值中的錯誤編號定義如下表。
錯誤類型 | a0值 |
---|---|
調用成功 | 0 |
發生了錯誤 | -1 |
不支持的功能 | -2 |
非法參數 | -3 |
禁止此操作 | -4 |
非法地址 | -5 |
資源已生效 | -6 |
已經啟動 | -7 |
已經停止 | -8 |
當擴展編號和函數編號不受當前環境支持時,特權層接口應當返回不支持的功能作為錯誤編號。
所有的接口函數應儘量選用特權層環境下寄存器寬度的類型作為傳入的數據類型,這樣在不同的RISC-V基礎擴展下都容易使用特權層接口。除此之外,如果一些參數的數據類型可能固定為32位寬,那麼特權層軟件應當只使用數據的低32位。
為便於選擇處理器核,特權層二進制接口定義統一的位集數據結構如下。所有需要選擇處理器核的特權層接口函數必須使用標準的位集數據結構。
標準的位集數據結構由遮罩位集和起始編號兩個參數組成。
參數名稱 | 參數類型 |
---|---|
遮罩位集 | usize |
起始編號 | usize |
當只調用一次特權層接口函數時,最大支持處理器核的數量與特權層下整數寄存器的位寬相同。如果更高權限的層級需要傳遞多於一個位寬的處理器核,它應當多次調用特權層接口函數。除此之外,如果起始編號的值是2^XLEN-1,那麼遮罩位集將被忽略,此時位集數據結構表示平台上所有可用的核都應被函數考慮在內。
對所有使用位集數據結構的函數來說,如果起始編號無效或遮罩位集給定的處理器核編號無效,即它表示選中的核至少有一個不能在特權層下使用時,應當返回非法參數錯誤。
錯誤類型 | 發生條件 |
---|---|
非法參數 | 至少有一個選中的核不能在當前特權層環境下使用 |
基礎擴展
[編輯]擴展編號為0x10。基礎擴展被設計得越小越好,它只包含探測標準版本和擴展模塊的最小功能。所有的特權層接口必須實現基礎擴展;基礎擴展的函數不會返回錯誤。
獲取特權層接口規範版本號函數
[編輯]這個函數沒有輸入參數。
返回當前的特權層規範版本號。這個函數不能返回錯誤。返回值中,低24位代表特權層規範的子版本號,而後較高的7位表示母版本號。返回值的第31位必須為0,它是為未來的擴展而保留的。
規範版本號的返回值 | |||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
31 | 30 | 29 | 28 | 27 | 26 | 25 | 24 | 23 | 22 | 21 | 20 | 19 | 18 | 17 | 16 | 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
保留 | 母版本號 | 子版本號 |
獲取特權層接口實現編號函數
[編輯]這個函數沒有輸入參數。
返回當前的特權層接口實現編號,每個特權層實現的返回都將不同。它是為了探測特權層實現的類型而設計的,允許軟件根據不同的特權層實現,具備不同的行為。
獲取特權層接口實現版本號函數
[編輯]這個函數沒有輸入參數。
返回當前的特權層實現版本。特權層實現版本的具體意義,由特權層實現來規定。
探測特權層接口模塊函數
[編輯]這個函數輸入一個參數,即待探測的擴展模塊編號。
順序 | 名稱 | 類型 |
---|---|---|
0 | 擴展模塊編號 | usize |
如果待測的擴展模塊不可用,返回0。當擴展的模塊可用,返回1,除非特權層實現規定的另外的非零返回值。
獲取機器製造商編號函數
[編輯]這個函數沒有輸入參數。
從mvendorid寄存器中返回機器製造商的編號;0也是一個合法的返回值。
獲取機器微架構編號函數
[編輯]這個函數沒有輸入參數。
從marchid寄存器中返回機器微架構的編號;0也是一個合法的返回值。
獲取機器實現編號函數
[編輯]這個函數沒有輸入參數。
從mimpid寄存器中返回機器微架構的編號;0也是一個合法的返回值。
基礎擴展函數列表
[編輯]函數名稱 | 規範版本 | 函數編號 | 擴展編號 |
---|---|---|---|
獲取特權層接口規範版本號函數 | 0.2 | 0 | 0x10 |
獲取特權層接口實現編號函數 | 0.2 | 1 | 0x10 |
獲取特權層接口實現版本號函數 | 0.2 | 2 | 0x10 |
探測特權層接口模塊函數 | 0.2 | 3 | 0x10 |
獲取機器製造商編號函數 | 0.2 | 4 | 0x10 |
獲取機器微架構編號函數 | 0.2 | 5 | 0x10 |
獲取機器實現編號函數 | 0.2 | 6 | 0x10 |
基礎擴展實現編號列表
[編輯]實現編號 | 名稱 |
---|---|
0 | Berkley Bootloader |
1 | OpenSBI |
2 | Xvisor |
3 | KVM |
4 | RustSBI |
5 | Diosix |
兼容性擴展
[編輯]擴展編號為0x00至0x0F。兼容性擴展忽略了函數編號,它直接占用了多個擴展編號。每個擴展編號必須單獨被使用探測函數來探測可用性。
兼容性擴展已經被棄用,它的功能被其它的擴展模塊替代。然而,控制台輸出和控制台輸入暫時沒有替代的模塊。
時鐘擴展
[編輯]替代了兼容性擴展0x00,時鐘擴展的編號為0x54494D45。
時鐘設置函數
[編輯]這個函數輸入一個參數,即下一個時鐘中斷發生的時刻。無論特權層的寄存器寬度如何,時刻值永遠是位寬為64的整數。
順序 | 名稱 | 類型 |
---|---|---|
0 | 時刻值 | u64 |
使用函數後,下一個時鐘中斷將在參數指定的時刻值發生。區分於時間的變化量即間隔,時刻值是時間數值的狀態。這個函數還將清除時鐘中斷的等待位。
如果特權層希望清除等待位,而不設置下一個時刻值,特權層可以選擇將時鐘設置到很遠的將來——比如2^64-1,或者可以清除sie寄存器的STIE位來關閉時鐘中斷。
這個函數一定成功,不會返回錯誤編碼。
時鐘擴展函數列表
[編輯]函數名稱 | 規範版本 | 函數編號 | 擴展編號 |
---|---|---|---|
時鐘設置函數 | 0.2 | 0 | 0x54494D45 |
核間中斷擴展
[編輯]這個擴展的編號是0x735049,它替代了兼容性擴展0x04。另一個與核間中斷有關的擴展0x03已經被棄用。所有的函數使用的位集參數都由二進制編碼章節規定。
核間中斷發送函數
[編輯]這個函數輸入兩個參數,它們共同選擇需要接收核間中斷的處理器核。
順序 | 名稱 | 類型 |
---|---|---|
0 | 處理器核遮罩位集 | usize |
1 | 處理器核位集起始編號 | usize |
函數將為所有選中的處理器核發送核間中斷。對所有的接收核來說,核間中斷將被表示為特權層的軟件中斷。
這個函數將只會成功,無論位集參數選中的核是否存在。
時鐘擴展函數列表
[編輯]函數名稱 | 規範版本 | 函數編號 | 擴展編號 |
---|---|---|---|
核間中斷發送函數 | 0.2 | 0 | 0x735049 |
遠程柵欄擴展
[編輯]擴展編號為0x52464E43。這個擴展定義了所有的遠程柵欄,替代了兼容性擴展0x05到0x07。所有函數使用的遮罩位集和起始編號參數,都由二進制編碼章節的標準位集數據結構規定。
所有刷新頁表緩存的函數都使用了起始地址和地址長度參數。通常,它們定義一個待刷新的虛擬地址區間。但當以下情況發生時:
- 起始地址和地址長度都是0,或者
- 地址長度為2^XLEN-1
則表示遠程柵欄函數將刷新完整的頁表緩存。下文將不再贅述遮罩位集、起始編號、起始地址和地址長度的參數意義。
遠程指令柵欄函數
[編輯]這個函數輸入兩個參數,決定要選取即將要發送柵欄操作的處理器核。
順序 | 名稱 | 類型 |
---|---|---|
0 | 遮罩位集 | usize |
1 | 起始編號 | usize |
函數將請求對應的處理器核執行一條FENCE.I指令。
本函數不會失敗。
錯誤類型 | 發生條件 |
---|---|
調用成功 | 成功發送刷新請求到選中的所有核 |
遠程全空間特權內存柵欄函數
[編輯]這個函數輸入四個參數,決定要選取即將要發送柵欄操作的處理器核,以及需要刷新的虛擬地址區間。
順序 | 名稱 | 類型 |
---|---|---|
0 | 遮罩位集 | usize |
1 | 起始編號 | usize |
2 | 起始地址 | usize |
3 | 地址長度 | usize |
函數將請求對應的處理器核執行一條SFENCE.VMA指令,這條指令包含起始地址之後地址長度區間內的虛擬地址段。
如果發生錯誤,將會返回以下的錯誤代碼。
錯誤類型 | 發生條件 |
---|---|
調用成功 | 成功發送刷新請求到選中的所有核 |
非法參數 | 起始地址和地址長度的參數數值不合法 |
遠程特定空間特權柵欄函數
[編輯]這個函數輸入五個參數,決定要選取即將要發送柵欄操作的處理器核,以及需要刷新的虛擬地址區間,以及需要刷新的地址空間的編號。
順序 | 名稱 | 類型 |
---|---|---|
0 | 遮罩位集 | usize |
1 | 起始編號 | usize |
2 | 起始地址 | usize |
3 | 地址長度 | usize |
4 | 地址空間編號 | usize |
函數將請求對應的處理器核執行一條帶地址空間編號的SFENCE.VMA指令,這條指令包含起始地址之後地址長度區間內的虛擬地址段。
如果發生錯誤,將會返回以下的錯誤代碼。
錯誤類型 | 發生條件 |
---|---|
調用成功 | 成功發送刷新請求到選中的所有核 |
非法參數 | 起始地址和地址長度的參數數值不合法 |
遠程特定虛擬機虛擬化內存柵欄函數
[編輯]這個函數輸入四個參數,決定要選取即將要發送柵欄操作的處理器核,以及需要刷新的虛擬地址區間,以及需要刷新的虛擬機的編號。
順序 | 名稱 | 類型 |
---|---|---|
0 | 遮罩位集 | usize |
1 | 起始編號 | usize |
2 | 起始地址 | usize |
3 | 地址長度 | usize |
4 | 虛擬機編號 | usize |
函數將請求對應的處理器核執行一條帶虛擬機編號的HFENCE.GVMA指令,這條指令包含起始地址之後地址長度區間內的虛擬地址段。
只有特權層環境支持虛擬化擴展時,這條函數有效,否則它將返回不支持的功能錯誤。如果發生其它錯誤,將會返回以下的錯誤代碼。
錯誤類型 | 發生條件 |
---|---|
調用成功 | 成功發送刷新請求到選中的所有核 |
不支持的功能 | 至少有一個選中的處理器核的特權層環境不支持虛擬化擴展 |
非法參數 | 起始地址和地址長度的參數數值不合法 |
遠程虛擬化全局階段內存柵欄函數
[編輯]這個函數輸入四個參數,決定要選取即將要發送柵欄操作的處理器核,以及需要刷新的虛擬地址區間。
順序 | 名稱 | 類型 |
---|---|---|
0 | 遮罩位集 | usize |
1 | 起始編號 | usize |
2 | 起始地址 | usize |
3 | 地址長度 | usize |
函數將請求對應的處理器核執行一條HFENCE.GVMA指令,這條指令包含起始地址之後地址長度區間內的虛擬地址段。
只有特權層環境支持虛擬化擴展時,這條函數有效,否則它將返回不支持的功能錯誤。如果發生其它錯誤,將會返回以下的錯誤代碼。
錯誤類型 | 發生條件 |
---|---|
調用成功 | 成功發送刷新請求到選中的所有核 |
不支持的功能 | 至少有一個選中的處理器核的特權層環境不支持虛擬化擴展 |
非法參數 | 起始地址和地址長度的參數數值不合法 |
遠程虛擬機內特定空間柵欄函數
[編輯]這個函數輸入五個參數,決定要選取即將要發送柵欄操作的處理器核,以及需要刷新的虛擬地址區間,以及需要刷新的地址空間的編號。
順序 | 名稱 | 類型 |
---|---|---|
0 | 遮罩位集 | usize |
1 | 起始編號 | usize |
2 | 起始地址 | usize |
3 | 地址長度 | usize |
4 | 地址空間編號 | usize |
函數將請求對應的處理器核執行一條帶地址空間編號的HFENCE.VVMA指令,這條指令包含起始地址之後地址長度區間內的虛擬地址段。
只有特權層環境支持虛擬化擴展時,這條函數有效,否則它將返回不支持的功能錯誤。如果發生其它錯誤,將會返回以下的錯誤代碼。
錯誤類型 | 發生條件 |
---|---|
調用成功 | 成功發送刷新請求到選中的所有核 |
不支持的功能 | 至少有一個選中的處理器核的特權層環境不支持虛擬化擴展 |
非法參數 | 起始地址和地址長度的參數數值不合法 |
遠程虛擬機內全空間柵欄函數
[編輯]這個函數輸入四個參數,決定要選取即將要發送柵欄操作的處理器核,以及需要刷新的虛擬地址區間。
順序 | 名稱 | 類型 |
---|---|---|
0 | 遮罩位集 | usize |
1 | 起始編號 | usize |
2 | 起始地址 | usize |
3 | 地址長度 | usize |
函數將請求對應的處理器核執行一條HFENCE.VVMA指令,這條指令包含起始地址之後地址長度區間內的虛擬地址段。
只有特權層環境支持虛擬化擴展時,這條函數有效,否則它將返回不支持的功能錯誤。如果發生其它錯誤,將會返回以下的錯誤代碼。
錯誤類型 | 發生條件 |
---|---|
調用成功 | 成功發送刷新請求到選中的所有核 |
不支持的功能 | 至少有一個選中的處理器核的特權層環境不支持虛擬化擴展 |
非法參數 | 起始地址和地址長度的參數數值不合法 |
遠程柵欄擴展函數列表
[編輯]函數名稱 | 規範版本 | 函數編號 | 擴展編號 |
---|---|---|---|
遠程指令柵欄函數 | 0.2 | 0 | 0x52464E43 |
遠程全空間特權內存柵欄函數 | 0.2 | 1 | 0x52464E43 |
遠程特定空間特權柵欄函數 | 0.2 | 2 | 0x52464E43 |
遠程特定虛擬機虛擬化內存柵欄函數 | 0.2 | 3 | 0x52464E43 |
遠程虛擬化全局階段內存柵欄函數 | 0.2 | 4 | 0x52464E43 |
遠程虛擬機內特定空間柵欄函數 | 0.2 | 5 | 0x52464E43 |
遠程虛擬機內全空間柵欄函數 | 0.2 | 6 | 0x52464E43 |
核狀態管理擴展
[編輯]編號為0x48534D。核狀態管理擴展引入了核的一系列狀態核一組函數,允許特權層軟件提交請求來更改核的狀態。
每個處理器核在特權層接口下能顯示不同的核狀態。所有可能的核狀態在下表中定義。
編號 | 狀態名稱 | 描述 |
---|---|---|
0 | 已啟動 | 處理器核已通電,正在正常運行 |
1 | 已停止 | 處理器核不在特權態或其它更低權限的狀態運行。如果特權層環境支持斷電操作,它可能已被特權層環境斷電 |
2 | 正在啟動 | 其它的核已請求該核從已停止狀態啟動,它仍在執行若干操作,以進入已啟動狀態 |
3 | 正在停止 | 其它的核已請求該核從已啟動狀態停止,它仍在執行若干操作,以進入已停止狀態 |
4 | 已暫停 | 處理器核正在平台定義的暫停或低電量狀態 |
5 | 正在暫停 | 其它的核已請求該核從已停止狀態暫停,它仍在執行若干操作,以進入已暫停狀態 |
6 | 正在恢復 | 其它的核已請求該核從已暫停狀態恢復,它仍在執行若干操作,以進入已啟動狀態 |
在任何的時間點上,處理器核應當處於以上狀態中的任意一種。
在一些情況下,一個平台可能將多個核捆綁在一種層級性的拓撲組織,它們可能共同組成簇團、節點或其它結構的組合,組合和高層級拓撲間不共享電源設置,或者定義了專門的低功耗狀態。這些平台定義的低功耗狀態可以被歸納為單獨處理器核的暫停狀態。特權層接口的實現可能使用不同的方法,來充分利用這些暫停狀態。
- 平台協調法。當一個處理器核在特權層開始空閒等待時,特權層上運行的電源管理軟件將通過特權層環境,向層級組織的更高級請求最深的暫停狀態。特權層接口的實現可能選擇不比給定暫停狀態更深,而且喚醒延遲不比暫停狀態更高的平台暫停狀態;
- 系統發起法。這種方法的特權層在所有某一層級組織的核全部暫停後,系統的電源管理軟件才將向更高層級的組織請求最深的暫停狀態。此時,特權層接口的實現從不為更高層級的組織選擇暫停狀態,而總是傾向於選擇最近一個為更高層級的組織選擇的掛起狀態。
處理器核啟動函數
[編輯]處理器核停止函數
[編輯]獲取處理器核當前狀態函數
[編輯]處理器核暫停函數
[編輯]核狀態管理擴展函數列表
[編輯]函數名稱 | 規範版本 | 函數編號 | 擴展編號 |
---|---|---|---|
處理器核啟動函數 | 0.2 | 0 | 0x48534D |
處理器核停止函數 | 0.2 | 1 | 0x48534D |
獲取處理器核當前狀態函數 | 0.2 | 2 | 0x48534D |
處理器核暫停函數 | 0.3 | 3 | 0x48534D |
系統復位擴展
[編輯]編號為0x53525354。系統復位擴展允許特權層軟件重啟或關閉當前的系統;這裡,「系統」可能是一台機器或者一個虛擬化軟件。
系統復位函數
[編輯]這個函數輸入兩個參數,分別代表系統復位的類型和原因。
順序 | 名稱 | 類型 |
---|---|---|
0 | 復位類型 | u32 |
1 | 復位原因 | u32 |
函數將根據類型和原因來復位系統。這是一個阻塞的函數,如果復位操作成功,函數將不會返回。
復位類型是必須給定的,而復位原因是可選的。它們的定義如下表。
復位類型值 | 說明 |
---|---|
0x00000000 | 關機 |
0x00000001 | 冷重啟 |
0x00000002 | 熱重啟 |
0x00000003 - 0xEFFFFFFF | 保留作未來使用 |
0xF0000000 - 0xFFFFFFFF | 供應商或平台定義的復位類型 |
> 0xFFFFFFFF | 保留作未來使用 |
復位原因值 | 說明 |
---|---|
0x00000000 | 未提供復位原因 |
0x00000001 | 系統錯誤 |
0x00000002 - 0xDFFFFFFF | 保留作未來使用 |
0xE0000000 - 0xEFFFFFFF | 特權層接口實現定義的復位原因 |
0xF0000000 - 0xFFFFFFFF | 供應商或平台定義的復位原因 |
> 0xFFFFFFFF | 保留作未來使用 |
當特權模式的軟件在硬件環境上運行時,特權層接口的實現稱作機器模式的固件。在這種情況下,關機操作相當於關閉物理系統的供電電源,而冷重啟相當於在物理供電上重新開始上電過程。除此之外,熱重啟相當於處理器和部分外設系統的電源重新啟動,而整個系統的供電並未重新啟動。特別地,擁有板載管理芯片的服務器主板上,熱重啟不會重啟此管理芯片,而冷重啟會重新啟動管理芯片。
當特權軟件在虛擬機中運行,特權層接口的實現通常是一個虛擬化軟件的管理模塊。關機、冷重啟、熱重啟在功能上與物理系統類似,但可能不會導致物理供電的變化。
當特權層軟件無法識別復位類型、復位原因參數時,系統復位函數將會返回錯誤。出於其它的原因,系統復位函數仍可能返回錯誤。所有失敗的錯誤編號列於下表。
錯誤類型 | 發生條件 |
---|---|
非法參數 | 復位類型或者復位參數不合法 |
不支持的功能 | 復位類型是合法的,但當前的特權層接口實現不支持此復位類型 |
發生了錯誤 | 發生了其它的錯誤 |
注意,系統復位函數成功時,函數將不會返回,所以錯誤編號列表中不包含成功的選項。
系統復位擴展函數列表
[編輯]函數名稱 | 規範版本 | 函數編號 | 擴展編號 |
---|---|---|---|
系統復位函數 | 0.3 | 0 | 0x53525354 |
性能監視器擴展
[編輯]性能監視器擴展的編號為0x504D55。
RISC-V硬件定義了若干性能計數器,如mcycle、minstret和mhpmcounterX寄存器,這些寄存器能在特權態下以cycle、instret和hpmcounterX的形式只讀地訪問。特權層接口的性能監視器擴展允許特權態在機器態的協助下,配置和使用RISC-V硬件上的性能計數器。這些硬件性能計數器只能在機器態下啟動、停止或者動態配置,這需要操作機器態寄存器mcountinhibit和mhpmeventX來完成這一點。因此,如果硬件上未實現mcountinhibit寄存器,機器態的特權層接口實現會禁用性能監視器擴展。
無論是否有特權層接口,一般的RISC-V平台通常提供一些硬件的事件監視器,它們以一個64位寬的數字值代表硬件計數器的狀態。而一個特權層接口實現也提供固件的性能監視器,這些監視器能監視固件的事件狀態,比如非對齊讀寫的次數,遠程柵欄的次數,跨核中斷次數等等。
特權層接口的性能計數器會提供:
- 特權態發現和配置每個核硬件、固件計數器的接口
- 一個與perf工具兼容的性能計數器接口
- 微架構完整的事件編碼
為了定義特權層接口的性能監視器模塊,我們定義計數器編號、事件編號和事件數據三個變量。硬件或固件定義了計數器和事件,它們的編號分別稱作計數器編號和事件編號。除此之外,事件的額外信息稱作事件數據。無論RISC-V架構的寄存器寬度如何,事件數據永遠是位寬為64的整數。
事件編號是一個位寬為20的非零整數,由事件類型和事件代碼組成。它的定義如下表。
事件編號的二進制位 | |||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
19 | 18 | 17 | 16 | 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
事件類型 | 事件代碼 |
通用硬件事件
[編輯]事件編號定義了事件類型字段和事件代碼字段。當事件類型字段的值為0x0時,表示這是一個通用硬件事件。以事件代碼區分不同的通用硬件事件,下表給出了通用硬件事件和它們名稱、描述的關係。
事件代碼0的通用硬件事件不被定義,因為事件編號被定義為非零的整數。
事件名稱 | 代碼 | 觸發前提 |
---|---|---|
硬件處理器運行周期事件 | 1 | 非暫停狀態的處理器核經歷的每個時鐘周期 |
硬件指令處理事件 | 2 | 每次完整地處理一條指令 |
硬件緩存命中事件 | 3 | 每次緩存命中 |
硬件緩存未命中事件 | 4 | 每次緩存未命中 |
硬件分支指令事件 | 5 | 每次執行分支指令 |
硬件分支預測失敗事件 | 6 | 每次分支預測不成功 |
硬件總線時鐘周期事件 | 7 | 總線時鐘經歷的每個周期 |
硬件前端失速周期事件 | 8 | 微架構前端空轉經歷的每個時鐘周期 |
硬件後端失速周期事件 | 9 | 微架構後端空轉經歷的每個時鐘周期 |
硬件處理器參考周期事件 | 10 | 處理器核參考時鐘經歷的每個周期 |
通用硬件事件暫時不包含事件數據,非零的事件數據值保留做未來使用。
硬件處理器的運行周期和參考周期是不同的。處理器處於等待狀態時,運行周期事件不會被觸發,而參考周期事件會被觸發。處理器處於非等待狀態時,前後兩個事件都會被觸發。
硬件處理器的運行周期永遠和cycle寄存器的處理器時鐘是相同的。而硬件處理器的參考周期是對某一固定處理器頻率的計數,無論是否進入等待狀態,都會記入時鐘周期;這個固定頻率可能會和time寄存器的值一致。
使用WFI等待,或使用特權層接口的暫停函數後,一些RISC-V平台會可能會暫停處理器時鐘,另一些RISC-V平台可能不會。處理器時鐘暫停時,硬件處理器的運行周期和時鐘周期事件都不會被觸發。
硬件總線時鐘周期事件定義為對某一固定總線頻率的計數。這個固定頻率可能和time寄存器的值一致,也可能和處理器核與總線邊界的某一計數器一致。
硬件緩存事件
[編輯]當事件類型為0x1時,表示發生了硬件緩存事件。所有的硬件緩存事件都通過事件編號來區分。硬件緩存事件的事件代碼擁有緩存區域類型、操作類型和結果類型三個字段,它們的定義如下。
事件類型 | 事件代碼 | ||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
19 | 18 | 17 | 16 | 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
都是0x1 | 緩存區域 | 操作 | 結果 |
對發生的所有硬件緩存事件,它們的緩存區域編號、操作編號和結果編號定義如下。
緩存區域名稱 | 編號 | 描述 |
---|---|---|
一級數據緩存 | 0 | 事件與一級數據緩存有關 |
一級指令緩存 | 1 | 事件與一級指令緩存有關 |
最高級緩存 | 2 | 事件與等級最高的緩存區域有關 |
數據快表緩存 | 3 | 事件與數據快表有關 |
指令快表緩存 | 4 | 事件與指令快表有關 |
分支預測單元緩存 | 5 | 事件與分支預測單元有關 |
節點緩存 | 6 | 事件與NUMA節點緩存有關 |
緩存操作 | 編號 | 描述 |
---|---|---|
讀操作 | 0 | 讀緩存行操作 |
寫操作 | 1 | 寫緩存行操作 |
預取操作 | 2 | 緩存行數據的預取操作 |
結果 | 編號 | 描述 |
---|---|---|
成功 | 0 | 成功訪問了緩存 |
失敗 | 1 | 本次事件屬於緩存未命中 |
硬件緩存事件暫未使用事件數據,非零的事件數據值保留做未來使用。
原始硬件事件
[編輯]當事件類型為0x2時,發生的是原始硬件事件。原始硬件事件的事件編號恆為零。
事件數據是一個64位的整數值。如果RISC-V環境的mhpmeventX位寬為32,事件數據包含將被填寫到mhpmeventX寄存器的32位值。
如果RISC-V環境的mhpmeventX位寬為64,事件數據的值具有兩個部分。低48位包含將被填寫到mhpmeventX中的低48位值。高16位將被填寫到mhpmeventX的值將由特權層二進制接口的實現決定。
一些RISC-V硬件實現會定義一些在事件發生時會被寫入mhpmeventX寄存器的值。發生通用硬件時間和硬件緩存事件時,為了簡單期間,RISC-V的硬件實現可以將零擴展的事件編號作為預期的值。
固件事件
[編輯]事件類型為0xf時,表示發生了固件事件。每個固件事件都通過不同的事件代碼來區分。固件事件的事件代碼定義如下。
事件名稱 | 代碼 | 發生條件 |
---|---|---|
固件非對齊讀取事件 | 0 | 固件處理的每次次非對稱讀取陷入 |
固件非對齊寫入事件 | 1 | 固件處理的每次非對稱寫入陷入 |
固件處理無權讀取事件 | 2 | 固件處理的每次權限不足讀取陷入 |
固件處理無權寫入事件 | 3 | 固件處理的每次權限不足寫入陷入 |
固件處理非法指令事件 | 4 | 固件處理的每次非法指令陷入 |
固件設置時鐘事件 | 5 | 每次由固件設置時鐘當前值 |
固件跨核中斷發送事件 | 6 | 每次固件發送跨核中斷到另一個核 |
固件跨核中斷接收事件 | 7 | 每次固件從另一個核接收到跨核中斷 |
固件遠程指令柵欄發送事件 | 8 | 每次固件請求另一核執行FENCE.I指令 |
固件遠程指令柵欄接收事件 | 9 | 每次固件接收到FENCI.I執行請求 |
固件遠程全空間特權內存柵欄發送事件 | 10 | 固件請求另一核執行SFENCE.VMA指令 |
固件遠程全空間特權內存柵欄接收事件 | 11 | 固件接收到SFENCE.VMA執行請求 |
固件遠程特定空間特權柵欄發送事件 | 12 | 固件發送具有地址空間編號的SFENCE.VMA指令 |
固件遠程特定空間特權柵欄接收事件 | 13 | 固件接收具有地址空間編號的SFENCE.VMA執行請求 |
固件遠程虛擬化全局階段內存柵欄發送事件 | 14 | 固件請求另一核執行HFENCE.GVMA指令 |
固件遠程虛擬化全局階段內存柵欄接收事件 | 15 | 固件接收到的HFENCE.GVMA執行請求 |
固件遠程特定虛擬機虛擬化內存柵欄發送事件 | 16 | 固件發送具有虛擬機編號的HFENCE.GVMA指令 |
固件遠程特定虛擬機虛擬化內存柵欄接收事件 | 17 | 固件接收具有虛擬機編號的HFENCE.GVMA執行請求 |
固件遠程虛擬機內全空間柵欄發送事件 | 18 | 固件請求另一核執行HFENCE.VVMA指令 |
固件遠程虛擬機內全空間柵欄接收事件 | 19 | 固件接收到的HFENCE.VVMA執行請求 |
固件遠程虛擬機內特定空間柵欄發送事件 | 20 | 固件發送具有地址空間編號的HFENCE.VVMA指令 |
固件遠程虛擬機內特定空間柵欄接收事件 | 21 | 固件接收具有地址空間編號的HFENCE.VVMA執行請求 |
固件事件暫未使用事件數據,非零的事件數據保留做未來使用。
獲取計數器數量函數
[編輯]這個函數沒有輸入參數。
函數返回當前特權層環境支持的計數器數量,這將包括硬件計數器和固件計數器。獲取計數器數量函數總會執行成功。
獲取計數器細節信息函數
[編輯]這個函數輸入一個參數,即待查詢細節信息的計數器編號。
順序 | 名稱 | 類型 |
---|---|---|
0 | 計數器編號 | usize |
函數返回對應計數器的細節信息。無論是固件或硬件計數器,都將返回計數器的類型。如果是硬件計數器,還將額外返回計數器的位寬,以及計數器對應控制與狀態寄存器的編號。
返回的細節定義包含在返回值的字段中,字段的定義如下。
計數器的細節信息 | |||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
XLEN-1 | XLEN-2 | ... | 18 | 17 | 16 | 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
類型 | 保留作未來使用 | 計數值的位寬減去1 | 控制狀態寄存器編號 |
返回值的類型為0或1;0代表硬件計數器,1代表固件計數器。當類型為1時,控制狀態寄存器編號和位寬字段應當被忽略。
位寬字段編碼為計數值的位寬減去1。當此字段為0,說明位寬為1;以此類推,字段為最大值63時,代表位寬為64。
當這個函數失敗時,它應當返回錯誤編號。它可能返回的所有錯誤編號如下。
錯誤類型 | 發生條件 |
---|---|
調用成功 | 成功返回了計數器的細節信息 |
非法參數 | 不存在編號為傳入參數的計數器 |
尋找和配置計數器函數
[編輯]這個函數輸入的參數依次如下表。
順序 | 名稱 | 類型 |
---|---|---|
0 | 計數器集合起始編號 | usize |
1 | 計數器集合編號遮罩 | usize |
2 | 配置位集* | usize |
3 | 事件編號 | usize |
4 | 事件數據 | u64 |
此函數將尋找和配置能監視給定事件的一個計數器。起始編號和編號遮罩參數將用於選取計數器,選中的計數器必須處於停止或者禁用狀態。事件編號表示計數器監視的事件,而事件數據表示額外的事件配置信息。
計數器的額外配置信息和過濾提示將由配置位集提供,它的每個位表示一種函數操作。每個位的定義如下表。
名稱 | 位編號 | 描述 |
---|---|---|
跳過匹配 | 0 | 函數將跳過匹配過程 |
清除計數器值 | 1 | 函數將清除選中計數器的值 |
自動啟動 | 2 | 配置完畢後,選中的計數器將自動啟動 |
虛擬用戶態不計數 | 3 | 進入VU態後停止計數 |
虛擬特權態不計數 | 4 | 進入VS態後停止計數 |
用戶態不計數 | 5 | 進入U態後停止計數 |
特權態不計數 | 6 | 進入S態後停止計數 |
機器態不計數 | 7 | 進入M態後停止計數 |
保留 | 8..XLEN | 留作未來使用 |
當跳過匹配被置位,特權層接口實現將從起始編號和編號遮罩決定的計數器集中。無條件地選擇第一個寄存器。
無論自動啟動計數器是否被置位,在執行函數的過程中,計數器的值都不會被改變。
配置位集第3至第7位是一種提示位,它提示特權層實現應當在不同的態過濾事件。當且僅當特權層實現認為這會帶來安全問題,或硬件不支持按特權層的事件過濾時,特權層實現可以忽略這些提示位。
當函數成功執行時,說明有一個計數器成功被配置,函數將返回它的編號。函數失敗時可能返回的所有錯誤編號如下。
錯誤類型 | 發生條件 |
---|---|
調用成功 | 成功找到並配置對應的計數器 |
非法參數 | 計數器集包含非法的計數器 |
不支持的功能 | 選中的計數器不能監視給定的事件 |
計數器啟動函數
[編輯]這個函數輸入的參數依次如下表。
順序 | 名稱 | 類型 |
---|---|---|
0 | 計數器集合起始編號 | usize |
1 | 計數器集合編號遮罩 | usize |
2 | 啟動配置位集* | usize |
3 | 初始值 | u64 |
此函數將在調用者的硬件線程中,啟動或者啟用計數器集中的所有計數器。計數器集將由起始編號和編號遮罩給定。初始值參數將決定選中計數器在啟動前設定的初始值。
函數的功能受到啟動配置位集的影響,它的定義如下。
名稱 | 位編號 | 描述 |
---|---|---|
設置初始值 | 0 | 函數將在啟動前先設置初始值 |
保留 | 1..XLEN | 所有非零值均留作未來使用 |
當設置初始值位未被設置時,計數器的值不會被修改。啟動後,計數器將從當前的值繼續計數。
此函數不會提供返回值,可能返回的所有錯誤編號如下。
錯誤類型 | 發生條件 |
---|---|
調用成功 | 成功啟動對應的計數器 |
非法參數 | 至少有一個選中的計數器無效 |
已經啟動 | 至少有一個選中的計數器已經啟動 |
計數器停止函數
[編輯]這個函數輸入的參數依次如下表。
順序 | 名稱 | 類型 |
---|---|---|
0 | 計數器集合起始編號 | usize |
1 | 計數器集合編號遮罩 | usize |
2 | 停止配置位集* | usize |
此函數將在調用者的硬件線程中,停止或者禁用計數器集中的所有計數器。計數器集將由起始編號和編號遮罩給定。函數的功能受到停止配置位集的影響,它的定義如下。
名稱 | 位編號 | 描述 |
---|---|---|
復位初始值 | 0 | 函數將在啟動前先復位初始值 |
保留 | 1..XLEN | 所有非零值均留作未來使用 |
此函數不會提供返回值,可能返回的所有錯誤編號如下。
錯誤類型 | 發生條件 |
---|---|
調用成功 | 成功停止對應的計數器 |
非法參數 | 至少有一個選中的計數器無效 |
已經停止 | 至少有一個選中的計數器已經停止 |
固件計數器讀取函數
[編輯]本函數將提供固件計數器當前的值。函數輸入一個參數,即待查詢細節信息的固件計數器編號。
順序 | 名稱 | 類型 |
---|---|---|
0 | 計數器編號 | usize |
本函數不能用於查詢硬件計數器的當前值。
函數可能返回的所有錯誤編號如下。
錯誤類型 | 發生條件 |
---|---|
調用成功 | 成功返回了計數器的細節信息 |
非法參數 | 指定計數器不存在,或指定計數器是硬件計數器 |
性能監視器擴展函數列表
[編輯]函數名稱 | 規範版本 | 函數編號 | 擴展編號 |
---|---|---|---|
獲取計數器數量函數 | 0.3 | 0 | 0x504D55 |
獲取計數器細節信息函數 | 0.3 | 1 | 0x504D55 |
尋找和配置計數器函數 | 0.3 | 2 | 0x504D55 |
計數器啟動函數 | 0.3 | 3 | 0x504D55 |
計數器停止函數 | 0.3 | 4 | 0x504D55 |
固件計數器讀取函數 | 0.3 | 5 | 0x504D55 |
實驗性擴展空間
[編輯]占用了擴展編號0x08000000至0x08FFFFFF,目前沒有定義。
供應商定義的擴展空間
[編輯]占用了擴展編號0x09000000至0x09FFFFFF;其中,低位與mvendorid的值相符。
固件定義的擴展空間
[編輯]占用了擴展編號0x0A000000至0x0AFFFFFF,低位是特權層接口的實現編號。
本譯文與其原文有分別的版權許可。譯文版權狀況僅適用於本版本。
原文 | |
---|---|
譯文 | Public domainPublic domainfalsefalse |