I915 GuC 提交/DRM 排程器章節¶
上游計劃¶
對於上游,GuC 提交和將 i915 與 DRM 排程器整合的總體計劃是
- 合併基本的 GuC 提交
對所有 gen11+ 平臺的基本提交支援
預設情況下未在任何當前平臺上啟用,但可以透過 modparam enable_guc 啟用
需要進行大量返工才能與 DRM 排程器整合,因此無需挑剔程式碼中的所有內容,它應該只是功能性的,沒有主要的編碼風格/分層錯誤,並且不會迴歸 execlists
根據需要更新 IGT/自測以與 GuC 提交一起使用
在支援的平臺上啟用 CI 作為基線
根據需要進行返工/使 CI 在 GuC 提交到位的情況下保持健康
- 合併新的並行提交 uAPI
Bonding uAPI 與 GuC 提交完全不相容,此外它通常存在嚴重的設計問題,這就是我們無論如何都想要棄用它的原因
新的 uAPI 添加了 I915_CONTEXT_ENGINES_EXT_PARALLEL 上下文設定步驟,該步驟配置具有 N 個上下文的插槽
在 I915_CONTEXT_ENGINES_EXT_PARALLEL 之後,使用者可以在單個 execbuf IOCTL 中將 N 個批處理提交到插槽,並且這些批處理在 GPU 上並行執行
最初僅用於 GuC 提交,但如果需要,可以支援 execlists
- 轉換 i915 以使用 DRM 排程器
- GuC 提交後端與 DRM 排程器完全整合
所有請求佇列從後端移除(例如,所有背壓在 DRM 排程器中處理)
在 DRM 排程器中重置/取消掛鉤
Watchdog 掛鉤到 DRM 排程器
一旦與 DRM 排程器整合,GuC 後端的許多複雜性都可以被提取出來(例如,狀態機變得更簡單,鎖定變得更簡單,等等...)
- Execlists 後端將最低限度地需要掛鉤到 DRM 排程器
傳統介面
諸如時間分片/搶佔/虛擬引擎之類的功能將難以與 DRM 排程器整合,並且這些功能對於 GuC 提交不是必需的,因為 GuC 為我們做了這些事情
完全整合到 DRM 排程器的 ROI 很低
完全整合會給 DRM 排程器增加很多複雜性
- 在 DRM 排程器中移植 i915 優先順序繼承/提升功能
用於 i915 頁面翻轉,也可能對其他 DRM 驅動程式有用
將是 DRM 排程器中的一個可選功能
- 從 DRM 排程器中刪除按順序完成的假設
即使在使用 DRM 排程器時,後端也會處理搶佔、時間分片等...因此作業可能會亂序完成
拉出 i915 優先順序級別並使用 DRM 優先順序級別
根據需要最佳化 DRM 排程器
GuC 提交上游的 TODO¶
需要更新 GuC 韌體/i915 以啟用錯誤狀態捕獲
開源工具來解碼 GuC 日誌
公共 GuC 規範
用於基本 GuC 提交的新 uAPI¶
對於基本 GuC 提交,不需要對 uAPI 進行重大更改。唯一的更改是新的排程器屬性:I915_SCHEDULER_CAP_STATIC_PRIORITY_MAP。此屬性指示 2k i915 使用者優先順序級別靜態對映到 3 個級別,如下所示
-1k 到 -1 低優先順序
0 中等優先順序
1 到 1k 高優先順序
這是必需的,因為 GuC 只有 4 個優先順序頻段。最高優先順序頻段由核心保留。這也與 DRM 排程器優先順序級別一致。
規範參考:¶
新的並行提交 uAPI¶
現有的 bonding uAPI 與 GuC 提交完全中斷,因為在透過 I915_SUBMIT_FENCE 啟用的 execbuf 時間之前,不知道提交是單上下文提交還是並行提交。為了使用 GuC 並行提交多個上下文,必須顯式地用 N 個上下文註冊該上下文,並且必須在單個命令中將所有 N 個上下文提交給 GuC。GuC 介面不支援像 bonding uAPI 那樣動態地在 N 個上下文之間切換。因此需要一個新的並行提交介面。此外,傳統的 bonding uAPI 非常令人困惑,並且根本不直觀。此外,根據設計,I915_SUBMIT_FENCE 是一個未來的 fence,所以我們真的不應該繼續支援它。
新的並行提交 uAPI 由 3 部分組成
匯出引擎邏輯對映
用於配置上下文以進行並行提交的“set_parallel”擴充套件
擴充套件 execbuf2 IOCTL 以支援在單個 IOCTL 中提交 N 個 BB
匯出引擎邏輯對映¶
某些用例要求 BB 按邏輯順序放置在引擎例項上(例如,gen11+ 上的拆分幀)。引擎例項的邏輯對映可以基於熔斷而改變。與其讓 UMD 意識到熔斷,不如簡單地使用現有的查詢引擎資訊 IOCTL 公開邏輯對映。此外,與 execlists 相比,GuC 提交介面當前僅支援以邏輯順序將多個上下文提交給引擎,這是一個新的要求。最後,所有當前平臺最多有 2 個引擎例項,並且邏輯順序與 uAPI 順序相同。這將會在具有超過 2 個引擎例項的平臺上發生變化。
一個單獨的位將被新增到 drm_i915_engine_info.flags 中,指示已返回邏輯例項,並且新欄位 drm_i915_engine_info.logical_instance 返回邏輯例項。
用於配置上下文以進行並行提交的“set_parallel”擴充套件¶
“set_parallel”擴充套件為並行提交 N 個 BB 配置一個插槽。這是一個設定步驟,必須在呼叫任何上下文之前呼叫。有關類似的現有示例,請參閱 I915_CONTEXT_ENGINES_EXT_LOAD_BALANCE 或 I915_CONTEXT_ENGINES_EXT_BOND。一旦為並行提交配置了一個插槽,就可以呼叫 execbuf2 IOCTL 以在單個 IOCTL 中提交 N 個 BB。最初僅支援 GuC 提交。如果需要,可以稍後新增 Execlists 支援。
新增 I915_CONTEXT_ENGINES_EXT_PARALLEL_SUBMIT 和 drm_i915_context_engines_parallel_submit 到 uAPI 以實現此擴充套件。
-
struct i915_context_engines_parallel_submit¶
配置引擎以進行並行提交。
定義:
struct i915_context_engines_parallel_submit {
struct i915_user_extension base;
__u16 engine_index;
__u16 width;
__u16 num_siblings;
__u16 mbz16;
__u64 flags;
__u64 mbz64[3];
struct i915_engine_class_instance engines[];
};
成員
base基本使用者擴充套件。
engine_index並行引擎的插槽
width每個並行引擎的上下文數,或者換句話說,每次提交中的批處理數
num_siblings每個上下文的兄弟數,或者換句話說,每次提交的可能放置數
mbz16保留供將來使用;必須為零
flags所有未定義的標誌必須為零,當前未定義標誌
mbz64保留供將來使用;必須為零
engines2-d 引擎例項陣列,用於配置並行引擎
長度 = width (i) * num_siblings (j) 索引 = j + i * num_siblings
描述
在上下文引擎對映中設定一個插槽,以允許在單個 execbuf IOCTL 中提交多個 BB。然後這些 BB 將被排程以在 GPU 上並行執行。在 i915 中內部建立多個硬體上下文以執行這些 BB。一旦為 N 個 BB 配置了一個插槽,每次 execbuf IOCTL 中只能提交 N 個 BB,這是隱式行為,例如,使用者不會告訴 execbuf IOCTL 有 N 個 BB,execbuf IOCTL 知道有多少 BB 基於插槽的配置。N 個 BB 是最後 N 個緩衝區物件,如果設定了 I915_EXEC_BATCH_FIRST,則為前 N 個。
預設的放置行為是在每個上下文對映到超過 1 個物理引擎(例如,上下文是虛擬引擎)時,在每個上下文之間建立隱式繫結。此外,我們只允許相同引擎類別的上下文,並且這些上下文必須按邏輯連續的順序排列。下面描述了放置行為的示例。最後,預設是不允許 BB 在批處理中間被搶佔。而是在每組 BB 之間在所有硬體上下文上插入協調的搶佔點。將來可能會新增標誌以更改這兩個預設行為。
如果硬體上下文放置配置無效,或者平臺/提交介面不支援放置配置,則返回 -EINVAL。如果平臺/提交介面不支援擴充套件,則返回 -ENODEV。
Examples syntax:
CS[X] = generic engine of same class, logical instance X
INVALID = I915_ENGINE_CLASS_INVALID, I915_ENGINE_CLASS_INVALID_NONE
Example 1 pseudo code:
set_engines(INVALID)
set_parallel(engine_index=0, width=2, num_siblings=1,
engines=CS[0],CS[1])
Results in the following valid placement:
CS[0], CS[1]
Example 2 pseudo code:
set_engines(INVALID)
set_parallel(engine_index=0, width=2, num_siblings=2,
engines=CS[0],CS[2],CS[1],CS[3])
Results in the following valid placements:
CS[0], CS[1]
CS[2], CS[3]
This can be thought of as two virtual engines, each containing two
engines thereby making a 2D array. However, there are bonds tying the
entries together and placing restrictions on how they can be scheduled.
Specifically, the scheduler can choose only vertical columns from the 2D
array. That is, CS[0] is bonded to CS[1] and CS[2] to CS[3]. So if the
scheduler wants to submit to CS[0], it must also choose CS[1] and vice
versa. Same for CS[2] requires also using CS[3].
VE[0] = CS[0], CS[2]
VE[1] = CS[1], CS[3]
Example 3 pseudo code:
set_engines(INVALID)
set_parallel(engine_index=0, width=2, num_siblings=2,
engines=CS[0],CS[1],CS[1],CS[3])
Results in the following valid and invalid placements:
CS[0], CS[1]
CS[1], CS[3] - Not logically contiguous, return -EINVAL
擴充套件 execbuf2 IOCTL 以支援在單個 IOCTL 中提交 N 個 BB¶
已使用“set_parallel”擴充套件配置的上下文只能在單個 execbuf2 IOCTL 中提交 N 個 BB。BB 要麼是 drm_i915_gem_exec_object2 列表中的最後 N 個物件,要麼是如果設定了 I915_EXEC_BATCH_FIRST,則為前 N 個。BB 的數量是隱式的,基於提交的插槽以及它如何透過“set_parallel”或其他擴充套件配置。execbuf2 IOCTL 不需要 uAPI 更改。