DRM 驱动 uAPI

drm/i915 uAPI

i915 在其设备节点上生成的 uevent

I915_L3_PARITY_UEVENT - 当驱动程序收到来自 GPU L3 缓存的奇偶校验不匹配事件时生成。 提供的附加信息是受影响的缓存行的 ROW、BANK、SUBBANK、SLICE。 用户空间应跟踪这些事件,如果特定的缓存行似乎有持续的错误,则使用 intel-gpu-tools 中提供的 L3 重映射工具重新映射它。 事件提供的值始终为 1。

event from the GPU L3 cache. Additional information supplied is ROW, BANK, SUBBANK, SLICE of the affected cacheline. Userspace should keep track of these events, and if a specific cache-line seems to have a persistent error, remap it with the L3 remapping tool supplied in intel-gpu-tools. The value supplied with the event is always 1.

I915_ERROR_UEVENT - 在检测到错误时生成,目前仅通过

hangcheck 生成。错误检测事件很好地指示了事情何时开始变得糟糕。事件提供的值在检测到错误时为 1,在重置完成时为 0,表示不再存在错误。注意:通过模块参数禁用 hangcheck 或重置将导致无法看到相关的事件。

I915_RESET_UEVENT - 该事件在尝试重置

GPU 之前生成。事件提供的值始终为 1。注意:通过模块参数禁用重置将导致无法看到此事件。

struct i915_user_extension

定义扩展链的基类

定义:

struct i915_user_extension {
    __u64 next_extension;
    __u32 name;
    __u32 flags;
    __u32 rsvd[4];
};

成员

next_extension

指向下一个 struct i915_user_extension 的指针,如果结束则为零。

name

扩展的名称。

请注意,此处的名称只是一个整数。

另请注意,此命名空间不是整个驱动程序的全局命名空间,而是其范围/含义仅限于嵌入 struct i915_user_extension 的特定 uAPI 部分。

flags

MBZ

所有未定义的位必须为零。

rsvd

MBZ

保留供将来使用;必须为零。

描述

许多接口需要随着时间的推移而增长。在大多数情况下,我们可以简单地扩展结构,让用户空间传入更多数据。另一种选择,如 Vulkan 为提供向前和向后兼容性的扩展方法所演示的那样,是使用可选结构的列表来提供这些额外的细节。

使用扩展链的关键优势在于,它允许我们比不断增长的复杂结构更容易地重新定义接口,并且该接口的很大一部分完全是可选的。缺点是指针追踪更多;在 u64 中封装的指针,跨 __user 边界追踪。

示例链接

struct i915_user_extension ext3 {
        .next_extension = 0, // end
        .name = ...,
};
struct i915_user_extension ext2 {
        .next_extension = (uintptr_t)&ext3,
        .name = ...,
};
struct i915_user_extension ext1 {
        .next_extension = (uintptr_t)&ext2,
        .name = ...,
};

通常,struct i915_user_extension 将嵌入到某个 uAPI 结构中,在这种情况下,我们将向其馈送链的头部(即 ext1),然后它将应用上述所有扩展。

enum drm_i915_gem_engine_class

uapi 引擎类型枚举

常量

I915_ENGINE_CLASS_RENDER

渲染引擎支持用于 3D、计算 (GPGPU) 和可编程媒体工作负载的指令。这些指令获取数据并将各个工作项分派到并行运行的线程。线程在 GPU 的执行单元 (EU) 上运行小程序(称为“内核”或“着色器”)。

I915_ENGINE_CLASS_COPY

复制引擎(也称为“blitters”)支持将数据块从内存中的一个位置移动到另一个位置的指令,或者用固定数据填充内存的指定位置的指令。复制引擎可以对源数据、目标数据或模式数据执行预定义的逻辑或按位运算。

I915_ENGINE_CLASS_VIDEO

视频引擎(也称为“比特流解码” (BSD) 或 “vdbox”)支持执行固定功能媒体解码和编码的指令。

I915_ENGINE_CLASS_VIDEO_ENHANCE

视频增强引擎(也称为“vebox”)支持与图像增强相关的指令。

I915_ENGINE_CLASS_COMPUTE

计算引擎支持渲染引擎上可用指令的子集:计算引擎支持计算 (GPGPU) 和可编程媒体工作负载,但不支持 3D 管道。

I915_ENGINE_CLASS_INVALID

表示无效引擎类分配的占位符值。

描述

不同的引擎服务于不同的角色,并且可能有多个引擎服务于每个角色。此枚举提供引擎角色的分类,该分类可用于请求在某些引擎子集上执行的操作,或用于提供有关该组的信息。

struct i915_engine_class_instance

引擎类/实例标识符

定义:

struct i915_engine_class_instance {
    __u16 engine_class;
#define I915_ENGINE_CLASS_INVALID_NONE -1;
#define I915_ENGINE_CLASS_INVALID_VIRTUAL -2;
    __u16 engine_instance;
};

成员

engine_class

来自 enum drm_i915_gem_engine_class 的引擎类

engine_instance

引擎实例。

描述

系统中可能存在多个引擎来满足任何角色。类的每个引擎都给定一个唯一的实例编号,因此可以通过其类:实例元组指定任何引擎。允许访问系统中任何引擎的 API 将使用 struct i915_engine_class_instance 进行此标识。

通过 /sys/bus/event_sources/drivers/i915 暴露的 i915 perf_events

struct drm_i915_getparam

驱动程序参数查询结构。

定义:

struct drm_i915_getparam {
    __s32 param;
    int __user *value;
};

成员

param

要查询的驱动程序参数。

value

应放置查询值的内存地址。

警告:使用指针而不是固定大小的 u64 意味着我们需要编写 compat32 代码。不要重复这个错误。

type drm_i915_getparam_t

驱动程序参数查询结构。请参阅 struct drm_i915_getparam

struct drm_i915_gem_mmap_offset

检索偏移量,以便我们可以 mmap 这个缓冲区对象。

定义:

struct drm_i915_gem_mmap_offset {
    __u32 handle;
    __u32 pad;
    __u64 offset;
    __u64 flags;
#define I915_MMAP_OFFSET_GTT    0;
#define I915_MMAP_OFFSET_WC     1;
#define I915_MMAP_OFFSET_WB     2;
#define I915_MMAP_OFFSET_UC     3;
#define I915_MMAP_OFFSET_FIXED  4;
    __u64 extensions;
};

成员

handle

要映射的对象的句柄。

pad

必须为零

offset

用于后续 mmap 调用的伪偏移量

这是一个用于 32/64 位兼容性的固定大小类型。

flags

用于扩展行为的标志。

必须包含一个 MMAP_OFFSET 类型

  • I915_MMAP_OFFSET_GTT:使用 mmap 和绑定到 GTT 的对象。(写合并)

  • I915_MMAP_OFFSET_WC:使用写合并缓存。

  • I915_MMAP_OFFSET_WB:使用写回缓存。

  • I915_MMAP_OFFSET_FIXED:使用对象放置来确定缓存。

在具有本地内存的设备上,I915_MMAP_OFFSET_FIXED 是唯一有效的类型。在没有本地内存的设备上,此缓存模式无效。

作为指定 I915_MMAP_OFFSET_FIXED 时的缓存模式,将使用 WC 或 WB,具体取决于创建时对象的放置。当对象只能存在于系统内存中时,将使用 WB,否则使用 WC。

extensions

以零结尾的扩展链。

未定义当前扩展;mbz。

描述

此结构作为参数传递给 DRM_IOCTL_I915_GEM_MMAP_OFFSET ioctl,并用于检索用于 mmap 由 handle 指定的对象的伪偏移量。

在 gen12+ 上删除了使用 DRM_IOCTL_I915_GEM_MMAP 的旧方法。DRM_IOCTL_I915_GEM_MMAP_GTT 是对此结构的较旧支持的别名,但其行为类似于将 extensions 设置为 0,并将 flags 设置为 I915_MMAP_OFFSET_GTT

struct drm_i915_gem_set_domain

调整对象的写入或读取域,为通过某些 CPU 域访问页面做准备。

定义:

struct drm_i915_gem_set_domain {
    __u32 handle;
    __u32 read_domains;
    __u32 write_domain;
};

成员

handle

对象的句柄。

read_domains

新的读取域。

write_domain

新的写入域。

请注意,在写入域中存在内容意味着它在读取域中,并且仅在该读取域中。

描述

指定新的写入或读取域将在更新对象的域跟踪之前,将对象刷新出先前的域(如果需要),并使用新的域。

注意,如果对象仍在 GPU 上处于活动状态,这可能需要先等待该对象。

read_domainswrite_domain 支持的值

  • I915_GEM_DOMAIN_WC:非缓存的写合并域

  • I915_GEM_DOMAIN_CPU:CPU 缓存域

  • I915_GEM_DOMAIN_GTT:可映射的孔径域

所有其他域都将被拒绝。

请注意,对于独立显卡,从 DG1 开始,不再支持此功能,而是会被拒绝。在此类平台上,CPU 域实际上是静态的,我们只支持一种 drm_i915_gem_mmap_offset 缓存模式,该模式不能显式设置,而是取决于对象的放置,如下所示。

从 DG1 开始的隐式缓存规则

  • 如果任何对象放置(请参阅 drm_i915_gem_create_ext_memory_regions)包含 I915_MEMORY_CLASS_DEVICE,则该对象将仅分配并映射为写合并。

  • 所有其他情况都将始终分配并映射为写回,并保证一切都与 GPU 保持一致。

请注意,这在未来可能会再次更改,我们可能需要在未来的设备上提供更大的灵活性,因此将所有这些显式化作为新的 drm_i915_gem_create_ext 扩展的一部分是可能的。

struct drm_i915_gem_exec_fence

execbuf ioctl 的输入或输出栅栏。

定义:

struct drm_i915_gem_exec_fence {
    __u32 handle;
    __u32 flags;
#define I915_EXEC_FENCE_WAIT            (1<<0);
#define I915_EXEC_FENCE_SIGNAL          (1<<1);
#define __I915_EXEC_FENCE_UNKNOWN_FLAGS (-(I915_EXEC_FENCE_SIGNAL << 1));
};

成员

handle

用户用于等待或发出信号的 drm_syncobj 的句柄。

flags

支持的标志是

I915_EXEC_FENCE_WAIT:在请求提交之前等待输入栅栏。

I915_EXEC_FENCE_SIGNAL:返回请求完成栅栏作为输出

描述

请求将在提交之前等待输入栅栏发出信号。

返回的输出栅栏将在请求完成后发出信号。

struct drm_i915_gem_execbuffer_ext_timeline_fences

execbuf ioctl 的时间线栅栏。

定义:

struct drm_i915_gem_execbuffer_ext_timeline_fences {
#define DRM_I915_GEM_EXECBUFFER_EXT_TIMELINE_FENCES 0;
    struct i915_user_extension base;
    __u64 fence_count;
    __u64 handles_ptr;
    __u64 values_ptr;
};

成员

base

扩展链接。请参阅 struct i915_user_extension

fence_count

handles_ptrvalue_ptr 数组中的元素数量。

handles_ptr

指向长度为 fence_countstruct drm_i915_gem_exec_fence 数组的指针。

values_ptr

指向长度为 fence_count 的 u64 值数组的指针。对于二进制 drm_syncobj,值必须为 0。对于时间线 drm_syncobj,值为 0 无效,因为它会将 drm_syncobj 转换为二进制 syncobj。

描述

此结构描述了 drm_syncobj 数组和时间线变体的 drm_syncobj 的相关点。如果设置了 I915_EXEC_FENCE_ARRAY,则将此结构附加到 execbuf 是无效的。

struct drm_i915_gem_execbuffer2

用于 DRM_I915_GEM_EXECBUFFER2 ioctl 的结构。

定义:

struct drm_i915_gem_execbuffer2 {
    __u64 buffers_ptr;
    __u32 buffer_count;
    __u32 batch_start_offset;
    __u32 batch_len;
    __u32 DR1;
    __u32 DR4;
    __u32 num_cliprects;
    __u64 cliprects_ptr;
    __u64 flags;
#define I915_EXEC_RING_MASK              (0x3f);
#define I915_EXEC_DEFAULT                (0<<0);
#define I915_EXEC_RENDER                 (1<<0);
#define I915_EXEC_BSD                    (2<<0);
#define I915_EXEC_BLT                    (3<<0);
#define I915_EXEC_VEBOX                  (4<<0);
#define I915_EXEC_CONSTANTS_MASK        (3<<6);
#define I915_EXEC_CONSTANTS_REL_GENERAL (0<<6) ;
#define I915_EXEC_CONSTANTS_ABSOLUTE    (1<<6);
#define I915_EXEC_CONSTANTS_REL_SURFACE (2<<6) ;
#define I915_EXEC_GEN7_SOL_RESET        (1<<8);
#define I915_EXEC_SECURE                (1<<9);
#define I915_EXEC_IS_PINNED             (1<<10);
#define I915_EXEC_NO_RELOC              (1<<11);
#define I915_EXEC_HANDLE_LUT            (1<<12);
#define I915_EXEC_BSD_SHIFT      (13);
#define I915_EXEC_BSD_MASK       (3 << I915_EXEC_BSD_SHIFT);
#define I915_EXEC_BSD_DEFAULT    (0 << I915_EXEC_BSD_SHIFT);
#define I915_EXEC_BSD_RING1      (1 << I915_EXEC_BSD_SHIFT);
#define I915_EXEC_BSD_RING2      (2 << I915_EXEC_BSD_SHIFT);
#define I915_EXEC_RESOURCE_STREAMER     (1<<15);
#define I915_EXEC_FENCE_IN              (1<<16);
#define I915_EXEC_FENCE_OUT             (1<<17);
#define I915_EXEC_BATCH_FIRST           (1<<18);
#define I915_EXEC_FENCE_ARRAY   (1<<19);
#define I915_EXEC_FENCE_SUBMIT          (1 << 20);
#define I915_EXEC_USE_EXTENSIONS        (1 << 21);
#define __I915_EXEC_UNKNOWN_FLAGS (-(I915_EXEC_USE_EXTENSIONS << 1));
    __u64 rsvd1;
    __u64 rsvd2;
};

成员

buffers_ptr

指向 gem_exec_object2 结构列表的指针

buffer_count

buffers_ptr 数组中的元素数量

batch_start_offset

批处理缓冲区中开始执行的偏移量。

batch_len

批处理缓冲区的长度(以字节为单位),从 batch_start_offset 开始。如果为 0,则假定长度为批处理缓冲区对象的大小。

DR1

已弃用

DR4

已弃用

num_cliprects

请参阅 cliprects_ptr

cliprects_ptr

内核剪切是 DRI1 的错误功能。

如果未设置 I915_EXEC_FENCE_ARRAY 或 I915_EXEC_USE_EXTENSIONS 标志,则使用此字段是无效的。

如果设置了 I915_EXEC_FENCE_ARRAY,则这是指向 drm_i915_gem_exec_fence 数组的指针,并且 num_cliprects 是数组的长度。

如果设置了 I915_EXEC_USE_EXTENSIONS,则这是指向单个 i915_user_extension 的指针,并且 num_cliprects 为 0。

flags

Execbuf 标志

rsvd1

上下文 ID

rsvd2

输入和输出 sync_file 文件描述符。

当设置 I915_EXEC_FENCE_IN 或 I915_EXEC_FENCE_SUBMIT 标志时,此字段的低 32 位将具有输入 sync_file fd(输入)。

当设置 I915_EXEC_FENCE_OUT 标志时,此字段的高 32 位将具有输出 sync_file fd(输出)。

struct drm_i915_gem_caching

设置或获取给定对象句柄的缓存。

定义:

struct drm_i915_gem_caching {
    __u32 handle;
#define I915_CACHING_NONE               0;
#define I915_CACHING_CACHED             1;
#define I915_CACHING_DISPLAY            2;
    __u32 caching;
};

成员

handle

用于设置/获取缓存级别的缓冲区句柄。

caching

要应用或可能返回的 GTT 缓存级别。

支持的 caching

I915_CACHING_NONE

GPU 访问与 CPU 缓存不一致。对于没有 LLC 的机器的默认值。这意味着如果我们要使 GPU 访问保持一致,则可能需要手动刷新。

I915_CACHING_CACHED

GPU 访问与 CPU 缓存一致,并且数据缓存在 CPU 内核和 GPU GT 之间共享的最后一级缓存中。

I915_CACHING_DISPLAY

特殊的 GPU 缓存模式,与扫描输出引擎一致。在没有特殊缓存模式(如直写或 gfdt 刷新)的平台上,透明地回退到 I915_CACHING_NONE。当使用缓冲区作为扫描输出目标时,内核会自动设置此模式。用户空间可以手动设置此模式,以避免在绘制第一帧的热路径中出现代价高昂的停顿和 clflush。

描述

允许用户空间在以后通过 ppGTT(或在较旧的缺少 ppGTT 支持的平台,或者如果该对象用于扫描输出)映射对象时,控制给定对象的 GTT 缓存位。请注意,如果其当前的缓存值不匹配,则可能需要先从 GTT 取消绑定该对象。

请注意,从 DG1 开始,所有这些在独立平台上都会发生变化,不再支持设置/获取缓存,现在会被拒绝。相反,CPU 缓存属性(WB 与 WC)将成为该对象的不可变的创建时间属性,以及 GTT 缓存级别。目前我们没有为此公开任何新的 uAPI,而是 DG1 上的所有这些都是隐式的,尽管这在很大程度上无关紧要,因为 DG1 默认是一致的(没有任何控制方式)。

从 DG1 开始的隐式缓存规则

  • 如果任何对象放置(请参阅 drm_i915_gem_create_ext_memory_regions)包含 I915_MEMORY_CLASS_DEVICE,则该对象将仅分配并映射为写合并。

  • 所有其他情况都将始终分配并映射为写回,并保证一切都与 GPU 保持一致。

请注意,这在未来可能会再次更改,我们可能需要在未来的设备上提供更大的灵活性,因此将所有这些显式化作为新的 drm_i915_gem_create_ext 扩展的一部分是可能的。

旁注:造成这种情况的部分原因是,如果我们需要稍后使用不同的缓存属性对页面进行 CPU 映射,则可能需要(并且代价昂贵)更改页面的分配时 CPU 缓存属性。这种不一致的缓存行为虽然在 x86 上受支持,但在其他架构上并不普遍支持。因此,为了简单起见,我们选择在创建时设置所有内容,同时使其在独立平台上不可变。

struct drm_i915_gem_context_create_ext

用于创建上下文的结构。

定义:

struct drm_i915_gem_context_create_ext {
    __u32 ctx_id;
    __u32 flags;
#define I915_CONTEXT_CREATE_FLAGS_USE_EXTENSIONS        (1u << 0);
#define I915_CONTEXT_CREATE_FLAGS_SINGLE_TIMELINE       (1u << 1);
#define I915_CONTEXT_CREATE_FLAGS_UNKNOWN       (-(I915_CONTEXT_CREATE_FLAGS_SINGLE_TIMELINE << 1));
    __u64 extensions;
#define I915_CONTEXT_CREATE_EXT_SETPARAM 0;
#define I915_CONTEXT_CREATE_EXT_CLONE 1;
};

成员

ctx_id

创建的上下文的 ID(输出)

flags

支持的标志是

I915_CONTEXT_CREATE_FLAGS_USE_EXTENSIONS

扩展可以附加到此结构,并且驱动程序必须检查这些扩展。请参阅 extensions

