Magma:移植指南

如要瞭解 Magma 的背景、硬體需求和架構說明等總覽資訊,請參閱「Magma:總覽」。

本文件說明驅動程式庫開發人員可遵循的程序,將 Vulkan 驅動程式庫移植到 Fuchsia。

需求條件

將 Vulkan 驅動程式庫移植到 Fuchsia 需要下列項目:

  • 硬體說明文件 (暫存器規格、運作原理)。
  • Vulkan 參考實作項目 (Linux)。
  • 用戶端驅動程式庫 (ICD) 應提供符合 Vulkan 1.1/1.2 的實作項目。

硬體必須通過啟動程序,才能運作網路存取、磁碟儲存空間和 fx pave 功能。

目前 Magma 僅支援 UMA 裝置,但如果您有雄心壯志,可以嘗試移植到具有獨立記憶體的 GPU。

建立 Stub 系統驅動程式庫

Magma 系統驅動程式庫 (MSD) 類似於其他作業系統上的核心驅動程式庫。此時,請考慮是否要從其他作業系統移植現有的核心驅動程式庫,或是從頭編寫一個。

此時請閱讀「驅動程式概念」一節,瞭解 Fuchsia 驅動程式庫模型。

這項選擇取決於現有核心驅動程式庫程式碼的許多方面。注意事項:

  • 驅動程式庫是否有平台抽象層,還是依附於 Linux 核心介面?
  • 授權。
  • 它的 ioctl 介面與 Magma 進入點有多相似?

第一個編碼步驟是建立可建構的基本 MSD。MSD 位於驅動程式庫目錄中。這些檔案是使用 GN 建構系統建構為 fuchsia_drivers。Magma 系統驅動程式庫必須是開放原始碼,但不得為 GPL,且必須託管於 fuchsia.googlesource.com

Fuchsia 驅動程式是正常的使用者空間程序。也就是說,他們可以存取大部分的 c 程式庫,以及部分 POSIX API。與大多數程序不同,不允許存取檔案系統。

目前 Magma 支援兩種不同的裝置類型:平台裝置和 PCI 裝置。

  • SoC 通常會有平台裝置。這些裝置並非隨插即用,而是需要主機板驅動程式,才能將適當的資源委派給這些裝置。
  • PCI 裝置位於 PCI 匯流排上,並由 PCI 匯流排驅動程式委派資源。

Fuchsia 驅動程式庫架構支援這兩者,因此可以建立及繫結為一般 Fuchsia 驅動程式。

要分攤責任嗎?(SoC 版本)

在 SoC 上,GPU 硬體通常會以獨立 IP 區塊的形式提供,可由 SoC 供應商自訂。視供應商的自訂程度而定,有幾種可能的做法。

  • 統一 MSD,但會先載入 SoC 專屬的驅動程式庫。
  • 請為每個 SoC 或 SoC 供應商分別製作 MSD。

如果 SoC 的自訂項目不多,最好使用統一的 MSD。廠商專屬驅動程式庫會先繫結,並匯出 MSD 的 Banjo 介面,以開啟/關閉 GPU、變更時脈等。這樣做的好處是,只要實作新的廠商專屬驅動程式庫,就能輕鬆將 MSD 移植到新硬體,不必進行修改。如需這個方法的範例,請參閱 msd-arm-maliaml-gpu

為每個 SoC 提供獨立的 MSD 可帶來更多彈性,如果 GPU IP 供應商允許在 SoC 中對 IP 區塊進行許多自訂作業,這項做法可能就很有必要。不同 SoC 的 MSD 實作項目可能會共用 SoC 獨立程式碼的程式庫,但會編譯為獨立的驅動程式。

要分攤責任嗎?(PCI 版本)

PCI GPU 通常包含螢幕控制器硬體。顯示控制器驅動程式庫最好與 GPU 硬體分開實作,因為這樣就能儲存在 bootfs 中,並在磁碟存取前提供開機控制台。顯示控制器應公開硬體專屬的 banjo 介面,而 MSD 可以繫結至顯示驅動程式庫。

如要查看分成兩部分的 PCI 驅動程式庫範例,請參閱 msd-intel-genintel-display

開啟電源

MSD 現在正在建構中,下一個步驟是編寫程式碼,重設裝置並讓裝置進入運作模式。這類資訊可能包括:

