DRM 驱动 uAPI

drm/i915 uAPI

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

I915_L3_PARITY_UEVENT - 驱动程序收到奇偶校验不匹配时生成

来自 GPU L3 缓存的事件。 提供的额外信息是受影响缓存行的 ROW、BANK、SUBBANK、SLICE。 用户空间应跟踪这些事件,如果特定的缓存行似乎存在持续错误,请使用 intel-gpu-tools 中提供的 L3 重映射工具对其进行重映射。 与该事件一起提供的值始终为 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 进行此标识。

i915 通过 /sys/bus/event_sources/drivers/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 转换为二进制 drm_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 枚举某个类的所有引擎。 之后,用户空间可以使用虚拟引擎的占位符槽创建 GEM 上下文(分别使用类和实例的 I915_ENGINE_CLASS_INVALIDI915_ENGINE_CLASS_INVALID_NONE),最后使用 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

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

engines

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

length = width (i) * num_siblings (j) index = j + i * num_siblings

描述

在上下文引擎映射中设置一个槽,以允许在单个 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

上下文引擎映射是在提交批处理缓冲区时寻址引擎的新方法,取代了使用 I915_EXEC_BLT 等标识符的现有方式(在 struct drm_i915_gem_execbuffer2 的标志字段中)。

要使用它,需要使用用户打算提交到的引擎列表来配置创建的 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 的 ID(绑定到 fd)用于 I915_CONTEXT_PARAM_VM 在 outparam id 中返回。

可以提供扩展链,从 extensions 开始,以 next_extension 为 0 结束。目前,未定义扩展。

DRM_I915_GEM_VM_DESTROY -

销毁先前创建的 VM ID,该 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 中的多路复用寄存器数。

n_boolean_regs

boolean_regs_ptr 中的布尔寄存器数。

n_flex_regs

flex_regs_ptr 中的弹性寄存器数。

mux_regs_ptr

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

boolean_regs_ptr

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

flex_regs_ptr

指向多路复用寄存器的 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 mask 的位数。

max_subslices

用于表示 subslice mask 的位数。

max_eus_per_subslice

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

subslice_offset

存储 subslice mask 的 data[] 中的偏移量。

subslice_stride

存储每个 slice 的每个 subslice mask 的步长。

eu_offset

存储 EU mask 的 data[] 中的偏移量。

eu_stride

存储每个 subslice 的每个 EU mask 的步长。

data

包含 3 个信息

  • slice mask,每个 slice 对应一位,指示 slice 是否可用。可以使用以下公式查询 slice X 的可用性

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

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

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

    (data[subslice_offset + X * subslice_stride + Y / 8] >> (Y % 8)) & 1
    
  • 每个 slice 中每个 subslice 的 EU mask,每个 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_GETPARAM 和引擎标识符(如 I915_PARAM_HAS_BLT)的旧方法。

从 Icelake 和更新的 GPU 开始出现对该接口的需求,这些 GPU 开始建立一种模式,即具有同一类的多个引擎,其中并非所有实例在功能上总是完全等效的。

此 uapi 的入口点是 DRM_IOCTL_I915_QUERY,其中 DRM_I915_QUERY_ENGINE_INFO 作为查询的 item 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

engines

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

class:instance 对编码

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)。

请注意,如果此处返回的值为零,则这必须是一个缺少相关的小型 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;
};

成员

branch

固件分支版本。

major

固件主版本。

minor

固件次版本。

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 上至少 2M 的 GTT 对齐,在硬件支持中我们遇到了以下复杂情况

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

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

但是,在实际的生产 HW 上,这已完全更改为现在允许在 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 中的对象的平面 CCS,因此我们不支持 I915_GEM_CREATE_EXT_FLAG_NEEDS_CPU_ACCESS 与平面 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 的数组或 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 数组的优先级顺序受到尊重,无论是在最初放置对象时还是由于内存压力而移动内存时

在支持平面 CCS 的 HW 上,支持压缩位于 I915_MEMORY_CLASS_DEVICE 中的对象。当此类对象(压缩)在 regions 中具有其他内存类并迁移到(由于内存约束)非 I915_MEMORY_CLASS_DEVICE 区域时,则 i915 需要解压缩内容。但是 i915 没有解压缩用户空间压缩对象所需的信息。

因此 i915 支持平面 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 作业。如果异步执行,用户空间可以提供此作业将等待的 syncobj 列表和/或内核将在 VM_BIND 作业完成执行后发出信号的 syncobj 列表。如果同步执行,则 ioctl 将阻塞,直到绑定作业完成。对于同步作业,内核将不允许提交任何 syncobj 到内核。

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

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

由于 VM_BIND 作业会在作业提交时更新 GPU 的 VA 空间,因此 EXEC 作业具有最新的 VA 空间视图。但是,实际映射可能仍在等待中。因此,EXEC 作业需要具有特定的 fence - 它们所依赖的相应 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

同步对象的句柄

timeline_value

如果 syncobj 的类型为 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 的结构体)。这些字段可以添加到结构体的末尾,也可以替换现有的填充字段。任何添加的新字段都必须保留添加这些字段之前存在的行为,当传递零值时。

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

  • 如果内核驱动程序太旧而无法识别某些字段,则如果它们为零将被忽略,否则将被拒绝(因此在输出时将为零)。

  • 如果 userspace 太旧而无法识别某些字段,则在内核驱动程序解析结构体之前,这些字段将被清零(输入)。

  • 每个新标志/字段的添加都必须带有驱动程序版本更新,因此 userspace 驱动程序不必通过试错来了解哪些标志受支持。

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

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

暴露给 userspace 的 MMIO 区域。

DRM_PANTHOR_USER_MMIO_OFFSET

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

DRM_PANTHOR_USER_FLUSH_ID_MMIO_OFFSET

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

IOCTL ID

enum drm_panthor_ioctl_id - IOCTL ID

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

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

IOCTL 参数

struct drm_panthor_obj_array

对象数组。

定义:

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

成员

stride

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

count

数组中对象的数量。

array

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

描述

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

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

DRM_PANTHOR_OBJ_ARRAY

DRM_PANTHOR_OBJ_ARRAY (cnt, ptr)

初始化 drm_panthor_obj_array 字段。

参数

cnt

数组中元素的数量。

ptr

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

描述

宏,根据 userspace 已知的对象大小初始化 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

同步句柄。

timeline_value

