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 鎖定順序如下。
Lock-A:vm_bind 互斥鎖將保護 vm_bind 列表。此鎖在 vm_bind/vm_unbind ioctl 呼叫、execbuf 路徑以及釋放對映時獲取。
將來,當支援 GPU 頁面錯誤時,我們可以潛在地使用 rwsem 代替,以便多個頁面錯誤處理程式可以獲取讀取側鎖以查詢對映,因此可以並行執行。舊的 execbuf 繫結模式不需要此鎖。
Lock-B:物件的 dma-resv 鎖將保護 i915_vma 狀態,需要在非同步工作程式中繫結/解綁 vma 時以及更新物件的 dma-resv 柵欄列表時持有。請注意,VM 的私有 BO 將共享一個 dma-resv 物件。
未來的系統分配器支援將使用 HMM 規定的鎖定。
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 結構,並且在交換頁面回來後,需要更新父頁面連結)。
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_bind和struct 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
操作將等待輸入柵欄發出訊號。
©核心開發社群。| 由 Sphinx 5.3.0 & Alabaster 0.7.16 提供支援 | 頁面來源