I915 VM_BIND 特性設計和用例

VM_BIND 特性

DRM_I915_GEM_VM_BIND/UNBIND ioctl 允許 UMD 在指定的地址空間 (VM) 的指定 GPU 虛擬地址上繫結/解綁 GEM 緩衝區物件 (BO) 或 BO 的部分。這些對映(也稱為持久對映)將在由 UMD 發出的多個 GPU 提交(execbuf 呼叫)中保持永續性,而無需使用者在每次提交期間提供所有必需對映的列表(舊 execbuf 模式所需)。

VM_BIND/UNBIND 呼叫允許 UMD 請求時間線輸出柵欄,以指示繫結/解綁操作的完成。

VM_BIND 特性透過 I915_PARAM_VM_BIND_VERSION 向用戶釋出。使用者必須在 VM 建立期間透過 I915_VM_CREATE_FLAGS_USE_VM_BIND 擴充套件選擇地址空間 (VM) 的 VM_BIND 繫結模式。

在不同的 CPU 執行緒上併發執行的 VM_BIND/UNBIND ioctl 呼叫沒有順序。此外,當指定了有效的輸出柵欄時,VM_BIND/UNBIND 操作的部分可以非同步完成。

VM_BIND 特性包括

  • 多個虛擬地址 (VA) 對映可以對映到物件的相同物理頁面(別名)。

  • VA 對映可以對映到 BO 的一部分(部分繫結)。

  • 支援在 GPU 錯誤時捕獲轉儲中的持久對映。

  • 支援 userptr gem 物件(無需特殊的 uapi)。

TLB 重新整理注意事項

i915 驅動程式為每次提交重新整理 TLB,並在釋放物件的頁面時重新整理 TLB。VM_BIND/UNBIND 操作不會執行任何額外的 TLB 重新整理。任何新增的 VM_BIND 對映都將位於該 VM 的後續提交的工作集中,並且不會位於當前正在執行的批處理的工作集中(這將需要額外的 TLB 重新整理,這是不支援的)。

VM_BIND 模式下的 Execbuf ioctl

VM_BIND 模式下的 VM 不支援舊的 execbuf 繫結模式。VM_BIND 模式下的 execbuf ioctl 處理與舊的 execbuf2 ioctl 有很大不同(參見 struct drm_i915_gem_execbuffer2)。因此,添加了一個新的 execbuf3 ioctl 來支援 VM_BIND 模式。(參見 struct drm_i915_gem_execbuffer3)。execbuf3 ioctl 不接受任何 execlist。因此,不支援隱式同步。預計以下工作將能夠支援所有用例中的物件依賴關係設定要求