如果 (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 暴露的平铺单元。

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

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

所有寄存器都可以被 userspace 命令流使用,但是当调用 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

正在查询的类型的大小。

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

pointer

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

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

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 空间的大小。

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

如果 user_va_range 为零,内核将根据 TASK_SIZE 和 GPU MMU 支持的虚拟范围选择一个合理的值(内核/用户拆分应为 userspace 进程留下足够的 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

要销毁的 VM 的 ID。

pad

MBZ。

enum drm_panthor_vm_bind_op_flags

VM 绑定操作标志

常量

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

无 VM 操作。

仅作为 VM 队列上的同步点。

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

struct drm_panthor_vm_bind_op

VM 绑定操作

定义:

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 同步操作数组。

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

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

enum drm_panthor_vm_bind_flags

VM 绑定标志

常量

DRM_PANTHOR_VM_BIND_ASYNC

VM 绑定操作排队到 VM 队列,而不是同步执行。

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

绑定请求的目标 VM。

flags

drm_panthor_vm_bind_flags 标志的组合。

ops

struct drm_panthor_vm_bind_op 绑定操作数组。

enum drm_panthor_vm_state

VM 状态。

常量

DRM_PANTHOR_VM_STATE_USABLE

VM 可用。

将在此 VM 上接受新的 VM 操作。

DRM_PANTHOR_VM_STATE_UNUSABLE

VM 不可用。

某些操作将 VM 置于不可用状态(例如,由于任何原因异步 VM_BIND 请求失败)。

一旦 VM 处于此状态,所有新的 MAP 操作将被拒绝,并且任何以该 VM 为目标的 GPU 作业将失败。仍然接受 UNMAP 操作。

从不可用的 VM 恢复的唯一方法是创建一个新的 VM,然后销毁旧的 VM。

struct drm_panthor_vm_get_state

获取 VM 状态。

定义:

struct drm_panthor_vm_get_state {
    __u32 vm_id;
    __u32 state;
};

成员

vm_id

get_state 请求的目标 VM。

state

驱动程序返回的状态。

必须是 enum drm_panthor_vm_state 值之一。

enum drm_panthor_bo_flags

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

常量

DRM_PANTHOR_BO_NO_MMAP

缓冲区对象永远不会在 userspace 中进行 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

此缓冲区对象将映射到的独占 VM。

如果不为零,则该字段必须引用有效的 VM ID,并暗示
  • 缓冲区对象将仅绑定到该 VM

  • 不能作为 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

用于绑定此组的 VM ID。

提交到绑定到此组的队列的所有内容都将使用此 VM。

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 同步操作数组。

描述

这描述了要从内核命令流环形缓冲区调用的 userspace 命令流。队列提交始终是组提交的一部分,采用一个或多个作业以提交到基础队列。

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

组有致命错误。

当组最终设置此标志时,无法将作业提交到其队列。

DRM_PANTHOR_GROUP_STATE_INNOCENT

组在由其他组引起的重置期间被终止。

只有在设置了 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

平铺器堆应映射到的 VM ID

initial_chunk_count

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

chunk_size

块大小。

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

max_chunks

可以分配的最大块数。

必须至少为 initial_chunk_count

target_in_flight

最大飞行中渲染过程数。

如果堆中有超过平铺器作业在飞行中,FW 将等待渲染过程完成,然后再将新的平铺器作业排队。

handle

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

tiler_heap_ctx_gpu_va

返回的堆 GPU 虚拟地址

first_heap_chunk_gpu_va

第一个堆块。

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

struct drm_panthor_tiler_heap_destroy

传递给 DRM_IOCTL_PANTHOR_TILER_HEAP_DESTROY 的参数

定义:

struct drm_panthor_tiler_heap_destroy {
    __u32 handle;
    __u32 pad;
};

成员

handle

要销毁的平铺器堆的句柄。

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

pad

填充字段,MBZ。

struct drm_panthor_bo_set_label

传递给 DRM_IOCTL_PANTHOR_BO_SET_LABEL 的参数

定义:

struct drm_panthor_bo_set_label {
    __u32 handle;
    __u32 pad;
    __u64 label;
};

成员

handle

要标记的缓冲区对象的句柄。

pad

MBZ。

label

指向以 NUL 结尾的字符串的用户指针

长度不能大于 4096

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 值。

Return

要从 userspace 传递给 ioctl() 的 IOCTL 数字。

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

基本用户扩展

属性

要设置的属性

pad

MBZ

value

属性值

保留

保留

描述

一个通用结构,允许使用 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];
};

成员

实例

drm_xe_engine_class_instance

保留

保留

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

engines

为此设备返回的引擎

描述

如果使用 .query 等于 DRM_XE_DEVICE_QUERY_ENGINES 的结构 drm_xe_device_query 进行查询,则答复会在 .data 中使用 struct 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

实例

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

min_page_size

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

当内核为此区域分配内存时,底层页面的大小将至少为 min_page_size。允许放置在此区域中的缓冲区对象必须使用与此值对齐的大小创建。 GPU 虚拟地址映射(部分)也可能放置在此区域中的缓冲区对象必须使其 GPU 虚拟地址和范围与此值对齐。如果未满足对齐限制,受影响的 IOCTLS 将返回 -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 区域进行跟踪(对于其他类型,此处的值将始终为零)。

保留

保留

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

为此设备返回的内存区域

描述

如果使用 .query 等于 DRM_XE_DEVICE_QUERY_MEM_REGIONS 的 struct drm_xe_device_query 进行查询,则答复会在 .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_FLAG_HAS_LOW_LATENCY        (1 << 1);
#define DRM_XE_QUERY_CONFIG_FLAG_HAS_CPU_ADDR_MIRROR    (1 << 2);
#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

在信息中返回的参数数量

pad

MBZ

info

包含配置信息的元素数组

描述

如果使用 .query 等于 DRM_XE_DEVICE_QUERY_CONFIG 的 struct drm_xe_device_query 进行查询,则答复会在 .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_FLAG_HAS_LOW_LATENCY - 如果设备支持低延迟提示,则设置标志

    • DRM_XE_QUERY_CONFIG_FLAG_HAS_CPU_ADDR_MIRROR - 如果设备具有 CPU 地址镜像支持,则设置标志

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

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

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

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 类型:主或媒体

tile_id

此 GT 所在的瓦片 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 相比,它们具有额外的间接性。对于离散设备,这可能意味着系统内存和驻留在不同瓦片中的内存。此掩码中的每个索引直接引用 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

保留

保留

描述

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

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 列表

描述

如果使用 .query 等于 DRM_XE_DEVICE_QUERY_GT_LIST 的 struct drm_xe_device_query 进行查询,则答复会在 .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

掩码与之关联的 GT ID

type

掩码类型

num_bytes

请求的掩码中的字节数

描述

mask

num_bytes 的小端掩码

这是硬件拓扑,它反映了 GPU 的内部物理结构。
  • 如果使用 .query 等于 DRM_XE_DEVICE_QUERY_GT_TOPOLOGY 的 struct drm_xe_device_query 进行查询,则答复会在 .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 存储体的掩码。如果驱动程序无法从硬件查询掩码,则可以省略此类型。

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 {
    struct drm_xe_engine_class_instance eci;
    __s32 clockid;
    __u32 width;
    __u64 engine_cycles;
    __u64 cpu_timestamp;
    __u64 cpu_delta;
};

成员

struct drm_xe_query_engine_cycles

关联 CPU 和 GPU 时间戳

eci

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

width

clockid

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

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

engine_cycles

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

cpu_timestamp

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

描述

cpu_delta

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

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

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

定义:

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;
};

成员

struct drm_xe_query_uc_fw_version

查询微控制器固件版本

pad

MBZ

uc_type

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

branch_ver

分支 uc 固件版本

major_ver

主要 uc 固件版本

minor_ver

次要 uc 固件版本

pad2

MBZ

保留

保留

描述

patch_ver

修补 uc 固件版本

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

定义:

struct drm_xe_query_pxp_status {
    __u32 status;
    __u32 supported_session_types;
};

成员

struct drm_xe_query_pxp_status

查询 PXP 是否已准备就绪

status

当前 PXP 状态

描述

supported_session_types

支持的 PXP 会话类型的位掩码

如果 PXP 已启用且未发生严重错误,则状态将设置为以下值之一:0:PXP 初始化仍在进行中 1:PXP 初始化完成

如果 PXP 未启用或出现问题,则查询将失败,并显示以下错误代码之一:-ENODEV:不支持或已禁用 PXP;-EIO:初始化期间发生严重错误,因此永远不会启用 PXP;-EINVAL:作为查询的一部分提供的 value 不正确;-EFAULT:内核和用户空间之间复制内存时出错。

状态只有在驱动程序加载后的前几秒钟内才能为 0。如果一切按预期运行,则状态将在不到 1 秒的时间内转换为初始化完成,而在出现错误的情况下,驱动程序可能需要更长的时间才能开始返回错误代码,但它仍然应该少于 10 秒。

支持的会话类型位掩码基于 enum drm_xe_pxp_session_type 中的值。 TYPE_NONE 始终受支持,因此不会在位掩码中报告。

定义:

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;
#define DRM_XE_DEVICE_QUERY_PXP_STATUS          9;
#define DRM_XE_DEVICE_QUERY_EU_STALL            10;
    __u32 query;
    __u32 size;
    __u64 data;
    __u64 reserved[2];
};

成员

extensions

struct drm_xe_device_query

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

ext

size

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

data

query

保留

