3、内核配置与编译:如何开启 CONFIG_DMA_SHARED_BUFFER、CONFIG_DRM 及其 Prime 相关选项

在动手编写 DRM Prime 驱动之前,必须确保 Linux 内核已经正确配置并编译了 DMA-BUF 基础设施和 DRM 子系统的 Prime 支持。本章将详细讲解关键内核选项的定位、依赖关系以及配置验证方法,帮助您构建一个支持 DMA-BUF 导出与导入的内核环境。

3.1 核心配置选项概览

DMA-BUF 与 DRM Prime 的配置涉及三个层次:通用内存共享层、DRM 核心层以及具体 GPU/显示控制器驱动层。下表列出了必须开启的选项及其功能描述:

配置选项 所属子系统 功能描述 默认值
CONFIG_DMA_SHARED_BUFFER 通用内核 启用 DMA-BUF 框架,提供缓冲区共享、同步和文件描述符管理 y(通常默认开启)
CONFIG_DRM DRM 核心 启用 Direct Rendering Manager 框架,提供 KMS 和 GEM 内存管理 n
CONFIG_DRM_PRIME DRM 核心 启用 DRM Prime 辅助函数,实现 GEM 对象与 DMA-BUF 的互转 n(依赖 CONFIG_DRM)
CONFIG_DRM_GEM_SHMEM_HELPER DRM 辅助 提供基于 shmem 的 GEM 实现,简化 Prime 导出/导入的页分配 n(推荐开启)
配置提示: 在嵌入式平台(如 i.MX8、RK3588、STM32MPU)上,CONFIG_DMA_SHARED_BUFFER 通常已被 defconfig 默认启用。如果手动裁剪内核,请务必确认该选项未被关闭,否则 DRM Prime 将无法工作。

3.2 配置依赖关系与 Kconfig 解析

理解 Kconfig 的依赖链有助于避免配置遗漏。以下是 DRM Prime 相关选项的简化依赖关系图:

DRM Prime 内核配置依赖关系 CONFIG_DMA_SHARED_BUFFER CONFIG_DRM CONFIG_DRM_PRIME CONFIG_DRM_GEM_SHMEM_HELPER 具体 GPU 驱动 (如 CONFIG_DRM_IMX_LCDIF) 说明:箭头方向表示“依赖”关系。CONFIG_DRM_PRIME 需要 CONFIG_DRM 和 CONFIG_DMA_SHARED_BUFFER 同时开启。 具体驱动(如 imx-drm、rockchip-drm)在自身 Kconfig 中 select DRM_PRIME。

关键依赖规则如下:

  • CONFIG_DRM_PRIME 依赖于 CONFIG_DRM 和 CONFIG_DMA_SHARED_BUFFER。如果后者未开启,DRM Prime 选项将不可见。
  • CONFIG_DRM_GEM_SHMEM_HELPER 是一个辅助选项,提供 drm_gem_shmem_prime_export_sg_table() 等默认实现。强烈建议开启,可大幅简化驱动开发。
  • 具体 GPU 或显示控制器驱动(如 CONFIG_DRM_IMX_LCDIF、CONFIG_DRM_ROCKCHIP)通常在 Kconfig 中使用 select DRM_PRIME 自动拉取依赖。

3.3 配置操作步骤

以下步骤基于 Linux 内核源码树,使用 menuconfig 图形化配置工具。命令行配置方式(make config 或直接编辑 .config)原理相同。

  1. 进入内核源码根目录,加载目标平台的默认配置(以 ARM64 为例):
    make ARCH=arm64 defconfig
  2. 启动 menuconfig:
    make ARCH=arm64 menuconfig
  3. 开启 DMA-BUF(通常位于 "Device Drivers" → "Generic Driver Options"):
    Device Drivers  --->
      Generic Driver Options  --->
        [*] DMA Buffer Sharing (CONFIG_DMA_SHARED_BUFFER)
  4. 开启 DRM 核心(位于 "Device Drivers" → "Graphics support"):
    Device Drivers  --->
      Graphics support  --->
        <*> Direct Rendering Manager (XFree86 4.1.0 and later DRI support) (CONFIG_DRM)
  5. 确认 DRM Prime 已自动选中:进入 DRM 子菜单,检查 CONFIG_DRM_PRIME 是否为 [*] 或 <*>。如果未自动选中,手动开启:
    Graphics support  --->
      Direct Rendering Manager  --->
        [*] Enable PRIME buffer sharing (CONFIG_DRM_PRIME)
  6. 开启 GEM shmem helper(推荐):
    Graphics support  --->
      Direct Rendering Manager  --->
        [*] GEM shmem helper (CONFIG_DRM_GEM_SHMEM_HELPER)
  7. 开启具体平台驱动(以 NXP i.MX8M 为例):
    Graphics support  --->
      <*> DRM Support for i.MX DCSS
      <*> DRM Support for i.MX LCDIF
  8. 保存配置并退出,生成 .config 文件。