I915_CONTEXT_CREATE_FLAGS_SINGLE_TIMELINE

创建的上下文将具有单个时间线。

extensions

以零结尾的扩展链。

I915_CONTEXT_CREATE_EXT_SETPARAM:在上下文创建期间设置或查询的上下文参数。请参阅 struct drm_i915_gem_context_create_ext_setparam

I915_CONTEXT_CREATE_EXT_CLONE:此扩展已删除。如果有人在某处尝试使用它,请永远不要重新使用此扩展号。

struct drm_i915_gem_context_param

要设置或查询的上下文参数。

定义:

struct drm_i915_gem_context_param {
    __u32 ctx_id;
    __u32 size;
    __u64 param;
#define I915_CONTEXT_PARAM_BAN_PERIOD   0x1;
#define I915_CONTEXT_PARAM_NO_ZEROMAP   0x2;
#define I915_CONTEXT_PARAM_GTT_SIZE     0x3;
#define I915_CONTEXT_PARAM_NO_ERROR_CAPTURE     0x4;
#define I915_CONTEXT_PARAM_BANNABLE     0x5;
#define I915_CONTEXT_PARAM_PRIORITY     0x6;
#define I915_CONTEXT_MAX_USER_PRIORITY        1023 ;
#define I915_CONTEXT_DEFAULT_PRIORITY         0;
#define I915_CONTEXT_MIN_USER_PRIORITY        -1023 ;
#define I915_CONTEXT_PARAM_SSEU         0x7;
#define I915_CONTEXT_PARAM_RECOVERABLE  0x8;
#define I915_CONTEXT_PARAM_VM           0x9;
#define I915_CONTEXT_PARAM_ENGINES      0xa;
#define I915_CONTEXT_PARAM_PERSISTENCE  0xb;
#define I915_CONTEXT_PARAM_RINGSIZE     0xc;
#define I915_CONTEXT_PARAM_PROTECTED_CONTENT    0xd;
#define I915_CONTEXT_PARAM_LOW_LATENCY          0xe;
#define I915_CONTEXT_PARAM_CONTEXT_IMAGE        0xf;
    __u64 value;
};

成员

ctx_id

上下文 ID

size

参数 value 的大小

param

要设置或查询的参数

value

要设置或查询的上下文参数值

虚拟引擎 uAPI

虚拟引擎是一种概念,用户空间可以在其中配置一组物理引擎,提交批处理缓冲区,并让驱动程序在它认为合适的该组中的任何引擎上执行它。

这主要在具有相同类引擎的多个实例的部件上很有用,例如具有两个 VCS 引擎的 GT3+ Skylake 部件。

例如,用户空间可以使用先前描述的 引擎发现 uAPI 枚举特定类的所有引擎。之后,用户空间可以使用虚拟引擎的占位符槽(分别使用 I915_ENGINE_CLASS_INVALIDI915_ENGINE_CLASS_INVALID_NONE 表示类和实例)创建一个 GEM 上下文,最后使用 I915_CONTEXT_ENGINES_EXT_LOAD_BALANCE 扩展将虚拟引擎放置在相同的保留槽中。

创建虚拟引擎并向其提交批处理缓冲区的示例

I915_DEFINE_CONTEXT_ENGINES_LOAD_BALANCE(virtual, 2) = {
        .base.name = I915_CONTEXT_ENGINES_EXT_LOAD_BALANCE,
        .engine_index = 0, // Place this virtual engine into engine map slot 0
        .num_siblings = 2,
        .engines = { { I915_ENGINE_CLASS_VIDEO, 0 },
                     { I915_ENGINE_CLASS_VIDEO, 1 }, },
};
I915_DEFINE_CONTEXT_PARAM_ENGINES(engines, 1) = {
        .engines = { { I915_ENGINE_CLASS_INVALID,
                       I915_ENGINE_CLASS_INVALID_NONE } },
        .extensions = to_user_pointer(&virtual), // Chains after load_balance extension
};
struct drm_i915_gem_context_create_ext_setparam p_engines = {
        .base = {
                .name = I915_CONTEXT_CREATE_EXT_SETPARAM,
        },
        .param = {
                .param = I915_CONTEXT_PARAM_ENGINES,
                .value = to_user_pointer(&engines),
                .size = sizeof(engines),
        },
};
struct drm_i915_gem_context_create_ext create = {
        .flags = I915_CONTEXT_CREATE_FLAGS_USE_EXTENSIONS,
        .extensions = to_user_pointer(&p_engines);
};

ctx_id = gem_context_create_ext(drm_fd, &create);

// Now we have created a GEM context with its engine map containing a
// single virtual engine. Submissions to this slot can go either to
// vcs0 or vcs1, depending on the load balancing algorithm used inside
// the driver. The load balancing is dynamic from one batch buffer to
// another and transparent to userspace.

...
execbuf.rsvd1 = ctx_id;
execbuf.flags = 0; // Submits to index 0 which is the virtual engine
gem_execbuf(drm_fd, &execbuf);
struct i915_context_engines_parallel_submit

配置引擎以进行并行提交。

定义:

struct i915_context_engines_parallel_submit {
    struct i915_user_extension base;
    __u16 engine_index;
    __u16 width;
    __u16 num_siblings;
    __u16 mbz16;
    __u64 flags;
    __u64 mbz64[3];
    struct i915_engine_class_instance engines[];
};

成员

base

基本用户扩展。

engine_index

用于并行引擎的槽

width

每个并行引擎的上下文数量,换句话说,每次提交中的批次数量

num_siblings

每个上下文的同级数量,换句话说,每次提交的可能放置位置的数量

mbz16

保留供将来使用;必须为零

flags

所有未定义的标志必须为零,当前未定义的标志

mbz64

保留供将来使用;必须为零

引擎

用于配置并行引擎的引擎实例的二维数组

长度 = 宽度 (i) * 兄弟数量 (j) 索引 = j + i * 兄弟数量

描述

在上下文引擎映射中设置一个槽位,允许在单个 execbuf IOCTL 中提交多个 BB。这些 BB 将被调度在 GPU 上并行运行。在 i915 内部会创建多个硬件上下文来运行这些 BB。一旦为 N 个 BB 配置了一个槽位,则每次 execbuf IOCTL 中只能提交 N 个 BB,这是一种隐式行为,例如,用户不会告诉 execbuf IOCTL 有 N 个 BB,execbuf IOCTL 会根据槽位的配置知道有多少个 BB。N 个 BB 是最后 N 个缓冲区对象,如果设置了 I915_EXEC_BATCH_FIRST,则是前 N 个。

默认的放置行为是在每个上下文映射到多个物理引擎时(例如,上下文是虚拟引擎),在每个上下文之间创建隐式绑定。此外,我们只允许具有相同引擎类别的上下文,并且这些上下文必须在逻辑上连续排序。放置行为的示例如下所述。最后,默认情况下不允许 BB 在批处理过程中被抢占。而是在每组 BB 之间,在所有硬件上下文上插入协调的抢占点。将来可能会添加标志来更改这两种默认行为。

如果硬件上下文放置配置无效,或者平台/提交接口不支持放置配置,则返回 -EINVAL。如果平台/提交接口不支持扩展,则返回 -ENODEV。

Examples syntax:
CS[X] = generic engine of same class, logical instance X
INVALID = I915_ENGINE_CLASS_INVALID, I915_ENGINE_CLASS_INVALID_NONE

Example 1 pseudo code:
set_engines(INVALID)
set_parallel(engine_index=0, width=2, num_siblings=1,
             engines=CS[0],CS[1])

Results in the following valid placement:
CS[0], CS[1]

Example 2 pseudo code:
set_engines(INVALID)
set_parallel(engine_index=0, width=2, num_siblings=2,
             engines=CS[0],CS[2],CS[1],CS[3])

Results in the following valid placements:
CS[0], CS[1]
CS[2], CS[3]

This can be thought of as two virtual engines, each containing two
engines thereby making a 2D array. However, there are bonds tying the
entries together and placing restrictions on how they can be scheduled.
Specifically, the scheduler can choose only vertical columns from the 2D
array. That is, CS[0] is bonded to CS[1] and CS[2] to CS[3]. So if the
scheduler wants to submit to CS[0], it must also choose CS[1] and vice
versa. Same for CS[2] requires also using CS[3].
VE[0] = CS[0], CS[2]
VE[1] = CS[1], CS[3]

Example 3 pseudo code:
set_engines(INVALID)
set_parallel(engine_index=0, width=2, num_siblings=2,
             engines=CS[0],CS[1],CS[1],CS[3])

Results in the following valid and invalid placements:
CS[0], CS[1]
CS[1], CS[3] - Not logically contiguous, return -EINVAL

上下文引擎映射 uAPI

上下文引擎映射是一种提交批处理缓冲区时寻址引擎的新方法,它取代了在 struct drm_i915_gem_execbuffer2 的标志字段中使用诸如 I915_EXEC_BLT 之类的标识符的现有方法。

要使用它,需要使用用户打算提交到的引擎列表配置已创建的 GEM 上下文。这可以使用 I915_CONTEXT_PARAM_ENGINES 参数和 struct i915_context_param_engines 来完成。

对于此类上下文,I915_EXEC_RING_MASK 字段将变为配置的映射的索引。

创建此类上下文并针对其提交的示例

I915_DEFINE_CONTEXT_PARAM_ENGINES(engines, 2) = {
        .engines = { { I915_ENGINE_CLASS_RENDER, 0 },
                     { I915_ENGINE_CLASS_COPY, 0 } }
};
struct drm_i915_gem_context_create_ext_setparam p_engines = {
        .base = {
                .name = I915_CONTEXT_CREATE_EXT_SETPARAM,
        },
        .param = {
                .param = I915_CONTEXT_PARAM_ENGINES,
                .value = to_user_pointer(&engines),
                .size = sizeof(engines),
        },
};
struct drm_i915_gem_context_create_ext create = {
        .flags = I915_CONTEXT_CREATE_FLAGS_USE_EXTENSIONS,
        .extensions = to_user_pointer(&p_engines);
};

ctx_id = gem_context_create_ext(drm_fd, &create);

// We have now created a GEM context with two engines in the map:
// Index 0 points to rcs0 while index 1 points to bcs0. Other engines
// will not be accessible from this context.

...
execbuf.rsvd1 = ctx_id;
execbuf.flags = 0; // Submits to index 0, which is rcs0 for this context
gem_execbuf(drm_fd, &execbuf);

...
execbuf.rsvd1 = ctx_id;
execbuf.flags = 1; // Submits to index 0, which is bcs0 for this context
gem_execbuf(drm_fd, &execbuf);
struct drm_i915_gem_context_create_ext_setparam

在上下文创建期间设置或查询的上下文参数。

定义:

struct drm_i915_gem_context_create_ext_setparam {
    struct i915_user_extension base;
    struct drm_i915_gem_context_param param;
};

成员

base

扩展链接。请参阅 struct i915_user_extension

param

要设置或查询的上下文参数。请参阅 struct drm_i915_gem_context_param

struct drm_i915_gem_vm_control

用于创建或销毁 VM 的结构。

定义:

struct drm_i915_gem_vm_control {
    __u64 extensions;
    __u32 flags;
    __u32 vm_id;
};

成员

extensions

以零结尾的扩展链。

flags

保留供将来使用,当前为 MBZ

vm_id

已创建或要销毁的 VM 的 ID

描述

DRM_I915_GEM_VM_CREATE -

创建一个新的虚拟内存地址空间 (ppGTT),用于在同一文件中的上下文中使用。可以提供扩展来配置在创建时如何设置地址空间。

新的 VM (绑定到 fd) 的 id,用于 I915_CONTEXT_PARAM_VM,在输出参数 **id** 中返回。

可以提供一个扩展链,从 **extensions** 开始,并以 **next_extension** 为 0 结束。目前,没有定义任何扩展。

DRM_I915_GEM_VM_DESTROY -

销毁先前创建的 VM id,在 **vm_id** 中指定。

当前不允许任何扩展或标志,因此必须为零。

struct drm_i915_gem_userptr

从用户分配的内存创建 GEM 对象。

定义:

struct drm_i915_gem_userptr {
    __u64 user_ptr;
    __u64 user_size;
    __u32 flags;
#define I915_USERPTR_READ_ONLY 0x1;
#define I915_USERPTR_PROBE 0x2;
#define I915_USERPTR_UNSYNCHRONIZED 0x80000000;
    __u32 handle;
};

成员

user_ptr

指向分配的内存的指针。

需要与 PAGE_SIZE 对齐。

user_size

分配的内存的大小(以字节为单位)。这也将成为对象大小。

需要与 PAGE_SIZE 对齐,并且应至少为 PAGE_SIZE 或更大。

flags

支持的标志

I915_USERPTR_READ_ONLY

将对象标记为只读,这也意味着 GPU 访问只能是只读的。这仅在支持通过 GTT 进行只读访问的硬件上受支持。如果硬件不支持只读访问,则会返回错误。

I915_USERPTR_PROBE

探测提供的 **user_ptr** 范围,并验证 **user_ptr** 是否确实指向普通内存,并且该范围也有效。例如,如果向内核提供了一些垃圾地址,则应该会报错。

如果探测失败,则返回 -EFAULT。

请注意,这不会填充后备页,并且也不保证对象在最终使用时保持有效。

如果 I915_PARAM_HAS_USERPTR_PROBE 返回非零值,则内核支持此功能。

I915_USERPTR_UNSYNCHRONIZED

未使用。设置此标志将导致错误。

handle

返回对象的句柄。

对象句柄为非零。

描述

Userptr 对象对可以与对象句柄一起使用的 ioctl 有一些限制。

struct drm_i915_perf_oa_config

定义:

struct drm_i915_perf_oa_config {
    char uuid[36];
    __u32 n_mux_regs;
    __u32 n_boolean_regs;
    __u32 n_flex_regs;
    __u64 mux_regs_ptr;
    __u64 boolean_regs_ptr;
    __u64 flex_regs_ptr;
};

成员

uuid

格式类似于 “%08x-%04x-%04x-%04x-%012x” 的字符串

n_mux_regs

mux_regs_ptr 中的 mux regs 数量。

n_boolean_regs

boolean_regs_ptr 中的 boolean regs 数量。

n_flex_regs

flex_regs_ptr 中的 flex regs 数量。

mux_regs_ptr

指向 mux 寄存器的 u32 值(寄存器地址、值)元组的指针。缓冲区的预期长度为 (2 * sizeof(u32) * n_mux_regs)。

boolean_regs_ptr

指向 mux 寄存器的 u32 值(寄存器地址、值)元组的指针。缓冲区的预期长度为 (2 * sizeof(u32) * n_boolean_regs)。

flex_regs_ptr

指向 mux 寄存器的 u32 值(寄存器地址、值)元组的指针。缓冲区的预期长度为 (2 * sizeof(u32) * n_flex_regs)。

描述

将 perf 动态配置上传到内核的结构。

struct drm_i915_query_item

内核要处理的单个查询。

定义:

struct drm_i915_query_item {
    __u64 query_id;
#define DRM_I915_QUERY_TOPOLOGY_INFO            1;
#define DRM_I915_QUERY_ENGINE_INFO              2;
#define DRM_I915_QUERY_PERF_CONFIG              3;
#define DRM_I915_QUERY_MEMORY_REGIONS           4;
#define DRM_I915_QUERY_HWCONFIG_BLOB            5;
#define DRM_I915_QUERY_GEOMETRY_SUBSLICES       6;
#define DRM_I915_QUERY_GUC_SUBMISSION_VERSION   7;
    __s32 length;
    __u32 flags;
#define DRM_I915_QUERY_PERF_CONFIG_LIST          1;
#define DRM_I915_QUERY_PERF_CONFIG_DATA_FOR_UUID 2;
#define DRM_I915_QUERY_PERF_CONFIG_DATA_FOR_ID   3;
    __u64 data_ptr;
};

成员

query_id
此查询的 ID。当前接受的查询 ID 为
length

当用户空间设置为零时,它将填充要写入 **data_ptr** 指针处的数据大小。内核将此值设置为负值以表示特定查询项上的错误。

flags

query_id == DRM_I915_QUERY_TOPOLOGY_INFO 时,必须为 0。

query_id == DRM_I915_QUERY_PERF_CONFIG 时,必须是以下之一

  • DRM_I915_QUERY_PERF_CONFIG_LIST

  • DRM_I915_QUERY_PERF_CONFIG_DATA_FOR_UUID

  • DRM_I915_QUERY_PERF_CONFIG_FOR_UUID

query_id == DRM_I915_QUERY_GEOMETRY_SUBSLICES 时,必须包含一个引用渲染引擎的 struct i915_engine_class_instance

data_ptr

当 **length** 的值与内核要写入的数据的长度匹配时,数据将写入 **data_ptr** 指向的位置。

描述

行为由 **query_id** 确定。请注意,**data_ptr** 的具体含义也取决于特定的 **query_id**。

struct drm_i915_query

提供一个 struct drm_i915_query_item 数组供内核填充。

定义:

struct drm_i915_query {
    __u32 num_items;
    __u32 flags;
    __u64 items_ptr;
};

成员

num_items

**items_ptr** 数组中的元素数量

flags

现在未使用。必须清除为零。

items_ptr

指向 struct drm_i915_query_item 数组的指针。数组元素的数量为 **num_items**。

描述

请注意,这通常是数组中每个 struct drm_i915_query_item 的两步过程

  1. 调用 DRM_IOCTL_I915_QUERY,提供我们的 struct drm_i915_query_item 数组,并将 drm_i915_query_item.length 设置为零。然后,内核将填充大小(以字节为单位),告诉用户空间需要为 blob 分配多少内存(例如,对于属性数组)。

  2. 接下来,我们再次调用 DRM_IOCTL_I915_QUERY,这次将 drm_i915_query_item.data_ptr 设置为我们新分配的 blob。请注意,drm_i915_query_item.length 应该仍然与内核之前设置的值相同。此时,内核可以填充该 blob。

请注意,对于某些查询项,用户空间可以直接传入等于或大于所需大小的缓冲区/blob。在这种情况下,只需要一次 ioctl 调用。对于一些较小的查询项,这种方式效果很好。

struct drm_i915_query_topology_info

定义:

struct drm_i915_query_topology_info {
    __u16 flags;
    __u16 max_slices;
    __u16 max_subslices;
    __u16 max_eus_per_subslice;
    __u16 subslice_offset;
    __u16 subslice_stride;
    __u16 eu_offset;
    __u16 eu_stride;
    __u8 data[];
};

成员

flags

现在未使用。必须清除为零。

max_slices

用于表示 slice 掩码的位数。

max_subslices

用于表示 subslice 掩码的位数。

max_eus_per_subslice

EU 掩码中对应于单个 subslice 的 EU 的位数。

subslice_offset

subslice 掩码存储在 data[] 中的偏移量。

subslice_stride

每个 slice 的 subslice 掩码的存储步长。

eu_offset

EU 掩码存储在 data[] 中的偏移量。

eu_stride

每个 subslice 的 EU 掩码的存储步长。

data