驅動程式也應視需要取得 MMIO 範圍的存取權,並開始處理中斷。對於 SoC,必須修改板載驅動程式,將這些資源傳遞至 MSD 或 SoC 專屬驅動程式庫,並新增裝置供 MSD 繫結。

這個階段的測試:

  • 在驅動程式庫啟動時記錄 MMIO 暫存器。

實作 MSD

以下是驅動程式庫可實作的主要函式清單:

  • 初始化硬體
    • msd_driver_create
    • msd_driver_configure
    • msd_driver_destroy
    • msd_driver_create_device
    • msd_device_destroy
  • 支援參數查詢
    • msd_device_query
  • 支援狀態傾印
    • msd_device_dump_status
  • 建立連結
    • msd_device_open
    • msd_connection_close
  • 建立緩衝區
    • msd_buffer_import
    • msd_buffer_destroy
  • 設定記憶體空間和緩衝區對應
    • msd_connection_map_buffer_gpu
    • msd_connection_unmap_buffer_gpu
    • msd_connection_commit_buffer
    • msd_connection_release_buffer
  • 設定硬體環境
    • msd_connection_create_context
    • msd_context_destroy
  • 指令緩衝區排程
    • msd_context_execute_command_buffer
    • msd_connection_set_notification_callback
  • 建立信號燈
    • msd_semaphore_import
    • msd_semaphore_destroy
  • 錯誤處理
  • 電源管理

硬體順利啟動後,下一步是決定如何將現有的 ioctl 對應至 MSD 進入點。

在大多數情況下,Linux DRI ioctl 和 MSD 函式之間的對應關係很簡單。但記憶體管理是例外情況:在 Magma 中,記憶體是由 ICD 分配及對應,而非 MSD (或核心驅動程式庫)。這可能會改變分配 VMO 的部分指令流程,因為 MSD 必須將現有緩衝區匯入 GPU 硬體。

如果這種方法不適用於某些類型的記憶體,驅動程式庫可能會使用 Sysmem 堆積來處理該記憶體的配置作業。用戶端會使用 Sysmem 分配記憶體,並透過一般的 Magma 介面匯入控制代碼。接著,MSD 就能與 sysmem 通訊,取得更多記憶體相關資訊。

驅動程式可能不需要實作所有函式。建議您視 ICD 的需求,逐步實作 MSD 函式。這有助於在實作 MSD 函式時提供背景資訊,並避免在不需要的函式上浪費精力。

這個階段的測試:

  • 驅動程式庫專屬單元測試 (非硬體專屬)
  • 硬體專屬驅動程式庫測試 (請參閱範例)。這些測試應盡量減少 GPU 的運作,例如寫入暫存器,或導致 GPU 修改記憶體位置。
  • 使用 Magma 介面的驅動程式庫專屬整合測試。
  • magma-conformance-tests (Magma L0 的一部分)。
  • magma-info-test (Magma L0 的一部分)。

建構 ICD

IHV ICD 必須移植到 Fuchsia。ICD 應使用 Bazel SDK 建構。ICD 建構作業可以移植到 Bazel,或包裝在 Bazel 建構作業中。rules_foreign_cc 是包裝現有建構作業的好例子。

由於 ICD ABI 限制,ICD 必須以靜態方式連結至所有依附元件。他們只能參照下列共用程式庫:

  • libc.so
  • libzircon.so

這會限制 ICD 可使用的依附元件。舉例來說,以下列出一些不允許使用的程式庫和可能的替代方案:

在這個階段,您可以視需要將所有其他參照設為虛設常式。ICD 也必須連結至 SDK 中提供的 Magma 執行階段程式庫,如 @fuchsia_pkg//pkg/magma_client

Vulkan 載入器服務會從套件擷取 ICD,並向 Vulkan 用戶端宣傳。ICD 必須包含在 Fuchsia 套件中,並附上中繼資料和資訊清單 JSON 檔案,如載入器服務文件所述。您可以使用 Bazel SDK 存放區指令,將這個套件提供給裝置。

如果 ICD 套件包含在宇宙中,可以透過 fx shell killall vulkan_loader.cm 重新載入。之後啟動的元件會取得新的 ICD 套件,而舊版元件在建立 Vulkan 執行個體時會失敗。