保留

描述

要查询的数据类型

size
  • 查询数据的大小

  • data

  • 查询的数据放置在此处

  • 用户在 DRM_XE_DEVICE_QUERY_* 中选择要查询的数据类型,并在查询成员中设置 value。这决定了驱动程序在数据中提供的结构的类型,在 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 - 查询类型以检索设备的硬件配置,例如有关切片、内存、缓存等的信息。它作为键/值属性的表提供。

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);
DRM_XE_DEVICE_QUERY_GT_TOPOLOGY

DRM_XE_DEVICE_QUERY_ENGINE_CYCLES

定义:

struct drm_xe_gem_create {
#define DRM_XE_GEM_CREATE_EXTENSION_SET_PROPERTY        0;
#define DRM_XE_GEM_CREATE_SET_PROPERTY_PXP_TYPE       0;
    __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

struct drm_xe_device_query

size

DRM_XE_DEVICE_QUERY_PXP_STATUS

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

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

flags

struct drm_xe_gem_create

vm_id

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

size

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

  2. placement

handle

返回的对象的句柄。

对象句柄为非零。

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

flags

pad

MBZ

保留

保留

描述

标志,当前 BO 可以放置在其中的内存实例的掩码
  • vm_id

  • 附加的 VM(如果有)

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

只能绑定到该 VM。
  • 无法导出为 PRIME fd。

  • cpu_caching

为此对象选择的 CPU 缓存模式。如果 mmaping 对象,则还将使用此处选择的模式。唯一的例外是在离散 GPU 上映射系统内存(包括驱逐到系统的数据)时。然后,所选缓存模式将被覆盖为 DRM_XE_GEM_CPU_CACHING_WB,并保证 GPU 和 CPU 之间的连贯性。现有 CPU 映射的缓存模式将透明地更新为用户空间客户端。

  • flags 可以是

DRM_XE_GEM_CREATE_FLAG_DEFER_BACKING

DRM_XE_GEM_CREATE_FLAG_SCANOUT

定义:

struct drm_xe_gem_mmap_offset {
    __u64 extensions;
    __u32 handle;
#define DRM_XE_MMAP_OFFSET_FLAG_PCI_BARRIER     (1 << 0);
    __u32 flags;
    __u64 offset;
    __u64 reserved[2];
};

成员

extensions

struct drm_xe_device_query

handle

要映射的对象的句柄。

flags

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

offset

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

保留

保留

描述

标志,当前 BO 可以放置在其中的内存实例的掩码
  • cpu_caching 支持以下值

DRM_XE_GEM_CPU_CACHING_WB - 使用回写缓存分配页面。在 iGPU 上,这不能用于扫描输出图面。当前不允许放置在 VRAM 中的对象。

struct drm_xe_gem_mmap_offset mmo = {
    .handle = 0, // must be set to 0
    .flags = DRM_XE_MMAP_OFFSET_FLAG_PCI_BARRIER,
};

err = ioctl(fd, DRM_IOCTL_XE_GEM_MMAP_OFFSET, &mmo);
map = mmap(NULL, size, PROT_WRITE, MAP_SHARED, fd, mmo.offset);
map[i] = 0xdeadbeaf; // issue barrier

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

此 ioctl 支持通过 DRM_XE_GEM_CREATE_EXTENSION_SET_PROPERTY 扩展设置以下属性,该扩展使用通用 drm_xe_ext_set_property 结构

DRM_XE_GEM_CREATE_SET_PROPERTY_PXP_TYPE - 设置此对象将使用的 PXP 会话类型。有效值在 enum drm_xe_pxp_session_type 中列出。 DRM_XE_PXP_TYPE_NONE 是默认行为,因此无需显式设置。与 DRM_XE_PXP_TYPE_HWDRM 类型的会话一起使用的对象将在其创建后发生 PXP 失效事件时标记为无效。尝试翻转无效对象将导致显示黑帧。将拒绝在 VM 中映射了无效对象的提交。

struct drm_xe_gem_mmap_offset

定义:

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

struct drm_xe_device_query

flags

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

vm_id

DRM_IOCTL_XE_GEM_MMAP_OFFSET 的输入

保留

保留

描述

标志,当前 BO 可以放置在其中的内存实例的掩码
  • flags

  • DRM_XE_MMAP_OFFSET_FLAG_PCI_BARRIER - 对于用户,用于查询在 mmap ioctl 中使用的特殊偏移量。写入返回的 mmap 地址将生成一个低开销的 PCI 内存屏障(避免 IOCTL 调用以及写入也会增加开销的 VRAM),就像 MI_MEM_FENCE 指令一样。

  • 大致用法如下

注意

由于硬件限制,mmap 大小最多为 4K。因此,仅在支持 4K 页面大小的 CPU 架构上支持此接口。 mmap_offset ioctl 将检测到这一点并优雅地返回错误,其中用户空间应具有用于触发屏障的不同回退方法。

定义:

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

成员

vm_id

struct drm_xe_vm_create

pad

MBZ

保留

保留

DRM_IOCTL_XE_VM_CREATE 的输入

vm_id

定义:

struct drm_xe_vm_bind_op {
    __u64 extensions;
    __u32 obj;
    __u16 pat_index;
    __u16 pad;
    union {
        __u64 obj_offset;
        __u64 userptr;
        __s64 cpu_addr_mirror_offset;
    };
    __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);
#define DRM_XE_VM_BIND_FLAG_CHECK_PXP   (1 << 4);
#define DRM_XE_VM_BIND_FLAG_CPU_ADDR_MIRROR     (1 << 5);
    __u32 flags;
    __u32 prefetch_mem_region_instance;
    __u32 pad2;
    __u64 reserved[3];
};

成员

extensions

struct drm_xe_device_query

返回的 VM ID

flags

pat_index

DRM_XE_VM_CREATE_FLAG_SCRATCH_PAGE - 将 VM 的整个虚拟地址空间映射到暂存页面。 vm_bind 会覆盖暂存页面映射。此标志与 DRM_XE_VM_CREATE_FLAG_FAULT_MODE 标志互斥,但在 x2 和 xe3 平台上除外。

DRM_XE_VM_CREATE_FLAG_LR_MODE - LR 或长时间运行的 VM 接受对其 exec_queues 的 exec 提交,这些提交对作业执行时间没有上限。但对这些 exec 的提交不允许任何标志 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 的输入

vm_id

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

pad

MBZ

{unnamed_union}

anonymous

obj_offset

对象中的偏移量,对于 CLEAR_RANGE 必须为零,对于取消绑定将被忽略

userptr

要绑定的用户指针

cpu_addr_mirror_offset

从 GPU addr 创建 CPU 地址镜像映射的偏移量。当前支持级别必须为零(例如,仅支持 GPU 和 CPU 映射之间的 1 对 1 映射)。

range

要绑定到 addr 的对象中的字节数,对于 UNMAP_ALL 必须为零

addr

要操作的地址,对于 UNMAP_ALL 必须为零

op

要执行的绑定操作

flags

绑定标志

prefetch_mem_region_instance

要将 VMA 预取的内存区域。这是一个区域实例,而不是掩码。只能与 DRM_XE_VM_BIND_OP_PREFETCH 操作一起使用。

pad2

MBZ

保留

保留

描述

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 句柄必须为零,并且 BO 偏移量必须为零。此标志旨在实现 VK 稀疏绑定。

  • DRM_XE_VM_BIND_FLAG_CHECK_PXP - 如果对象通过 PXP 加密,如果加密密钥不再有效,则拒绝绑定。此标志对未标记为使用 PXP 的 BO 无效。

  • DRM_XE_VM_BIND_FLAG_CPU_ADDR_MIRROR - 设置 CPU 地址镜像标志后,不会创建任何映射,而是为 CPU 地址镜像保留该范围,该镜像将在 GPU 页面错误或预取时填充。仅对设置了 DRM_XE_VM_CREATE_FLAG_FAULT_MODE 的 VM 有效。CPU 地址镜像标志仅对 DRM_XE_VM_BIND_OP_MAP 操作有效,BO 句柄必须为零,并且 BO 偏移量必须为零。

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

