DRM 客户端使用统计

DRM 驱动程序可以选择通过 fops->show_fdinfo() 作为在 struct drm_driver 对象中注册的驱动程序特定文件操作的一部分,导出部分标准化的文本输出,该对象已注册到 DRM 核心。

此输出的一个目的是尽可能通用地编写类似 top(1) 的用户空间监控工具。

鉴于各种 DRM 驱动程序之间的差异,输出的规范分为通用部分和驱动程序特定部分。 也就是说,在可能的情况下,仍应努力尽可能地标准化。

文件格式规范

  • 文件应包含每行文本一个键值对。

  • 冒号字符 (:) 必须用于分隔键和值。

  • 所有标准化的键都应以 drm- 为前缀。

  • 驱动程序特定的键应以 driver_name- 为前缀,其中 driver_name 理想情况下应与 struct drm_driver 中的 name 字段相同,尽管这不是强制性的。

  • 解析时应忽略分隔符和第一个非空白字符之间的空白。

  • 不允许键包含空白字符。

  • 数字键值对可以以可选的单位字符串结尾。

  • 值的数据类型已固定,如规范中所定义。

键类型

  1. 强制性,完全标准化。

  2. 可选,完全标准化。

  3. 驱动程序特定。

数据类型

  • <uint> - 无符号整数,不定义最大值。

  • <keystr> - 字符串,不包含任何上述定义的保留字符或空格。

  • <valstr> - 字符串。

强制性完全标准化键

  • drm-driver: <valstr>

字符串应包含此驱动程序通过各自的 struct drm_driver 数据结构注册的名称。

可选的完全标准化键

标识

  • drm-pdev: <aaaa:bb.cc.d>

对于 PCI 设备,这应包含相关设备的 PCI 插槽地址。

  • drm-client-id: <uint>

与打开的 DRM 文件描述符相关的唯一值,用于区分重复和共享的文件描述符。 从概念上讲,该值应 1:1 映射到 struct drm_file 实例的内核表示形式。

该值的唯一性应是全局唯一的,或者在每个设备的范围内是唯一的,在这种情况下,也应存在 drm-pdev

用户空间应确保通过使用上述描述的标准将数据与各个客户端相关联,从而避免重复计算任何使用统计信息。

  • drm-client-name: <valstr>

用户空间使用 DRM_IOCTL_SET_CLIENT_NAME 可选设置的字符串。

利用率

  • drm-engine-<keystr>: <uint> ns

GPU 通常包含多个执行引擎。 每个引擎都应具有稳定且唯一的名称 (keystr),可能的值记录在驱动程序特定的文档中。

该值应为指定的时间单位,即相应的 GPU 引擎花费的时间,忙于执行属于此客户端的工作负载。

如果这使驱动程序的实现更容易,则不需要这些值始终是单调的,但是需要在合理的时间段内赶上先前报告的更大值。 在观察到小于先前读取的值时,用户空间应保持该更大的先前值,直到看到单调更新。

  • drm-engine-capacity-<keystr>: <uint>

引擎标识符字符串必须与 drm-engine-<keystr> 标签中指定的字符串相同,并且如果导出的引擎对应于一组相同的硬件引擎,则应包含大于零的数字。

如果缺少此标签,则解析器应假定容量为 1。 不允许零容量。

  • drm-cycles-<keystr>: <uint>

引擎标识符字符串必须与 drm-engine-<keystr> 标签中指定的字符串相同,并且应包含给定引擎的繁忙周期数。

如果这使驱动程序的实现更容易,则不需要这些值始终是单调的,但是需要在合理的时间段内赶上先前报告的更大值。 在观察到小于先前读取的值时,用户空间应保持该更大的先前值,直到看到单调更新。

  • drm-total-cycles-<keystr>: <uint>

引擎标识符字符串必须与 drm-cycles-<keystr> 标签中指定的字符串相同,并且应包含给定引擎的总周期数。

这是一个 GPU 未指定单元中的时间戳,它与 drm-cycles-<keystr> 的更新速率匹配。 对于实现此接口的驱动程序,引擎利用率可以完全在 GPU 时钟域上计算,而无需考虑 2 个样本之间的 CPU 休眠时间。

驱动程序可以实现此键或 drm-maxfreq-<keystr>,但不能同时实现两者。

  • drm-maxfreq-<keystr>: <uint> [Hz|MHz|KHz]

引擎标识符字符串必须与 drm-engine-<keystr> 标签中指定的字符串相同,并且应包含给定引擎的最大频率。 将其与 drm-cycles-<keystr> 结合使用,可以计算引擎的百分比利用率,而 drm-engine-<keystr> 仅反映活动时间,而不考虑引擎以其最大频率的百分比运行的频率。

驱动程序可以实现此键或 drm-total-cycles-<keystr>,但不能同时实现两者。

内存

每个可能的内存类型,GPU 可以使用该内存类型来存储缓冲区对象,都应具有一个稳定且唯一的名称,该名称用作 "<region>" 字符串。

区域名称 "memory" 保留用于指代正常系统内存。

该值应反映属于此客户端的缓冲区对象在相应内存区域中当前消耗的存储量。

默认单位应为字节,可选单位说明符为 "KiB" 或 "MiB",表示千字节或兆字节。

  • drm-total-<region>: <uint> [KiB|MiB]

所有请求的缓冲区(包括共享和私有内存)的总大小。缓冲区的后备存储不需要当前实例化才能在此类别下计数。为避免重复计数,如果缓冲区有多个可以分配到的区域,则实现应始终选择单个区域进行核算。

  • drm-shared-<region>: <uint> [KiB|MiB]

与其他文件共享(即,具有多个句柄)的缓冲区的总大小。适用于 drm-total-<region> 的避免重复计数的相同要求也适用于此处。

  • drm-resident-<region>: <uint> [KiB|MiB]

驻留在指定区域中的缓冲区(即,具有其后备存储存在或已实例化)的总大小。

  • drm-memory-<region>: <uint> [KiB|MiB]

此键已弃用,仅由 amdgpu 打印; 它是 drm-resident-<region> 的别名。

  • drm-purgeable-<region>: <uint> [KiB|MiB]

驻留且可清除的缓冲区的总大小。

例如,实现类似于“madvise”功能的驱动程序可以计算具有实例化后备存储但已标记为 MADV_DONTNEED 等效项的缓冲区。

  • drm-active-<region>: <uint> [KiB|MiB]

在一个或多个引擎上处于活动状态的缓冲区的总大小。

一个实际示例可能是 GEM 缓冲区预留对象中存在未发出信号的栅栏。 因此,活动类别是驻留类别的子集。

实现细节

驱动程序应在其 struct file_operations 中使用 drm_show_fdinfo(),并且如果希望提供任何 drm_show_fdinfo() 未提供的统计信息,则实现 &drm_driver.show_fdinfo。 但是,即使是驱动程序特定的统计信息也应在上面记录,并在可能的情况下与其他驱动程序对齐。

驱动程序特定实现