包含 3 个信息:

  • slice 掩码,每个 slice 用一位表示该 slice 是否可用。可以使用以下公式查询 slice X 的可用性:

    (data[X / 8] >> (X % 8)) & 1
    

    从 Xe_HP 平台开始,Intel 硬件不再具有传统的 slice,因此 i915 将始终报告一个包含所有平台 subslice 的单个 slice(硬编码的 slicemask = 0x1)。也就是说,这里的掩码不反映任何较新的硬件概念,例如“gslices”或“cslices”,因为用户空间可以从 subslice 掩码中推断出这些概念。

  • 每个 slice 的 subslice 掩码,每个 subslice 用一位表示该 subslice 是否可用。从 Gen12 开始,我们使用术语“subslice”来指代硬件文档中描述的“dual-subslices”。可以使用以下公式查询 slice X 中 subslice Y 的可用性:

    (data[subslice_offset + X * subslice_stride + Y / 8] >> (Y % 8)) & 1
    
  • 每个 slice 中每个 subslice 的 EU 掩码,每个 EU 用一位表示该 EU 是否可用。可以使用以下公式查询 slice X 中 subslice Y 中 EU Z 的可用性:

    (data[eu_offset +
          (X * max_subslices + Y) * eu_stride +
          Z / 8
     ] >> (Z % 8)) & 1
    

描述

描述通过 DRM_I915_QUERY_TOPOLOGY_INFO 查询的 slice/subslice/EU 信息

引擎发现 uAPI

引擎发现 uAPI 是一种枚举与打开的 i915 DRM 文件描述符关联的 GPU 中存在的物理引擎的方法。这取代了使用 DRM_IOCTL_I915_GETPARAMI915_PARAM_HAS_BLT 等引擎标识符的旧方法。

之所以需要此接口,是因为从 Icelake 和较新的 GPU 开始,它们开始建立一种具有多个相同类别的引擎的模式,其中并非所有实例在功能上都完全等效。

此 uapi 的入口点是 DRM_IOCTL_I915_QUERY,其中 DRM_I915_QUERY_ENGINE_INFO 作为查询的项 id。

获取引擎列表的示例

struct drm_i915_query_engine_info *info;
struct drm_i915_query_item item = {
        .query_id = DRM_I915_QUERY_ENGINE_INFO;
};
struct drm_i915_query query = {
        .num_items = 1,
        .items_ptr = (uintptr_t)&item,
};
int err, i;

// First query the size of the blob we need, this needs to be large
// enough to hold our array of engines. The kernel will fill out the
// item.length for us, which is the number of bytes we need.
//
// Alternatively a large buffer can be allocated straightaway enabling
// querying in one pass, in which case item.length should contain the
// length of the provided buffer.
err = ioctl(fd, DRM_IOCTL_I915_QUERY, &query);
if (err) ...

info = calloc(1, item.length);
// Now that we allocated the required number of bytes, we call the ioctl
// again, this time with the data_ptr pointing to our newly allocated
// blob, which the kernel can then populate with info on all engines.
item.data_ptr = (uintptr_t)&info;

err = ioctl(fd, DRM_IOCTL_I915_QUERY, &query);
if (err) ...

// We can now access each engine in the array
for (i = 0; i < info->num_engines; i++) {
        struct drm_i915_engine_info einfo = info->engines[i];
        u16 class = einfo.engine.class;
        u16 instance = einfo.engine.instance;
        ....
}

free(info);

每个枚举的引擎,除了由其类和实例定义(请参阅 struct i915_engine_class_instance)之外,还可以具有在 i915_drm.h 中记录的标志和功能。

例如,支持 HEVC 编码的视频引擎将设置 I915_VIDEO_CLASS_CAPABILITY_HEVC 功能位。

当与使用配置了引擎映射的上下文提交批处理缓冲区的新引擎寻址方式结合使用时,引擎发现才能充分发挥其作用。

struct drm_i915_engine_info

定义:

struct drm_i915_engine_info {
    struct i915_engine_class_instance engine;
    __u32 rsvd0;
    __u64 flags;
#define I915_ENGINE_INFO_HAS_LOGICAL_INSTANCE           (1 << 0);
    __u64 capabilities;
#define I915_VIDEO_CLASS_CAPABILITY_HEVC                (1 << 0);
#define I915_VIDEO_AND_ENHANCE_CLASS_CAPABILITY_SFC     (1 << 1);
    __u16 logical_instance;
    __u16 rsvd1[3];
    __u64 rsvd2[3];
};

成员

engine

引擎类和实例。

rsvd0

保留字段。

flags

引擎标志。

capabilities

此引擎的功能。

logical_instance

引擎的逻辑实例

rsvd1

保留字段。

rsvd2

保留字段。

描述

描述驱动程序已知的一个引擎及其功能。

struct drm_i915_query_engine_info

定义:

struct drm_i915_query_engine_info {
    __u32 num_engines;
    __u32 rsvd[3];
    struct drm_i915_engine_info engines[];
};

成员

num_engines

后续 struct drm_i915_engine_info 结构的个数。

rsvd

MBZ

引擎

drm_i915_engine_info 结构的标记。

描述

引擎信息查询通过填充 struct drm_i915_engine_info 结构数组来枚举驱动程序已知的所有引擎。

struct drm_i915_query_perf_config

定义:

struct drm_i915_query_perf_config {
    union {
        __u64 n_configs;
        __u64 config;
        char uuid[36];
    };
    __u32 flags;
    __u8 data[];
};

成员

{unnamed_union}

anonymous

n_configs

drm_i915_query_item.flags == DRM_I915_QUERY_PERF_CONFIG_LIST 时,i915 会将此字段设置为可用的配置数量。

config

drm_i915_query_item.flags == DRM_I915_QUERY_PERF_CONFIG_DATA_FOR_ID 时,i915 将使用此字段中的值作为配置标识符来决定要将哪些数据写入 config_ptr。

uuid

drm_i915_query_item.flags == DRM_I915_QUERY_PERF_CONFIG_DATA_FOR_UUID 时,i915 将使用此字段中的值作为配置标识符来决定要将哪些数据写入 config_ptr。

字符串格式如 “08x-````04x-````04x-````04x-````012x

flags

现在未使用。必须清除为零。

data

drm_i915_query_item.flags == DRM_I915_QUERY_PERF_CONFIG_LIST 时,i915 将写入配置标识符的 __u64 数组。

drm_i915_query_item.flags == DRM_I915_QUERY_PERF_CONFIG_DATA 时,i915 将写入 struct drm_i915_perf_oa_config。如果 struct drm_i915_perf_oa_config 的以下字段未设置为 0,则 i915 将把创建配置时提交的值写入相关的指针中:

描述

内核使用查询 DRM_I915_QUERY_PERF_CONFIGDRM_I915_QUERY_GEOMETRY_SUBSLICES 写入的数据。

enum drm_i915_gem_memory_class

支持的内存类

常量

I915_MEMORY_CLASS_SYSTEM

系统内存

I915_MEMORY_CLASS_DEVICE

设备本地内存

struct drm_i915_gem_memory_class_instance

标识特定的内存区域

定义:

struct drm_i915_gem_memory_class_instance {
    __u16 memory_class;
    __u16 memory_instance;
};

成员

memory_class

请参阅 enum drm_i915_gem_memory_class

memory_instance

哪个实例

struct drm_i915_memory_region_info

描述驱动程序已知的一个区域。

定义:

struct drm_i915_memory_region_info {
    struct drm_i915_gem_memory_class_instance region;
    __u32 rsvd0;
    __u64 probed_size;
    __u64 unallocated_size;
    union {
        __u64 rsvd1[8];
        struct {
            __u64 probed_cpu_visible_size;
            __u64 unallocated_cpu_visible_size;
        };
    };
};

成员

region

类:实例对编码

rsvd0

MBZ

probed_size

驱动程序探测到的内存

请注意,这里不应该出现零值,还要注意,当前没有区域类型会在这里返回 -1。尽管对于未来的区域类型,这可能是一种可能性。同样适用于其他大小字段。

unallocated_size

剩余内存的估计值

需要 CAP_PERFMON 或 CAP_SYS_ADMIN 才能获得可靠的帐户信息。如果没有此权限(或者如果这是一个较旧的内核),则此处的值将始终等于 probed_size。请注意,这目前仅针对 I915_MEMORY_CLASS_DEVICE 区域进行跟踪(对于其他类型,此处的值将始终等于 probed_size)。

{unnamed_union}

anonymous

rsvd1

MBZ

{unnamed_struct}

anonymous

probed_cpu_visible_size

驱动程序探测到的 CPU 可访问的内存。

这始终 <= probed_size,其余部分(如果有的话)将无法通过 CPU 访问。

在没有小 BAR 的系统上,probed_size 将始终等于 probed_cpu_visible_size,因为所有内存都将是 CPU 可访问的。

请注意,这仅针对 I915_MEMORY_CLASS_DEVICE 区域进行跟踪(对于其他类型,此处的值将始终等于 probed_size)。

请注意,如果此处返回的值为零,则必须是一个缺少相关 small-bar uAPI 支持(包括 I915_GEM_CREATE_EXT_FLAG_NEEDS_CPU_ACCESS)的旧内核,但在这样的系统上,如果能够加载内核模块,则不应该出现小 BAR 配置。因此,可以安全地将这种情况视为 probed_cpu_visible_size == probed_size 的情况。

unallocated_cpu_visible_size

剩余的 CPU 可见内存的估计值。

请注意,这仅针对 I915_MEMORY_CLASS_DEVICE 区域进行跟踪(对于其他类型,此处的值将始终等于 probed_cpu_visible_size)。

需要 CAP_PERFMON 或 CAP_SYS_ADMIN 才能获得可靠的帐户信息。否则此处的值将始终等于 probed_cpu_visible_size。请注意,这目前仅针对 I915_MEMORY_CLASS_DEVICE 区域进行跟踪(对于其他类型,此处的值也将始终等于 probed_cpu_visible_size)。

如果这是一个较旧的内核,则此处的值将为零,另请参见 probed_cpu_visible_size

描述

请注意,这里同时使用了 struct drm_i915_query_itemstruct drm_i915_query。对于这个新的查询,我们在 drm_i915_query_item.query_id 中添加了新的查询 ID DRM_I915_QUERY_MEMORY_REGIONS。

struct drm_i915_query_memory_regions

定义:

struct drm_i915_query_memory_regions {
    __u32 num_regions;
    __u32 rsvd[3];
    struct drm_i915_memory_region_info regions[];
};

成员

num_regions

支持的区域数量

rsvd

MBZ

regions

有关每个支持区域的信息

描述

区域信息查询通过填充 struct drm_i915_memory_region_info 结构体数组,来枚举驱动程序已知的所有区域。

获取支持区域列表的示例

struct drm_i915_query_memory_regions *info;
struct drm_i915_query_item item = {
        .query_id = DRM_I915_QUERY_MEMORY_REGIONS;
};
struct drm_i915_query query = {
        .num_items = 1,
        .items_ptr = (uintptr_t)&item,
};
int err, i;

// First query the size of the blob we need, this needs to be large
// enough to hold our array of regions. The kernel will fill out the
// item.length for us, which is the number of bytes we need.
err = ioctl(fd, DRM_IOCTL_I915_QUERY, &query);
if (err) ...

info = calloc(1, item.length);
// Now that we allocated the required number of bytes, we call the ioctl
// again, this time with the data_ptr pointing to our newly allocated
// blob, which the kernel can then populate with the all the region info.
item.data_ptr = (uintptr_t)&info,

err = ioctl(fd, DRM_IOCTL_I915_QUERY, &query);
if (err) ...

// We can now access each region in the array
for (i = 0; i < info->num_regions; i++) {
        struct drm_i915_memory_region_info mr = info->regions[i];
        u16 class = mr.region.class;
        u16 instance = mr.region.instance;

        ....
}

free(info);
struct drm_i915_query_guc_submission_version

查询 GuC 提交接口版本

定义:

struct drm_i915_query_guc_submission_version {
    __u32 branch;
    __u32 major;
    __u32 minor;
    __u32 patch;
};

成员

分支

固件分支版本。

主版本号

固件主版本号。

次版本号

固件次版本号。

补丁版本号

固件补丁版本号。

GuC HWCONFIG blob uAPI

GuC 生成一个包含当前设备信息的 blob。i915 从 GuC 读取此 blob,并通过此 uAPI 提供它。

blob 内容的格式和含义记录在《程序员参考手册》中。

struct drm_i915_gem_create_ext

现有的 gem_create 行为,增加了使用 struct i915_user_extension 的扩展支持。

定义:

struct drm_i915_gem_create_ext {
    __u64 size;
    __u32 handle;
#define I915_GEM_CREATE_EXT_FLAG_NEEDS_CPU_ACCESS (1 << 0);
    __u32 flags;
#define I915_GEM_CREATE_EXT_MEMORY_REGIONS 0;
#define I915_GEM_CREATE_EXT_PROTECTED_CONTENT 1;
#define I915_GEM_CREATE_EXT_SET_PAT 2;
    __u64 extensions;
};

成员

size

请求的对象大小。

将返回对象(按页对齐)的分配大小。

在像 DG2/ATS 这样的平台上,内核将始终对 I915_MEMORY_CLASS_DEVICE 使用 64K 或更大的页。内核还要求此类对象至少具有 64K GTT 对齐。

注意:之前,由于硬件实现 64K GTT 页支持的方式,这里的 ABI 要求 DG2/ATS 上 GTT 的最小对齐为 2M,我们有以下复杂情况

1) 整个 PDE(覆盖 2MB 虚拟地址范围)必须仅包含 64K PTE,即硬件禁止在同一 PDE 中混合 4K 和 64K PTE。

2) 我们仍然需要支持 I915_MEMORY_CLASS_SYSTEM 对象的 4K PTE。

但是,在实际生产硬件上,这完全改变了,现在允许在 PTE 级别设置 TLB 提示(请参阅 PS64),这比上述方法灵活得多。这样,就取消了 2M 的限制,现在我们只需要 64K。

handle

返回对象的句柄。

对象句柄为非零。

flags

可选标志。

支持的值

I915_GEM_CREATE_EXT_FLAG_NEEDS_CPU_ACCESS - 向内核发出信号,表明该对象将需要通过 CPU 访问。

仅当将对象放置在 I915_MEMORY_CLASS_DEVICE 中时有效,并且仅在某些设备内存通过 CPU 直接可见/可映射(我们也称之为小 BAR)的配置上严格要求,例如在某些 DG2+ 系统上。请注意,这是非常不可取的,但由于客户端 CPU、BIOS 等各种因素,我们可能会在实际应用中遇到这种情况。有关如何确定此系统是否适用,请参阅 drm_i915_memory_region_info.probed_cpu_visible_size

请注意,必须有一个位置为 I915_MEMORY_CLASS_SYSTEM,以确保如果该对象无法分配到 I915_MEMORY_CLASS_DEVICE 的可映射部分,内核始终可以将分配溢出到系统内存。

另请注意,由于内核仅在 *只能* 放置在 I915_MEMORY_CLASS_DEVICE 中的对象上支持 flat-CCS,因此我们不支持将 I915_GEM_CREATE_EXT_FLAG_NEEDS_CPU_ACCESS 与 flat-CCS 一起使用。

如果没有此提示,内核将假定此对象首选不可映射的 I915_MEMORY_CLASS_DEVICE。请注意,如果用户空间对该对象出现 CPU 故障,内核仍然可以将该对象迁移到可映射的部分作为最后的手段,但这可能代价高昂,因此理想情况下应该避免。

在缺少相关小 bar uAPI 支持的旧内核上(另请参阅 drm_i915_memory_region_info.probed_cpu_visible_size),使用该标志将导致错误,但假设我们也能成功加载 i915 内核模块,则应该永远不可能出现小 BAR 配置。在这种情况下,整个 I915_MEMORY_CLASS_DEVICE 区域都可由 CPU 访问,因此对对象可以放置的位置没有限制。

extensions

应用于此对象的扩展链。

当我们需要支持多个不同的扩展时,并且在创建对象时需要应用多个扩展时,这将很有用。请参阅 struct i915_user_extension

如果我们不提供任何扩展,那么我们将获得相同的旧 gem_create 行为。

有关 I915_GEM_CREATE_EXT_MEMORY_REGIONS 的用法,请参阅 struct drm_i915_gem_create_ext_memory_regions

有关 I915_GEM_CREATE_EXT_PROTECTED_CONTENT 的用法,请参阅 struct drm_i915_gem_create_ext_protected_content

有关 I915_GEM_CREATE_EXT_SET_PAT 的用法,请参阅 struct drm_i915_gem_create_ext_set_pat

描述

请注意,至少对于不可变的内容,应该在此处添加新的缓冲区标志。以前,我们将有两个 ioctl,一个用于使用 gem_create 创建对象,另一个用于应用各种参数,但这会给被认为是不可变的参数带来一些歧义。通常,我们正在逐步淘汰各种 SET/GET ioctl。

struct drm_i915_gem_create_ext_memory_regions

I915_GEM_CREATE_EXT_MEMORY_REGIONS 扩展。

定义:

struct drm_i915_gem_create_ext_memory_regions {
    struct i915_user_extension base;
    __u32 pad;
    __u32 num_regions;
    __u64 regions;
};

成员

base

扩展链接。请参阅 struct i915_user_extension

pad

MBZ

num_regions

regions 数组中的元素数量。

regions

regions/placements 数组。

一个 struct drm_i915_gem_memory_class_instance 的数组。

描述

按优先级顺序设置具有所需位置/区域的对象。每个条目都必须是唯一的且受设备支持。

这以 struct drm_i915_gem_memory_class_instance 的数组或类:实例对编码的等效布局提供。有关如何查询设备支持的区域,请参阅 struct drm_i915_query_memory_regions 和 DRM_I915_QUERY_MEMORY_REGIONS。

例如,在离散设备上,如果我们希望将位置设置为设备本地内存,我们可以执行以下操作:

struct drm_i915_gem_memory_class_instance region_lmem = {
        .memory_class = I915_MEMORY_CLASS_DEVICE,
        .memory_instance = 0,
};
struct drm_i915_gem_create_ext_memory_regions regions = {
        .base = { .name = I915_GEM_CREATE_EXT_MEMORY_REGIONS },
        .regions = (uintptr_t)&region_lmem,
        .num_regions = 1,
};
struct drm_i915_gem_create_ext create_ext = {
        .size = 16 * PAGE_SIZE,
        .extensions = (uintptr_t)&regions,
};

int err = ioctl(fd, DRM_IOCTL_I915_GEM_CREATE_EXT, &create_ext);
if (err) ...

此时,我们在 drm_i915_gem_create_ext.handle 中获取对象句柄,并在 drm_i915_gem_create_ext.size 中获取最终对象大小,这应考虑任何必要的向上舍入。

请注意,对于 num_regions 大于 1 的对象,用户空间无法知道对象的当前后备区域。内核仅确保在初始放置对象时或由于内存压力移动内存时,遵守 regions 数组的优先级顺序

在支持 Flat-CCS 的硬件上,对驻留在 I915_MEMORY_CLASS_DEVICE 中的对象支持压缩。当此类对象(压缩的)在 regions 中具有其他内存类,并且(由于内存限制)被 i915 迁移到非 I915_MEMORY_CLASS_DEVICE 区域时,则 i915 需要解压缩内容。但是,i915 没有解压缩用户空间压缩对象所需的必要信息。

因此,i915 支持 Flat-CCS,仅限于可以驻留在 I915_MEMORY_CLASS_DEVICE 区域的对象。

struct drm_i915_gem_create_ext_protected_content

I915_OBJECT_PARAM_PROTECTED_CONTENT 扩展。

定义:

struct drm_i915_gem_create_ext_protected_content {
    struct i915_user_extension base;
    __u32 flags;
};

成员

base

扩展链接。请参阅 struct i915_user_extension

flags

保留供将来使用,当前为 MBZ

描述