struct drm_xe_device_query

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 数组的指针

保留

保留

描述

以下是 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;
#define DRM_XE_EXEC_QUEUE_SET_PROPERTY_PXP_TYPE               2;
    __u64 extensions;
    __u16 width;
    __u16 num_placements;
    __u32 vm_id;
#define DRM_XE_EXEC_QUEUE_LOW_LATENCY_HINT      (1 << 0);
    __u32 flags;
    __u32 exec_queue_id;
    __u64 instances;
    __u64 reserved[2];
};

成员

extensions

struct drm_xe_device_query

width

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

num_placements

此执行队列的有效位置数

vm_id

此执行队列要使用的 VM

flags

此执行队列要使用的标志

exec_queue_id

返回的执行队列 ID

instances

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

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

保留

保留

描述

此 ioctl 支持通过 DRM_XE_EXEC_QUEUE_EXTENSION_SET_PROPERTY 扩展设置以下属性,该扩展使用通用的 drm_xe_ext_set_property 结构

  • DRM_XE_EXEC_QUEUE_SET_PROPERTY_PRIORITY - 设置队列优先级。需要 CAP_SYS_NICE 才能设置高于正常的值。

  • DRM_XE_EXEC_QUEUE_SET_PROPERTY_TIMESLICE - 设置队列时间片持续时间,以微秒为单位。

  • DRM_XE_EXEC_QUEUE_SET_PROPERTY_PXP_TYPE - 设置此队列将使用的 PXP 会话的类型。有效值在 enum drm_xe_pxp_session_type 中列出。DRM_XE_PXP_TYPE_NONE 是默认行为,因此无需显式设置它。创建 DRM_XE_PXP_TYPE_HWDRM 类型的队列时,将启动 PXP 默认 HWDRM 会话(XE_PXP_HWDRM_DEFAULT_SESSION),如果尚未运行。用户应通过查询 ioctl 查询 PXP 状态(请参阅 DRM_XE_DEVICE_QUERY_PXP_STATUS)并等待 PXP 准备就绪,然后再尝试创建具有此属性的队列。如果在 PXP 准备就绪之前创建队列,则如果初始化仍在进行中,ioctl 将返回 -EBUSY;如果初始化失败,则返回 -EIO。鉴于进入省电状态会终止 PXP HWDRM 会话,因此在此类型的队列处于活动状态时,将阻止运行时 PM。如果发生 PXP 失效事件,所有 PXP 队列都将被终止。

下面的示例展示了如何使用 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);

Allow users to provide a hint to kernel for cases demanding low latency
profile. Please note it will have impact on power consumption. User can
indicate low latency hint with flag while creating exec queue as
mentioned below,

struct drm_xe_exec_queue_create exec_queue_create = {
     .flags = DRM_XE_EXEC_QUEUE_LOW_LATENCY_HINT,
     .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

保留

保留

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

struct drm_xe_device_query

exec_queue_id

执行队列 ID

属性

要获取的属性

value

属性值

保留

保留

描述

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

struct drm_xe_device_query

type

此同步对象的类型

flags

同步标志

{unnamed_union}

anonymous

handle

对象的句柄

addr

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

timeline_value

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

保留

保留

描述

这是硬件拓扑,它反映了 GPU 的内部物理结构。
  • 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

struct drm_xe_device_query

exec_queue_id

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

num_syncs

数组中 struct drm_xe_sync 的数量。

syncs

指向 struct drm_xe_sync 数组的指针。

address

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

num_batch_buffer

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

pad

MBZ

保留

保留

描述

以下示例展示了如何使用 drm_xe_exec 通过 exec_queue(请参阅 drm_xe_exec_queue_create 中的示例)执行 BIND_ADDRESS 处的对象(请参阅 drm_xe_vm_bind 中的示例)。可以使用为 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

struct drm_xe_device_query

addr

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

op

等待操作(比较类型)

flags

等待标志

pad

MBZ

value

比较值

num_bytes

比较掩码

timeout

放弃等待前的等待时间,以纳秒为单位。如果不设置 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

保留

保留

描述

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

(*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 观察流类型

DRM_XE_OBSERVATION_TYPE_EU_STALL

EU 停顿采样观察流类型

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

struct drm_xe_device_query

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);
#define DRM_XE_OA_CAPS_OA_BUFFER_SIZE   (1 << 2);
#define DRM_XE_OA_CAPS_WAIT_NUM_REPORTS (1 << 3);
    __u64 oa_timestamp_freq;
    __u64 reserved[4];
    __u64 num_engines;
    struct drm_xe_engine_class_instance eci[];
};

成员

extensions

struct drm_xe_device_query

oa_unit_id

OA 单元 ID

oa_unit_type

drm_xe_oa_unit_type 的 OA 单元类型

capabilities

OA 功能位掩码

oa_timestamp_freq

OA 时间戳频率

保留

MBZ

num_engines

eci 数组中的引擎数量

struct drm_xe_query_engine_cycles

附加到此 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

struct drm_xe_device_query

num_oa_units

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

pad

MBZ

oa_units

为此设备返回的 struct drm_xe_oa_unit 数组。下面写成 u64 数组以避免某些编译器中嵌套的灵活数组出现问题

描述

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

可以使用下面的代码块访问所有 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_OA_PROPERTY_OA_BUFFER_SIZE

驱动程序要分配的 OA 缓冲区的大小,以字节为单位。支持的大小是 2 的幂,从 128 KiB 到 128 MiB。如果未指定,默认情况下将分配 16 MiB OA 缓冲区。

DRM_XE_OA_PROPERTY_WAIT_NUM_REPORTS

取消阻止轮询或读取之前要等待的报告数

描述

流参数指定为 drm_xe_ext_set_property 结构的链,其中 property 值来自枚举 drm_xe_oa_property_id 并且 drm_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

struct drm_xe_device_query

uuid

字符串格式为“%08x-%04x-%04x-%04x-%012x”

n_regs

regs_ptr 中的 regs 数

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

struct drm_xe_device_query

oa_status

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

保留

保留供将来使用

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

struct drm_xe_device_query

oa_buf_size

OA 缓冲区大小

保留

保留供将来使用

enum drm_xe_pxp_session_type

支持的 PXP 会话类型。

常量

DRM_XE_PXP_TYPE_NONE

未使用 PXP

DRM_XE_PXP_TYPE_HWDRM

HWDRM 会话用于最终显示的内容。

描述

我们目前仅支持 HWDRM 会话,该会话用于最终被显示的受保护内容,但 HW 支持多种类型,因此我们可能会在将来扩展支持。

enum drm_xe_eu_stall_property_id

EU 停顿采样输入属性 ID。

常量

DRM_XE_EU_STALL_PROP_GT_ID

将在其上捕获 EU 停顿数据的 GT 的 gt_id

DRM_XE_EU_STALL_PROP_SAMPLE_RATE

来自 struct drm_xe_query_eu_stallsampling_rates 的 GPU 周期中的采样率

DRM_XE_EU_STALL_PROP_WAIT_NUM_REPORTS

在取消阻止阻塞的轮询或读取之前,内核缓冲区中存在的最小 EU 停顿数据报告数。

描述

这些属性在打开时作为 drm_xe_ext_set_property 结构的链传递给驱动程序,其中 property 设置为这些属性的枚举,value 设置为这些属性的相应值。drm_xe_user_extension base.name 应设置为 DRM_XE_EU_STALL_EXTENSION_SET_PROPERTY

使用从打开获得的 文件描述符,用户空间必须在使用 read() 之前使用 DRM_XE_OBSERVATION_IOCTL_ENABLE 启用 EU 停顿流 fd。来自 read() 的 EIO errno 指示由于缓冲区已满,HW 丢弃了数据。

struct drm_xe_query_eu_stall

