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_domains 和 write_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_ptr 和 value_ptr 数组中的元素数。
handles_ptr
指向长度为 fence_count 的
struct 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_INVALID 和 I915_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 有
DRM_I915_QUERY_TOPOLOGY_INFO
(请参阅struct drm_i915_query_topology_info
)DRM_I915_QUERY_ENGINE_INFO
(参见struct drm_i915_engine_info
)DRM_I915_QUERY_PERF_CONFIG
(参见struct drm_i915_query_perf_config
)DRM_I915_QUERY_MEMORY_REGIONS
(参见struct drm_i915_query_memory_regions
)DRM_I915_QUERY_HWCONFIG_BLOB
(参见 GuC HWCONFIG blob uAPI)DRM_I915_QUERY_GEOMETRY_SUBSLICES
(参见struct drm_i915_query_topology_info
)DRM_I915_QUERY_GUC_SUBMISSION_VERSION
(参见struct drm_i915_query_guc_submission_version
)
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
,这通常是一个两步过程
调用 DRM_IOCTL_I915_QUERY,提供我们的
struct drm_i915_query_item
数组,并将drm_i915_query_item.length
设置为零。然后,内核将填充大小(以字节为单位),以告知用户空间需要为 blob 分配多少内存(例如,用于属性数组)。接下来,我们再次调用 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_CONFIG
和 DRM_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
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_item
和 struct 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
的数组或 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)®ion_lmem,
.num_regions = 1,
};
struct drm_i915_gem_create_ext create_ext = {
.size = 16 * PAGE_SIZE,
.extensions = (uintptr_t)®ions,
};
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_SPARSE
- 指示分配的 VA 空间区域应为稀疏。 handle
要映射的 DRM GEM 对象的句柄
pad
32 位填充,应为 0
addr
VA 空间区域或(内存支持)映射应映射到的地址
bo_offset
支持映射的 BO 中的偏移量
range
请求映射的大小(以字节为单位)
描述
此结构表示单个 VM_BIND 操作。 UMD 应通过 struct drm_nouveau_vm_bind
的 op_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
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_exec
的 push_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_create 和 drm_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_64KDRM_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_cycles
。struct 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
要创建的对象的大小,必须与区域(系统或 vram)最小对齐 (
min_page_size
) 匹配。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[];
};
成员
-
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_FENCE,addr 是一个用户指针,类似于 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_stall 中 sampling_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_start 和 vm_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_start 和 kernel_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
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 数字。