如果提供了此扩展,则缓冲区内容应受 PXP 加密保护,并且需要解密才能进行扫描输出和处理。这仅在启用 PXP 的平台上才有可能,在所有其他情况下,使用此扩展将导致 ioctl 失败并返回 -ENODEV。 flags 参数保留供将来扩展使用,目前必须设置为零。

PXP 会话关闭后,缓冲区内容被视为无效。

仅当使用 I915_CONTEXT_PARAM_PROTECTED_CONTENT 标志创建的上下文提交对象时,才能保证正确处理加密。这也将在提交时对所涉及对象的有效性启用额外的检查。

下面是如何创建受保护对象的示例

struct drm_i915_gem_create_ext_protected_content protected_ext = {
        .base = { .name = I915_GEM_CREATE_EXT_PROTECTED_CONTENT },
        .flags = 0,
};
struct drm_i915_gem_create_ext create_ext = {
        .size = PAGE_SIZE,
        .extensions = (uintptr_t)&protected_ext,
};

int err = ioctl(fd, DRM_IOCTL_I915_GEM_CREATE_EXT, &create_ext);
if (err) ...
struct drm_i915_gem_create_ext_set_pat

I915_GEM_CREATE_EXT_SET_PAT 扩展。

定义:

struct drm_i915_gem_create_ext_set_pat {
    struct i915_user_extension base;
    __u32 pat_index;
    __u32 rsvd;
};

成员

base

扩展链接。请参阅 struct i915_user_extension

pat_index

要设置的 PAT 索引。PAT 索引是页表条目中的一个位字段,用于控制 GPU 访问的缓存行为。PAT 索引的定义取决于平台,可以在硬件规范中找到。

rsvd

保留供将来使用

描述

如果提供了此扩展,则将指定的缓存策略(PAT 索引)应用于缓冲区对象。

下面是如何使用特定缓存策略创建对象的示例

struct drm_i915_gem_create_ext_set_pat set_pat_ext = {
        .base = { .name = I915_GEM_CREATE_EXT_SET_PAT },
        .pat_index = 0,
};
struct drm_i915_gem_create_ext create_ext = {
        .size = PAGE_SIZE,
        .extensions = (uintptr_t)&set_pat_ext,
};

int err = ioctl(fd, DRM_IOCTL_I915_GEM_CREATE_EXT, &create_ext);
if (err) ...

drm/nouveau uAPI

VM_BIND / EXEC uAPI

Nouveau 的 VM_BIND / EXEC UAPI 由三个 ioctl 组成:DRM_NOUVEAU_VM_INIT、DRM_NOUVEAU_VM_BIND 和 DRM_NOUVEAU_EXEC。

为了使用 UAPI,用户客户端必须首先使用 DRM_NOUVEAU_VM_INIT ioctl 初始化 VA 空间,指定 VA 空间的哪个区域应由内核管理,哪个区域应由 UMD 管理。

DRM_NOUVEAU_VM_BIND ioctl 为客户端提供了一个管理 VA 空间中用户空间可管理部分的接口。它提供了映射和取消映射内存的操作。映射可以标记为稀疏。稀疏映射没有 GEM 对象支持,内核将忽略与稀疏映射一起提供的 GEM 句柄。

用户空间可以请求在先前映射的稀疏映射的边界内或边界外(但不跨越这些边界)的内存支持映射。后续在稀疏映射内请求的内存支持映射将优先于稀疏映射的相应范围。如果此类内存支持映射被取消映射,内核将确保相应的稀疏映射再次占据其位置。请求取消映射仍包含内存支持映射的稀疏映射将导致这些内存支持映射首先被取消映射。

取消映射请求不受现有映射范围的限制,甚至可以与稀疏映射的边界重叠。对于此类请求,内核将确保取消映射给定范围内的所有内存支持映射,并拆分仅部分包含在给定范围内的内存支持映射。设置了稀疏标志的取消映射请求必须与先前映射的稀疏映射的范围完全匹配。

虽然内核通常允许映射和取消映射内存支持映射的任意序列和范围,无论是在单个还是多个 VM_BIND ioctl 调用中,但对于稀疏映射有一些限制。

内核不允许
  • 取消映射不存在的稀疏映射

  • 在同一个 VM_BIND ioctl 中取消映射一个稀疏映射并映射一个新的与先前取消映射的稀疏映射范围重叠的稀疏映射

  • 在同一个 VM_BIND ioctl 中取消映射一个稀疏映射并映射新的与先前取消映射的稀疏映射范围重叠的内存支持映射

当使用 VM_BIND ioctl 请求内核将内存映射到 GPU 的 VA 空间中的给定虚拟地址时,不能保证实际映射是在 GPU 的 MMU 中创建的。如果在执行绑定操作时给定的内存被换出,内核会将映射详细信息存储到其内部分配器中,并在内存被换回时创建实际的 MMU 映射。虽然这对用户空间是透明的,但可以保证一旦调用 DRM_NOUVEAU_EXEC ioctl 提交 exec 作业,所有后备内存都将被换回,并且所有先前由用户空间请求的内存映射都将被实际映射。

VM_BIND 作业可以同步或异步执行。如果异步执行,用户空间可以提供此作业将等待的同步对象列表,和/或内核在 VM_BIND 作业完成执行后将发出信号的同步对象列表。如果同步执行,ioctl 将阻塞直到绑定作业完成。对于同步作业,内核不允许提交任何同步对象。

要执行推送缓冲区,UAPI 提供了 DRM_NOUVEAU_EXEC ioctl。EXEC 作业始终异步执行,并且与 VM_BIND 作业一样,提供使用同步对象同步它们的选项。

除此之外,EXEC 作业可以安排在指定的通道上执行。

由于 VM_BIND 作业在作业提交时更新 GPU 的 VA 空间,因此 EXEC 作业具有 VA 空间的最新视图。但是,实际映射可能仍在挂起。因此,EXEC 作业需要附加其所依赖的相应 VM_BIND 作业的特定 fence。

struct drm_nouveau_sync

同步对象

定义:

struct drm_nouveau_sync {
    __u32 flags;
#define DRM_NOUVEAU_SYNC_SYNCOBJ 0x0;
#define DRM_NOUVEAU_SYNC_TIMELINE_SYNCOBJ 0x1;
#define DRM_NOUVEAU_SYNC_TYPE_MASK 0xf;
    __u32 handle;
    __u64 timeline_value;
};

成员

flags

同步对象的标志

前 8 位用于确定同步对象的类型。

handle

同步对象的句柄

时间线值

如果同步对象类型为 DRM_NOUVEAU_SYNC_TIMELINE_SYNCOBJ,则为同步对象的时间线点。

描述

此结构用作(可能)异步操作(如 EXEC 或 VM_BIND)的同步机制。

struct drm_nouveau_vm_init

GPU VA 空间初始化结构

定义:

struct drm_nouveau_vm_init {
    __u64 kernel_managed_addr;
    __u64 kernel_managed_size;
};

成员

kernel_managed_addr

内核管理的 VA 空间区域的起始地址

kernel_managed_size

内核管理的 VA 空间区域的大小(以字节为单位)

描述

用于为用户客户端初始化 GPU 的 VA 空间,告知内核 VA 空间的哪个部分分别由 UMD 和内核管理。

为了使 UMD 使用 VM_BIND uAPI,必须在创建任何 BO 或通道之前调用此函数;如果之后调用,则 DRM_IOCTL_NOUVEAU_VM_INIT 将失败,并返回 -ENOSYS。

struct drm_nouveau_vm_bind_op

VM_BIND 操作

定义:

struct drm_nouveau_vm_bind_op {
    __u32 op;
#define DRM_NOUVEAU_VM_BIND_OP_MAP 0x0;
#define DRM_NOUVEAU_VM_BIND_OP_UNMAP 0x1;
    __u32 flags;
#define DRM_NOUVEAU_VM_BIND_SPARSE (1 << 8);
    __u32 handle;
    __u32 pad;
    __u64 addr;
    __u64 bo_offset;
    __u64 range;
};

成员

op

操作类型

支持的值

DRM_NOUVEAU_VM_BIND_OP_MAP - 将 GEM 对象映射到 GPU 的 VA 空间。可选地,可以传递 DRM_NOUVEAU_VM_BIND_SPARSE 标志,以指示内核为给定范围创建稀疏映射。

DRM_NOUVEAU_VM_BIND_OP_UNMAP - 取消映射 GPU 的 VA 空间中的现有映射。如果映射所在的区域是稀疏区域,则在先前映射的取消映射(内存支持)映射的位置创建新的稀疏映射。要删除稀疏区域,必须设置 DRM_NOUVEAU_VM_BIND_SPARSE

flags

drm_nouveau_vm_bind_op 的标志

支持的值

DRM_NOUVEAU_VM_BIND_SPARSE - 表示分配的 VA 空间区域应该是稀疏的。

handle

要映射的 DRM GEM 对象的句柄

pad

32 位填充,应为 0

addr

VA 空间区域或(内存支持)映射应映射到的地址

bo_offset

映射后备 BO 中的偏移量

range

请求的映射的大小(以字节为单位)

描述

此结构表示单个 VM_BIND 操作。UMD 应通过 struct drm_nouveau_vm_bindop_ptr 字段传递此结构数组。

struct drm_nouveau_vm_bind

用于 DRM_IOCTL_NOUVEAU_VM_BIND 的结构

定义:

struct drm_nouveau_vm_bind {
    __u32 op_count;
    __u32 flags;
#define DRM_NOUVEAU_VM_BIND_RUN_ASYNC 0x1;
    __u32 wait_count;
    __u32 sig_count;
    __u64 wait_ptr;
    __u64 sig_ptr;
    __u64 op_ptr;
};

成员

op_count

drm_nouveau_vm_bind_op 的数量

flags

drm_nouveau_vm_bind ioctl 的标志

支持的值

DRM_NOUVEAU_VM_BIND_RUN_ASYNC - 表示给定的 VM_BIND 操作应由内核异步执行。

如果未提供此标志,则内核将同步执行相关操作,并且不接受任何 drm_nouveau_sync 对象。

wait_count

要等待的 drm_nouveau_syncs 的数量

sig_count

完成时要发出信号的 drm_nouveau_syncs 的数量

wait_ptr

指向要等待的 drm_nouveau_syncs 的指针

sig_ptr

指向完成时要发出信号的 drm_nouveau_syncs 的指针

op_ptr

指向要执行的 drm_nouveau_vm_bind_ops 的指针

struct drm_nouveau_exec_push

EXEC 推送操作

定义:

struct drm_nouveau_exec_push {
    __u64 va;
    __u32 va_len;
    __u32 flags;
#define DRM_NOUVEAU_EXEC_PUSH_NO_PREFETCH 0x1;
};

成员

va

推送缓冲区映射的虚拟地址

va_len

推送缓冲区映射的长度

flags

此推送缓冲区映射的标志

描述

此结构表示单个 EXEC 推送操作。UMD 应通过 struct drm_nouveau_execpush_ptr 字段传递此结构数组。

struct drm_nouveau_exec

用于 DRM_IOCTL_NOUVEAU_EXEC 的结构

定义:

struct drm_nouveau_exec {
    __u32 channel;
    __u32 push_count;
    __u32 wait_count;
    __u32 sig_count;
    __u64 wait_ptr;
    __u64 sig_ptr;
    __u64 push_ptr;
};

成员

channel

要在其中执行推送缓冲区的通道

push_count

drm_nouveau_exec_push 操作的数量

wait_count

要等待的 drm_nouveau_syncs 的数量

sig_count

完成时要发出信号的 drm_nouveau_syncs 的数量

wait_ptr

指向要等待的 drm_nouveau_syncs 的指针

sig_ptr

指向完成时要发出信号的 drm_nouveau_syncs 的指针

push_ptr

指向 drm_nouveau_exec_push 操作的指针

drm/panthor uAPI

简介

本文档介绍了 Panthor IOCTL。

关于传递给 Panthor IOCTL 的数据的一些通用规则

  • 结构必须按 64 位/8 字节对齐。如果对象不是自然对齐的,则必须添加一个填充字段。

  • 字段必须显式地与其自然类型对齐(使用 pad[0..N] 字段)。

  • 驱动程序将检查所有填充字段,以确保它们已清零。

  • 标志可以添加,但不能移除/替换。

  • 新的字段可以添加到主结构体(直接传递给 ioctl 的结构体)。这些字段可以添加到结构体的末尾,或者替换现有的填充字段。任何添加的新字段都必须在传递零值时保持添加这些字段之前存在的行为。

  • 新的字段可以添加到间接对象(主结构体指向的对象),前提是这些对象被传递了一个大小,以反映用户空间驱动程序已知的大小(请参阅 drm_panthor_obj_array::stride 或 drm_panthor_dev_query::size)。

  • 如果内核驱动程序太旧而不知道某些字段,则如果为零,则会忽略这些字段,否则会被拒绝(因此在输出时将为零)。

  • 如果用户空间太旧而不知道某些字段,则在内核驱动程序解析结构体之前,这些字段将被置零(输入)。

  • 每次添加新的标志/字段时,都必须进行驱动程序版本更新,以便用户空间驱动程序不必通过试错来了解支持哪些标志。

  • 结构体不应包含联合体,因为这会破坏此类结构体的可扩展性。

  • IOCTL 不能被移除或替换。新的 IOCTL ID 应放置在 drm_panthor_ioctl_id 枚举的末尾。

暴露给用户空间的 MMIO 区域。

DRM_PANTHOR_USER_MMIO_OFFSET

暴露给用户空间的所有 MMIO 区域的文件偏移量。不要直接使用此值,而应使用 DRM_PANTHOR_USER_<name>_OFFSET 值。传递给 mmap2() 的 pgoffset 是一个无符号长整型,这迫使我们在 32 位和 64 位系统上使用不同的偏移量。

DRM_PANTHOR_USER_FLUSH_ID_MMIO_OFFSET

LATEST_FLUSH_ID 寄存器的文件偏移量。用户空间驱动程序通过 CS 指令控制 GPU 缓存刷新,但刷新减少机制需要一个 flush_id。此 flush_id 可以通过 ioctl 查询,但 Arm 提供了一个隔离良好的寄存器页,其中仅包含此只读寄存器,因此让我们通过静态 mmap 偏移量公开此页,并允许直接映射此 MMIO 区域,以便我们可以避免用户 <-> 内核往返。

IOCTL ID

enum drm_panthor_ioctl_id - IOCTL ID

将新的 ioctl 放在末尾,不要重新排序,不要替换或删除条目。

这些 ID 不应直接使用。请改用 DRM_IOCTL_PANTHOR_xxx 定义。

DRM_IOCTL_PANTHOR

DRM_IOCTL_PANTHOR (__access, __id, __type)

构建 Panthor IOCTL 编号

参数

__access

访问类型。必须为 R、W 或 RW。

__id

DRM_PANTHOR_xxx id 之一。

__type

传递给 IOCTL 的类型的后缀。

描述

不要直接使用此宏,请改用 DRM_IOCTL_PANTHOR_xxx 值。

返回

要从用户空间传递给 ioctl() 的 IOCTL 编号。

IOCTL 参数

struct drm_panthor_obj_array

对象数组。

定义:

struct drm_panthor_obj_array {
    __u32 stride;
    __u32 count;
    __u64 array;
};

成员

stride

对象结构体的步幅。用于版本控制。

count

数组中的对象数量。

array

指向对象数组的用户指针。

描述

此对象用于传递一个对象数组,该数组的大小可能会在驱动程序的未来版本中发生更改。为了支持这种可变性,我们传递一个描述用户空间已知的对象大小的步幅。

您不应该直接填充 drm_panthor_obj_array 字段。您应该改用 DRM_PANTHOR_OBJ_ARRAY() 宏,该宏负责将步幅初始化为对象大小。

DRM_PANTHOR_OBJ_ARRAY

DRM_PANTHOR_OBJ_ARRAY (cnt, ptr)

初始化 drm_panthor_obj_array 字段。

参数

cnt

数组中的元素数量。

ptr

指向要传递给内核的数组的指针。

描述

基于用户空间已知的对象大小初始化 drm_panthor_obj_array 的宏。

enum drm_panthor_sync_op_flags

同步操作标志。

常量

DRM_PANTHOR_SYNC_OP_HANDLE_TYPE_MASK

同步句柄类型掩码。

DRM_PANTHOR_SYNC_OP_HANDLE_TYPE_SYNCOBJ

同步对象类型。

DRM_PANTHOR_SYNC_OP_HANDLE_TYPE_TIMELINE_SYNCOBJ

时间线同步对象类型。

DRM_PANTHOR_SYNC_OP_WAIT

等待操作。

DRM_PANTHOR_SYNC_OP_SIGNAL

信号操作。

struct drm_panthor_sync_op

同步操作。

定义:

struct drm_panthor_sync_op {
    __u32 flags;
    __u32 handle;
    __u64 timeline_value;
};

成员

flags

同步操作标志。DRM_PANTHOR_SYNC_OP 值的组合。

handle

同步句柄。

时间线值

如果 (flags & DRM_PANTHOR_SYNC_OP_HANDLE_TYPE_MASK) != DRM_PANTHOR_SYNC_OP_HANDLE_TYPE_TIMELINE_SYNCOBJ,则为 MBZ。

enum drm_panthor_dev_query_type

查询类型

常量

DRM_PANTHOR_DEV_QUERY_GPU_INFO

查询 GPU 信息。

DRM_PANTHOR_DEV_QUERY_CSIF_INFO

查询命令流接口信息。

DRM_PANTHOR_DEV_QUERY_TIMESTAMP_INFO

查询时间戳信息。

DRM_PANTHOR_DEV_QUERY_GROUP_PRIORITIES_INFO

查询允许的组优先级信息。

描述

将新的类型放在末尾,不要重新排序,不要删除或替换。

struct drm_panthor_gpu_info

GPU 信息

定义:

struct drm_panthor_gpu_info {
    __u32 gpu_id;
#define DRM_PANTHOR_ARCH_MAJOR(x)               ((x) >> 28);
#define DRM_PANTHOR_ARCH_MINOR(x)               (((x) >> 24) & 0xf);
#define DRM_PANTHOR_ARCH_REV(x)                 (((x) >> 20) & 0xf);
#define DRM_PANTHOR_PRODUCT_MAJOR(x)            (((x) >> 16) & 0xf);
#define DRM_PANTHOR_VERSION_MAJOR(x)            (((x) >> 12) & 0xf);
#define DRM_PANTHOR_VERSION_MINOR(x)            (((x) >> 4) & 0xff);
#define DRM_PANTHOR_VERSION_STATUS(x)           ((x) & 0xf);
    __u32 gpu_rev;
    __u32 csf_id;
#define DRM_PANTHOR_CSHW_MAJOR(x)               (((x) >> 26) & 0x3f);
#define DRM_PANTHOR_CSHW_MINOR(x)               (((x) >> 20) & 0x3f);
#define DRM_PANTHOR_CSHW_REV(x)                 (((x) >> 16) & 0xf);
#define DRM_PANTHOR_MCU_MAJOR(x)                (((x) >> 10) & 0x3f);
#define DRM_PANTHOR_MCU_MINOR(x)                (((x) >> 4) & 0x3f);
#define DRM_PANTHOR_MCU_REV(x)                  ((x) & 0xf);
    __u32 l2_features;
    __u32 tiler_features;
    __u32 mem_features;
    __u32 mmu_features;
#define DRM_PANTHOR_MMU_VA_BITS(x)              ((x) & 0xff);
    __u32 thread_features;
    __u32 max_threads;
    __u32 thread_max_workgroup_size;
    __u32 thread_max_barrier_size;
    __u32 coherency_features;
    __u32 texture_features[4];
    __u32 as_present;
    __u64 shader_present;
    __u64 l2_present;
    __u64 tiler_present;
    __u32 core_features;
    __u32 pad;
};