有关 EU 停顿采样的信息。

定义:

struct drm_xe_query_eu_stall {
    __u64 extensions;
    __u64 capabilities;
#define DRM_XE_EU_STALL_CAPS_BASE               (1 << 0);
    __u64 record_size;
    __u64 per_xecore_buf_size;
    __u64 reserved[5];
    __u64 num_sampling_rates;
    __u64 sampling_rates[];
};

成员

extensions

struct drm_xe_device_query

capabilities

EU 停顿功能位掩码

record_size

每个 EU 停顿数据记录的大小

per_xecore_buf_size

内部每个 XeCore 缓冲区大小

保留

保留

num_sampling_rates

sampling_rates 数组中的采样率数

sampling_rates

采样率的灵活数组,按最快到最慢的顺序排序。采样率以 GPU 时钟周期指定。

描述

如果使用 .query 等于 DRM_XE_DEVICE_QUERY_EU_STALL 的 struct drm_xe_device_query 进行查询,则回复在 .data 中使用 struct drm_xe_query_eu_stall

drm/asahi uAPI

Asahi UAPI 简介

本文档介绍了 Asahi IOCTL。

关于传递给 Asahi IOCTL 的数据的一些通用规则(从 Panthor 抄来的)

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

  • 字段必须与其自然类型对齐对齐,使用 pad[0..N] 字段。

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

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

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

  • 如果传递了大小以反映用户空间驱动程序已知的大小(请参阅 drm_asahi_cmd_header::size),则可以将新字段添加到间接对象(主结构指向的对象)。

  • 如果内核驱动程序太旧而无法识别某些字段,则如果它们为零将被忽略,否则将被拒绝(因此在输出时将为零)。

  • 如果 userspace 太旧而无法识别某些字段,则在内核驱动程序解析结构体之前,这些字段将被清零(输入)。

  • 每个新的标志/字段添加都必须附带驱动程序版本更新,以便用户空间驱动程序不必猜测支持哪些标志。

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

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

enum drm_asahi_ioctl_id

IOCTL ID

常量

DRM_ASAHI_GET_PARAMS

查询设备属性。

DRM_ASAHI_GET_TIME

查询设备时间。

DRM_ASAHI_VM_CREATE

创建 GPU VM 地址空间。

DRM_ASAHI_VM_DESTROY

销毁 VM。

DRM_ASAHI_VM_BIND

将内存绑定/解除绑定到 VM。

DRM_ASAHI_GEM_CREATE

创建缓冲区对象。

DRM_ASAHI_GEM_MMAP_OFFSET

获取要传递给 mmap() 以映射给定 GEM 句柄的偏移量。

DRM_ASAHI_GEM_BIND_OBJECT

将内存绑定为特殊对象

DRM_ASAHI_QUEUE_CREATE

创建调度队列。

DRM_ASAHI_QUEUE_DESTROY

销毁调度队列。

DRM_ASAHI_SUBMIT

将命令提交到队列。

描述

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

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

struct drm_asahi_params_global

全局参数。

定义:

struct drm_asahi_params_global {
    __u64 features;
    __u32 gpu_generation;
    __u32 gpu_variant;
    __u32 gpu_revision;
    __u32 chip_id;
    __u32 num_dies;
    __u32 num_clusters_total;
    __u32 num_cores_per_cluster;
    __u32 max_frequency_khz;
    __u64 core_masks[DRM_ASAHI_MAX_CLUSTERS];
    __u64 vm_start;
    __u64 vm_end;
    __u64 vm_kernel_min_size;
    __u32 max_commands_per_submission;
    __u32 max_attachments;
    __u64 command_timestamp_frequency_hz;
};

成员

features

来自 drm_asahi_feature 的功能位

gpu_generation

GPU 代数,例如 G13G 为 13

gpu_variant

GPU 变体,例如 G13C 的“C”

gpu_revision

BCD 中的 GPU 修订版,例如 “A0” 为 0x00 或 “C1” 为 0x21

chip_id

BCD 中的芯片 ID,例如 T8103 为 0x8103

num_dies

SoC 中的晶片数量

num_clusters_total

GPU 集群数量(跨所有晶片)

num_cores_per_cluster

每个集群的逻辑核心数(包括非活动/不存在的)

max_frequency_khz

最大 GPU 核心时钟频率

core_masks

每个集群中存在的/启用的核心的位掩码

vm_start

VM 范围起始 VMA。与 vm_end 一起,这定义了有效 GPU VA 的窗口。用户空间应从此窗口中细分 VA。

此窗口包含用户空间需要了解的所有虚拟地址。此范围之外可能存在内核内部 GPU VA,但此细节不相关。

vm_end

VM 范围结束 VMA

vm_kernel_min_size

最小内核 VMA 窗口大小。

创建 VM 时,用户空间需要划分一个虚拟地址部分(在 vm_startvm_end 给出的范围内)。内核将在指定的 VA 范围内分配各种内部结构。

允许用户空间选择内核的 VA 范围,而不是内核保留 VA 并要求用户空间处理,这有助于实现 SVM。

max_commands_per_submission

每次提交支持的最大命令数。这反映了固件限制。用户空间必须拆分更大的命令缓冲区,这可能需要插入额外的同步。

max_attachments

每个命令的最大 drm_asahi_attachment 数

command_timestamp_frequency_hz

命令执行期间写入的时间戳的时基频率,通过 drm_asahi_timestamp 结构指定。由于此速率由固件控制,因此它是一个可查询的参数。

用户空间必须除以此频率才能将时间戳转换为秒,而不是硬编码特定固件的速率。

描述

此结构可以通过 drm_asahi_get_params 查询。

enum drm_asahi_feature

功能位

常量

DRM_ASAHI_FEATURE_SOFT_FAULTS

GPU 启用了 “软故障”。对未映射内存的着色器加载将返回零。对未映射内存的着色器存储将被静默丢弃。请注意,只有着色器加载/存储受到影响。其他硬件单元不受影响,特别是包括纹理采样。

软故障在初始化 GPU 时设置,不能在运行时切换。因此,它作为功能位公开,而不是 VM 上的用户空间可设置标志。启用软故障后,用户空间可以更积极地推测内存访问。

描述

这仅涵盖用户空间无法从架构版本推断的功能。大多数功能不需要在此处。

struct drm_asahi_get_params

传递给 DRM_IOCTL_ASAHI_GET_PARAMS 的参数

定义:

struct drm_asahi_get_params {
    __u32 param_group;
    __u32 pad;
    __u64 pointer;
    __u64 size;
};

成员

param_group

要获取的参数组 (MBZ)

pad

MBZ

pointer

用于写入参数结构的用户指针

size

用户缓冲区的大小。对于旧的用户空间,这个值可能小于 sizeof(struct drm_asahi_params_global)。内核不会写入超过此处指定的长度,从而允许扩展。

struct drm_asahi_vm_create

传递给 DRM_IOCTL_ASAHI_VM_CREATE 的参数

定义:

struct drm_asahi_vm_create {
    __u64 kernel_start;
    __u64 kernel_end;
    __u32 vm_id;
    __u32 pad;
};

成员

kernel_start

内核保留地址范围的起始位置。请参阅 drm_asahi_params_global::vm_kernel_min_size。

kernel_startkernel_end 都必须在 drm_asahi_params_global::vm_start 和 drm_asahi_params_global::vm_end 给出的有效 VA 范围内。内核范围的大小 (kernel_end - kernel_start) 必须至少为 drm_asahi_params_global::vm_kernel_min_size。

用户空间不得将任何内存绑定到此 VM 的此保留范围内,此范围仅供内核使用。

kernel_end

内核保留地址范围的结束位置。请参阅 kernel_start

vm_id

DRM_IOCTL_XE_GEM_MMAP_OFFSET 的输入

pad

MBZ

struct drm_asahi_vm_destroy

传递给 DRM_IOCTL_ASAHI_VM_DESTROY 的参数

定义:

