基於PMU事件的分支

基於事件的分支 (EBB) 是一種特性,允許硬體在特定事件發生時直接分支到指定的使用者空間地址。

完整規範可在 Power ISA v2.07 中找到

EBB 可以配置的一種事件型別是 PMU 異常。本文件描述了使用 Linux perf_events API 配置 Power PMU 以生成 EBB 的 API。

術語

在本文件中,我們將提到“EBB 事件”或“EBB events”。這僅指在其 attr.config 中設定了“EBB”標誌的 struct perf_event。可以在硬體 PMU 上配置的所有事件都是可能的“EBB 事件”。

背景

當發生 PMU EBB 時,它會被傳遞給當前執行的程序。因此,EBB 只能被程式用於自我監控。

perf_events API 的一個特性是可以在其他程序上建立事件,但需要經過標準許可權檢查。EBB 事件也是如此,但是,除非目標程序啟用 EBB(透過 mtspr(BESCR)),否則永遠不會傳遞 EBB。

這使得程序可以為自己啟用 EBB,但實際上沒有配置任何事件。稍後,另一個程序可以連線一個 EBB 事件到該程序,這將導致 EBB 被傳遞到第一個程序。目前尚不清楚這是否真的有用。

當 PMU 配置為 EBB 時,所有 PMU 中斷都傳遞給使用者程序。這意味著一旦在 PMU 上排程了 EBB 事件,就無法配置非 EBB 事件。這意味著 EBB 事件不能與常規“perf”命令或任何其他 perf 事件同時執行。

但是,在正在使用 EBB 的程序上執行“perf”命令是安全的。核心通常會排程 EBB 事件,並且 perf 將收到通知,告知其事件無法執行。

EBB 事件和常規事件之間的排除是使用 perf_events 的現有“pinned”和“exclusive”屬性實現的。這意味著 EBB 事件將優先於其他事件,除非它們也被 pinned。如果 EBB 事件和常規事件都 pinned,那麼首先啟用的事件將被排程,另一個事件將處於錯誤狀態。有關更多資訊,請參閱下面標題為“啟用 EBB 事件”的部分。

建立 EBB 事件

要請求使用 EBB 計數事件,事件程式碼應設定位 63。

必須使用特定且限制性的屬性集建立 EBB 事件 - 這是為了使它們與 perf_events 子系統的其餘部分正確地相互操作。

必須使用設定的“pinned”和“exclusive”屬性建立 EBB 事件。請注意,如果要建立一組 EBB 事件,則只有 leader 才能設定這些屬性。

EBB 事件不得設定任何“inherit”、“sample_period”、“freq”或“enable_on_exec”屬性。

EBB 事件必須附加到任務。這透過傳遞 pid 值指定給 perf_event_open(),通常 0 表示當前任務。

組中的所有事件必須就它們是否想要 EBB 達成一致。也就是說,所有事件都必須請求 EBB,或者沒有事件可以請求 EBB。

EBB 事件必須指定要在其上計數的 PMC。這確保使用者空間能夠可靠地確定事件排程在哪個 PMC 上。

啟用 EBB 事件

成功開啟 EBB 事件後,必須使用 perf_events API 啟用它。這可以透過 ioctl() 介面或 prctl() 介面來實現。

但是,由於 perf_events API 的設計,啟用事件並不能保證它已在 PMU 上排程。要確保 EBB 事件已在 PMU 上排程,必須對該事件執行 read()。如果 read() 返回 EOF,則該事件尚未排程,並且未啟用 EBB。

發生此行為是因為 EBB 事件已 pinned 且 exclusive。當啟用 EBB 事件時,它將強制所有其他未 pinned 的事件從 PMU 上退出。在這種情況下,啟用將成功。但是,如果 PMU 上已經 pinned 了一個事件,則啟用將不成功。

讀取 EBB 事件

可以從 EBB 事件中 read()。但是,結果毫無意義。由於中斷正在傳遞到使用者程序,因此核心無法計數該事件,因此將返回垃圾值。

關閉 EBB 事件

完成 EBB 事件後,您可以像任何常規事件一樣使用 close() 關閉它。如果這是最後一個 EBB 事件,則將取消配置 PMU,並且不會再傳遞 PMU EBB。

EBB 處理程式

EBB 處理程式只是常規的使用者空間程式碼,但是必須以中斷處理程式的樣式編寫。當進入處理程式時,所有暫存器都是活動的(可能),因此必須在處理程式呼叫其他程式碼之前以某種方式儲存。

如何處理這取決於程式。對於 C 程式,一個相對簡單的選擇是在堆疊上建立一箇中斷幀並將暫存器儲存在那裡。

Fork

EBB 事件不會透過 fork 繼承。如果子程序希望使用 EBB,它應該為自己開啟一個新事件。類似地,BESCR/EBBHR/EBBRR 中的 EBB 狀態會在 fork() 之後清除。