成员

gpu_id

GPU ID。

gpu_rev

GPU 版本。

csf_id

命令流前端 ID。

l2_features

L2 缓存功能。

tiler_features

Tiler 功能。

mem_features

内存功能。

mmu_features

MMU 功能。

thread_features

线程功能。

max_threads

最大线程数。

thread_max_workgroup_size

最大工作组大小。

thread_max_barrier_size

可以在屏障上同时等待的最大线程数。

coherency_features

一致性功能。

texture_features

纹理功能。

as_present

位掩码,编码 MMU 暴露的地址空间数量。

shader_present

位掩码,编码 GPU 暴露的着色器核心。

l2_present

位掩码,编码 GPU 暴露的 L2 缓存。

tiler_present

位掩码,编码 GPU 暴露的 Tiler 单元。

core_features

用于区分核心变体(如果存在)。

pad

MBZ。

描述

将与 GPU 相关的所有可查询信息分组的结构体。

struct drm_panthor_csif_info

命令流接口信息

定义:

struct drm_panthor_csif_info {
    __u32 csg_slot_count;
    __u32 cs_slot_count;
    __u32 cs_reg_count;
    __u32 scoreboard_slot_count;
    __u32 unpreserved_cs_reg_count;
    __u32 pad;
};

成员

csg_slot_count

固件暴露的命令流组槽数量。

cs_slot_count

每组的命令流槽数量。

cs_reg_count

命令流寄存器的数量。

scoreboard_slot_count

记分牌槽的数量。

unpreserved_cs_reg_count

内核驱动程序保留用于调用用户空间命令流的命令流寄存器的数量。

所有寄存器都可以被用户空间命令流使用,但当调用 DRM_PANTHOR_IOCTL_GROUP_SUBMIT 时,内核会使用 [cs_slot_count - unpreserved_cs_reg_count .. cs_slot_count] 寄存器。

pad

填充字段,设置为零。

描述

将与命令流接口相关的所有可查询信息分组的结构体。

struct drm_panthor_timestamp_info

时间戳信息

定义:

struct drm_panthor_timestamp_info {
    __u64 timestamp_frequency;
    __u64 current_timestamp;
    __u64 timestamp_offset;
};

成员

timestamp_frequency

时间戳计时器的频率,如果未知则为 0。

current_timestamp

当前时间戳。

timestamp_offset

时间戳计时器的偏移量。

描述

将与 GPU 时间戳相关的所有可查询信息分组的结构体。

struct drm_panthor_group_priorities_info

组优先级信息

定义:

struct drm_panthor_group_priorities_info {
    __u8 allowed_mask;
    __u8 pad[3];
};

成员

allowed_mask

允许的组优先级的位掩码。

每个位表示 enum drm_panthor_group_priority 的一个变体。

pad

填充字段,MBZ。

描述

将与允许的组优先级相关的所有可查询信息分组的结构体。

struct drm_panthor_dev_query

传递给 DRM_PANTHOR_IOCTL_DEV_QUERY 的参数

定义:

struct drm_panthor_dev_query {
    __u32 type;
    __u32 size;
    __u64 pointer;
};

成员

type

查询类型(请参阅 drm_panthor_dev_query_type)。

size

被查询的类型的大小。

如果指针为 NULL,则驱动程序会更新大小以提供输出结构大小。如果指针不为 NULL,则驱动程序只会将 min(size, actual_structure_size) 字节复制到指针,并相应地更新大小。这允许我们在不破坏用户空间的情况下扩展查询类型。

pointer

指向查询类型结构体的用户指针。

指针可以为 NULL,在这种情况下,不会复制任何内容,但会返回实际的结构大小。如果不是 NULL,则它必须指向一个足够大的位置,以容纳大小字节。

struct drm_panthor_vm_create

传递给 DRM_PANTHOR_IOCTL_VM_CREATE 的参数

定义:

struct drm_panthor_vm_create {
    __u32 flags;
    __u32 id;
    __u64 user_va_range;
};

成员

flags

VM 标志,MBZ。

id

返回的 VM ID。

user_va_range

为用户对象保留的 VA 空间大小。

内核将选择剩余空间来映射仅限内核使用的对象到虚拟机(堆块、堆上下文、环形缓冲区、内核同步对象等)。如果留给内核对象的空间太小,内核对象的分配将在后续过程中失败。可以使用 drm_panthor_gpu_info::mmu_features 来提取总的虚拟地址范围,并选择一个 user_va_range,为内核留出一些空间。

如果 user_va_range 为零,内核将根据 TASK_SIZE 和 GPU MMU 支持的虚拟范围选择一个合理的值(内核/用户空间分割应为用户空间进程留下足够的 VA 空间来支持 SVM,同时仍然允许内核在内核 VA 范围内映射一些内核对象)。驱动程序选择的值将返回在 user_va_range 中。

用户 VA 空间始终从 0x0 开始,内核 VA 空间始终位于用户 VA 范围之后。

struct drm_panthor_vm_destroy

传递给 DRM_PANTHOR_IOCTL_VM_DESTROY 的参数

定义:

struct drm_panthor_vm_destroy {
    __u32 id;
    __u32 pad;
};

成员

id

要销毁的虚拟机的 ID。

pad

MBZ。

enum drm_panthor_vm_bind_op_flags

虚拟机绑定操作标志

常量

DRM_PANTHOR_VM_BIND_OP_MAP_READONLY

以只读方式映射内存。

仅对 DRM_PANTHOR_VM_BIND_OP_TYPE_MAP 有效。

DRM_PANTHOR_VM_BIND_OP_MAP_NOEXEC

将内存映射为不可执行。

仅对 DRM_PANTHOR_VM_BIND_OP_TYPE_MAP 有效。

DRM_PANTHOR_VM_BIND_OP_MAP_UNCACHED

将内存映射为不缓存。

仅对 DRM_PANTHOR_VM_BIND_OP_TYPE_MAP 有效。

DRM_PANTHOR_VM_BIND_OP_TYPE_MASK

用于确定操作类型的掩码。

DRM_PANTHOR_VM_BIND_OP_TYPE_MAP

映射操作。

DRM_PANTHOR_VM_BIND_OP_TYPE_UNMAP

取消映射操作。

DRM_PANTHOR_VM_BIND_OP_TYPE_SYNC_ONLY

无虚拟机操作。

仅作为虚拟机队列上的同步点。

仅当在 drm_panthor_vm_bind::flags 中设置了 DRM_PANTHOR_VM_BIND_ASYNC 并且 drm_panthor_vm_bind_op::syncs 至少包含一个元素时有效。

struct drm_panthor_vm_bind_op

虚拟机绑定操作

定义:

struct drm_panthor_vm_bind_op {
    __u32 flags;
    __u32 bo_handle;
    __u64 bo_offset;
    __u64 va;
    __u64 size;
    struct drm_panthor_obj_array syncs;
};

成员

flags

drm_panthor_vm_bind_op_flags 标志的组合。

bo_handle

要映射的缓冲区对象的句柄。对于取消映射或仅同步操作,MBZ。

bo_offset

缓冲区对象偏移量。对于取消映射或仅同步操作,MBZ。

va

要映射/取消映射的虚拟地址。对于仅同步操作,MBZ。

size

要映射/取消映射的大小。对于仅同步操作,MBZ。

syncs

struct drm_panthor_sync_op 同步操作的数组。

如果包含此虚拟机绑定操作的 drm_panthor_vm_bind 对象上未设置 DRM_PANTHOR_VM_BIND_ASYNC,则此数组必须为空。

对于仅同步操作,此数组不得为空。

enum drm_panthor_vm_bind_flags

虚拟机绑定标志

常量

DRM_PANTHOR_VM_BIND_ASYNC

虚拟机绑定操作被排队到虚拟机队列,而不是同步执行。

struct drm_panthor_vm_bind

传递给 DRM_IOCTL_PANTHOR_VM_BIND 的参数

定义:

struct drm_panthor_vm_bind {
    __u32 vm_id;
    __u32 flags;
    struct drm_panthor_obj_array ops;
};

成员

vm_id

绑定请求的目标虚拟机。

flags

drm_panthor_vm_bind_flags 标志的组合。

ops

struct drm_panthor_vm_bind_op 绑定操作的数组。

enum drm_panthor_vm_state

虚拟机状态。

常量

DRM_PANTHOR_VM_STATE_USABLE

虚拟机可用。

将接受此虚拟机上的新虚拟机操作。

DRM_PANTHOR_VM_STATE_UNUSABLE

虚拟机不可用。

某些原因导致虚拟机处于不可用状态(例如,任何原因导致的异步 VM_BIND 请求失败)。

一旦虚拟机处于此状态,所有新的 MAP 操作都将被拒绝,并且任何针对此虚拟机的 GPU 作业都将失败。仍然接受 UNMAP 操作。

从不可用的虚拟机恢复的唯一方法是创建一个新的虚拟机,并销毁旧的虚拟机。

struct drm_panthor_vm_get_state

获取虚拟机状态。

定义:

struct drm_panthor_vm_get_state {
    __u32 vm_id;
    __u32 state;
};

成员

vm_id

get_state 请求的目标虚拟机。

state

驱动程序返回的状态。

必须是 enum drm_panthor_vm_state 值之一。

enum drm_panthor_bo_flags

缓冲区对象标志,在创建时传递。

常量

DRM_PANTHOR_BO_NO_MMAP

缓冲区对象将永远不会在用户空间中进行 CPU 映射。

struct drm_panthor_bo_create

传递给 DRM_IOCTL_PANTHOR_BO_CREATE 的参数。

定义:

struct drm_panthor_bo_create {
    __u64 size;
    __u32 flags;
    __u32 exclusive_vm_id;
    __u32 handle;
    __u32 pad;
};

成员

size

请求的对象的尺寸

将返回对象(按页对齐)的分配大小。

flags

标志。必须是 drm_panthor_bo_flags 标志的组合。

exclusive_vm_id

此缓冲区对象将映射到的独占虚拟机。

如果非零,则该字段必须引用有效的虚拟机 ID,并且表示
  • 该缓冲区对象将始终仅绑定到该虚拟机

  • 不能导出为 PRIME fd

handle

返回对象的句柄。

对象句柄为非零。

pad

MBZ。

struct drm_panthor_bo_mmap_offset

传递给 DRM_IOCTL_PANTHOR_BO_MMAP_OFFSET 的参数。

定义:

struct drm_panthor_bo_mmap_offset {
    __u32 handle;
    __u32 pad;
    __u64 offset;
};

成员

handle

我们想要 mmap 偏移量的对象的句柄。

pad

MBZ。

offset

用于后续 mmap 调用的假偏移量。

struct drm_panthor_queue_create

队列创建参数。

定义:

struct drm_panthor_queue_create {
    __u8 priority;
    __u8 pad[3];
    __u32 ringbuf_size;
};

成员

priority

定义组内队列的优先级。范围从 0 到 15,15 为最高优先级。

pad

填充字段,MBZ。

ringbuf_size

要为此队列分配的环形缓冲区的大小。

enum drm_panthor_group_priority

调度组优先级

常量

PANTHOR_GROUP_PRIORITY_LOW

低优先级组。

PANTHOR_GROUP_PRIORITY_MEDIUM

中优先级组。

PANTHOR_GROUP_PRIORITY_HIGH

高优先级组。

需要 CAP_SYS_NICE 或 DRM_MASTER。

PANTHOR_GROUP_PRIORITY_REALTIME

实时优先级组。

需要 CAP_SYS_NICE 或 DRM_MASTER。

struct drm_panthor_group_create

传递给 DRM_IOCTL_PANTHOR_GROUP_CREATE 的参数

定义:

struct drm_panthor_group_create {
    struct drm_panthor_obj_array queues;
    __u8 max_compute_cores;
    __u8 max_fragment_cores;
    __u8 max_tiler_cores;
    __u8 priority;
    __u32 pad;
    __u64 compute_core_mask;
    __u64 fragment_core_mask;
    __u64 tiler_core_mask;
    __u32 vm_id;
    __u32 group_handle;
};

成员

queues

drm_panthor_queue_create 元素的数组。

max_compute_cores

绑定到此组的 CS 队列中的计算作业可以使用的最大核心数。

必须小于或等于 compute_core_mask 中设置的位数。

max_fragment_cores

绑定到此组的 CS 队列中的片段作业可以使用的最大核心数。

必须小于或等于 fragment_core_mask 中设置的位数。

max_tiler_cores

绑定到此组的 CS 队列中的分块器作业可以使用的最大分块器数量。

必须小于或等于 tiler_core_mask 中设置的位数。

priority

组优先级(请参阅 enum drm_panthor_group_priority)。

pad

填充字段,MBZ。

compute_core_mask

用于编码可用于计算作业的核心的掩码。

此字段必须至少设置 max_compute_cores 位。

此处设置的位也应在 drm_panthor_gpu_info::shader_present 中设置。

fragment_core_mask

用于编码可用于片段作业的核心的掩码。

此字段必须至少设置 max_fragment_cores 位。

此处设置的位也应在 drm_panthor_gpu_info::shader_present 中设置。

tiler_core_mask

用于编码可用于分块器作业的核心的掩码。

此字段必须至少设置 max_tiler_cores 位。

此处设置的位也应在 drm_panthor_gpu_info::tiler_present 中设置。

vm_id

要将此组绑定到的虚拟机 ID。

提交到绑定到此组的队列的所有操作都将使用此虚拟机。

group_handle

返回的组句柄。在提交作业或销毁组时传回。

struct drm_panthor_group_destroy

传递给 DRM_IOCTL_PANTHOR_GROUP_DESTROY 的参数

定义:

struct drm_panthor_group_destroy {
    __u32 group_handle;
    __u32 pad;
};

成员

group_handle

要销毁的组

pad

填充字段,MBZ。

struct drm_panthor_queue_submit

作业提交参数。

定义:

struct drm_panthor_queue_submit {
    __u32 queue_index;
    __u32 stream_size;
    __u64 stream_addr;
    __u32 latest_flush;
    __u32 pad;
    struct drm_panthor_obj_array syncs;
};

成员

queue_index

组内队列的索引。

stream_size

要执行的命令流的大小。

必须是 64 位/8 字节对齐(CS 指令的大小)

如果 stream_addr 也为零,则可以为零。

当流大小为零时,队列提交充当同步点。

stream_addr

要执行的命令流的 GPU 地址。

必须在 64 字节上对齐。

如果 stream_size 也为零,则可以为零。

latest_flush

构建流时读取的 FLUSH_ID。

这允许在提交时为自动刷新+使失效(全部)消除缓存刷新,这是必要的,以确保 GPU 在读取间接命令流缓冲区时不会得到垃圾。如果希望无条件地进行缓存刷新,请在此处传递零。

当 stream_size 为零时忽略。

pad

MBZ。

syncs

struct drm_panthor_sync_op 同步操作的数组。

描述

这描述了从内核命令流环形缓冲区调用的用户空间命令流。队列提交始终是组提交的一部分,将一个或多个作业提交到底层队列。

struct drm_panthor_group_submit

传递给 DRM_IOCTL_PANTHOR_GROUP_SUBMIT 的参数

定义:

struct drm_panthor_group_submit {
    __u32 group_handle;
    __u32 pad;
    struct drm_panthor_obj_array queue_submits;
};

成员

group_handle

用于将作业加入队列的组的句柄。

pad

MBZ。

queue_submits

drm_panthor_queue_submit 对象的数组。

enum drm_panthor_group_state_flags

组状态标志

常量

DRM_PANTHOR_GROUP_STATE_TIMEDOUT

组有未完成的作业。

当组设置了此标志时,无法向其队列提交作业。

DRM_PANTHOR_GROUP_STATE_FATAL_FAULT

组发生了致命错误。

当组设置了此标志时,无法向其队列提交作业。

struct drm_panthor_group_get_state

传递给 DRM_IOCTL_PANTHOR_GROUP_GET_STATE 的参数

定义:

struct drm_panthor_group_get_state {
    __u32 group_handle;
    __u32 state;
    __u32 fatal_queues;
    __u32 pad;
};

成员

group_handle

要查询状态的组的句柄

state

DRM_PANTHOR_GROUP_STATE_* 标志的组合,用于编码组状态。

fatal_queues

发生致命错误的队列的位掩码。

pad

MBZ

描述

用于查询组的状态,并决定是否应创建新组来替换它。

struct drm_panthor_tiler_heap_create

传递给 DRM_IOCTL_PANTHOR_TILER_HEAP_CREATE 的参数

定义:

struct drm_panthor_tiler_heap_create {
    __u32 vm_id;
    __u32 initial_chunk_count;
    __u32 chunk_size;
    __u32 max_chunks;
    __u32 target_in_flight;
    __u32 handle;
    __u64 tiler_heap_ctx_gpu_va;
    __u64 first_heap_chunk_gpu_va;
};

成员

vm_id

tiler 堆应映射到的 VM ID

initial_chunk_count

要分配的初始块数。必须至少为一。

chunk_size

块大小。

必须按页面对齐,并且位于 [128k:8M] 范围内。

max_chunks

可以分配的最大块数。

必须至少为 initial_chunk_count

target_in_flight

正在进行的渲染通道的最大数量。

如果堆中有超过正在进行的 tiler 作业,FW 将等待渲染通道完成,然后再将新的 tiler 作业加入队列。

handle

返回的堆句柄。传递回 DESTROY_TILER_HEAP。

tiler_heap_ctx_gpu_va

返回的堆 GPU 虚拟地址

first_heap_chunk_gpu_va

第一个堆块。

tiler 堆由形成单链表的堆块组成。这是列表中的第一个元素。

struct drm_panthor_tiler_heap_destroy

传递给 DRM_IOCTL_PANTHOR_TILER_HEAP_DESTROY 的参数

定义:

struct drm_panthor_tiler_heap_destroy {
    __u32 handle;
    __u32 pad;
};

成员

handle

要销毁的 tiler 堆的句柄。

必须是由 DRM_IOCTL_PANTHOR_TILER_HEAP_CREATE 返回的有效堆句柄。

pad

填充字段,MBZ。

drm/xe uAPI

Xe 设备框图

下图表示 Xe 驱动程序支持的离散 GPU 的高级简化图。它显示了一些理解此 API 所必需的设备组件,以及它们之间的关系。此图不代表真实的硬件

