I915 Small BAR RFC 章节¶
从 DG2 开始,我们将支持设备本地内存(即 I915_MEMORY_CLASS_DEVICE)的可调整大小的 BAR 支持,但在某些情况下,最终的 BAR 大小可能仍小于总探测大小。在这种情况下,只有 I915_MEMORY_CLASS_DEVICE 的一部分可以被 CPU 访问(例如前 256M),而其余部分只能通过 GPU 访问。
I915_GEM_CREATE_EXT_FLAG_NEEDS_CPU_ACCESS 标志¶
新的 gem_create_ext 标志,用于告知内核一个 BO 将需要 CPU 访问。当将对象放置在 I915_MEMORY_CLASS_DEVICE 中时,这变得非常重要,因为底层设备具有一个小的 BAR,这意味着只有一部分可以被 CPU 访问。如果没有此标志,内核将假定不需要 CPU 访问,并优先使用 I915_MEMORY_CLASS_DEVICE 中非 CPU 可见的部分。
-
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;
__u64 extensions;
};
成员
size
对象请求的大小。
将返回对象的(页对齐的)已分配大小。
请注意,对于某些设备,我们可能还有其他最小页面大小限制(大于 4K),例如对于设备本地内存。但是,通常,如果使用 I915_GEM_CREATE_EXT_MEMORY_REGIONS 扩展将对象放置在设备本地内存中,则此处的最终大小应始终反映任何向上舍入。内核将始终为一组可能的放置选择最大的最小页面大小作为向上舍入 **size** 时使用的值。
handle
返回对象的句柄。
对象句柄为非零。
flags
可选标志。
支持的值
I915_GEM_CREATE_EXT_FLAG_NEEDS_CPU_ACCESS - 向内核发出信号,表明该对象将需要通过 CPU 访问。
仅在将对象放置在 I915_MEMORY_CLASS_DEVICE 中时有效,并且仅在设备内存的某些子集可以直接通过 CPU 可见/映射的配置中严格需要(我们也称之为 small 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 故障,内核仍然可以将该对象迁移到可映射部分,作为最后的手段,但这可能会很昂贵,因此理想情况下应避免这种情况。
在缺少相关 small-bar uAPI 支持的旧内核上(另请参见
__drm_i915_memory_region_info.probed_cpu_visible_size
),使用该标志将导致错误,但假设我们也可以成功加载 i915 内核模块,则永远不可能最终得到 small 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
。
描述
请注意,新的缓冲区标志应该在此处添加,至少对于不可变的东西。以前,我们将有两个 ioctl,一个用于使用 gem_create 创建对象,另一个用于应用各种参数,但是这为被认为是不可变的参数创建了一些歧义。通常,我们也在逐步淘汰各种 SET/GET ioctl。
probed_cpu_visible_size 属性¶
新的 struct__drm_i915_memory_region 属性,用于返回特定区域的 CPU 可访问部分的总大小。这应该仅适用于 I915_MEMORY_CLASS_DEVICE。我们还报告 unallocated_cpu_visible_size,以及 unallocated_size。
Vulkan 将需要此作为创建具有 VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT 设置的单独 VkMemoryHeap 的一部分,以表示 CPU 可见部分,其中需要知道堆的总大小。它还希望能够大致估计内存的潜在分配方式。
-
struct __drm_i915_memory_region_info¶
描述驱动程序已知的一个区域。
定义:
struct __drm_i915_memory_region_info {
struct drm_i915_gem_memory_class_instance region;
__u32 rsvd0;
__u64 probed_size;
__u64 unallocated_size;
union {
__u64 rsvd1[8];
struct {
__u64 probed_cpu_visible_size;
__u64 unallocated_cpu_visible_size;
};
};
};
成员
region
类:实例对编码
rsvd0
MBZ
probed_size
驱动程序探测到的内存
请注意,永远不可能遇到零值,还请注意,当前没有区域类型会在此处返回 -1。虽然对于将来的区域类型,这可能是一种可能性。其他大小字段也适用。
unallocated_size
剩余内存的估计
需要 CAP_PERFMON 或 CAP_SYS_ADMIN 才能获得可靠的帐户信息。如果没有此权限(或者如果这是一个旧内核),则此处的值将始终等于 **probed_size**。请注意,这目前仅针对 I915_MEMORY_CLASS_DEVICE 区域进行跟踪(对于其他类型,此处的值将始终等于 **probed_size**)。
{unnamed_union}
anonymous
rsvd1
MBZ
{unnamed_struct}
anonymous
probed_cpu_visible_size
驱动程序探测到的 CPU 可访问的内存。
这将始终 <= **probed_size**,其余部分(如果有)将无法被 CPU 访问。
在没有 small BAR 的系统上,**probed_size** 将始终等于 **probed_cpu_visible_size**,因为所有这些都将被 CPU 访问。
请注意,这仅针对 I915_MEMORY_CLASS_DEVICE 区域进行跟踪(对于其他类型,此处的值将始终等于 **probed_size**)。
请注意,如果此处返回的值为零,那么这必须是缺少相关 small-bar uAPI 支持的旧内核(包括 I915_GEM_CREATE_EXT_FLAG_NEEDS_CPU_ACCESS),但在这样的系统上,我们实际上永远不应该最终得到 small 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。
错误捕获限制¶
使用错误捕获,我们有两个新的限制
1) 在 small BAR 系统上,错误捕获是尽力而为的;如果在捕获时页面无法被 CPU 访问,则内核可以自由地跳过尝试捕获它们。
2) 在独立和较新的集成平台上,我们现在拒绝在可恢复的上下文中进行错误捕获。将来,当某些内容当前无法被 CPU 访问时,内核可能希望在错误捕获期间进行 blit。