“dma-buf: 新增用於匯出同步檔案的 API”(https://lwn.net/Articles/859290/)

新的 execbuf3 ioctl 僅在 VM_BIND 模式下工作,VM_BIND 模式僅適用於 execbuf3 ioctl 進行提交。在 execbuf3 呼叫時對映到該 VM 上的所有 BO(透過 VM_BIND 呼叫)都被視為該提交所需的。

execbuf3 ioctl 直接指定批處理地址,而不是像 execbuf2 ioctl 中那樣指定物件控制代碼。execbuf3 ioctl 也不支援許多舊功能,如 in/out/submit 柵欄、柵欄陣列、預設 gem 上下文等(參見 struct drm_i915_gem_execbuffer3)。

在 VM_BIND 模式下,VA 分配完全由使用者管理,而不是由 i915 驅動程式管理。因此,所有 VA 分配、驅逐在 VM_BIND 模式下均不適用。此外,對於確定物件活動性,VM_BIND 模式將不使用 i915_vma 活動引用跟蹤。它將改為使用 dma-resv 物件(參見 VM_BIND dma_resv 用法)。

因此,許多支援 execbuf2 ioctl 的現有程式碼(如重定位、VA 驅逐、vma 查詢表、隱式同步、vma 活動引用跟蹤等)不適用於 execbuf3 ioctl。因此,所有 execbuf3 特定的處理都應該在一個單獨的檔案中,只有這些 ioctl 共有的功能才能儘可能地成為共享程式碼。

VM_PRIVATE 物件

預設情況下,BO 可以對映到多個 VM,也可以 dma-buf 匯出。因此,這些 BO 被稱為共享 BO。在每次 execbuf 提交期間,請求柵欄必須新增到對映到 VM 上的所有共享 BO 的 dma-resv 柵欄列表中。

VM_BIND 特性引入了一種最佳化,即使用者可以在 BO 建立期間透過 I915_GEM_CREATE_EXT_VM_PRIVATE 標誌建立一個 VM 私有的 BO。與共享 BO 不同,這些 VM 私有 BO 只能對映到它們私有的 VM 上,並且不能 dma-buf 匯出。VM 的所有私有 BO 共享 dma-resv 物件。因此,在每次 execbuf 提交期間,它們只需要更新一個 dma-resv 柵欄列表。因此,快速路徑(其中所需的對映已經繫結)提交延遲是關於 VM 私有 BO 數量的 O(1)。

VM_BIND 鎖定層次結構

此處的鎖定設計支援舊的(基於 execlist)execbuf 模式、新的 VM_BIND 模式、帶 GPU 頁面錯誤的 VM_BIND 模式以及可能的未來系統分配器支援(參見 共享虛擬記憶體 (SVM) 支援)。舊的 execbuf 模式和新的無頁面錯誤的 VM_BIND 模式使用 dma_fence 管理後備儲存的駐留。帶頁面錯誤的 VM_BIND 模式和系統分配器支援根本不使用任何 dma_fence。

VM_BIND 鎖定順序如下。

  1. Lock-A:vm_bind 互斥鎖將保護 vm_bind 列表。此鎖在 vm_bind/vm_unbind ioctl 呼叫、execbuf 路徑以及釋放對映時獲取。

    將來,當支援 GPU 頁面錯誤時,我們可以潛在地使用 rwsem 代替,以便多個頁面錯誤處理程式可以獲取讀取側鎖以查詢對映,因此可以並行執行。舊的 execbuf 繫結模式不需要此鎖。

  2. Lock-B:物件的 dma-resv 鎖將保護 i915_vma 狀態,需要在非同步工作程式中繫結/解綁 vma 時以及更新物件的 dma-resv 柵欄列表時持有。請注意,VM 的私有 BO 將共享一個 dma-resv 物件。

    未來的系統分配器支援將使用 HMM 規定的鎖定。

  3. Lock-C:spinlock/s 用於保護某些 VM 的列表,如因驅逐和 userptr 失效而失效的 vma 列表等。

當支援 GPU 頁面錯誤時,execbuf 路徑不會獲取任何這些鎖。在那裡,我們將簡單地將新的批處理緩衝區地址粉碎到環中,然後告訴排程程式執行它。獲取鎖僅發生在頁面錯誤處理程式中,我們在讀取模式下獲取 lock-A,無論我們需要哪個 lock-B 才能找到後備儲存(gem 物件的 dma_resv 鎖和系統分配器的 hmm/core mm)以及一些額外的鎖 (lock-D) 用於處理頁表競爭。頁面錯誤模式不應需要操作 vm 列表,因此永遠不需要 lock-C。

VM_BIND LRU 處理

我們需要確保 VM_BIND 對映的物件被正確地 LRU 標記,以避免效能下降。我們還需要支援 VM_BIND 物件的批次 LRU 移動,以避免 execbuf 路徑中的額外延遲。

頁表頁面類似於 VM_BIND 對映的物件(參見 可驅逐的頁表分配),並且每個 VM 維護,並且需要在 VM 啟用時(即,在呼叫帶有該 VM 的 execbuf 時)固定在記憶體中。因此,也需要頁表頁面的批次 LRU 移動。

VM_BIND dma_resv 用法

需要將柵欄新增到所有 VM_BIND 對映的物件。在每次 execbuf 提交期間,它們都使用 DMA_RESV_USAGE_BOOKKEEP 用法新增,以防止過度同步(參見 enum dma_resv_usage)。可以在顯式物件依賴關係設定期間使用 DMA_RESV_USAGE_READ 或 DMA_RESV_USAGE_WRITE 用法覆蓋它。

請注意,DRM_I915_GEM_WAIT 和 DRM_I915_GEM_BUSY ioctl 不檢查 DMA_RESV_USAGE_BOOKKEEP 用法,因此不應用於批處理結束檢查。相反,execbuf3 輸出柵欄應用於批處理結束檢查(參見 struct drm_i915_gem_execbuffer3)。

此外,在 VM_BIND 模式下,使用 dma-resv apis 來確定物件活動性(參見 dma_resv_test_signaled()dma_resv_wait_timeout()),不要使用已棄用的舊 i915_vma 活動引用跟蹤。這應該更容易與當前的 TTM 後端一起工作。

Mesa 用例

VM_BIND 可以潛在地減少 Mesa 中的 CPU 開銷(Vulkan 和 Iris),從而提高 CPU 密集型應用程式的效能。它還允許我們實現 Vulkan 的稀疏資源。隨著 GPU 硬體效能的提高,減少 CPU 開銷變得更具影響力。

其他 VM_BIND 用例

長時間執行的計算上下文

dma-fence 的使用期望它們在合理的時間內完成。另一方面,計算可能會長時間執行。因此,計算使用使用者/記憶體柵欄是合適的(參見 使用者/記憶體柵欄),並且 dma-fence 的使用必須僅限於核心內部使用。

在 GPU 頁面錯誤不可用的情況下,核心驅動程式將在緩衝區失效時啟動長時間執行的上下文的掛起(搶佔),完成失效,重新驗證 BO,然後恢復計算上下文。這是透過使用每個上下文的搶佔柵欄來完成的,該柵欄在有人嘗試等待它時啟用並觸發上下文搶佔。

使用者/記憶體柵欄

使用者/記憶體柵欄是一個 <地址,值> 對。要指示使用者柵欄,指定的值將被寫入指定的虛擬地址並喚醒等待程序。使用者柵欄可以由 GPU 或核心非同步工作程式指示(例如繫結完成時)。使用者可以使用新的使用者柵欄等待 ioctl 等待使用者柵欄。

這是關於此的一些先前工作:https://patchwork.freedesktop.org/patch/349417/

低延遲提交

允許計算 UMD 直接提交 GPU 作業,而不是透過 execbuf ioctl。這是透過 VM_BIND 未與 execbuf 同步來實現的。VM_BIND 允許繫結/解綁直接提交的作業所需的對映。

偵錯程式

透過除錯事件介面,使用者空間程序(偵錯程式)能夠跟蹤並作用於由另一個程序(被除錯)建立並透過 vm_bind 介面附加到 GPU 的資源。

GPU 頁面錯誤

GPU 頁面錯誤(如果將來支援)將僅在 VM_BIND 模式下支援。雖然舊的 execbuf 模式和新的 VM_BIND 繫結模式都需要使用 dma-fence 來確保駐留,但 GPU 頁面錯誤模式(如果支援)將不使用任何 dma-fence,因為駐留完全透過安裝和刪除/使頁表條目無效來管理。

頁面級別提示設定

VM_BIND 允許每個對映設定任何提示,而不是每個 BO。子 BO 級別的位置提示對於即將到來的 GPU 按需頁面錯誤支援將更重要。

頁面級別快取/CLOS 設定

VM_BIND 允許每個對映設定快取/CLOS,而不是每個 BO。

可驅逐的頁表分配

使頁表分配可驅逐,並以類似於 VM_BIND 對映物件的方式管理它們。頁表頁面類似於 VM 的持久對映(此處的區別在於頁表頁面將沒有 i915_vma 結構,並且在交換頁面回來後,需要更新父頁面連結)。

共享虛擬記憶體 (SVM) 支援

VM_BIND 介面可用於使用 HMM 介面直接對映系統記憶體(無需 gem BO 抽象)。僅在啟用 GPU 頁面錯誤時才支援 SVM。

VM_BIND UAPI

I915_PARAM_VM_BIND_VERSION

支援的 VM_BIND 特性版本。參見 typedef drm_i915_getparam_t 引數。

指定支援的 VM_BIND 特性版本。已定義以下 VM_BIND 版本

0:不支援 VM_BIND。

1:在 VM_UNBIND 呼叫中,UMD 必須指定先前使用 VM_BIND 建立的確切對映,ioctl 將不支援解綁多個對映或拆分它們。同樣,VM_BIND 呼叫不會替換任何現有對映。

2:取消了對解綁部分或多個對映的限制

。同樣,繫結將替換給定範圍內的任何對映。

參見 struct drm_i915_gem_vm_bindstruct drm_i915_gem_vm_unbind

I915_VM_CREATE_FLAGS_USE_VM_BIND

在 VM 建立期間選擇 VM_BIND 繫結模式的標誌。參見 struct drm_i915_gem_vm_control 標誌。

舊的 execbuf2 ioctl 不支援 VM_BIND 模式的操作。對於 VM_BIND 模式,我們有新的 execbuf3 ioctl,它不接受任何 execlist(有關更多詳細資訊,請參見 struct drm_i915_gem_execbuffer3)。

struct drm_i915_gem_timeline_fence

輸入或輸出時間線柵欄。

定義

成員:

struct drm_i915_gem_timeline_fence {
    __u32 handle;
    __u32 flags;
#define I915_TIMELINE_FENCE_WAIT            (1 << 0);
#define I915_TIMELINE_FENCE_SIGNAL          (1 << 1);
#define __I915_TIMELINE_FENCE_UNKNOWN_FLAGS (-(I915_TIMELINE_FENCE_SIGNAL << 1));
    __u64 value;
};

控制代碼

使用者的 drm_syncobj 控制代碼,用於等待或發出訊號。

標誌

支援的標誌是

I915_TIMELINE_FENCE_WAIT:在操作之前等待輸入柵欄。

I915_TIMELINE_FENCE_SIGNAL:返回作為輸出的操作完成柵欄。

時間線中的一個點。對於二進位制 drm_syncobj,值必須為 0。時間線 drm_syncobj 的值為 0 無效,因為它將 drm_syncobj 轉換為二進位制。

描述

操作將等待輸入柵欄發出訊號。

返回的輸出柵欄將在操作完成後發出訊號。

struct drm_i915_gem_vm_bind

要繫結的 VA 到物件對映。

vm_id

成員:

struct drm_i915_gem_vm_bind {
    __u32 vm_id;
    __u32 handle;
    __u64 start;
    __u64 offset;
    __u64 length;
    __u64 flags;
#define I915_GEM_VM_BIND_CAPTURE        (1 << 0);
    struct drm_i915_gem_timeline_fence fence;
    __u64 extensions;
};

控制代碼

要繫結的 VM(地址空間)id

物件控制代碼

使用者的 drm_syncobj 控制代碼,用於等待或發出訊號。

開始

要繫結的虛擬地址起始

偏移量

要繫結的物件中的偏移量

長度

要繫結的對映長度

I915_GEM_VM_BIND_CAPTURE:在 GPU 錯誤時捕獲轉儲中的此對映。

支援的標誌是

I915_TIMELINE_FENCE_WAIT:在操作之前等待輸入柵欄。

請注意,柵欄 帶有自己的標誌。

柵欄

用於繫結完成訊號的時間線柵欄。

時間線柵欄的格式為 struct drm_i915_gem_timeline_fence

它是一個輸出柵欄,因此使用 I915_TIMELINE_FENCE_WAIT 標誌無效,並且將返回錯誤。

如果未設定 I915_TIMELINE_FENCE_SIGNAL 標誌,則不請求輸出柵欄,並且同步完成繫結。

擴充套件

以零結尾的擴充套件鏈。

用於未來的擴充套件。參見 struct i915_user_extension

此結構傳遞給 VM_BIND ioctl,並指定 GPU 虛擬地址 (VA) 範圍到物件部分的對映,該對映應繫結在指定地址空間 (VM) 的裝置頁表中。指定的 VA 範圍必須是唯一的(即,當前未繫結),並且可以對映到整個物件或物件的一部分(部分繫結)。可以建立多個 VA 對映到物件的同一部分(別名)。

操作將等待輸入柵欄發出訊號。

開始偏移量長度 必須與 4K 頁面對齊。但是,DG2 的裝置本地記憶體的頁面大小為 64K,並具有緊湊的頁表。在該平臺上,對於繫結裝置本地記憶體物件,開始偏移量長度 必須與 64K 對齊。此外,UMD 不應在同一 2M 範圍內混合本地記憶體 64K 頁面和系統記憶體 4K 頁面繫結。

如果 開始偏移量長度 未正確對齊,則將返回錯誤程式碼 -EINVAL。在版本 1 中(參見 I915_PARAM_VM_BIND_VERSION),如果無法保留指定的 VA 範圍,則將返回錯誤程式碼 -ENOSPC。

在不同的 CPU 執行緒上併發執行的 VM_BIND/UNBIND ioctl 呼叫沒有順序。此外,如果指定了有效的 柵欄,則可以非同步完成 VM_BIND 操作的部分。

struct drm_i915_gem_vm_unbind

要解綁的 VA 到物件對映。

rsvd

成員:

struct drm_i915_gem_vm_unbind {
    __u32 vm_id;
    __u32 rsvd;
    __u64 start;
    __u64 length;
    __u64 flags;
    struct drm_i915_gem_timeline_fence fence;
    __u64 extensions;
};

控制代碼

要繫結的 VM(地址空間)id

物件控制代碼

保留,MBZ

要解綁的虛擬地址起始

要繫結的虛擬地址起始

要解綁的對映長度

要繫結的對映長度

當前保留,MBZ。

支援的標誌是

用於解綁完成訊號的時間線柵欄。

柵欄

用於繫結完成訊號的時間線柵欄。

如果未設定 I915_TIMELINE_FENCE_SIGNAL 標誌,則不請求輸出柵欄,並且同步完成解綁。

它是一個輸出柵欄,因此使用 I915_TIMELINE_FENCE_WAIT 標誌無效,並且將返回錯誤。

如果未設定 I915_TIMELINE_FENCE_SIGNAL 標誌,則不請求輸出柵欄,並且同步完成繫結。

此結構傳遞給 VM_UNBIND ioctl,並指定應從指定地址空間 (VM) 的裝置頁表中解綁的 GPU 虛擬地址 (VA) 範圍。VM_UNBIND 將強制從裝置頁表中解綁指定的範圍,而無需等待任何 GPU 作業完成。UMD 有責任確保在呼叫 VM_UNBIND 之前不再使用該對映。

以零結尾的擴充套件鏈。

用於未來的擴充套件。參見 struct i915_user_extension

此結構傳遞給 VM_BIND ioctl,並指定 GPU 虛擬地址 (VA) 範圍到物件部分的對映,該對映應繫結在指定地址空間 (VM) 的裝置頁表中。指定的 VA 範圍必須是唯一的(即,當前未繫結),並且可以對映到整個物件或物件的一部分(部分繫結)。可以建立多個 VA 對映到物件的同一部分(別名)。

操作將等待輸入柵欄發出訊號。

如果找不到指定的對映,ioctl 將簡單地返回,而不產生任何錯誤。

在不同的 CPU 執行緒上併發執行的 VM_BIND/UNBIND ioctl 呼叫沒有順序。此外,如果指定了有效的 柵欄,則可以非同步完成 VM_UNBIND 操作的部分。

struct drm_i915_gem_execbuffer3

DRM_I915_GEM_EXECBUFFER3 ioctl 的結構。

ctx_id

成員:

struct drm_i915_gem_execbuffer3 {
    __u32 ctx_id;
    __u32 engine_idx;
    __u64 batch_address;
    __u64 flags;
    __u32 rsvd1;
    __u32 fence_count;
    __u64 timeline_fences;
    __u64 rsvd2;
    __u64 extensions;
};

控制代碼

上下文 id

僅允許具有使用者引擎對映的上下文。

engine_idx

引擎索引

ctx_id 指定的上下文的使用者引擎對映中的索引。

batch_address

批處理 gpu 虛擬地址/es。

對於正常提交,它是批處理緩衝區的 gpu 虛擬地址。對於並行提交,它是一個指向批處理緩衝區 gpu 虛擬地址陣列的指標,陣列大小等於參與該提交的(並行)引擎的數量(參見 struct i915_context_engines_parallel_submit)。

當前保留,MBZ

支援的標誌是

rsvd1

fence_count

要解綁的虛擬地址起始

timeline_fences 陣列中的柵欄數。

timeline_fences

指向時間線柵欄陣列的指標。

時間線柵欄的格式為 struct drm_i915_gem_timeline_fence

rsvd2

DRM_I915_GEM_EXECBUFFER3 ioctl 僅在 VM_BIND 模式下工作,VM_BIND 模式僅適用於此 ioctl 進行提交。參見 I915_VM_CREATE_FLAGS_USE_VM_BIND。

要解綁的虛擬地址起始

以零結尾的擴充套件鏈。

用於未來的擴充套件。參見 struct i915_user_extension

此結構傳遞給 VM_BIND ioctl,並指定 GPU 虛擬地址 (VA) 範圍到物件部分的對映,該對映應繫結在指定地址空間 (VM) 的裝置頁表中。指定的 VA 範圍必須是唯一的(即,當前未繫結),並且可以對映到整個物件或物件的一部分(部分繫結)。可以建立多個 VA 對映到物件的同一部分(別名)。

操作將等待輸入柵欄發出訊號。

struct drm_i915_gem_create_ext_vm_private

使物件對指定 VM 私有的擴充套件。

base

成員:

struct drm_i915_gem_create_ext_vm_private {
#define I915_GEM_CREATE_EXT_VM_PRIVATE          2;
    struct i915_user_extension base;
    __u32 vm_id;
};

控制代碼

擴充套件連結。參見 struct i915_user_extension

VM 的 Id,物件是私有的

要繫結的 VM(地址空間)id

參見 struct drm_i915_gem_create_ext

操作將等待輸入柵欄發出訊號。

©核心開發社群。| 由 Sphinx 5.3.0 & Alabaster 0.7.16 提供支援 | 頁面來源