┌──────────────────────────────────────────────────────────────────┐
│ ┌──────────────────────────────────────────────────┐ ┌─────────┐ │
│ │        ┌───────────────────────┐   ┌─────┐       │ │ ┌─────┐ │ │
│ │        │         VRAM0         ├───┤ ... │       │ │ │VRAM1│ │ │
│ │        └───────────┬───────────┘   └─GT1─┘       │ │ └──┬──┘ │ │
│ │ ┌──────────────────┴───────────────────────────┐ │ │ ┌──┴──┐ │ │
│ │ │ ┌─────────────────────┐  ┌─────────────────┐ │ │ │ │     │ │ │
│ │ │ │ ┌──┐ ┌──┐ ┌──┐ ┌──┐ │  │ ┌─────┐ ┌─────┐ │ │ │ │ │     │ │ │
│ │ │ │ │EU│ │EU│ │EU│ │EU│ │  │ │RCS0 │ │BCS0 │ │ │ │ │ │     │ │ │
│ │ │ │ └──┘ └──┘ └──┘ └──┘ │  │ └─────┘ └─────┘ │ │ │ │ │     │ │ │
│ │ │ │ ┌──┐ ┌──┐ ┌──┐ ┌──┐ │  │ ┌─────┐ ┌─────┐ │ │ │ │ │     │ │ │
│ │ │ │ │EU│ │EU│ │EU│ │EU│ │  │ │VCS0 │ │VCS1 │ │ │ │ │ │     │ │ │
│ │ │ │ └──┘ └──┘ └──┘ └──┘ │  │ └─────┘ └─────┘ │ │ │ │ │     │ │ │
│ │ │ │ ┌──┐ ┌──┐ ┌──┐ ┌──┐ │  │ ┌─────┐ ┌─────┐ │ │ │ │ │     │ │ │
│ │ │ │ │EU│ │EU│ │EU│ │EU│ │  │ │VECS0│ │VECS1│ │ │ │ │ │ ... │ │ │
│ │ │ │ └──┘ └──┘ └──┘ └──┘ │  │ └─────┘ └─────┘ │ │ │ │ │     │ │ │
│ │ │ │ ┌──┐ ┌──┐ ┌──┐ ┌──┐ │  │ ┌─────┐ ┌─────┐ │ │ │ │ │     │ │ │
│ │ │ │ │EU│ │EU│ │EU│ │EU│ │  │ │CCS0 │ │CCS1 │ │ │ │ │ │     │ │ │
│ │ │ │ └──┘ └──┘ └──┘ └──┘ │  │ └─────┘ └─────┘ │ │ │ │ │     │ │ │
│ │ │ └─────────DSS─────────┘  │ ┌─────┐ ┌─────┐ │ │ │ │ │     │ │ │
│ │ │                          │ │CCS2 │ │CCS3 │ │ │ │ │ │     │ │ │
│ │ │ ┌─────┐ ┌─────┐ ┌─────┐  │ └─────┘ └─────┘ │ │ │ │ │     │ │ │
│ │ │ │ ... │ │ ... │ │ ... │  │                 │ │ │ │ │     │ │ │
│ │ │ └─DSS─┘ └─DSS─┘ └─DSS─┘  └─────Engines─────┘ │ │ │ │     │ │ │
│ │ └───────────────────────────GT0────────────────┘ │ │ └─GT2─┘ │ │
│ └────────────────────────────Tile0─────────────────┘ └─ Tile1──┘ │
└─────────────────────────────Device0───────┬──────────────────────┘
                                            │
                     ───────────────────────┴────────── PCI bus

Xe uAPI 概述

本节旨在描述 Xe 的 IOCTL 条目、其结构以及其他与 Xe 相关的 uAPI,例如 uevent 和 PMU(平台监控单元)相关的条目和用法。

支持的 IOCTL 列表
  • DRM_IOCTL_XE_DEVICE_QUERY

  • DRM_IOCTL_XE_GEM_CREATE

  • DRM_IOCTL_XE_GEM_MMAP_OFFSET

  • DRM_IOCTL_XE_VM_CREATE

  • DRM_IOCTL_XE_VM_DESTROY

  • DRM_IOCTL_XE_VM_BIND

  • DRM_IOCTL_XE_EXEC_QUEUE_CREATE

  • DRM_IOCTL_XE_EXEC_QUEUE_DESTROY

  • DRM_IOCTL_XE_EXEC_QUEUE_GET_PROPERTY

  • DRM_IOCTL_XE_EXEC

  • DRM_IOCTL_XE_WAIT_USER_FENCE

  • DRM_IOCTL_XE_OBSERVATION

Xe IOCTL 扩展

在详细介绍 IOCTL 及其结构之前,重要的是要强调 Xe 中的每个 IOCTL 都是可扩展的。

许多接口需要随着时间的推移而增长。在大多数情况下,我们可以简单地扩展结构,让用户空间传入更多数据。另一种选择,如 Vulkan 为提供向前和向后兼容性的扩展方法所演示的那样,是使用可选结构的列表来提供这些额外的细节。

使用扩展链的关键优势在于,它允许我们比不断增长的复杂结构更容易地重新定义接口,并且该接口的很大一部分完全是可选的。缺点是指针追踪更多;在 u64 中封装的指针,跨 __user 边界追踪。

示例链接

struct drm_xe_user_extension ext3 {
        .next_extension = 0, // end
        .name = ...,
};
struct drm_xe_user_extension ext2 {
        .next_extension = (uintptr_t)&ext3,
        .name = ...,
};
struct drm_xe_user_extension ext1 {
        .next_extension = (uintptr_t)&ext2,
        .name = ...,
};

通常,struct drm_xe_user_extension 会嵌入到某些 uAPI 结构中,在这种情况下,我们将向其提供链的头部(即 ext1),然后它将应用以上所有扩展。

struct drm_xe_user_extension

定义扩展链的基类

定义:

struct drm_xe_user_extension {
    __u64 next_extension;
    __u32 name;
    __u32 pad;
};

成员

next_extension

指向下一个 struct drm_xe_user_extension 的指针,如果结束则为零。

name

扩展的名称。

请注意,此处的名称只是一个整数。

另请注意,此命名空间对于整个驱动程序不是全局的,而是其范围/含义仅限于嵌入了 struct drm_xe_user_extension 的特定 uAPI 部分。

pad

MBZ

所有未定义的位必须为零。

struct drm_xe_ext_set_property

通用设置属性扩展

定义:

struct drm_xe_ext_set_property {
    struct drm_xe_user_extension base;
    __u32 property;
    __u32 pad;
    __u64 value;
    __u64 reserved[2];
};

成员

base

基本用户扩展

property

要设置的属性

pad

MBZ

value

属性值

reserved

保留

描述

一个通用结构,允许使用 set_property 操作扩展 Xe 的任何 IOCTL。

struct drm_xe_engine_class_instance

引擎类实例

定义:

struct drm_xe_engine_class_instance {
#define DRM_XE_ENGINE_CLASS_RENDER              0;
#define DRM_XE_ENGINE_CLASS_COPY                1;
#define DRM_XE_ENGINE_CLASS_VIDEO_DECODE        2;
#define DRM_XE_ENGINE_CLASS_VIDEO_ENHANCE       3;
#define DRM_XE_ENGINE_CLASS_COMPUTE             4;
#define DRM_XE_ENGINE_CLASS_VM_BIND             5;
    __u16 engine_class;
    __u16 engine_instance;
    __u16 gt_id;
    __u16 pad;
};

成员

engine_class

引擎类 ID

engine_instance

引擎实例 ID

gt_id

此 GT 在 PCI 设备中的唯一 ID

pad

MBZ

描述

它作为 drm_xe_engine 的一部分返回,但也用作 drm_xe_exec_queue_createdrm_xe_query_engine_cycles 的引擎选择的输入

engine_class 可以是
  • DRM_XE_ENGINE_CLASS_RENDER

  • DRM_XE_ENGINE_CLASS_COPY

  • DRM_XE_ENGINE_CLASS_VIDEO_DECODE

  • DRM_XE_ENGINE_CLASS_VIDEO_ENHANCE

  • DRM_XE_ENGINE_CLASS_COMPUTE

  • DRM_XE_ENGINE_CLASS_VM_BIND - 仅内核类(不是实际的硬件引擎类)。用于创建 VM 绑定操作的有序队列。

struct drm_xe_engine

描述硬件引擎

定义:

struct drm_xe_engine {
    struct drm_xe_engine_class_instance instance;
    __u64 reserved[3];
};

成员

instance

drm_xe_engine_class_instance

reserved

保留

struct drm_xe_query_engines

描述引擎

定义:

struct drm_xe_query_engines {
    __u32 num_engines;
    __u32 pad;
    struct drm_xe_engine engines[];
};

成员

num_engines

engines 中返回的引擎数

pad

MBZ

引擎

此设备返回的引擎

描述

如果使用结构体 drm_xe_device_query 进行查询,其中 .query 等于 DRM_XE_DEVICE_QUERY_ENGINES,则回复在 .data 中使用结构体 drm_xe_query_engines 的数组。

enum drm_xe_memory_class

支持的内存类。

常量

DRM_XE_MEM_REGION_CLASS_SYSMEM

表示系统内存。

DRM_XE_MEM_REGION_CLASS_VRAM

在离散平台上,这表示设备本地的内存,我们称之为 VRAM。在集成平台上无效。

struct drm_xe_mem_region

描述驱动程序已知的某个区域。

定义:

struct drm_xe_mem_region {
    __u16 mem_class;
    __u16 instance;
    __u32 min_page_size;
    __u64 total_size;
    __u64 used;
    __u64 cpu_visible_size;
    __u64 cpu_visible_used;
    __u64 reserved[6];
};

成员

mem_class

描述此区域的内存类。

有关支持的值,请参阅 enum drm_xe_memory_class

instance

此区域的唯一 ID,用作 DRM_IOCTL_XE_GEM_CREATE 的参数使用的位置位掩码中的索引

min_page_size

此区域的最小页大小(以字节为单位)。

当内核为此区域分配内存时,基础页的大小将至少为 min_page_size。在此区域中允许放置的缓冲区对象必须创建为与此值对齐的大小。也可能放置在此区域中的缓冲区对象(部分)的 GPU 虚拟地址映射必须使其 GPU 虚拟地址和范围与此值对齐。如果未满足对齐限制,受影响的 IOCTL 将返回 -EINVAL

total_size

此区域的可用大小(以字节为单位)。

used

此区域中使用的内存的估计值(以字节为单位)。

需要 CAP_PERFMON 或 CAP_SYS_ADMIN 才能获得可靠的记帐。如果没有此权限,此处的该值将始终等于零。

cpu_visible_size

此区域中 CPU 可以访问的量(以字节为单位)。

这始终 <= total_size,其余部分(如果有)CPU 将无法访问。如果 CPU 可访问的部分小于 total_size,则称为小 BAR 系统。

在没有小 BAR(完整 BAR)的系统上,probed_size 将始终等于 total_size,因为所有这些都将是 CPU 可访问的。

请注意,这仅针对 DRM_XE_MEM_REGION_CLASS_VRAM 区域进行跟踪(对于其他类型,此处的值将始终等于零)。

cpu_visible_used

CPU 可见内存使用量的估计值(以字节为单位)。

需要 CAP_PERFMON 或 CAP_SYS_ADMIN 才能获得可靠的记帐。如果没有此权限,此处的该值将始终等于零。请注意,这目前仅针对 DRM_XE_MEM_REGION_CLASS_VRAM 区域进行跟踪(对于其他类型,此处的值将始终为零)。

reserved

保留

struct drm_xe_query_mem_regions

描述内存区域

定义:

struct drm_xe_query_mem_regions {
    __u32 num_mem_regions;
    __u32 pad;
    struct drm_xe_mem_region mem_regions[];
};

成员

num_mem_regions

mem_regions 中返回的内存区域的数量

pad

MBZ

mem_regions

此设备返回的内存区域

描述

如果使用 struct drm_xe_device_query 进行查询,其中 .query 等于 DRM_XE_DEVICE_QUERY_MEM_REGIONS,则回复在 .data 中使用 struct drm_xe_query_mem_regions

struct drm_xe_query_config

描述设备配置

定义:

struct drm_xe_query_config {
    __u32 num_params;
    __u32 pad;
#define DRM_XE_QUERY_CONFIG_REV_AND_DEVICE_ID   0;
#define DRM_XE_QUERY_CONFIG_FLAGS                       1;
#define DRM_XE_QUERY_CONFIG_FLAG_HAS_VRAM       (1 << 0);
#define DRM_XE_QUERY_CONFIG_MIN_ALIGNMENT               2;
#define DRM_XE_QUERY_CONFIG_VA_BITS                     3;
#define DRM_XE_QUERY_CONFIG_MAX_EXEC_QUEUE_PRIORITY     4;
    __u64 info[];
};

成员

num_params

在 info 中返回的参数的数量

pad

MBZ

info

包含配置信息的元素数组

描述

如果使用 struct drm_xe_device_query 进行查询,其中 .query 等于 DRM_XE_DEVICE_QUERY_CONFIG,则回复在 .data 中使用 struct drm_xe_query_config

info 中的索引可以是
  • DRM_XE_QUERY_CONFIG_REV_AND_DEVICE_ID - 设备 ID(低 16 位)和设备修订(接下来的 8 位)

  • DRM_XE_QUERY_CONFIG_FLAGS - 描述设备配置的标志,请参阅下面的列表

    • DRM_XE_QUERY_CONFIG_FLAG_HAS_VRAM - 如果设备具有可用的 VRAM,则设置该标志

  • DRM_XE_QUERY_CONFIG_MIN_ALIGNMENT - 此设备所需的最小内存对齐方式,通常为 SZ_4K 或 SZ_64K

  • DRM_XE_QUERY_CONFIG_VA_BITS - 虚拟地址的最大位数

  • DRM_XE_QUERY_CONFIG_MAX_EXEC_QUEUE_PRIORITY - 最高可用执行队列优先级的数值

struct drm_xe_gt

描述一个独立的 GT。

定义:

struct drm_xe_gt {
#define DRM_XE_QUERY_GT_TYPE_MAIN               0;
#define DRM_XE_QUERY_GT_TYPE_MEDIA              1;
    __u16 type;
    __u16 tile_id;
    __u16 gt_id;
    __u16 pad[3];
    __u32 reference_clock;
    __u64 near_mem_regions;
    __u64 far_mem_regions;
    __u16 ip_ver_major;
    __u16 ip_ver_minor;
    __u16 ip_ver_rev;
    __u16 pad2;
    __u64 reserved[7];
};

成员

type

GT 类型:主 GT 或媒体 GT

tile_id

此 GT 所在的 Tile ID(仅供参考)

gt_id

此 GT 在 PCI 设备中的唯一 ID

pad

MBZ

reference_clock

用于时间戳的时钟频率

near_mem_regions

来自 drm_xe_query_mem_regions 的实例的位掩码,这些实例最靠近此 GT 的当前引擎。此掩码中的每个索引都直接引用 struct drm_xe_query_mem_regions 的实例,不应对顺序做任何假设。每个区域的类型由 struct drm_xe_query_mem_regions 的 mem_class 描述。

far_mem_regions

来自 drm_xe_query_mem_regions 的实例的位掩码,这些实例远离此 GT 的引擎。通常,与 near_mem_regions 相比,它们具有额外的间接寻址。对于离散设备,这可能意味着系统内存和位于不同 Tile 中的内存。此掩码中的每个索引都直接引用 struct drm_xe_query_mem_regions 的实例,不应对顺序做任何假设。每个区域的类型由 struct drm_xe_query_mem_regions 的 mem_class 描述。

ip_ver_major

GMD_ID 平台上的图形/媒体 IP 主要版本

ip_ver_minor

GMD_ID 平台上的图形/媒体 IP 次要版本

ip_ver_rev

GMD_ID 平台上的图形/媒体 IP 修订版本

pad2

MBZ

reserved

保留

描述

与 drm_xe_query_gt_list 一起使用,它将返回包含所有现有 GT 单独描述的列表。图形技术 (GT) 是 GPU/Tile 的一个子集,负责实现图形和/或媒体操作。

type 中的索引可以是
  • DRM_XE_QUERY_GT_TYPE_MAIN

  • DRM_XE_QUERY_GT_TYPE_MEDIA

struct drm_xe_query_gt_list

包含 GT 描述项的列表。

定义:

struct drm_xe_query_gt_list {
    __u32 num_gt;
    __u32 pad;
    struct drm_xe_gt gt_list[];
};

成员

num_gt

在 gt_list 中返回的 GT 项的数量

pad

MBZ

gt_list

为此设备返回的 GT 列表

描述

如果使用 struct drm_xe_device_query 进行查询,其中 .query 等于 DRM_XE_DEVICE_QUERY_GT_LIST,则回复在 .data 中使用 struct drm_xe_query_gt_list

struct drm_xe_query_topology_mask

描述 GT 的拓扑掩码

定义:

struct drm_xe_query_topology_mask {
    __u16 gt_id;
#define DRM_XE_TOPO_DSS_GEOMETRY        1;
#define DRM_XE_TOPO_DSS_COMPUTE         2;
#define DRM_XE_TOPO_L3_BANK             3;
#define DRM_XE_TOPO_EU_PER_DSS          4;
#define DRM_XE_TOPO_SIMD16_EU_PER_DSS   5;
    __u16 type;
    __u32 num_bytes;
    __u8 mask[];
};

成员

gt_id

掩码关联的 GT ID

type

掩码类型

num_bytes

请求的掩码中的字节数

mask

num_bytes 的小端掩码

描述

这是反映 GPU 内部物理结构的硬件拓扑。

如果使用 struct drm_xe_device_query 进行查询,其中 .query 等于 DRM_XE_DEVICE_QUERY_GT_TOPOLOGY,则回复在 .data 中使用 struct drm_xe_query_topology_mask

type 可以是
  • DRM_XE_TOPO_DSS_GEOMETRY - 查询可用于几何操作的双子切片 (DSS) 的掩码。例如,查询响应在掩码中包含以下内容:DSS_GEOMETRY    ff ff ff ff 00 00 00 00 表示有 32 个 DSS 可用于几何操作。

  • DRM_XE_TOPO_DSS_COMPUTE - 查询可用于计算操作的双子切片 (DSS) 的掩码。例如,查询响应在掩码中包含以下内容:DSS_COMPUTE    ff ff ff ff 00 00 00 00 表示有 32 个 DSS 可用于计算。

  • DRM_XE_TOPO_L3_BANK - 查询已启用的 L3 bank 的掩码。如果驱动程序无法从硬件查询掩码,则可能会省略此类型。

  • DRM_XE_TOPO_EU_PER_DSS - 查询每个双子切片 (DSS) 可用的执行单元 (EU) 的掩码。例如,查询响应在掩码中包含以下内容:EU_PER_DSS    ff ff 00 00 00 00 00 00 表示每个 DSS 都有 16 个 SIMD8 EU。如果设备没有 SIMD8 EU,则可能会省略此类型。

  • DRM_XE_TOPO_SIMD16_EU_PER_DSS - 查询每个双子切片 (DSS) 可用的 SIMD16 执行单元 (EU) 的掩码。例如,查询响应在掩码中包含以下内容:SIMD16_EU_PER_DSS    ff ff 00 00 00 00 00 00 表示每个 DSS 都有 16 个 SIMD16 EU。如果设备没有 SIMD16 EU,则可能会省略此类型。

struct drm_xe_query_engine_cycles

关联 CPU 和 GPU 时间戳

定义:

struct drm_xe_query_engine_cycles {
    struct drm_xe_engine_class_instance eci;
    __s32 clockid;
    __u32 width;
    __u64 engine_cycles;
    __u64 cpu_timestamp;
    __u64 cpu_delta;
};

成员

eci

这是用户输入的,是要查询命令流处理器周期的引擎。

clockid

这是用户输入的,是 CPU 时间戳的参考时钟 ID。有关定义,请参阅 clock_gettime(2) 和 perf_event_open(2)。支持的时钟 ID 为 CLOCK_MONOTONIC、CLOCK_MONOTONIC_RAW、CLOCK_REALTIME、CLOCK_BOOTTIME、CLOCK_TAI。

width

引擎周期计数器的宽度(以位为单位)。

engine_cycles

