Magma:携号转网指南

简要介绍 Magma,包括背景信息、硬件要求和 请参阅 Magma:概览

本文档介绍了驱动程序开发者可遵循的流程来移植 Vulkan 送到 Fuchsia。

要求

将 Vulkan 驱动程序移植到 Fuchsia 需要满足以下条件:

  • 硬件文档(注册规范、运行理论)。
  • Vulkan 参考实现 (Linux)。
  • 客户端驱动程序库 (ICD) 应提供符合要求的实现 Vulkan 1.1/1.2。

硬件必须通过启动过程,以便进行网络访问、磁盘存储 和 fx pave 函数。

Magma 目前仅支持 UMA 设备,但如果你有兴趣 可以尝试移植到具有独立内存的 GPU。

创建桩系统驱动程序

Magma 系统驱动程序 (MSD) 类似于 操作系统此时,请考虑是否移植现有内核 驱动程序,或从头开始编写一个驱动程序。

此时,您应阅读驱动程序概念部分,以获取 了解 Fuchsia 驱动程序模型。

这一选择取决于现有内核驱动程序代码的许多方面。 一些注意事项:

  • 该驱动程序是具有平台抽象层,还是依赖于 Linux 内核接口?
  • 许可。
  • 其 ioctl 接口与 Magma 入口点的相似程度如何?

第一个编码步骤是创建一个可以构建的基本 MSD。MSD 位于 驱动程序目录下。它们是以 fuchsia_drivers 形式构建的 使用 GN 构建系统。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.特定于供应商的驱动程序将首先绑定,然后导出 banjo 用于启动/关闭 GPU、更改时钟等 MSD 接口。 其优点是可以更轻松地将 MSD 移植到新硬件上 通过实现新的供应商专用驱动程序来进行修改。请参阅 msd-arm-maliaml-gpu 作为示例 方法。

每个 SoC 具有单独的 MSD 可以提高灵活性,这或许是必要的 (前提是 GPU IP 供应商允许对 SoC 中的 IP 块进行多项自定义)。 不同 SoC 的 MSD 实现可以共享一个独立于 SoC 的库 但将被编译为独立的驱动程序。

分担职责?(PCI 版本)

PCI GPU 通常包含显示控制器硬件。显示控制器 驱动程序最好与 GPU 硬件分开实现, 因为这样就可以将其存储在 bootfs 文件 它还能提供 控制台,然后才能访问磁盘。显示控制器应 硬件专用 banjo 接口,而 MSD 可以绑定到 显卡驱动程序。

请参阅 msd-intel-genintel-display,了解 分为两部分的 PCI 驱动程序示例。

正在接通电源

随着 MSD 的构建,下一步是编写代码来重置设备 并进入操作模式此类信息包括:

驱动程序还应根据需要访问 MMIO 范围,并应启动 处理中断。对于 SoC,板级驱动程序必须是 以便将这些资源传递给 MSD 或 SoC 专用驱动程序,并且必须 添加要绑定到 MSD 的设备。

在此阶段进行测试:

  • 在驱动程序启动时记录 MMIO 寄存器。

实现 MSD

下面列出了驱动程序可以实现的主函数,这些函数有序:

  • 初始化硬件 <ph type="x-smartling-placeholder">
      </ph>
    • msd_driver_create
    • msd_driver_configure
    • msd_driver_destroy
    • msd_driver_create_device
    • msd_device_destroy
  • 支持参数查询 <ph type="x-smartling-placeholder">
      </ph>
    • msd_device_query
  • 支持状态转储 <ph type="x-smartling-placeholder">
      </ph>
    • msd_device_dump_status
  • 创建连接 <ph type="x-smartling-placeholder">
      </ph>
    • msd_device_open
    • msd_connection_close
  • 创建缓冲区 <ph type="x-smartling-placeholder">
      </ph>
    • msd_buffer_import
    • msd_buffer_destroy
  • 设置内存空间和缓冲区映射 <ph type="x-smartling-placeholder">
      </ph>
    • msd_connection_map_buffer_gpu
    • msd_connection_unmap_buffer_gpu
    • msd_connection_commit_buffer
    • msd_connection_release_buffer
  • 设置硬件上下文 <ph type="x-smartling-placeholder">
      </ph>
    • msd_connection_create_context
    • msd_context_destroy
  • 命令缓冲区调度 <ph type="x-smartling-placeholder">
      </ph>
    • msd_context_execute_command_buffer
    • msd_context_execute_immediate_commands
    • msd_connection_set_notification_callback
  • 创建信号量 <ph type="x-smartling-placeholder">
      </ph>
    • msd_semaphore_import
    • msd_semaphore_destroy
  • 故障处理
  • 电源管理

硬件成功开机后,下一步是决定 将现有的 ioctl 映射到 MSD 入口点。

在大多数情况下,linux DRI ioctl 与 MSD 函数之间的映射是 简单明了。内存管理是个例外:在 Magma 中, 是分配和映射内存的 ICD,而非 MSD(或内核驱动程序)。 这可能会改变一些用于分配 VMO 的命令的流程,因为 MSD 必须将现有的缓冲区导入 GPU 硬件。

如果该方法不适用于某些类型的内存,则驱动程序可能 请使用 Sysmem 堆来处理该内存的分配。客户 使用 Sysmem 分配内存,并使用常规 Magma 导入句柄 界面。然后,MSD 可与系统进程通信,以获取更多信息 关于回忆

驱动程序可能不需要实现所有函数。我们建议 根据 ICD 的需要逐步实施 MSD 功能。这可以提供 上下文,并有助于避免浪费工作 不需要的函数

在此阶段进行测试:

  • 特定于驱动程序的单元测试(不特定于硬件)
  • 特定于硬件的驱动程序测试(请参阅示例)。这些测试 应以最少的方式使用 GPU,例如写入寄存器或 会导致 GPU 修改内存位置。
  • 使用 Magma 接口的特定于驱动程序的集成测试。
  • magma-conformance-tests(Magma L0 的一部分)。
  • magma-info-test(Magma L0 的一部分)。

打造 ICD 平台

IHV ICD 必须转移到 Fuchsia。应使用Bazel SDK。ICD 构建可以移植到 Bazel,也可以封装到 运行 Bazel 构建rules_foreign_cc 就是关于如何 封装现有 build。

由于 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 软件包包含在 universe 中,它可以 通过执行 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 以查看是否已加载。系统会将错误记录到 Syslog 中。
  • 运行 vulkan_icd_load 测试。此测试会检查是否存在 系统上的 ICD 有效,因此请先确保系统中没有其他 ICD 运行应用所需的资源

将 ICD 连接到 Magma

此时,ICD 应连接到 /loader-gpu-devices/class/gpu 目录(提供给 vk_icdInitializeOpenInNamespaceCallback。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(绘制颜色,然后回读帧缓冲区) 值)。这是 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 导入/从 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-zirconVulkan CTS 的一部分)。

VK_FUCHSIA_buffer_collection

此扩展程序会与系统内存交互,并允许客户端协商映像 并分配内存如需了解详情,请参阅 sysmem 文档。

此扩展程序目前仍在开发中,可能会发生变化,但您可在 Fuchsia 内部 Vulkan 头文件

在此阶段进行测试:

验证

上述各子部分中列出的所有测试都必须通过。查看测试 策略文档,了解更多详情和 测试用例

长期支持

必须使用来自硬件供应商的新代码植入来更新 MSD 和 ICD。 理想情况下,代码位于上游,GPU 供应商将提供和维护 使用 Zircon DDK 构建系统驱动程序。