struct drm_asahi_vm_destroy {
    __u32 vm_id;
    __u32 pad;
};

成员

vm_id

要销毁的 VM ID

pad

MBZ

enum drm_asahi_gem_flags

GEM 创建的标志

常量

DRM_ASAHI_GEM_WRITEBACK

BO 应该以写回方式映射到 CPU。

以写回而不是写组合方式映射。这样可以优化 CPU 读取。

DRM_ASAHI_GEM_VM_PRIVATE

BO 是此 GPU VM 私有的(没有导出)。

struct drm_asahi_gem_create

传递给 DRM_IOCTL_ASAHI_GEM_CREATE 的参数

定义:

struct drm_asahi_gem_create {
    __u64 size;
    __u32 flags;
    __u32 vm_id;
    __u32 handle;
    __u32 pad;
};

成员

size

BO 的大小

flags

drm_asahi_gem_flags 标志的组合。

vm_id

如果设置了 DRM_ASAHI_GEM_VM_PRIVATE,则要分配给 BO 的 VM ID

handle

BO 的返回 GEM 句柄

pad

MBZ

struct drm_asahi_gem_mmap_offset

传递给 DRM_IOCTL_ASAHI_GEM_MMAP_OFFSET 的参数

定义:

struct drm_asahi_gem_mmap_offset {
    __u32 handle;
    __u32 flags;
    __u64 offset;
};

成员

handle

要映射的对象的句柄。

flags

必须为零

offset

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

enum drm_asahi_bind_flags

GEM 绑定的标志

常量

DRM_ASAHI_BIND_UNBIND

不是将 GEM 对象绑定到该范围,而是简单地解除 GPU VMA 范围的绑定。

DRM_ASAHI_BIND_READ

使用 GPU 读取权限映射 BO

DRM_ASAHI_BIND_WRITE

使用 GPU 写入权限映射 BO

DRM_ASAHI_BIND_SINGLE_PAGE

在 VA 范围内重复映射 BO 的单个页面。

这对于用暂存页或零页填充 VA 范围很有用。它旨在加速稀疏。

struct drm_asahi_gem_bind_op

单个 GEM 绑定操作的描述。

定义:

struct drm_asahi_gem_bind_op {
    __u32 flags;
    __u32 handle;
    __u64 offset;
    __u64 range;
    __u64 addr;
};

成员

flags

drm_asahi_bind_flags 标志的组合。

handle

要绑定的 GEM 对象(UNBIND 除外)

offset

对象中的偏移量(UNBIND 除外)。

对于常规绑定,这是要绑定的 GEM 对象区域的开始位置。

对于单页绑定,这是将重复绑定的单个页面的偏移量。

必须按页面大小对齐。

range

要绑定/解除绑定到 addr 的字节数。

必须按页面大小对齐。

addr

要绑定到的地址。

必须按页面大小对齐。

struct drm_asahi_vm_bind

传递给 DRM_IOCTL_ASAHI_VM_BIND 的参数

定义:

struct drm_asahi_vm_bind {
    __u32 vm_id;
    __u32 num_binds;
    __u32 stride;
    __u32 pad;
    __u64 userptr;
};

成员

vm_id

要绑定的 VM 的 ID

num_binds

此 IOCTL 中的绑定数。

stride

连续绑定之间的字节步幅。这允许扩展 drm_asahi_gem_bind_op。

pad

MBZ

userptr

指向类型为 drm_asahi_gem_bind_op 且大小为 stride 字节的 num_binds 个结构的数组的用户指针。

enum drm_asahi_bind_object_op

特殊对象绑定操作

常量

DRM_ASAHI_BIND_OBJECT_OP_BIND

将 BO 绑定为特殊的 GPU 对象

DRM_ASAHI_BIND_OBJECT_OP_UNBIND

解除绑定特殊的 GPU 对象

enum drm_asahi_bind_object_flags

特殊对象绑定标志

常量

DRM_ASAHI_BIND_OBJECT_USAGE_TIMESTAMPS

将 BO 映射为时间戳缓冲区。

struct drm_asahi_gem_bind_object

传递给 DRM_IOCTL_ASAHI_GEM_BIND_OBJECT 的参数

定义:

struct drm_asahi_gem_bind_object {
    __u32 op;
    __u32 flags;
    __u32 handle;
    __u32 vm_id;
    __u64 offset;
    __u64 range;
    __u32 object_handle;
    __u32 pad;
};

成员

op

绑定操作 (enum drm_asahi_bind_object_op)

flags

drm_asahi_bind_object_flags 标志的组合。

handle

要绑定/解除绑定的 GEM 对象 (BIND)

vm_id

要操作的 VM 的 ID(目前 MBZ)

offset

对象中的偏移量(仅限 BIND)

range

要绑定/解除绑定的字节数(仅限 BIND)

object_handle

对象句柄(BIND 的输出,UNBIND 的输入)

pad

MBZ

enum drm_asahi_cmd_type

命令类型

常量

DRM_ASAHI_CMD_RENDER

渲染命令,在渲染子队列上执行。组合顶点和片段操作。

后跟一个 drm_asahi_cmd_render 负载。

DRM_ASAHI_CMD_COMPUTE

计算子队列上的计算命令。

后跟一个 drm_asahi_cmd_compute 负载。

DRM_ASAHI_SET_VERTEX_ATTACHMENTS

软件命令,用于设置同一提交中后续顶点着色器的附件。

后跟(可能多个)drm_asahi_attachment 负载。

DRM_ASAHI_SET_FRAGMENT_ATTACHMENTS

软件命令,用于设置同一提交中后续片段着色器的附件。

后跟(可能多个)drm_asahi_attachment 负载。

DRM_ASAHI_SET_COMPUTE_ATTACHMENTS

软件命令,用于设置同一提交中后续计算着色器的附件。

后跟(可能多个)drm_asahi_attachment 负载。

enum drm_asahi_priority

调度队列优先级。

常量

DRM_ASAHI_PRIORITY_LOW

低优先级队列。

DRM_ASAHI_PRIORITY_MEDIUM

中优先级队列。

DRM_ASAHI_PRIORITY_HIGH

高优先级队列。

保留供将来扩展使用。

DRM_ASAHI_PRIORITY_REALTIME

实时优先级队列。

保留供将来扩展使用。

描述

这些优先级会转发到固件,以影响固件调度。确切的策略最终由固件决定,但这些枚举允许用户空间通信意图。

struct drm_asahi_queue_create

传递给 DRM_IOCTL_ASAHI_QUEUE_CREATE 的参数

定义:

struct drm_asahi_queue_create {
    __u32 flags;
    __u32 vm_id;
    __u32 priority;
    __u32 queue_id;
    __u64 usc_exec_base;
};

成员

flags

MBZ

vm_id

此队列绑定到的 VM 的 ID

priority

drm_asahi_priority 之一

queue_id

返回的队列 ID

usc_exec_base

此队列上所有 USC 二进制文件(着色器)的 GPU 基本地址。USC 地址是相对于此 64 位基址的 32 位地址。

这会在所有队列命令上设置以下寄存器

USC_EXEC_BASE_TA(顶点)USC_EXEC_BASE_ISP(片段)USC_EXEC_BASE_CP(计算)

虽然硬件允许我们为每个命令独立配置这些寄存器,但我们没有用例。相反,我们希望用户空间为 USC 内存修复一个 4GiB VA 划分,并在此处传递其基本地址。

struct drm_asahi_queue_destroy

传递给 DRM_IOCTL_ASAHI_QUEUE_DESTROY 的参数

定义:

struct drm_asahi_queue_destroy {
    __u32 queue_id;
    __u32 pad;
};

成员

queue_id

要销毁的队列 ID

pad

MBZ

enum drm_asahi_sync_type

同步项目类型

常量

DRM_ASAHI_SYNC_SYNCOBJ

二进制同步对象

DRM_ASAHI_SYNC_TIMELINE_SYNCOBJ

时间线同步对象

