资讯详情

资讯详情

第三章:GEM分析 3.1.1 从文件视角理解 drm_gem_object(导读)

本文是第三章的导读承接 3.1 GEM 概述在进入 3.2 drm_gem_object 的字段详解之前用 Linux 文件的直觉把设备、drm_file、gem bo 对象、handle、mmap 与回调表串成一条线。阅读提示本文只建立直觉涉及的机制都在后续小节展开。遇到暂不理解的术语可先跳过读完后续内容再回来看这篇。初学者看drm_gem_object常被它的一堆字段和回调劝退。但如果你用过 Linux 的open()/mmap()其实已经有了理解它所需的直觉把一块 GPUdrm_device看作一个大文件。第二章已经讲过这在 VFS 层并不只是比喻DRM 就是这样实现的。1. drm_device 就是一个大文件用户态访问 GPU要先打开一个设备节点。本专栏走 render node/dev/dri/renderD128见 2.1 同一块 GPU 通常还有 primary 节点/dev/dri/card0。节点有多个文件却只有一个。2.2 讲过drm_open()会执行filp-f_mappingdev-anon_inode-i_mapping;同一设备所有节点、所有 open 实例的f_mapping都指向设备的同一个address_space。从 mmap 的角度看它们打开的是同一个文件。也正因如此对象迁移或设备拔出时内核可以在这一个address_space上撤销所有进程对该对象的 CPU 映射。这个文件的偏移空间中有一段窗口由设备的dev-vma_offset_manager管理专门分配给对象在 64 位系统上从 4 GiB 处开始大小约 1 TiB见 3.3 §1。2. drm_file 就是对这个文件的一次 open()每次open()设备节点内核创建一个drm_file它与 VFS 的struct fileopen file description一一对应挂在filp-private_data上。和普通文件一样见 2.1.3 §1隔离的边界是open 实例不是进程同一进程 open 两次得到两个独立的drm_filedup()、fork()产生的 fd 共享同一个drm_filelibdrm_amdgpu 的设备去重也会让同一进程内的多个组件共享一个drm_file见 2.2 §9。drm_file不拥有对象它只持有一张句柄表object_idr把 per-file 的 32 位 handle 映射到共享的drm_gem_object。两个drm_file里的 handle 1 可以指向不同的对象。3. drm_gem_object 就是文件里的一段区间需要 CPU 映射的对象会在设备的偏移空间里分配一段按页对齐、互不重叠的区间记录在对象的vma_node中。这个偏移不对应任何物理地址只是大文件里的一个位置因此称为伪偏移fake offset。于是一个drm_gem_object≈ 设备这个大文件里的一段区间handle 是某个 open 实例给它起的名字。区间是对象的属性一个对象只有一段handle 是 open 实例的属性同一个对象可以在多个drm_file中各有 handle。图中的 objB 就被两个drm_file同时引用。4. mmap按偏移找到对象再交给对象自己一次 mmap 的完整步骤见下图①② 在用户态③④⑤ 由设备唯一的 file 级.mmap入口drm_gem_mmap()完成。结合文件类比有两点值得强调偏移不需要保密权限靠 handle④。建 handle 时drm_vma_node_allow()把该drm_file加入对象的允许列表其他drm_file即使拿到偏移值也会被拒绝。handle 决定谁能看见对象偏移决定它在文件里的位置mmap 两者都要。入口只有一个做法由对象决定⑤。未实现funcs-mmap时由 core 按默认方式设置 VMA缺页交给vm_ops-fault。5. 为什么是 funcsfile 接口细化到每个对象第 4 节的步骤 ⑤ 揭示了drm_gem_object_funcs的本质。对象的后备存储千差万别shmem 页drm_gem_shmem_object、物理连续内存drm_gem_dma_object、VRAM 与 GTTttm_buffer_object但 core 只有一套流程。解决办法是给每个对象挂一张函数指针表funcs让同一段 core 代码对不同对象表现出不同行为相当于 C 的虚函数表是对象级的多态。其中一部分回调正是把 file 级操作下放到对象回调对应的 file 级操作mmap/vm_ops设备 fd 的mmap()fops-mmapopen/close在某个drm_file中建立、释放一个 handleexportPRIME_HANDLE_TO_FD对象被包进 dma-buf 自己的匿名struct filestatus/rss读取/proc/pid/fdinfo/fdfops-show_fdinfo见 2.1.3 §6amdgpu 用自己的统计实现不经过这两个回调其余回调由内核内部事件触发不对应 file 级入口free在refcount归零时调用pin/get_sg_table由 dma-buf 导入方触发vmap由需要 CPU 地址的内核代码触发evict由驱动的回收路径触发。完整分组见 3.2.1 drm_gem_object_funcs回调的分组、功能与调用时机。6. 类比的边界对象 文件里的一段区间在偏移空间这一层成立但 GEM 对象不是磁盘文件里的静态字节维度磁盘文件的一段内容GEM 对象内容落点固定在文件里后备页会迁移、被驱逐、缺页时按需填入偏移稳定物理落点动态归属属于这个文件可被多个drm_file引用经 dma-buf 还可跨进程、跨设备共享寿命随文件由refcount决定独立于任何drm_file另有四点要摆正大文件是drm_device不是某个设备节点也不是某个drm_file。各节点只是它的入口drm_file只是对它的一次 open。有两种文件。设备这个大文件提供偏移空间用来定位对象对象的后备存储可能是另一个文件shmem 对象的obj-filp就是一个真实的 shmem 文件页从那里来。前者回答在哪里找到它后者回答内容存在哪里。handle 与偏移是两层名字。handle 是 per-file 的ioctl 用它指称对象偏移是全设备的mmap 用它定位对象。两者经 mmap 的权限检查连在一起第 4 节的步骤 ④。类比只覆盖身份与 CPU 视图。按 3.1 §4 的划分对象还有 GPU 视图gpuva见 3.4与设备间视图dma_buf/import_attach见 3.5这两类访问不经过设备的偏移空间不在本类比的适用范围内。7. 小结把drm_device看作一个大文件它的偏移空间被切成每对象一段每段就是一个drm_gem_objectdrm_file是对它的一次open()用 per-file 的 handle 引用这些共享对象设备唯一的.mmap入口按偏移找到对象、确认本 open 实例持有 handle再交给对象的funcs完成映射这就是对象级多态。有了这个模型再读 3.2 drm_gem_object 的字段详解vma_node它在文件里的位置、handle_count它有几个名字、refcount它的寿命、funcs它的虚函数表、filpshmem 后备存储就都各归其位了。
觉得有用,分享给同行:

为您的企业打造数字门面

稳重轻奢商务风格,端正雅致视觉,长效耐看不易过时。

立即咨询 →