命令提交¶
Execs 在 DRM 驅動程式中一直相當複雜(至少在 i915 中),因為一些事情:
傳入一個 BO 列表,該列表被讀取/寫入以建立隱式同步
在執行時繫結
在執行時流量控制環
在 XE 中,我們透過不允許將 BO 列表傳遞到 exec 中,使用 dma-buf 隱式同步 uAPI,將繫結作為單獨的操作,並使用 DRM 排程程式來流量控制環,從而避免了所有這些複雜性。 讓我們深入瞭解這些。
我們可以透過強制使用者在每次 exec 上使用輸入/輸出 fences 而不是核心跟蹤 BO 的依賴關係來避免 BO 列表(例如,如果使用者知道一個 exec 寫入一個 BO 並在下一個 exec 中從 BO 讀取,則使用者有責任在兩個 exec 之間傳遞輸入/輸出 fence)。
我們不允許使用者在執行時觸發繫結,而是有一個 VM 繫結 IOCTL,它使用與 exec 相同的輸入/輸出 fence 介面。 從這個意義上講,從使用者的角度來看,VM 繫結基本上與 exec 操作相同。 例如,如果 exec 依賴於 VM 繫結,則使用輸入/輸出 fence 介面 (struct drm_xe_sync) 來同步,就像在兩個依賴的 exec 之間同步一樣。
雖然使用者無法觸發繫結,但我們仍然必須在自上次 exec 以來已失效的 VM 中重新繫結 userptrs,同樣,我們還必須重新繫結已被核心驅逐的 BO。 我們在 VM 中任何外部 BO 上的任何掛起的核心操作之後,或者任何 VM 私有的 BO 之後,安排這些重新繫結。 這是透過重新繫結等待 BO 的 DMA_RESV_USAGE_KERNEL 插槽(核心操作)和核心操作等待所有 BO 的插槽(正在進行中的 exec 位於私有 BO 的 DMA_RESV_USAGE_BOOKKEEP 中,對於外部 BO)。
重新繫結/ dma-resv 使用僅適用於非計算模式 VM,因為對於計算模式 VM,我們使用搶佔 fences 和重新繫結 worker(TODO:新增連結)。
無需在 exec 中流量控制環,因為我們在提交時寫入環,並設定 DRM 排程程式最大作業限制 SIZE_OF_RING / MAX_JOB_SIZE。 然後,DRM 排程程式將保持所有作業,直到環中有可用空間。
所有這些都會導致一個相當簡單的 exec 實現。
流程¶
Parse input arguments
Wait for any async VM bind passed as in-fences to start
<----------------------------------------------------------------------|
Lock global VM lock in read mode |
Pin userptrs (also finds userptr invalidated since last exec) |
Lock exec (VM dma-resv lock, external BOs dma-resv locks) |
Validate BOs that have been evicted |
Create job |
Rebind invalidated userptrs + evicted BOs (non-compute-mode) |
Add rebind fence dependency to job |
Add job VM dma-resv bookkeeping slot (non-compute mode) |
Add job to external BOs dma-resv write slots (non-compute mode) |
Check if any userptrs invalidated since pin ------ Drop locks ---------|
Install in / out fences for job
Submit job
Unlock all