ICD 必須匯出特定符號集,詳情請參閱 Vulkan ABI 定義。您應該在這個時間點實作這些方法。

這個階段的測試:

  • readelf -d,確保除了 libc.solibzircon.so 之外,共用程式庫沒有其他依附元件。
  • 使用 fx shell cat /svc/fuchsia.vulkan.loader.Loader 啟動 Vulkan 載入器,並檢查 ffx inspect show core/vulkan_loader 是否已載入。錯誤會記錄在系統記錄檔中。
  • 執行 vulkan_icd_load 測試。這項測試會檢查系統上是否有任何 ICD 正常運作,因此請務必先移除系統上的其他 ICD,再執行測試。

將 ICD 連線至 Magma

此時,ICD 應使用提供給 vk_icdInitializeOpenInNamespaceCallback 的回呼,連線至 /loader-gpu-devices/class/gpu 目錄。ICD 可以使用 fuchsia.io.Directory FIDL 通訊協定列出目錄內容。這個目錄包含系統上所有 MSD 的裝置節點,每個節點的名稱都是不重複的三位數。數字在開機期間會保持穩定,但只要重新載入 MSD (例如重新啟動裝置時),數字就可能會變更。

每個 magma 裝置路徑都可以使用 vk_icdInitializeOpenInNamespaceCallback 開啟,而產生的 zircon 管道可以使用 magma_device_import 提供給 libmagma。如果系統有多個 magma 裝置,驅動程式庫必須使用 magma_queryMAGMA_QUERY_VENDOR_ID 來判斷要使用哪個裝置。

這個階段結束後,magma_* 函式就會開始運作,因此 ioctl() 呼叫可以逐步轉換為對等的 Magma 呼叫。

這個階段的測試:

  • vkreadback (繪製顏色,然後讀回 frame buffer 值)。這是 Magma L0 的一部分。
  • Vulkan 一致性測試。理想情況下,完成這個階段後,通過率應為 100%。詳情請參閱 Magma 測試策略

移除不允許的符號

連結 ICD 時,請使用版本指令碼,確保只公開 Fuchsia 系統 ABI 允許的符號。

ICD 只能使用符號許可清單中列出的符號。如要檢查,請將允許清單與在 ICD 共用程式庫上執行 llvm-nm -gD 取得的清單進行比較。

部分不支援的檔案作業可能會替換為對 OpenInNamespace 回呼的呼叫,並提供給 vk_icdInitializeOpenInNamespaceCallback

這個階段的測試:

實作 Fuchsia 擴充功能

目前 ICD 無法與 scenic 搭配使用,且未整合視窗系統。驅動程式必須實作 Fuchsia 專用的 Vulkan 擴充功能。用戶端驅動程式庫應提供符合 Vulkan 1.0/1.1/1.2 的實作項目。

VK_FUCHSIA_external_memory

這項擴充功能與 VK_KHR_external_memory_fd 類似,可從/向 VMO 匯入/匯出 VkDeviceMemory。這項擴充功能已上傳至 Vulkan 規格

這個階段的測試:

  • vkext --gtest_filter=VulkanExtension.* (Magma L0 的一部分)。

VK_FUCHSIA_external_semaphore

這項擴充功能與 VK_KHR_external_semaphore_fd 類似,可將二進位信號燈匯入/匯出至 Zircon 事件。這項擴充功能已上傳至 Vulkan 規格

這個階段的測試:

  • vkext --gtest_filter=VulkanExtension.* (Magma L0 的一部分)。
  • vulkan-cts-zircon (Vulkan CTS 的一部分)。

VK_FUCHSIA_buffer_collection

這個擴充功能會與 sysmem 互動,並允許用戶端協商圖片格式和分配記憶體。詳情請參閱 sysmem 說明文件。

這項擴充功能目前仍在開發中,可能會有所變動,但可在 Fuchsia 內部 Vulkan 標頭中找到。

這個階段的測試:

驗證

上述各小節列出的所有測試都必須通過。如需更多詳細資料和完整的測試案例清單,請參閱測試策略說明文件

長期支援

必須使用硬體供應商提供的新程式碼,更新 MSD 和 ICD。 理想情況下,程式碼會上游化,而 GPU 供應商會使用 Zircon DDK 提供及維護系統驅動程式。