常见错误: 如果 CONFIG_DRM_PRIME 选项呈灰色不可选,请检查 CONFIG_DMA_SHARED_BUFFER 是否已开启。某些架构(如 x86)的默认配置可能关闭了 DMA-BUF,需要手动打开。

3.4 配置验证方法

编译内核前,建议通过以下方式验证配置是否正确:

3.4.1 使用 grep 检查 .config 文件

grep -E "CONFIG_(DMA_SHARED_BUFFER|DRM|DRM_PRIME|DRM_GEM_SHMEM_HELPER)" .config

期望输出示例:

CONFIG_DMA_SHARED_BUFFER=y
CONFIG_DRM=y
CONFIG_DRM_PRIME=y
CONFIG_DRM_GEM_SHMEM_HELPER=y

3.4.2 使用 scripts/config 脚本检查

scripts/config --state CONFIG_DMA_SHARED_BUFFER
scripts/config --state CONFIG_DRM_PRIME

如果返回 y 或 m,表示已开启。

3.4.3 编译后验证内核模块

编译并启动新内核后,检查 /sys/kernel/debug/dri/ 目录是否存在,以及 /sys/kernel/debug/dma_buf/ 是否包含缓冲区信息:

ls /sys/kernel/debug/dri/
ls /sys/kernel/debug/dma_buf/
验证要点: 如果 /sys/kernel/debug/dma_buf/ 目录存在,说明 DMA-BUF 框架已正确初始化。如果 /sys/kernel/debug/dri/ 下出现 0/name 等子目录,说明 DRM 设备已注册成功。

3.5 配置选项与 Prime 功能的对应关系

下表总结了每个配置选项对 Prime 导出/导入功能的具体影响:

功能点 所需配置 缺失后果
分配 DMA-BUF 并导出为 fd CONFIG_DMA_SHARED_BUFFER + CONFIG_DRM_PRIME dma_buf_export() 返回 NULL,导出失败
从 fd 导入 DMA-BUF 到 GEM 对象 CONFIG_DRM_PRIME + CONFIG_DRM_GEM_SHMEM_HELPER drm_gem_prime_import() 缺少默认实现,需手动编写
跨设备共享(如 GPU 到 VPU) CONFIG_DMA_SHARED_BUFFER + IOMMU 支持 共享时出现 DMA 地址映射错误
使用 drm_prime_get_sg_table() 等辅助函数 CONFIG_DRM_GEM_SHMEM_HELPER 链接时缺少符号,编译失败

3.6 常见平台配置示例

以下列出几种常见嵌入式平台的 Prime 相关配置片段,供参考:

平台 关键配置项 备注
NXP i.MX8M Plus CONFIG_DRM_IMX_DCSS=y
CONFIG_DRM_IMX_LCDIF=y
DCSS 和 LCDIF 驱动均 select DRM_PRIME
Rockchip RK3588 CONFIG_DRM_ROCKCHIP=y
CONFIG_ROCKCHIP_VOP2=y
VOP2 驱动依赖 DRM_PRIME
STM32MP157 CONFIG_DRM_STM=y
CONFIG_DRM_STM_DSI=y
STM DRM 驱动通过 select 开启 Prime
QEMU virt (测试用) CONFIG_DRM_VIRTIO_GPU=y virtio-gpu 支持 Prime 导出/导入
开发建议: 如果使用 QEMU 或模拟器进行 Prime 功能验证,推荐开启 CONFIG_DRM_VIRTIO_GPU 和 CONFIG_DRM_VIRTIO_GPU_PRIME(如果存在)。这可以在没有真实硬件的情况下测试 Prime 导出/导入流程。

3.7 编译与常见问题排查

配置完成后,执行编译:

make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- -j$(nproc)

如果编译过程中出现与 Prime 相关的错误,请参考下表排查:

错误现象 可能原因 解决方案
undefined reference to 'dma_buf_export' CONFIG_DMA_SHARED_BUFFER 未开启 检查 .config,确保该选项为 y
error: 'struct dma_buf_export_info' has no member named 'priv' 内核版本过旧,API 不兼容 升级内核至 5.10+,或适配旧版 API
WARNING: modpost: missing MODULE_LICENSE() 驱动模块未声明许可证 在驱动源码中添加 MODULE_LICENSE("GPL")
运行时 drm_prime_import 返回 -ENOSYS 驱动未实现 gem_prime_import 回调 实现 struct drm_driver 中的 Prime 回调函数
本章小结: 正确配置 CONFIG_DMA_SHARED_BUFFER、CONFIG_DRM 和 CONFIG_DRM_PRIME 是 DRM Prime 驱动开发的基础。建议在开发板上使用 make savedefconfig 保存最小配置,便于后续复用。下一章将基于已配置好的内核,开始编写第一个 Prime 导出驱动的核心代码。