从 0x358 偏移量处的寄存器读取的引擎周期。

cpu_timestamp

CPU 时间戳,以纳秒为单位。时间戳是在使用用户设置的参考 clockid 读取 engine_cycles 寄存器之前捕获的。

cpu_delta

在读取 engine_cycles 寄存器的低位双字时捕获的时间增量(以纳秒为单位)。

描述

如果使用 struct drm_xe_device_query 进行查询,其中 .query 等于 DRM_XE_DEVICE_QUERY_ENGINE_CYCLES,则回复在 .data 中使用 struct drm_xe_query_engine_cyclesstruct drm_xe_query_engine_cycles 由用户分配,并且 .data 指向此分配的结构。

查询返回引擎周期,该周期与 GT 的 reference_clock 一起,可用于计算引擎时间戳。此外,查询还会返回一组 CPU 时间戳,指示何时捕获命令流处理器周期计数。

struct drm_xe_query_uc_fw_version

查询微控制器固件版本

定义:

struct drm_xe_query_uc_fw_version {
#define XE_QUERY_UC_TYPE_GUC_SUBMISSION 0;
#define XE_QUERY_UC_TYPE_HUC 1;
    __u16 uc_type;
    __u16 pad;
    __u32 branch_ver;
    __u32 major_ver;
    __u32 minor_ver;
    __u32 patch_ver;
    __u32 pad2;
    __u64 reserved;
};

成员

uc_type

要查询固件版本的微控制器类型

pad

MBZ

branch_ver

分支 uc 固件版本

major_ver

主要 uc 固件版本

minor_ver

次要 uc 固件版本

patch_ver

修补 uc 固件版本

pad2

MBZ

reserved

保留

描述

给定 uc_type,这将返回微控制器固件的分支、主要、次要和修补版本。

struct drm_xe_device_query

DRM_IOCTL_XE_DEVICE_QUERY 的输入 - 用于查询设备信息的主结构

定义:

struct drm_xe_device_query {
    __u64 extensions;
#define DRM_XE_DEVICE_QUERY_ENGINES             0;
#define DRM_XE_DEVICE_QUERY_MEM_REGIONS         1;
#define DRM_XE_DEVICE_QUERY_CONFIG              2;
#define DRM_XE_DEVICE_QUERY_GT_LIST             3;
#define DRM_XE_DEVICE_QUERY_HWCONFIG            4;
#define DRM_XE_DEVICE_QUERY_GT_TOPOLOGY         5;
#define DRM_XE_DEVICE_QUERY_ENGINE_CYCLES       6;
#define DRM_XE_DEVICE_QUERY_UC_FW_VERSION       7;
#define DRM_XE_DEVICE_QUERY_OA_UNITS            8;
    __u32 query;
    __u32 size;
    __u64 data;
    __u64 reserved[2];
};

成员

extensions

指向第一个扩展结构的指针(如果有)

query

要查询的数据类型

size

查询数据的大小

data

查询的数据放置在此处

reserved

保留

描述

用户在 DRM_XE_DEVICE_QUERY_* 中选择要查询的数据类型,并在 query 成员中设置该值。这决定了驱动程序在数据中提供的结构的类型,在 struct drm_xe_query_* 中。

query 可以是
  • DRM_XE_DEVICE_QUERY_ENGINES

  • DRM_XE_DEVICE_QUERY_MEM_REGIONS

  • DRM_XE_DEVICE_QUERY_CONFIG

  • DRM_XE_DEVICE_QUERY_GT_LIST

  • DRM_XE_DEVICE_QUERY_HWCONFIG - 查询类型以检索设备的硬件配置,例如有关切片、内存、缓存等的信息。它以键/值属性表的形式提供。

  • DRM_XE_DEVICE_QUERY_GT_TOPOLOGY

  • DRM_XE_DEVICE_QUERY_ENGINE_CYCLES

如果 size 设置为 0,则驱动程序会使用请求的数据类型所需的 size 填充它。如果 size 等于所需的 size,则查询的信息会复制到数据中。如果 size 设置为不同于 0 且不同于所需 size 的值,则 IOCTL 调用将返回 -EINVAL。

例如,以下代码片段允许使用 DRM_XE_DEVICE_QUERY_ENGINES 检索和打印有关设备引擎的信息

struct drm_xe_query_engines *engines;
struct drm_xe_device_query query = {
    .extensions = 0,
    .query = DRM_XE_DEVICE_QUERY_ENGINES,
    .size = 0,
    .data = 0,
};
ioctl(fd, DRM_IOCTL_XE_DEVICE_QUERY, &query);
engines = malloc(query.size);
query.data = (uintptr_t)engines;
ioctl(fd, DRM_IOCTL_XE_DEVICE_QUERY, &query);
for (int i = 0; i < engines->num_engines; i++) {
    printf("Engine %d: %s\n", i,
        engines->engines[i].instance.engine_class ==
            DRM_XE_ENGINE_CLASS_RENDER ? "RENDER":
        engines->engines[i].instance.engine_class ==
            DRM_XE_ENGINE_CLASS_COPY ? "COPY":
        engines->engines[i].instance.engine_class ==
            DRM_XE_ENGINE_CLASS_VIDEO_DECODE ? "VIDEO_DECODE":
        engines->engines[i].instance.engine_class ==
            DRM_XE_ENGINE_CLASS_VIDEO_ENHANCE ? "VIDEO_ENHANCE":
        engines->engines[i].instance.engine_class ==
            DRM_XE_ENGINE_CLASS_COMPUTE ? "COMPUTE":
        "UNKNOWN");
}
free(engines);
struct drm_xe_gem_create

DRM_IOCTL_XE_GEM_CREATE 的输入 - 用于 GEM 创建的结构

定义:

struct drm_xe_gem_create {
    __u64 extensions;
    __u64 size;
    __u32 placement;
#define DRM_XE_GEM_CREATE_FLAG_DEFER_BACKING            (1 << 0);
#define DRM_XE_GEM_CREATE_FLAG_SCANOUT                  (1 << 1);
#define DRM_XE_GEM_CREATE_FLAG_NEEDS_VISIBLE_VRAM       (1 << 2);
    __u32 flags;
    __u32 vm_id;
    __u32 handle;
#define DRM_XE_GEM_CPU_CACHING_WB                      1;
#define DRM_XE_GEM_CPU_CACHING_WC                      2;
    __u16 cpu_caching;
    __u16 pad[3];
    __u64 reserved[2];
};

成员

extensions

指向第一个扩展结构的指针(如果有)

size

要创建的对象的大小,必须与区域(系统或 VRAM)的最小对齐方式(min_page_size)匹配。

placement

可放置 BO 的内存实例的掩码。此掩码中的每个索引都直接引用 struct drm_xe_query_mem_regions 的实例,不应对顺序做任何假设。每个区域的类型由 struct drm_xe_query_mem_regions 的 mem_class 描述。

flags

标志,当前是可放置 BO 的内存实例的掩码

vm_id

附加的 VM(如果有)

如果指定了 VM,则此 BO 必须

  1. 仅绑定到该 VM。

  2. 无法导出为 PRIME fd。

handle

返回对象的句柄。

对象句柄为非零。

cpu_caching

为此对象选择的 CPU 缓存模式。如果对该对象进行内存映射,此处选择的模式也将被使用。例外情况是在离散 GPU 上映射系统内存(包括被逐出到系统的数据)时。此时,选择的缓存模式将被覆盖为 DRM_XE_GEM_CPU_CACHING_WB,并保证 GPU 和 CPU 之间的缓存一致性。现有 CPU 映射的缓存模式将透明地更新到用户空间客户端。

pad

MBZ

reserved

保留

描述

flags 可以是
  • DRM_XE_GEM_CREATE_FLAG_DEFER_BACKING

  • DRM_XE_GEM_CREATE_FLAG_SCANOUT

  • DRM_XE_GEM_CREATE_FLAG_NEEDS_VISIBLE_VRAM - 当使用 VRAM 作为可能的放置位置时,确保对应的 VRAM 分配始终使用 VRAM 中 CPU 可访问的部分。这对于小 BAR 系统非常重要(在全 BAR 系统上,这会变成空操作)。注意 1:如果内核应将分配溢出到系统内存,如果 CPU 可访问的 VRAM 部分中没有足够的空间可用,则系统内存可以用作额外的放置位置(提供与 i915 接口相同的行为,请参阅 I915_GEM_CREATE_EXT_FLAG_NEEDS_CPU_ACCESS)。注意 2:对于清除颜色 CCS 图面,内核需要读取存储在缓冲区中的清除颜色值,并且在离散平台上,我们需要将 VRAM 用于显示图面,因此内核需要为此类对象设置此标志,否则在小 BAR 系统上会抛出错误。

cpu_caching 支持以下值
  • DRM_XE_GEM_CPU_CACHING_WB - 使用写回缓存分配页面。在 iGPU 上,这不能用于扫描输出表面。目前不允许用于放置在 VRAM 中的对象。

  • DRM_XE_GEM_CPU_CACHING_WC - 将页面分配为写组合。这是非缓存的。扫描输出表面应可能使用此值。所有可以放置在 VRAM 中的对象都必须使用此值。

struct drm_xe_gem_mmap_offset

DRM_IOCTL_XE_GEM_MMAP_OFFSET 的输入

定义:

struct drm_xe_gem_mmap_offset {
    __u64 extensions;
    __u32 handle;
    __u32 flags;
    __u64 offset;
    __u64 reserved[2];
};

成员

extensions

指向第一个扩展结构的指针(如果有)

handle

要映射的对象的句柄。

flags

必须为零

offset

用于后续 mmap 调用的伪偏移量

reserved

保留

struct drm_xe_vm_create

DRM_IOCTL_XE_VM_CREATE 的输入

定义:

struct drm_xe_vm_create {
    __u64 extensions;
#define DRM_XE_VM_CREATE_FLAG_SCRATCH_PAGE      (1 << 0);
#define DRM_XE_VM_CREATE_FLAG_LR_MODE           (1 << 1);
#define DRM_XE_VM_CREATE_FLAG_FAULT_MODE        (1 << 2);
    __u32 flags;
    __u32 vm_id;
    __u64 reserved[2];
};

成员

extensions

指向第一个扩展结构的指针(如果有)

flags

标志

vm_id

返回的 VM ID

reserved

保留

描述

flags 可以是
  • DRM_XE_VM_CREATE_FLAG_SCRATCH_PAGE

  • DRM_XE_VM_CREATE_FLAG_LR_MODE - LR 或长时间运行的 VM 接受向其 exec_queues 提交的执行,这些执行对作业执行时间没有上限。但是,向这些提交的执行不允许任何标志 DRM_XE_SYNC_FLAG_SYNCOBJ、DRM_XE_SYNC_FLAG_TIMELINE_SYNCOBJ、DRM_XE_SYNC_FLAG_DMA_BUF 用作 out-syncobjs,即与 DRM_XE_SYNC_FLAG_SIGNAL 一起使用。如果设备支持,可以使用 DRM_XE_VM_CREATE_FLAG_FAULT_MODE 在可恢复的页面错误模式下创建 LR VM。如果省略该标志,则 UMD 不能依赖于 DRM_XE_VM_CREATE_FLAG_FAULT_MODE 启用的略有不同的每个 VM 过度提交语义(见下文),但如果设备支持,KMD 仍然可以启用可恢复的页面错误。

  • DRM_XE_VM_CREATE_FLAG_FAULT_MODE - 还需要 DRM_XE_VM_CREATE_FLAG_LR_MODE。它允许在访问时按需分配内存,并允许每个 VM 过度提交内存。xe 驱动程序在内部使用可恢复的页面错误来实现此目的。

struct drm_xe_vm_destroy

DRM_IOCTL_XE_VM_DESTROY 的输入

定义:

struct drm_xe_vm_destroy {
    __u32 vm_id;
    __u32 pad;
    __u64 reserved[2];
};

成员

vm_id

VM ID

pad

MBZ

reserved

保留

struct drm_xe_vm_bind_op

运行绑定操作

定义:

struct drm_xe_vm_bind_op {
    __u64 extensions;
    __u32 obj;
    __u16 pat_index;
    __u16 pad;
    union {
        __u64 obj_offset;
        __u64 userptr;
    };
    __u64 range;
    __u64 addr;
#define DRM_XE_VM_BIND_OP_MAP           0x0;
#define DRM_XE_VM_BIND_OP_UNMAP         0x1;
#define DRM_XE_VM_BIND_OP_MAP_USERPTR   0x2;
#define DRM_XE_VM_BIND_OP_UNMAP_ALL     0x3;
#define DRM_XE_VM_BIND_OP_PREFETCH      0x4;
    __u32 op;
#define DRM_XE_VM_BIND_FLAG_READONLY    (1 << 0);
#define DRM_XE_VM_BIND_FLAG_IMMEDIATE   (1 << 1);
#define DRM_XE_VM_BIND_FLAG_NULL        (1 << 2);
#define DRM_XE_VM_BIND_FLAG_DUMPABLE    (1 << 3);
    __u32 flags;
    __u32 prefetch_mem_region_instance;
    __u32 pad2;
    __u64 reserved[3];
};

成员

extensions

指向第一个扩展结构的指针(如果有)

obj

要操作的 GEM 对象,对于 MAP_USERPTR 为 MBZ,对于 UNMAP 为 MBZ

pat_index

平台定义的 pat_index 用于此映射。该索引基本上映射到一些预定义的内存属性,包括诸如缓存、一致性、压缩等。pat_index 的确切含义是平台特定的,并在 Bspec 和 PRM 中定义。当 KMD 设置绑定时,此处的索引被编码到 ppGTT PTE 中。

对于一致性,当 drm_xe_gem_create.cpu_caching 为 DRM_XE_GEM_CPU_CACHING_WB 时,pat_index 需要至少为 1 路一致。KMD 将从 pat_index 中提取一致性模式,如果存在不匹配则拒绝(有关 pre-MTL 平台,请参见下面的注释)。

注意:在 pre-MTL 平台上,只有缓存模式而没有显式一致性模式,但在这种硬件上,始终有一个共享 LLC(或者是 dgpu),因此即使将缓存模式设置为非缓存,所有 GT 内存访问也与 CPU 缓存一致。只有显示引擎是不一致的(在 dgpu 上,它必须在 VRAM 中,VRAM 在 CPU 上始终映射为 WC)。但是,为了使 uapi 与较新的平台保持某种程度的一致性,KMD 将不同的缓存级别分组到所有 pre-MTL 平台上的以下一致性存储桶中

ppGTT UC -> COH_NONE ppGTT WC -> COH_NONE ppGTT WT -> COH_NONE ppGTT WB -> COH_AT_LEAST_1WAY

实际上,UC/WC/WT 应该只用于此类平台上的扫描输出表面(或者可能一般用于与另一个设备共享的 dma-buf),因为只有显示引擎实际上是不一致的。考虑到我们有一个共享的 LLC,其他所有内容通常都应该使用 WB。在 MTL+ 上,这会完全改变,并且 HW 将一致性模式定义为 pat_index 的一部分,其中可能存在不一致的 GT 访问。

注意:对于 userptr 和外部导入的 dma-buf,内核期望 pat_index 为 1WAY 或 2WAY。

对于 DRM_XE_VM_BIND_FLAG_NULL 绑定,KMD 对 pat_index 没有限制。对于此类映射,没有映射实际内存(PTE 中的地址无效),因此各种 PAT 内存属性可能不适用。简单地保留为零是一种选择(仍然是有效的 pat_index)。

pad

MBZ

{unnamed_union}

anonymous

obj_offset

对象中的偏移量,对于 CLEAR_RANGE 为 MBZ,对于 unbind 则忽略

userptr

要绑定的用户指针

range

从要绑定到 addr 的对象的字节数,对于 UNMAP_ALL 为 MBZ

addr

要操作的地址,对于 UNMAP_ALL 为 MBZ

op

要执行的绑定操作

flags

绑定标志

prefetch_mem_region_instance

预取 VMA 的内存区域。它是一个区域实例,而不是掩码。仅与 DRM_XE_VM_BIND_OP_PREFETCH 操作一起使用。

pad2

MBZ

reserved

保留

描述

op 可以是
  • DRM_XE_VM_BIND_OP_MAP

  • DRM_XE_VM_BIND_OP_UNMAP

  • DRM_XE_VM_BIND_OP_MAP_USERPTR

  • DRM_XE_VM_BIND_OP_UNMAP_ALL

  • DRM_XE_VM_BIND_OP_PREFETCH

flags 可以是
  • DRM_XE_VM_BIND_FLAG_READONLY - 将页表设置为只读以确保写保护

  • DRM_XE_VM_BIND_FLAG_IMMEDIATE - 在出现错误的 VM 上,立即执行 MAP 操作,而不是将 MAP 推迟到页面错误处理程序。这在非故障 VM 上是隐含的,因为没有故障处理程序可以推迟。

  • DRM_XE_VM_BIND_FLAG_NULL - 设置 NULL 标志时,将使用特殊位设置页表,该位指示写入被丢弃,所有读取返回零。将来,NULL 标志仅对 DRM_XE_VM_BIND_OP_MAP 操作有效,BO 句柄为 MBZ,BO 偏移量为 MBZ。此标志旨在实现 VK 稀疏绑定。

struct drm_xe_vm_bind

DRM_IOCTL_XE_VM_BIND 的输入

定义:

struct drm_xe_vm_bind {
    __u64 extensions;
    __u32 vm_id;
    __u32 exec_queue_id;
    __u32 pad;
    __u32 num_binds;
    union {
        struct drm_xe_vm_bind_op bind;
        __u64 vector_of_binds;
    };
    __u32 pad2;
    __u32 num_syncs;
    __u64 syncs;
    __u64 reserved[2];
};

成员

extensions

指向第一个扩展结构的指针(如果有)

vm_id

要绑定到的 VM 的 ID

exec_queue_id

exec_queue_id,必须是 DRM_XE_ENGINE_CLASS_VM_BIND 类,并且执行队列必须具有相同的 vm_id。如果为零,则使用默认的 VM 绑定引擎。

pad

MBZ

num_binds

此 IOCTL 中的绑定数

{unnamed_union}

anonymous

bind

如果 num_binds == 1,则使用

vector_of_binds

如果 num_binds > 1,则为指向 struct drm_xe_vm_bind_op 数组的用户指针

pad2

MBZ

num_syncs

要等待的同步数量

syncs

指向 struct drm_xe_sync 数组的指针

reserved

保留

描述

下面是一个使用 drm_xe_vm_bind 异步绑定地址为 BIND_ADDRESS 的缓冲区 data 以说明 userptr 的最小示例。可以使用为 drm_xe_sync 提供的示例进行同步。

data = aligned_alloc(ALIGNMENT, BO_SIZE);
struct drm_xe_vm_bind bind = {
    .vm_id = vm,
    .num_binds = 1,
    .bind.obj = 0,
    .bind.obj_offset = to_user_pointer(data),
    .bind.range = BO_SIZE,
    .bind.addr = BIND_ADDRESS,
    .bind.op = DRM_XE_VM_BIND_OP_MAP_USERPTR,
    .bind.flags = 0,
    .num_syncs = 1,
    .syncs = &sync,
    .exec_queue_id = 0,
};
ioctl(fd, DRM_IOCTL_XE_VM_BIND, &bind);
struct drm_xe_exec_queue_create

DRM_IOCTL_XE_EXEC_QUEUE_CREATE 的输入

定义:

struct drm_xe_exec_queue_create {
#define DRM_XE_EXEC_QUEUE_EXTENSION_SET_PROPERTY                0;
#define DRM_XE_EXEC_QUEUE_SET_PROPERTY_PRIORITY               0;
#define DRM_XE_EXEC_QUEUE_SET_PROPERTY_TIMESLICE              1;
    __u64 extensions;
    __u16 width;
    __u16 num_placements;
    __u32 vm_id;
    __u32 flags;
    __u32 exec_queue_id;
    __u64 instances;
    __u64 reserved[2];
};

成员

extensions

指向第一个扩展结构的指针(如果有)

width

此执行队列的提交宽度(每个执行的 BB 数)

num_placements

此执行队列的有效放置数量

vm_id

用于此执行队列的 VM

flags

MBZ

exec_queue_id

返回的执行队列 ID

instances

指向 struct drm_xe_engine_class_instance 的二维数组的用户指针

长度 = 宽度 (i) * 放置数 (j) 索引 = j + i * 宽度

reserved

保留

描述

下面的示例显示了如何使用 drm_xe_exec_queue_create 创建 DRM_XE_ENGINE_CLASS_RENDER 类的简单 exec_queue(无并行提交)。

struct drm_xe_engine_class_instance instance = {
    .engine_class = DRM_XE_ENGINE_CLASS_RENDER,
};
struct drm_xe_exec_queue_create exec_queue_create = {
     .extensions = 0,
     .vm_id = vm,
     .num_bb_per_exec = 1,
     .num_eng_per_bb = 1,
     .instances = to_user_pointer(&instance),
};
ioctl(fd, DRM_IOCTL_XE_EXEC_QUEUE_CREATE, &exec_queue_create);
struct drm_xe_exec_queue_destroy

DRM_IOCTL_XE_EXEC_QUEUE_DESTROY 的输入

定义:

struct drm_xe_exec_queue_destroy {
    __u32 exec_queue_id;
    __u32 pad;
    __u64 reserved[2];
};

成员

exec_queue_id

执行队列 ID

pad

MBZ

reserved

保留

struct drm_xe_exec_queue_get_property

DRM_IOCTL_XE_EXEC_QUEUE_GET_PROPERTY 的输入

定义:

struct drm_xe_exec_queue_get_property {
    __u64 extensions;
    __u32 exec_queue_id;
#define DRM_XE_EXEC_QUEUE_GET_PROPERTY_BAN      0;
    __u32 property;
    __u64 value;
    __u64 reserved[2];
};

成员

extensions

指向第一个扩展结构的指针(如果有)

exec_queue_id

执行队列 ID

property

要获取的属性

value

属性值

reserved

保留

描述

property 可以是
  • DRM_XE_EXEC_QUEUE_GET_PROPERTY_BAN

struct drm_xe_sync

同步对象

定义:

struct drm_xe_sync {
    __u64 extensions;
#define DRM_XE_SYNC_TYPE_SYNCOBJ                0x0;
#define DRM_XE_SYNC_TYPE_TIMELINE_SYNCOBJ       0x1;
#define DRM_XE_SYNC_TYPE_USER_FENCE             0x2;
    __u32 type;
#define DRM_XE_SYNC_FLAG_SIGNAL (1 << 0);
    __u32 flags;
    union {
        __u32 handle;
        __u64 addr;
    };
    __u64 timeline_value;
    __u64 reserved[2];
};

成员

extensions

指向第一个扩展结构的指针(如果有)

type

此同步对象的类型

flags

同步标志

{unnamed_union}

anonymous

handle

对象的句柄

addr

用户栅栏的地址。当通过 exec IOCTL 传入同步时,这是 VM 中的 GPU 地址。当通过 VM bind IOCTL 传入同步时,这是一个用户指针。在任何一种情况下,用户都有责任确保当用户栅栏发出信号时,此地址存在并且已映射。必须是 qword 对齐的。

时间线值

时间线同步对象的输入。当与 DRM_XE_SYNC_FLAG_TIMELINE_SYNCOBJ 一起使用时,需要与 0 不同。

reserved

保留

描述

type 可以是
  • DRM_XE_SYNC_TYPE_SYNCOBJ

  • DRM_XE_SYNC_TYPE_TIMELINE_SYNCOBJ

  • DRM_XE_SYNC_TYPE_USER_FENCE

flags 可以是
  • DRM_XE_SYNC_FLAG_SIGNAL

drm_xe_sync 的最小使用示例如下

struct drm_xe_sync sync = {
    .flags = DRM_XE_SYNC_FLAG_SIGNAL,
    .type = DRM_XE_SYNC_TYPE_SYNCOBJ,
};
struct drm_syncobj_create syncobj_create = { 0 };
ioctl(fd, DRM_IOCTL_SYNCOBJ_CREATE, &syncobj_create);
sync.handle = syncobj_create.handle;
    ...
    use of &sync in drm_xe_exec or drm_xe_vm_bind
    ...
struct drm_syncobj_wait wait = {
    .handles = &sync.handle,
    .timeout_nsec = INT64_MAX,
    .count_handles = 1,
    .flags = 0,
    .first_signaled = 0,
    .pad = 0,
};
ioctl(fd, DRM_IOCTL_SYNCOBJ_WAIT, &wait);
struct drm_xe_exec

DRM_IOCTL_XE_EXEC 的输入

定义:

struct drm_xe_exec {
    __u64 extensions;
    __u32 exec_queue_id;
    __u32 num_syncs;
    __u64 syncs;
    __u64 address;
    __u16 num_batch_buffer;
    __u16 pad[3];
    __u64 reserved[2];
};

成员

extensions

指向第一个扩展结构的指针(如果有)

exec_queue_id

批处理缓冲区的执行队列 ID

num_syncs

数组中 struct drm_xe_sync 的数量。

syncs

指向 struct drm_xe_sync 数组的指针。

地址

如果 num_batch_buffer == 1,则为批处理缓冲区的地址;否则为批处理缓冲区地址的数组

num_batch_buffer

此执行中的批处理缓冲区数量,必须与引擎的宽度匹配

pad

MBZ

reserved

保留

描述

这是一个使用 drm_xe_exec 执行 BIND_ADDRESS 处对象(请参阅 drm_xe_vm_bind 中的示例)的示例,该执行通过 exec_queue 进行(请参阅 drm_xe_exec_queue_create 中的示例)。它可以使用为 drm_xe_sync 提供的示例进行同步。

struct drm_xe_exec exec = {
    .exec_queue_id = exec_queue,
    .syncs = &sync,
    .num_syncs = 1,
    .address = BIND_ADDRESS,
    .num_batch_buffer = 1,
};
ioctl(fd, DRM_IOCTL_XE_EXEC, &exec);
struct drm_xe_wait_user_fence

DRM_IOCTL_XE_WAIT_USER_FENCE 的输入

定义:

struct drm_xe_wait_user_fence {
    __u64 extensions;
    __u64 addr;
#define DRM_XE_UFENCE_WAIT_OP_EQ        0x0;
#define DRM_XE_UFENCE_WAIT_OP_NEQ       0x1;
#define DRM_XE_UFENCE_WAIT_OP_GT        0x2;
#define DRM_XE_UFENCE_WAIT_OP_GTE       0x3;
#define DRM_XE_UFENCE_WAIT_OP_LT        0x4;
#define DRM_XE_UFENCE_WAIT_OP_LTE       0x5;
    __u16 op;
#define DRM_XE_UFENCE_WAIT_FLAG_ABSTIME (1 << 0);
    __u16 flags;
    __u32 pad;
    __u64 value;
    __u64 mask;
    __s64 timeout;
    __u32 exec_queue_id;
    __u32 pad2;
    __u64 reserved[2];
};

成员

extensions

指向第一个扩展结构的指针(如果有)

addr

要等待的用户指针地址,必须是四字对齐的

op

等待操作(比较类型)

flags

等待标志

pad

MBZ

value

比较值

mask

比较掩码

超时

在放弃之前等待多长时间,以纳秒为单位的值。如果不设置 DRM_XE_UFENCE_WAIT_FLAG_ABSTIME 标志(相对超时),则它包含以纳秒为单位的等待超时时间(栅栏将在 now() + 超时时过期)。当设置 DRM_XE_UFENCE_WAIT_FLAG_ABSTIME 标志(绝对超时)时,等待将在超时时结束(使用系统 MONOTONIC_CLOCK)。传递负超时会导致永无止境的等待。

在相对超时时,此值会使用剩余的超时时间进行更新(以便在信号传递的情况下重新启动调用)。在绝对超时时,此值保持不变(重新启动的调用仍然会在同一时间点过期)。

exec_queue_id

从 xe_exec_queue_create_ioctl 返回的 exec_queue_id

pad2

MBZ

reserved

保留

描述

等待用户栅栏,XE 将在实例列表中的每个硬件引擎中断时唤醒,并检查用户栅栏是否完成

(*addr & MASK) OP (VALUE & MASK)

在用户栅栏完成或超时时返回给用户。

op 可以是
  • DRM_XE_UFENCE_WAIT_OP_EQ

  • DRM_XE_UFENCE_WAIT_OP_NEQ

  • DRM_XE_UFENCE_WAIT_OP_GT

  • DRM_XE_UFENCE_WAIT_OP_GTE

  • DRM_XE_UFENCE_WAIT_OP_LT

  • DRM_XE_UFENCE_WAIT_OP_LTE

flags 可以是
  • DRM_XE_UFENCE_WAIT_FLAG_ABSTIME

  • DRM_XE_UFENCE_WAIT_FLAG_SOFT_OP

mask 值可以是例如
  • u8 的 0xffu

  • u16 的 0xffffu

  • u32 的 0xffffffffu

  • u64 的 0xffffffffffffffffu

enum drm_xe_observation_type

观测流类型

常量

DRM_XE_OBSERVATION_TYPE_OA

OA 观测流类型

enum drm_xe_observation_op

观测流操作

常量

DRM_XE_OBSERVATION_OP_STREAM_OPEN

打开观测流

DRM_XE_OBSERVATION_OP_ADD_CONFIG

添加观测流配置

DRM_XE_OBSERVATION_OP_REMOVE_CONFIG

删除观测流配置

struct drm_xe_observation_param

DRM_XE_OBSERVATION 的输入

定义:

struct drm_xe_observation_param {
    __u64 extensions;
    __u64 observation_type;
    __u64 observation_op;
    __u64 param;
};

成员

extensions

指向第一个扩展结构的指针(如果有)

observation_type

观测流类型,属于枚举 drm_xe_observation_type

observation_op

观测流操作,属于枚举 drm_xe_observation_op

param

指向实际流参数的指针

描述

观测层启用多种类型的观测流的多路复用。特定流操作的实际参数通过 param 指针提供(使用 __copy_from_user 获取这些参数)。

enum drm_xe_observation_ioctls

观测流 fd ioctl

常量

DRM_XE_OBSERVATION_IOCTL_ENABLE

启用观测流的数据捕获

DRM_XE_OBSERVATION_IOCTL_DISABLE

禁用观测流的数据捕获

DRM_XE_OBSERVATION_IOCTL_CONFIG

更改观测流配置

DRM_XE_OBSERVATION_IOCTL_STATUS

返回观测流状态

DRM_XE_OBSERVATION_IOCTL_INFO

返回观测流信息

描述

用户空间和内核之间为观测 fd ioctl 交换的信息是特定于流类型的

enum drm_xe_oa_unit_type

OA 单元类型

常量

DRM_XE_OA_UNIT_TYPE_OAG

OAG OA 单元。OAR/OAC 被认为是 OAG 的子类型。对于 OAR/OAC,请使用 OAG。

DRM_XE_OA_UNIT_TYPE_OAM

OAM OA 单元

struct drm_xe_oa_unit

描述 OA 单元

定义:

struct drm_xe_oa_unit {
    __u64 extensions;
    __u32 oa_unit_id;
    __u32 oa_unit_type;
    __u64 capabilities;
#define DRM_XE_OA_CAPS_BASE             (1 << 0);
#define DRM_XE_OA_CAPS_SYNCS            (1 << 1);
    __u64 oa_timestamp_freq;
    __u64 reserved[4];
    __u64 num_engines;
    struct drm_xe_engine_class_instance eci[];
};

成员

extensions

指向第一个扩展结构的指针(如果有)

oa_unit_id

OA 单元 ID

oa_unit_type

属于 drm_xe_oa_unit_type 的 OA 单元类型

capabilities

OA 功能位掩码

oa_timestamp_freq

OA 时间戳频率

reserved

MBZ

num_engines

eci 数组中的引擎数量

eci

附加到此 OA 单元的引擎

struct drm_xe_query_oa_units

描述 OA 单元

定义:

struct drm_xe_query_oa_units {
    __u64 extensions;
    __u32 num_oa_units;
    __u32 pad;
    __u64 oa_units[];
};

成员

extensions

指向第一个扩展结构的指针(如果有)

num_oa_units

在 oau[] 中返回的 OA 单元数量

pad

MBZ

oa_units

为此设备返回的 struct drm_xe_oa_unit 数组。在下面以 u64 数组的形式写入,以避免某些编译器使用嵌套的弹性数组时出现问题

描述

如果使用 struct drm_xe_device_query 进行查询,其中 .query 等于 DRM_XE_DEVICE_QUERY_OA_UNITS,则回复在 .data 中使用 struct drm_xe_query_oa_units

可以使用如下代码块访问所有 OA 单元的 OA 单元属性

struct drm_xe_query_oa_units *qoa;
struct drm_xe_oa_unit *oau;
u8 *poau;

// malloc qoa and issue DRM_XE_DEVICE_QUERY_OA_UNITS. Then:
poau = (u8 *)&qoa->oa_units[0];
for (int i = 0; i < qoa->num_oa_units; i++) {
        oau = (struct drm_xe_oa_unit *)poau;
        // Access 'struct drm_xe_oa_unit' fields here
        poau += sizeof(*oau) + oau->num_engines * sizeof(oau->eci[0]);
}
enum drm_xe_oa_format_type

PRM/Bspec 52198/60942 中指定的 OA 格式类型

常量

DRM_XE_OA_FMT_TYPE_OAG

OAG 报告格式

DRM_XE_OA_FMT_TYPE_OAR

OAR 报告格式

DRM_XE_OA_FMT_TYPE_OAM

OAM 报告格式

DRM_XE_OA_FMT_TYPE_OAC

OAC 报告格式

DRM_XE_OA_FMT_TYPE_OAM_MPEC

OAM SAMEDIA 或 OAM MPEC 报告格式

DRM_XE_OA_FMT_TYPE_PEC

PEC 报告格式

enum drm_xe_oa_property_id

OA 流属性 ID

常量

DRM_XE_OA_PROPERTY_OA_UNIT_ID

要在其上打开 OA 流的 OA 单元 ID,请参阅 ‘struct drm_xe_query_oa_units’ 中的 oa_unit_id。如果未提供,则默认为 0。

DRM_XE_OA_PROPERTY_SAMPLE_OA

值为 1 时,请求在附加到 OA 单元的全局缓冲区中包含原始 OA 单元报告或流样本。

DRM_XE_OA_PROPERTY_OA_METRIC_SET

定义 OA 报告内容的 OA 指标,之前通过 DRM_XE_OBSERVATION_OP_ADD_CONFIG 添加。

DRM_XE_OA_PROPERTY_OA_FORMAT

OA 计数器报告格式

DRM_XE_OA_PROPERTY_OA_PERIOD_EXPONENT

请求定期 OA 单元采样,采样频率与 2^(period_exponent + 1) 成正比

DRM_XE_OA_PROPERTY_OA_DISABLED

值为 1 将在 DISABLED 状态下打开 OA 流(请参阅 DRM_XE_OBSERVATION_IOCTL_ENABLE)。

DRM_XE_OA_PROPERTY_EXEC_QUEUE_ID

为特定的 exec_queue_id 打开流。可以在此执行队列上执行 OA 查询。

DRM_XE_OA_PROPERTY_OA_ENGINE_INSTANCE

可选的引擎实例,与 DRM_XE_OA_PROPERTY_EXEC_QUEUE_ID 一起传递,或者默认为 0。

DRM_XE_OA_PROPERTY_NO_PREEMPT

允许禁用流执行队列的抢占和时间分片。

DRM_XE_OA_PROPERTY_NUM_SYNCS

DRM_XE_OA_PROPERTY_SYNCS 中指定的同步数组中的同步数

DRM_XE_OA_PROPERTY_SYNCS

指向 struct drm_xe_sync 数组的指针,数组大小通过 DRM_XE_OA_PROPERTY_NUM_SYNCS 指定。OA 配置将等待,直到输入栅栏发出信号。新的 OA 配置生效后,输出栅栏将发出信号。对于 DRM_XE_SYNC_TYPE_USER_FENCEaddr 是一个用户指针,类似于 VM 绑定情况。

描述

流参数被指定为 drm_xe_ext_set_property 结构链,其中 property 值来自枚举 drm_xe_oa_property_iddrm_xe_user_extension base.name 设置为 DRM_XE_OA_EXTENSION_SET_PROPERTY。struct drm_xe_observation_param 中的 param 字段指向第一个 drm_xe_ext_set_property 结构。

完全相同的机制也用于使用 DRM_XE_OBSERVATION_IOCTL_CONFIG 观测流 fd ioctl 进行流重新配置,尽管对于流重新配置只能指定下面属性的一个子集。

struct drm_xe_oa_config

OA 指标配置

定义:

struct drm_xe_oa_config {
    __u64 extensions;
    char uuid[36];
    __u32 n_regs;
    __u64 regs_ptr;
};

成员

extensions

指向第一个扩展结构的指针(如果有)

uuid

格式类似于 “%08x-%04x-%04x-%04x-%012x” 的字符串

n_regs

regs_ptr 中的寄存器数量

regs_ptr

指向 OA 配置寄存器的(寄存器地址,值)对的指针。缓冲区的预期长度为:(2 * sizeof(u32) * n_regs)。

描述

可以使用 DRM_XE_OBSERVATION_OP_ADD_CONFIG 添加多个 OA 配置。在使用 DRM_XE_OA_PROPERTY_OA_METRIC_SET 属性打开 OA 流时,可以指定特定的配置。

struct drm_xe_oa_stream_status

DRM_XE_OBSERVATION_IOCTL_STATUS 观测流 fd ioctl 返回的 OA 流状态。用户空间可以调用 ioctl 来查询流状态,以响应来自观测 fd read() 的 EIO errno。

定义:

struct drm_xe_oa_stream_status {
    __u64 extensions;
    __u64 oa_status;
#define DRM_XE_OASTATUS_MMIO_TRG_Q_FULL         (1 << 3);
#define DRM_XE_OASTATUS_COUNTER_OVERFLOW        (1 << 2);
#define DRM_XE_OASTATUS_BUFFER_OVERFLOW         (1 << 1);
#define DRM_XE_OASTATUS_REPORT_LOST             (1 << 0);
    __u64 reserved[3];
};

成员

extensions

指向第一个扩展结构的指针(如果有)

oa_status

OA 流状态(请参阅 Bspec 46717/61226)

reserved

保留供将来使用

struct drm_xe_oa_stream_info

DRM_XE_OBSERVATION_IOCTL_INFO 观测流 fd ioctl 返回的 OA 流信息

定义:

struct drm_xe_oa_stream_info {
    __u64 extensions;
    __u64 oa_buf_size;
    __u64 reserved[3];
};

成员

extensions

指向第一个扩展结构的指针(如果有)

oa_buf_size

OA 缓冲区大小

reserved

保留供将来使用