struct drm_asahi_sync

同步项目

定义:

struct drm_asahi_sync {
    __u32 sync_type;
    __u32 handle;
    __u64 timeline_value;
};

成员

sync_type

drm_asahi_sync_type 之一

handle

同步对象句柄

timeline_value

时间线同步对象的时间线值

DRM_ASAHI_BARRIER_NONE

DRM_ASAHI_BARRIER_NONE

无屏障的命令索引

描述

此特殊值可以传递到 drm_asahi_command::vdm_barrier 或 drm_asahi_command::cdm_barrier,以指示相应的子队列不应等待任何先前的工作。

struct drm_asahi_cmd_header

顶层命令结构

定义:

struct drm_asahi_cmd_header {
    __u16 cmd_type;
    __u16 size;
    __u16 vdm_barrier;
    __u16 cdm_barrier;
};

成员

cmd_type

drm_asahi_cmd_type 之一

size

此命令的大小,不包括此标头。

对于硬件命令,这允许扩展命令而无需额外的命令类型。为了向后兼容,显式允许传递比预期短的命令。截断的字段将为零。

对于合成附件设置命令,这隐式编码附件的数量。这些命令采用多个固定大小的 drm_asahi_attachment 结构作为其负载,因此大小等于附件数 * sizeof(struct drm_asahi_attachment)。

vdm_barrier

要等待的 VDM(渲染)命令索引。

屏障是相对于给定提交的开始位置的索引。屏障 0 等待提交给先前提交 ioctl 中相应子队列的命令。屏障 N 等待当前提交 ioctl 中子队列上的 N 个先前命令。作为一种特殊情况,传递 DRM_ASAHI_BARRIER_NONE 可避免等待子队列中的任何命令。

示例

0:这会等待所有先前的工作。

NONE:这不会等待此子队列上的任何内容。

1:这会等待提交中的第一个渲染命令。这仅在同一提交中有多个渲染命令时才有效。

屏障仅对硬件命令有效。用于设置附件的合成软件命令必须在此处传递 NONE。

cdm_barrier

要等待的 CDM(计算)命令索引。

请参阅 vdm_barrier,并将 VDM/渲染替换为 CDM/计算。

描述

此结构是命令缓冲区定义的核心,因此不可扩展。

struct drm_asahi_submit

传递给 DRM_IOCTL_ASAHI_SUBMIT 的参数

定义:

struct drm_asahi_submit {
    __u64 syncs;
    __u64 cmdbuf;
    __u32 flags;
    __u32 queue_id;
    __u32 in_sync_count;
    __u32 out_sync_count;
    __u32 cmdbuf_size;
    __u32 pad;
};

成员

syncs

指向 drm_asahi_sync 数组的可选指针。前 in_sync_count 个元素是输入同步对象,其余 out_sync_count 个元素是输出同步对象。使用具有显式分区的单个数组简化了处理。

cmdbuf

指向要提交的命令缓冲区的指针。

这是一个平面命令缓冲区。按照设计,它不包含 CPU 指针,这使其适用于 virtgpu 线协议,而无需任何序列化/反序列化步骤。

它由一系列命令组成。每个命令都以固定大小的 drm_asahi_cmd_header 标头开始,后跟一个根据标头中的类型和大小而定的可变长度负载。

“真实”硬件命令的组合计数必须非零且最多为 drm_asahi_params_global::max_commands_per_submission。

flags

命令提交的标志 (MBZ)

queue_id

要提交到的队列 ID

in_sync_count

在开始此作业之前要等待的同步对象的数量。

out_sync_count

此作业完成后要发出信号的同步对象的数量。

cmdbuf_size

命令缓冲区大小(以字节为单位)

pad

MBZ

struct drm_asahi_attachment

描述一个“附件”。

定义:

struct drm_asahi_attachment {
    __u64 pointer;
    __u64 size;
    __u32 pad;
    __u32 flags;
};

成员

pointer

附件的基本地址

size

附件的大小(以字节为单位)

pad

MBZ

flags

MBZ

描述

附件是由着色器写入的任何内存,尤其包括由图块结束程序写入的渲染目标附件。这纯粹是关于已访问内存区域的提示。指定它是可选的,这很幸运,因为无论如何都无法通过无绑定访问精确地指定它。但是如果可能,用户空间最好包含这些提示,并将其转发到固件。

此结构是隐式大小的,因此不可扩展。

struct drm_asahi_zls_buffer

描述深度或模板缓冲区。

定义:

struct drm_asahi_zls_buffer {
    __u64 base;
    __u64 comp_base;
    __u32 stride;
    __u32 comp_stride;
};

成员

base

缓冲区的基本地址

comp_base

如果加载缓冲区已压缩,则压缩元数据部分的地址。

stride

如果启用了分层渲染,则缓冲区每层之间的字节数。

comp_stride

如果启用了分层渲染,则压缩元数据的每层之间的字节数。

描述

这些字段分别对应于 ZLS(Z 加载/存储)单元中的硬件寄存器。每个字段分别有三个用于加载、存储和部分渲染的硬件寄存器。在实践中,将所有值设置为相同的值是有意义的,除非在用户空间中尚未实现的特殊情况下,因此为了简单/高效起见,我们在此处不重复。

此结构嵌入在其他结构中,因此不可扩展。

struct drm_asahi_timestamp

描述时间戳写入。

定义:

struct drm_asahi_timestamp {
    __u32 handle;
    __u32 offset;
};

成员

handle

时间戳缓冲区的句柄,如果跳过此时间戳,则为 0。如果为非零,则必须等于 drm_asahi_gem_bind_object::object_handle 中返回的值。

offset

写入时间戳缓冲区的偏移量

描述

固件可以选择在渲染过程粒度上写入 GPU 时间戳,但需要通过 DRM_IOCTL_ASAHI_GEM_BIND_OBJECT 进行特殊映射。因此,此结构描述了要写入的位置,作为句柄偏移量对,而不是像通常那样的 GPU 地址。

此结构嵌入在其他结构中,因此不可扩展。

struct drm_asahi_timestamps

描述时间戳写入。

定义:

struct drm_asahi_timestamps {
    struct drm_asahi_timestamp start;
    struct drm_asahi_timestamp end;
};

成员

start

在操作开始时记录的时间戳

end

在操作结束时记录的时间戳

描述

可以加盖时间戳的每个操作都可以在开始和结束时加盖时间戳。因此,drm_asahi_timestamp 结构总是成对出现,捆绑到 drm_asahi_timestamps 中。

此结构嵌入在其他结构中,因此不可扩展。

struct drm_asahi_helper_program

描述辅助程序配置。

定义:

struct drm_asahi_helper_program {
    __u32 binary;
    __u32 cfg;
    __u64 data;
};

成员

binary

辅助程序二进制文件的 USC 地址。这是一个带标记的指针,其底部位中包含配置。

cfg

辅助程序的其他配置位。

data

传递给辅助程序的数据。此值不会被内核、固件或硬件以任何方式解释。它只是用户空间的侧带,通过提交 ioctl 设置,并通过辅助程序中的特殊寄存器读取。

在实践中,用户空间将在此处传递一个 64 位 GPU VA,指向实际参数,这些参数可能不适合 64 位。

描述

辅助程序是各种硬件功能所需的类似计算的内核。其最重要的作用是通过划分整个设备共享的静态分配,为各个子组动态分配暂存/堆栈内存。它由用户空间通过 drm_asahi_helper_program 提供,并由硬件在内部根据需要进行调度。

此结构嵌入在其他结构中,因此不可扩展。

struct drm_asahi_bg_eot

描述后台程序或图块结束程序。

定义:

struct drm_asahi_bg_eot {
    __u32 usc;
    __u32 rsrc_spec;
};

成员

usc

硬件 USC 字的 USC 地址,用于绑定资源(包括图像和统一变量)以及程序本身。请注意,与辅助程序相比,这是一个额外的间接层,避免了对数据侧带的需求。这是一个带标记的指针,其底部位中包含其他配置。

