2. GPU驱动框架概述:Linux DRM子系统架构

在开始实际的GPU驱动移植之前,必须理解承载GPU驱动的软件框架——Linux DRM (Direct Rendering Manager) 子系统。DRM是Linux内核中负责图形显示与GPU管理的核心框架,它向上提供统一的用户空间API,向下抽象各类GPU硬件差异。本章将系统梳理DRM子系统的整体架构,并深入剖析其三大核心组件:GEM、KMS与Framebuffer。

2.1 DRM子系统整体架构

DRM子系统采用分层设计,从用户态到硬件共分为四层。每一层职责清晰,通过标准接口进行交互。

架构要点: DRM的核心设计哲学是“内核管理资源,用户态管理渲染”。内核负责内存分配、模式设置、同步等关键资源管理,用户态驱动(如Mesa)负责OpenGL/Vulkan命令生成与提交。
DRM子系统分层架构 用户空间层 (User Space) Mesa 3D / libdrm / Xorg / Wayland / 应用程序 系统调用接口 (ioctl / mmap) 内核DRM核心层 (DRM Core) drm_driver / drm_device / drm_file / drm_ioctl GEM内存管理 | KMS模式设置 | Framebuffer管理 同步对象 (dma-fence / sync_file) | 调度器 (DRM scheduler) 驱动适配层 (Driver Adapter) GPU厂商驱动 (i915 / amdgpu / msm / panfrost / etnaviv) 硬件抽象层 (Hardware Abstraction) GPU核心 / 显示控制器(CRTC) / 编码器(Encoder) / 连接器(Connector) 说明:驱动适配层实现DRM核心回调函数,硬件抽象层由设备树描述,两者通过platform_driver绑定

2.2 GEM — 图形执行管理器

GEM (Graphics Execution Manager) 是DRM框架中负责GPU缓冲区对象(BO)管理的核心组件。它提供了一套标准化的内存分配、共享、映射与同步机制。

2.2.1 GEM核心概念

概念 说明 关键数据结构/函数
GEM对象 (BO) GPU可访问的内存缓冲区,包含元数据与物理内存页 struct drm_gem_object
句柄 (Handle) 用户空间通过整数句柄引用GEM对象,类似文件描述符 drm_gem_handle_create()
全局名称 (Global Name) 用于跨进程共享GEM对象的全局标识符 drm_gem_flink() / drm_gem_open()
DMA-BUF 现代跨设备共享机制,基于dma-buf框架 drm_gem_prime_export()
CPU映射 将GEM对象映射到用户空间虚拟地址空间 drm_gem_mmap()

2.2.2 GEM对象生命周期

  1. 创建: 驱动实现 gem_create_object() 回调,分配GEM对象与物理内存
  2. 句柄导出: 内核生成句柄返回用户空间,用户通过句柄操作对象
  3. 共享: 通过flink或PRIME机制在进程/设备间共享
  4. 映射: 用户调用mmap将GEM对象映射到自身地址空间
  5. 销毁: 引用计数归零时,驱动释放内存
移植要点: 在移植GPU驱动时,必须实现 struct drm_gem_object_funcs 中的回调函数,包括 free、open、close、print_info、export、vmap 等。这些回调决定了GEM对象的行为。
GEM对象生命周期与共享流程 用户空间进程A 用户空间进程B 内核DRM GEM子系统 GEM对象 (BO) refcount=2 句柄: 42 句柄: 7 说明:进程A通过flink导出全局名称,进程B通过open导入,两个句柄指向同一个GEM对象,引用计数为2

2.3 KMS — 内核模式设置

KMS (Kernel Mode Setting) 是DRM框架中负责显示输出管理的组件。它将显示管线的配置权从用户空间移入内核,确保模式切换的原子性与安全性。

2.3.1 KMS核心对象模型

对象 角色 对应硬件 关键属性
CRTC 显示控制器,生成像素时钟与同步信号 LCD控制器 / HDMI TX内部时序发生器 分辨率、刷新率、扫描模式、背景色
Encoder 编码器,将像素数据转换为特定接口信号 HDMI编码器 / LVDS发送器 / eDP桥接芯片 编码类型、支持的连接器类型
Connector 连接器,代表物理显示接口 HDMI端口 / DP端口 / VGA接口 / DSI接口 物理连接状态、EDID数据、支持的显示模式
Plane 硬件图层,支持叠加合成 GPU的Overlay / 主图层 / 光标图层 Z序、透明度、颜色格式、裁剪区域
Bridge 桥接芯片,连接Encoder与Connector HDMI转DP / LVDS转eDP / 电平转换芯片 输入输出格式、I2C配置、电源控制

