2.1 DRM 框架核心对象速览确立了三个对象的关系:drm_driver是静态能力表,drm_device是每卡一份的运行时实例,drm_file是每次 open 的客户端上下文。本节把drm_device作为一等对象讲清:它的关键字段、driver_features与 BO 主线的对应关系,以及现代驱动「把drm_device嵌入更大私有结构」的标准手法。
1. 定位:一块 GPU 的运行时实例
drm_device在整个驱动生命周期中每块设备只有一个实例(per PCI function),在 PCI probe 阶段由devm_drm_dev_alloc()分配、由drm_dev_register()注册。它承载「这一块具体硬件」的全部运行时状态:设备节点、已打开的文件列表、mmap 用的匿名 inode、指向能力表的driver指针等。
一句话区分三者:drm_driver说「这类设备能做什么」,drm_device是「某一块具体设备」,drm_file是「某进程的一次打开」。
2. 与后续章节相关的关键字段
| 字段 | 类型 | 与 BO 主线的关联 |
|---|---|---|
driver | const struct drm_driver * | 指向能力表;Ch3 的gem_create_object回调即经此触达(详见 2.1.1) |
primary/render/accel | struct drm_minor * | 决定用户通过哪个设备节点访问(见 2.1 §2) |
anon_inode | struct inode * | Ch3:GEM mmap 使用的匿名 inode,drm_vma_offset_manager基于此 |
filelist | struct list_head | 所有已打开的drm_file链表;fdinfo/clients 调试遍历此表 |
driver_features | u32 | 从driver拷贝而来的功能标志位,决定是否启用 GEM/RENDER/SYNCOBJ/GPUVA |
dev_private | void * | 传统驱动的私有指针;现代驱动改用「嵌入」模式(§4) |
driver与driver_features是理解后续章节能力开关的入口,下面单独展开。
3. driver_features 与 BO 主线的关联
driver_features是一组 bit flag,声明这类驱动启用了哪些 DRM 子系统。它由drm_driver.driver_features定义、在设备注册时落到drm_device上。与本专栏相关的标志:
// include/drm/drm_drv.hDRIVER_GEM=BIT(0),// 启用 GEM 子系统 → Ch3DRIVER_RENDER=BIT(3),// 创建 render 节点(compute 必须)DRIVER_MODESET=BIT(1),// 显示 / KMS(本专栏不展开)DRIVER_ATOMIC=BIT(10),// 原子显示(本专栏不展开)DRIVER_SYNCOBJ=BIT(5),// 启用 syncobj → Ch6DRIVER_SYNCOBJ_TIMELINE=BIT(6),// timeline syncobj → Ch6DRIVER_GEM_GPUVA=BIT(8),// 启用 GPUVM 辅助(gpuva manager)→ Ch9DRIVER_COMPUTE_ACCEL=BIT(7),// 计算加速专用节点(与 RENDER 互斥)amdgpu 实际声明为DRIVER_ATOMIC | DRIVER_GEM | DRIVER_RENDER | DRIVER_MODESET | DRIVER_SYNCOBJ | DRIVER_SYNCOBJ_TIMELINE——注意它并未设置DRIVER_GEM_GPUVA:amdgpu 用的是自研的amdgpu_vm而非 DRM 通用的 gpuva manager(Ch9 展开)。每个标志的「声明侧」细节见 2.1.1 drm_driver §3,此处只需记住:drm_device上的driver_features是这些能力的运行时体现。
4. 驱动嵌入模式:drm_device 只是一个字段
现代 DRM 驱动不把drm_device当作独立分配的对象,而是把它内嵌进更大的驱动私有结构,让「DRM 核心视角的设备」与「驱动视角的设备」共享同一块内存:
// drivers/gpu/drm/amd/amdgpu/amdgpu.hstructamdgpu_device{structdrm_deviceddev;// 内嵌 drm_device(通常是第一个/靠前的成员)// ... 数千个 amdgpu 私有字段:ring、vm manager、ttm、power ...};正反向转换都靠container_of:
// 由 drm_device 反查驱动私有结构structamdgpu_device*adev=drm_to_adev(ddev);// container_of(ddev, struct amdgpu_device, ddev)// 由 amdgpu_device 取 drm_devicestructdrm_device*ddev=adev_to_drm(adev);// &adev->ddev这与dma_fence家族「内嵌 base +container_of向下转型」(见 6.1.6)、GEM 对象「内嵌drm_gem_object」(见 Ch3)是同一套 C 语言多态手法。Xe 驱动同理:struct xe_device内嵌struct drm_device。
为什么这样设计:DRM 核心的通用流程只认struct drm_device *,而每个回调里驱动又需要拿到自己的全部状态。内嵌 +container_of让一次指针换算就能在「通用视角」与「驱动视角」之间自由切换,零额外分配、零额外查表。
5. 小结
drm_device是「一块 GPU」的运行时实例,per PCI function 唯一,生命周期等同硬件在位。- 关键字段中,
driver指向能力表、filelist串起所有打开的drm_file、anon_inode支撑 Ch3 的 GEM mmap。 driver_features是能力开关的运行时体现,决定 GEM/RENDER/SYNCOBJ/GPUVA 是否可用。- 现代驱动把
drm_device内嵌进amdgpu_device/xe_device,用container_of双向换算——这是贯穿本专栏的 C 多态基石。
drm_device的创建发生在 PCI probe 阶段,本专栏不展。下一节 2.1.3 drm_file 讲客户端上下文——BO 主线中出现频率最高的关联对象。