rsrc_spec

程序的资源说明符。这是一个压缩的硬件数据结构,描述了所需的寄存器、统一变量、绑定纹理和绑定采样器的数量。

描述

后台程序和图块结束程序由硬件在渲染开始和结束时调度。由于硬件“图块缓冲区”只是本地内存,因此这些程序对于实现 API 级别的渲染目标是必需的。类似片段的后台程序负责加载清除颜色或现有的渲染目标内容,而类似计算的图块结束程序将图块缓冲区内容存储到内存中。

此结构嵌入在其他结构中,因此不可扩展。

struct drm_asahi_cmd_render

提交 3D 的命令

定义:

struct drm_asahi_cmd_render {
    __u32 flags;
    __u32 isp_zls_pixels;
    __u64 vdm_ctrl_stream_base;
    struct drm_asahi_helper_program vertex_helper;
    struct drm_asahi_helper_program fragment_helper;
    __u64 isp_scissor_base;
    __u64 isp_dbias_base;
    __u64 isp_oclqry_base;
    struct drm_asahi_zls_buffer depth;
    struct drm_asahi_zls_buffer stencil;
    __u64 zls_ctrl;
    __u64 ppp_multisamplectl;
    __u64 sampler_heap;
    __u32 ppp_ctrl;
    __u16 width_px;
    __u16 height_px;
    __u16 layers;
    __u16 sampler_count;
    __u8 utile_width_px;
    __u8 utile_height_px;
    __u8 samples;
    __u8 sample_size_B;
    __u32 isp_merge_upper_x;
    __u32 isp_merge_upper_y;
    struct drm_asahi_bg_eot bg;
    struct drm_asahi_bg_eot eot;
    struct drm_asahi_bg_eot partial_bg;
    struct drm_asahi_bg_eot partial_eot;
    __u32 isp_bgobjdepth;
    __u32 isp_bgobjvals;
    struct drm_asahi_timestamps ts_vtx;
    struct drm_asahi_timestamps ts_frag;
};

成员

flags

drm_asahi_render_flags 标志的组合。

isp_zls_pixels

ISP_ZLS_PIXELS 寄存器值。这包含深度/模板宽度/高度,可能与帧缓冲区宽度/高度不同。

vdm_ctrl_stream_base

VDM_CTRL_STREAM_BASE 寄存器值。指向 VDM 控制流开头的 GPU 地址。

vertex_helper

用于顶点着色器的辅助程序

fragment_helper

用于片段着色器的辅助程序

isp_scissor_base

ISP_SCISSOR_BASE 寄存器值。以渲染过程索引的剪刀描述符数组的 GPU 地址。

isp_dbias_base

ISP_DBIAS_BASE 寄存器值。以渲染过程索引的深度偏差值数组的 GPU 地址。

isp_oclqry_base

ISP_OCLQRY_BASE 寄存器值。由渲染过程写入的遮挡查询结果数组的 GPU 地址。

depth

深度缓冲区

stencil

模板缓冲区

zls_ctrl

ZLS_CTRL 寄存器值

ppp_multisamplectl

PPP_MULTISAMPLECTL 寄存器值

sampler_heap

采样器堆的基本地址。此堆用于顶点着色器和片段着色器。这些寄存器是按阶段划分的,但没有已知的使用单独堆的用例。

ppp_ctrl

PPP_CTRL 寄存器值

width_px

帧缓冲区宽度(以像素为单位)

height_px

帧缓冲区高度(以像素为单位)

layers

帧缓冲区中的层数

sampler_count

采样器堆中采样器的数量。

utile_width_px

逻辑图块缓冲区图块的宽度(以像素为单位)

utile_height_px

逻辑图块缓冲区图块的高度(以像素为单位)

samples

帧缓冲区中的采样数。必须为 1、2 或 4。

sample_size_B

每个采样所需的图块缓冲区中的字节数。

isp_merge_upper_x

用于硬件三角形合并的 32 位浮点数。计算为:tan(60 度) * 宽度。

使这些值成为 UAPI 可避免在热路径中要求内核进行浮点计算。

isp_merge_upper_y

32 位浮点数。计算为:tan(60 度) * 高度。请参阅 isp_merge_upper_x

bg

在开始时为每个图块运行的后台程序

eot

在结束时为每个图块运行的图块结束程序

partial_bg

在部分渲染期间恢复渲染过程时,在每个图块的开始处运行的后台程序。

partial_eot

在部分渲染期间暂停渲染过程时,在每个图块的结尾处运行的图块结束程序。

isp_bgobjdepth

ISP_BGOBJDEPTH 寄存器值。这是深度缓冲区清除值,以深度缓冲区的格式编码:32 位浮点数或 16 位 unorm(高位为零)。

isp_bgobjvals

ISP_BGOBJVALS 寄存器值。底部 8 位包含模板缓冲区清除值。

ts_vtx

渲染的顶点部分的时间戳

ts_frag

渲染的片段部分的时间戳

描述

此命令提交单个渲染过程。硬件控制流可能包括许多绘制和子过程,但在命令中,帧缓冲区尺寸和附件是固定的。

硬件要求固件在每个渲染 3D 的命令之前设置大量控制寄存器,以在渲染过程粒度上设置状态。固件将此状态捆绑到数据结构中。不幸的是,我们无法将任何这些直接暴露给用户空间,因为内核固件 ABI 不稳定。虽然我们可以保证固件与内核同步更新,但我们无法在升级固件和内核时中断旧的用户空间。因此,我们需要很好地抽象数据结构,以避免用未来的固件束缚自己。

因此,drm_asahi_cmd_render 的大部分由硬件控制寄存器的值组成,这些值通过固件接口进行编组。

帧缓冲区/图块缓冲区尺寸也在此处指定。除了传递给固件/硬件之外,内核还需要这些尺寸来计算各种基本图块相关的数据结构。不幸的是,我们的提交比在具有更健全的硬件-软件接口的供应商上更重。结果是所有这些信息都可以通过所有当前的 API 轻松地提供给用户空间。

它看起来很奇怪 - 但它不是过于繁重,并且它确保我们可以与旧的用户空间保持兼容。

struct drm_asahi_cmd_compute

提交计算的命令

定义:

struct drm_asahi_cmd_compute {
    __u32 flags;
    __u32 sampler_count;
    __u64 cdm_ctrl_stream_base;
    __u64 cdm_ctrl_stream_end;
    __u64 sampler_heap;
    struct drm_asahi_helper_program helper;
    struct drm_asahi_timestamps ts;
};

成员

flags

MBZ

sampler_count

采样器堆中采样器的数量。

cdm_ctrl_stream_base

CDM_CTRL_STREAM_BASE 寄存器值。指向 CDM 控制流开头的 GPU 地址。

cdm_ctrl_stream_end

指向硬件控制流末尾的 GPU 基本地址。请注意,这仅考虑了控制流的第一个连续段,因为流可能会跳转到其他位置。

sampler_heap

采样器堆的基本地址。

helper

用于此计算命令的辅助程序

ts

计算命令的时间戳

描述

此命令提交由计算调度组成的控制流。单个计算命令中可以包含的计算调度本质上没有限制,尽管时间戳是在命令粒度上进行的。

struct drm_asahi_get_time

传递给 DRM_IOCTL_ASAHI_GET_TIME 的参数

定义:

struct drm_asahi_get_time {
    __u64 flags;
    __u64 gpu_timestamp;
};

成员

flags

MBZ。

gpu_timestamp

返回时,GPU 时间戳(以纳秒为单位)。

DRM_IOCTL_ASAHI

DRM_IOCTL_ASAHI (__access, __id, __type)

生成 Asahi IOCTL 编号

参数

__access

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

__id

DRM_ASAHI_xxx id 之一。

__type

传递给 IOCTL 的类型的后缀。

描述

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

Return

要从 userspace 传递给 ioctl() 的 IOCTL 数字。