2.3.2 KMS管线连接关系

一个完整的显示管线从Framebuffer开始,经过Plane合成、CRTC时序生成、Encoder编码、Bridge桥接,最终到达Connector输出。驱动必须正确建立这些对象之间的连接关系。

KMS显示管线连接关系 Framebuffer 像素数据缓冲区 Plane 硬件图层 CRTC 显示控制器 Encoder 信号编码器 Bridge 桥接芯片 Connector 物理接口 说明:Bridge为可选组件,当Encoder与Connector之间需要电平转换或协议桥接时插入。 驱动通过drm_connector_init() / drm_encoder_init() / drm_crtc_init_with_planes()注册对象

2.4 Framebuffer — 帧缓冲区

Framebuffer是DRM中表示显示帧的缓冲区对象。它封装了像素数据的格式、尺寸、行宽和内存地址,是KMS管线中数据流的起点。

2.4.1 Framebuffer与GEM的关系

Framebuffer建立在GEM对象之上,一个Framebuffer可以引用一个或多个GEM对象(多平面格式如NV12需要两个平面)。

// Framebuffer核心数据结构
struct drm_framebuffer {
    struct drm_device *dev;
    struct list_head head;
    struct drm_mode_object base;
    const struct drm_framebuffer_funcs *funcs;
    unsigned int pitches[4];        // 每行字节数
    unsigned int offsets[4];        // 平面偏移
    uint64_t modifier;              // 内存布局修饰符
    unsigned int width;             // 像素宽度
    unsigned int height;            // 像素高度
    int flags;
    int hot_y;
    struct drm_gem_object *obj[4];  // 引用的GEM对象
};

2.4.2 Framebuffer创建流程

步骤 用户空间操作 内核处理
1 调用 drmIoctl(DRM_IOCTL_MODE_ADDFB2) 验证参数合法性,分配 drm_framebuffer 结构体
2 传递GEM句柄、宽度、高度、像素格式 通过句柄查找GEM对象,增加引用计数
3 指定修饰符(modifier)描述内存布局 调用驱动 fb_create 回调进行硬件校验
4 获取Framebuffer ID用于后续显示操作 注册到DRM设备,返回用户空间ID

2.4.3 常见像素格式与修饰符

格式 描述 每像素位数 典型应用
DRM_FORMAT_XRGB8888 32位RGB,无Alpha 32 桌面显示、UI
DRM_FORMAT_ARGB8888 32位RGBA,有Alpha 32 窗口合成、透明叠加
DRM_FORMAT_NV12 YUV 4:2:0 半平面 12 视频播放、摄像头预览
DRM_FORMAT_RGB565 16位RGB 16 低端嵌入式设备、帧率优先
常见陷阱: 在移植过程中,Framebuffer的 pitches(行宽)计算必须与硬件DMA引擎对齐。许多GPU要求行宽是16字节或64字节对齐,否则会导致显示错位或性能下降。务必查阅硬件手册确认对齐要求。

2.5 DRM驱动核心数据结构

每个DRM驱动都需要实现一个 struct drm_driver 实例,这是驱动与DRM核心交互的契约。

// DRM驱动核心结构体(简化)
static struct drm_driver mygpu_drm_driver = {
    .driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_RENDER,
    .gem_create_object = mygpu_gem_create_object,  // GEM对象创建
    .prime_handle_to_fd = drm_gem_prime_handle_to_fd,
    .prime_fd_to_handle = drm_gem_prime_fd_to_handle,
    .gem_prime_import = mygpu_gem_prime_import,
    .gem_prime_import_sg_table = mygpu_gem_prime_import_sg_table,
    .dumb_create = mygpu_dumb_create,              // 创建 dumb buffer
    .dumb_map_offset = mygpu_dumb_map_offset,
    .dumb_destroy = mygpu_dumb_destroy,
    .fops = &mygpu_fops,                           // 文件操作
    .name = "mygpu",
    .desc = "My GPU DRM Driver",
    .date = "20250101",
    .major = 1,
    .minor = 0,
};

2.6 本章小结

本章建立了DRM子系统的整体认知框架:

  • 架构分层: 用户空间 → 系统调用 → DRM核心 → 驱动适配 → 硬件抽象
  • GEM: 管理GPU缓冲区对象,提供分配、共享、映射、同步机制
  • KMS: 管理显示管线,包含CRTC、Encoder、Connector、Plane、Bridge对象模型
  • Framebuffer: 基于GEM的帧缓冲区,定义像素格式与内存布局