核心驱动程序基础设施

GPU 硬件结构

每个 ASIC 都是硬件块的集合。 我们将它们称为“IP”(知识产权块)。 每个 IP 封装了特定的功能。 IP 是有版本的,也可以混合和匹配。 例如,您可能有两个不同的 ASIC,它们都具有 System DMA (SDMA) 5.x IP。 驱动程序按 IP 排列。 有驱动程序组件来处理每个 IP 的初始化和操作。 还有一些较小的 IP,实际上不需要太多驱动程序交互。 这些最终会被归入 soc 文件中的常见内容中。 soc 文件(例如 vi.c、soc15.c nv.c)包含 SoC 本身方面的代码,而不是特定 IP。 例如,诸如 GPU 重置和寄存器访问功能之类的东西是 SoC 相关的。

APU 包含的不仅仅是 CPU 和 GPU,它还包含所有平台内容(音频、USB、GPIO 等)。 此外,许多组件在 CPU、平台和 GPU 之间共享(例如,SMU、PSP 等)。 特定组件(CPU、GPU 等)通常具有与其交互的接口,这些通用组件。 对于像 S0i3 这样的东西,需要在所有组件之间进行大量的协调,但这可能有点超出本节的范围。

关于 GPU,我们有以下主要 IP

GMC(图形内存控制器)

这在较旧的 pre-vega 芯片上是一个专用 IP,但自 Vega 和更新的芯片以来,它在某种程度上变得分散。 它们现在为特定的 IP 或 IP 组配备了专用的内存集线器。 但是,我们在驱动程序中仍然将其视为单个组件,因为编程模型仍然非常相似。 这是 GPU 上的不同 IP 获取内存(VRAM 或系统内存)的方式。 它还为每个进程 GPU 虚拟地址空间提供支持。

IH(中断处理程序)

这是 GPU 上的中断控制器。 所有 IP 都将其中断馈送到此 IP,它将它们聚合到一组环形缓冲区中,驱动程序可以解析这些缓冲区以处理来自不同 IP 的中断。

PSP(平台安全处理器)

它处理 SoC 的安全策略并执行受信任的应用程序,并验证和加载其他块的固件。

SMU(系统管理单元)

这是电源管理微控制器。 它管理整个 SoC。 驱动程序与它交互以控制时钟、电压、电源轨等电源管理功能。

DCN(下一代显示控制器)

这是显示控制器。 它处理显示硬件。 在 显示核心 中进行了更详细的描述。

SDMA(系统 DMA)

这是一个多用途 DMA 引擎。 内核驱动程序将其用于各种用途,包括分页和 GPU 页表更新。 它也暴露给用户空间,供用户模式驱动程序(OpenGL、Vulkan 等)使用。

GC(图形和计算)

这是图形和计算引擎,即包含 3D 管道和着色器块的块。 这是 GPU 上迄今为止最大的块。 3D 管道有大量的子块。 除此之外,它还包含 CP 微控制器(ME、PFP、CE、MEC)和 RLC 微控制器。 它暴露给用户空间,供用户模式驱动程序(OpenGL、Vulkan、OpenCL 等)使用。 在 图形 (GFX) 和计算 中提供了更多详细信息。

VCN(下一代视频核心)

这是多媒体引擎。 它处理视频和图像编码和解码。 它暴露给用户空间,供用户模式驱动程序(VA-API、OpenMAX 等)使用。

GFX、计算和 SDMA 总体行为

注意

为简单起见,只要在本节中使用术语块,它就表示 GFX、计算和 SDMA。

GFX、计算和 SDMA 共享一种类似的操作形式,可以对其进行抽象以方便理解这些块的行为。 请参见下图,该图说明了这些块的常见组件

../../_images/pipe_and_queue_abstraction.svg

在此图的中心部分,您可以看到两个硬件元件,一个称为 管道,另一个称为 队列; 重要的是要强调队列必须与管道相关联,反之亦然。 每个特定的硬件 IP 可能具有不同数量的管道,进而具有不同数量的队列; 例如,GFX 11 每个管道有两个管道和两个队列,用于 GFX 前端。

管道是处理队列中可用指令的硬件; 换句话说,它是一个执行插入队列中的操作的线程。 管道的一个关键特征是它们一次只能执行一个队列; 无论硬件在管道中有多少个队列,它每个管道只运行一个队列。

管道具有在硬件级别在队列之间交换的机制。 然而,它们仅利用被认为是映射的队列。 管道可以基于以下任何输入在队列之间切换

  1. 命令流;

  2. 逐个数据包;

  3. 其他硬件请求更改(例如,MES)。

管道中的队列由硬件队列描述符 (HQD) 定义。 与 HQD 概念相关联,我们有内存队列描述符 (MQD),它负责存储有关内存中每个可用队列状态的信息。 队列的状态包含诸如队列本身的 GPU 虚拟地址、保存区域、门铃等信息。 MQD 还存储 HQD 寄存器,这对于激活或停用给定的队列至关重要。 调度固件(例如,MES)负责从 MQD 加载 HQD,反之亦然。

队列切换过程也可能发生在固件请求抢占或取消映射队列时。 固件等待 HQD_ACTIVE 位变为低电平,然后将状态保存到 MQD 中。 为了使不同的队列变为活动队列,固件将 MQD 状态复制到 HQD 寄存器中并加载任何其他状态。 最后,它将 HQD_ACTIVE 位设置为高电平,以指示队列处于活动状态。 然后,管道将执行来自活动队列的工作。

驱动程序结构

通常,驱动程序具有特定 SoC 上所有 IP 的列表,并且对于诸如 init/fini/suspend/resume 之类的事情,或多或少只是遍历列表并处理每个 IP。

一些有用的构造

KIQ(内核接口队列)

这是内核驱动程序用来管理 GFX/计算引擎上的其他 gfx 和计算队列的控制队列。 您可以使用它来映射/取消映射其他队列等。 这在 GFX 11 和更新的硬件上被 MES 取代。

IB(间接缓冲区)

特定引擎的命令缓冲区。 您可以将命令写入内存块中,而不是直接将命令写入队列中,然后将指向该内存的指针放入队列中。 然后,硬件将跟踪指针并执行内存中的命令,然后返回到环形缓冲区中的其余命令。

内存域

AMDGPU_GEM_DOMAIN_CPU 不是 GPU 可访问的系统内存。 如果存在压力,此池中的内存可能会被交换到磁盘。

AMDGPU_GEM_DOMAIN_GTT GPU 可访问的系统内存,通过 gart 映射到 GPU 的虚拟地址空间中。 Gart 内存线性化系统内存的非连续页面,允许 GPU 以线性方式访问系统内存。

AMDGPU_GEM_DOMAIN_VRAM 本地视频内存。 对于 APU,它是 BIOS 雕刻出的内存。

AMDGPU_GEM_DOMAIN_GDS 用于跨着色器线程共享数据的全局片上数据存储。

AMDGPU_GEM_DOMAIN_GWS 全局波同步,用于同步设备上所有波的执行。

AMDGPU_GEM_DOMAIN_OA 有序追加,由 3D 或计算引擎用于追加数据。

AMDGPU_GEM_DOMAIN_DOORBELL 门铃。 它是用于向用户模式队列发出信号的 MMIO 区域。

缓冲区对象

这定义了在 amdgpu_bo 缓冲区对象上进行操作的接口,该对象表示驱动程序使用的内存(VRAM、系统内存等)。 驱动程序为用户空间提供 DRM/GEM API。 然后,DRM/GEM API 使用这些接口来创建/销毁/设置缓冲区对象,然后由内核 TTM 内存管理器管理这些对象。 这些接口也供内核客户端在内部使用,包括 gfx、uvd 等,用于 GPU 使用的内核管理分配。

bool amdgpu_bo_is_amdgpu_bo(struct ttm_buffer_object *bo)

检查缓冲区对象是否为 amdgpu_bo

参数

struct ttm_buffer_object *bo

要检查的缓冲区对象

描述

使用与对象关联的销毁函数来确定这是否为 amdgpu_bo

返回

如果对象属于 amdgpu_bo,则为 true,否则为 false。

void amdgpu_bo_placement_from_domain(struct amdgpu_bo *abo, u32 domain)

设置缓冲区的放置位置

参数

struct amdgpu_bo *abo

amdgpu_bo 要设置放置位置的缓冲区对象

u32 domain

请求的域

描述

根据请求的域和缓冲区的标志设置缓冲区的放置位置。

int amdgpu_bo_create_reserved(struct amdgpu_device *adev, unsigned long size, int align, u32 domain, struct amdgpu_bo **bo_ptr, u64 *gpu_addr, void **cpu_addr)

为内核使用创建保留的 BO

参数

struct amdgpu_device *adev

amdgpu 设备对象

unsigned long size

新 BO 的大小

int align

新 BO 的对齐方式

u32 domain

将其放置在何处

struct amdgpu_bo **bo_ptr

用于初始化结构中的 BO

u64 *gpu_addr

固定 BO 的 GPU 地址

void **cpu_addr

可选的 CPU 地址映射

描述

为内核内部使用分配和固定 BO,并返回仍保留的 BO。

注意

对于 bo_ptr,仅当 bo_ptr 指向 NULL 时才创建新 BO。

返回

成功时为 0,否则为负错误代码。

int amdgpu_bo_create_kernel_at(struct amdgpu_device *adev, uint64_t offset, uint64_t size, struct amdgpu_bo **bo_ptr, void **cpu_addr)

在特定位置为内核使用创建 BO

参数

struct amdgpu_device *adev

amdgpu 设备对象

uint64_t offset

BO 的偏移量

uint64_t size

BO 的大小

struct amdgpu_bo **bo_ptr

用于初始化结构中的 BO

void **cpu_addr

可选的 CPU 地址映射

描述

在 VRAM 中的特定偏移量处创建内核 BO。

返回

成功时为 0,否则为负错误代码。

int amdgpu_bo_create(struct amdgpu_device *adev, struct amdgpu_bo_param *bp, struct amdgpu_bo **bo_ptr)

创建一个 amdgpu_bo 缓冲区对象

参数

struct amdgpu_device *adev

amdgpu 设备对象

struct amdgpu_bo_param *bp

要用于缓冲区对象的参数

struct amdgpu_bo **bo_ptr

指向缓冲区对象指针的指针

描述

创建 amdgpu_bo 缓冲区对象。

返回

成功时为 0,失败时为负错误代码。

int amdgpu_bo_create_user(struct amdgpu_device *adev, struct amdgpu_bo_param *bp, struct amdgpu_bo_user **ubo_ptr)

创建 amdgpu_bo_user 缓冲区对象

参数

struct amdgpu_device *adev

amdgpu 设备对象

struct amdgpu_bo_param *bp

要用于缓冲区对象的参数

struct amdgpu_bo_user **ubo_ptr

指向缓冲区对象指针的指针

描述

创建一个要由用户应用程序使用的 BO;

返回

成功时为 0,失败时为负错误代码。

int amdgpu_bo_create_vm(struct amdgpu_device *adev, struct amdgpu_bo_param *bp, struct amdgpu_bo_vm **vmbo_ptr)

创建 amdgpu_bo_vm 缓冲区对象

参数

struct amdgpu_device *adev

amdgpu 设备对象

struct amdgpu_bo_param *bp

要用于缓冲区对象的参数

struct amdgpu_bo_vm **vmbo_ptr

指向缓冲区对象指针的指针

描述

创建一个用于 GPUVM 的 BO。

返回

成功时为 0,失败时为负错误代码。

int amdgpu_bo_kmap(struct amdgpu_bo *bo, void **ptr)

映射 amdgpu_bo 缓冲区对象

参数

struct amdgpu_bo *bo

要映射的 amdgpu_bo 缓冲区对象

void **ptr

要返回的内核虚拟地址

描述

调用 ttm_bo_kmap() 设置内核虚拟映射; 调用 amdgpu_bo_kptr() 获取内核虚拟地址。

返回

成功时为 0,失败时为负错误代码。

void *amdgpu_bo_kptr(struct amdgpu_bo *bo)

返回缓冲区对象的内核虚拟地址

参数

struct amdgpu_bo *bo

amdgpu_bo 缓冲区对象

描述

调用 ttm_kmap_obj_virtual() 获取内核虚拟地址

返回

缓冲区对象区域的虚拟地址。

void amdgpu_bo_kunmap(struct amdgpu_bo *bo)

取消映射 amdgpu_bo 缓冲区对象

参数

struct amdgpu_bo *bo

要取消映射的 amdgpu_bo 缓冲区对象

描述

取消映射由 amdgpu_bo_kmap() 设置的内核映射。

struct amdgpu_bo *amdgpu_bo_ref(struct amdgpu_bo *bo)

引用 amdgpu_bo 缓冲区对象

参数

struct amdgpu_bo *bo

amdgpu_bo 缓冲区对象

描述

引用包含的 ttm_buffer_object

返回

指向 amdgpu_bo 缓冲区对象的引用计数指针。

void amdgpu_bo_unref(struct amdgpu_bo **bo)

取消引用 amdgpu_bo 缓冲区对象

参数

struct amdgpu_bo **bo

amdgpu_bo 缓冲区对象

描述

取消引用包含的 ttm_buffer_object 并清除指针

int amdgpu_bo_pin(struct amdgpu_bo *bo, u32 domain)

固定 amdgpu_bo 缓冲区对象

参数

struct amdgpu_bo *bo

amdgpu_bo 要固定的缓冲区对象

u32 domain

要固定到的域

描述

根据请求的域固定缓冲区对象。 如果内存是未绑定的 gart 内存,则将页面绑定到 gart 表中。 相应地调整 pin_count 和 pin_size。

固定意味着锁定内存中的页面以及将它们保持在固定的偏移量处。 当缓冲区无法移动时(例如,当显示缓冲区正在扫描输出时)需要这样做。

返回

成功时为 0,失败时为负错误代码。

void amdgpu_bo_unpin(struct amdgpu_bo *bo)

取消固定 amdgpu_bo 缓冲区对象

参数

struct amdgpu_bo *bo

amdgpu_bo 要取消固定的缓冲区对象

描述

减少 pin_count,如果 pin_count 达到 0,则清除标志。 相应地更改放置位置和固定大小。

返回

成功时为 0,失败时为负错误代码。

int amdgpu_bo_init(struct amdgpu_device *adev)

初始化内存管理器

参数

struct amdgpu_device *adev

amdgpu 设备对象

描述

调用 amdgpu_ttm_init() 初始化 amdgpu 内存管理器。

返回

成功时为 0,失败时为负错误代码。

void amdgpu_bo_fini(struct amdgpu_device *adev)

拆除内存管理器

参数

struct amdgpu_device *adev

amdgpu 设备对象

描述

反转 amdgpu_bo_init() 以拆除内存管理器。

int amdgpu_bo_set_tiling_flags(struct amdgpu_bo *bo, u64 tiling_flags)

设置平铺标志

参数

struct amdgpu_bo *bo

amdgpu_bo 缓冲区对象

u64 tiling_flags

新标志

描述

使用新的平铺标志设置缓冲区对象的平铺标志。 由 GEM ioctl 或内核驱动程序用于设置缓冲区上的平铺标志。

返回

成功时为 0,失败时为负错误代码。

void amdgpu_bo_get_tiling_flags(struct amdgpu_bo *bo, u64 *tiling_flags)

获取平铺标志

参数

struct amdgpu_bo *bo

amdgpu_bo 缓冲区对象

u64 *tiling_flags

返回的标志

描述

获取缓冲区对象的平铺标志。 由 GEM ioctl 或内核驱动程序用于设置缓冲区上的平铺标志。

int amdgpu_bo_set_metadata(struct amdgpu_bo *bo, void *metadata, u32 metadata_size, uint64_t flags)

设置元数据

参数

struct amdgpu_bo *bo

amdgpu_bo 缓冲区对象

void *metadata

新元数据

u32 metadata_size

新元数据的大小

uint64_t flags

新元数据的标志

描述

设置缓冲区对象的元数据、大小和标志。 通过 GEM ioctl 使用。

返回

成功时为 0,失败时为负错误代码。

int amdgpu_bo_get_metadata(struct amdgpu_bo *bo, void *buffer, size_t buffer_size, uint32_t *metadata_size, uint64_t *flags)

获取元数据

参数

struct amdgpu_bo *bo

amdgpu_bo 缓冲区对象

void *buffer

返回的元数据

size_t buffer_size

缓冲区的大小

uint32_t *metadata_size

返回的元数据的大小

uint64_t *flags

返回的元数据的标志

描述

获取缓冲区对象的元数据、大小和标志。 buffer_size 不应小于 metadata_size。 通过 GEM ioctl 使用。

返回

成功时为 0,失败时为负错误代码。

void amdgpu_bo_move_notify(struct ttm_buffer_object *bo, bool evict, struct ttm_resource *new_mem)

内存移动的通知

参数

struct ttm_buffer_object *bo

指向缓冲区对象的指针

bool evict

如果此移动将缓冲区从图形地址空间中逐出

struct ttm_resource *new_mem

用于支持 BO 的新资源

描述

将相应的 amdgpu_bo 缓冲区对象标记为无效,同时执行簿记。TTM 驱动程序回调,在 ttm 移动缓冲区时调用。

void amdgpu_bo_release_notify(struct ttm_buffer_object *bo)

关于 BO 被释放的通知

参数

struct ttm_buffer_object *bo

指向缓冲区对象的指针

描述

清除 VRAM 缓冲区,其中的内容在内存释放之前不应泄漏。

vm_fault_t amdgpu_bo_fault_reserve_notify(struct ttm_buffer_object *bo)

关于内存错误的通知

参数

struct ttm_buffer_object *bo

指向缓冲区对象的指针

描述

通知驱动程序我们正在处理此 BO 上的错误并已保留它,同时执行簿记。TTM 驱动程序回调,用于处理 vm 错误。

返回

成功时为 0,失败时为负错误代码。

void amdgpu_bo_fence(struct amdgpu_bo *bo, struct dma_fence *fence, bool shared)

将 fence 添加到缓冲区对象

参数

struct amdgpu_bo *bo

有问题的缓冲区对象

struct dma_fence *fence

要添加的 fence

bool shared

如果 fence 应该以共享方式添加,则为 true

int amdgpu_bo_sync_wait_resv(struct amdgpu_device *adev, struct dma_resv *resv, enum amdgpu_sync_mode sync_mode, void *owner, bool intr)

等待 BO 预留 fence

参数

struct amdgpu_device *adev

amdgpu 设备指针

struct dma_resv *resv

要同步到的预留对象

enum amdgpu_sync_mode sync_mode

同步模式

void *owner

fence 所有者

bool intr

等待是否可中断

描述

从预留对象中提取 fence 并等待它们完成。

返回

成功时为 0,否则为 errno。

int amdgpu_bo_sync_wait(struct amdgpu_bo *bo, void *owner, bool intr)

amdgpu_bo_sync_wait_resv 的包装器

参数

struct amdgpu_bo *bo

要等待的缓冲区对象

void *owner

fence 所有者

bool intr

等待是否可中断

描述

用于等待 BO 中 fence 的包装器。

返回

成功时为 0,否则为 errno。

u64 amdgpu_bo_gpu_offset(struct amdgpu_bo *bo)

返回 bo 的 GPU 偏移量

参数

struct amdgpu_bo *bo

我们查询偏移量的 amdgpu 对象

注意

在调用此函数时,对象应该被固定或预留,为调试添加此检查可能很有用。

返回

对象的当前 GPU 偏移量。

u64 amdgpu_bo_gpu_offset_no_check(struct amdgpu_bo *bo)

返回 bo 的 GPU 偏移量

参数

struct amdgpu_bo *bo

我们查询偏移量的 amdgpu 对象

返回

对象的当前 GPU 偏移量,不引发警告。

uint32_t amdgpu_bo_mem_stats_placement(struct amdgpu_bo *bo)

用于内存统计的 bo 放置

参数

struct amdgpu_bo *bo

我们应该查看的缓冲区对象

描述

BO 可以有多个首选放置位置,为了避免重复计数,我们希望将其归档在单个放置位置下的内存统计信息中。幸运的是,如果我们采用 preferred_domains 中设置的最高位,结果是相当合理的。

返回

BO 应该在哪个放置位置下进行统计。

uint32_t amdgpu_bo_get_preferred_domain(struct amdgpu_device *adev, uint32_t domain)

获取首选域

参数

struct amdgpu_device *adev

amdgpu 设备对象

uint32_t domain

允许的内存域

返回

对于分配 BO,首选哪个允许的域。

u64 amdgpu_bo_print_info(int id, struct amdgpu_bo *bo, struct seq_file *m)

在 debugfs 文件中打印 BO 信息

参数

int id

BO 的索引或 Id

struct amdgpu_bo *bo

请求打印信息的 BO

struct seq_file *m

debugfs 文件

描述

在 debugfs 文件中打印 BO 信息

返回

BO 的大小,以字节为单位。

PRIME 缓冲区共享

以下回调实现用于通过 PRIME 在不同设备之间共享 GEM 缓冲区对象

struct amdgpu_device *dma_buf_attach_adev(struct dma_buf_attachment *attach)

帮助器,用于获取附件的 adev

参数

struct dma_buf_attachment *attach

附件

返回

如果附加设备是 amdgpu 设备或分区,则为 struct amdgpu_device *,否则为 NULL。

int amdgpu_dma_buf_attach(struct dma_buf *dmabuf, struct dma_buf_attachment *attach)

dma_buf_ops.attach 实现

参数

struct dma_buf *dmabuf

我们附加到的 DMA-buf

struct dma_buf_attachment *attach

要添加的附件

描述

将附件作为用户添加到导出的 DMA-buf。

int amdgpu_dma_buf_pin(struct dma_buf_attachment *attach)

dma_buf_ops.pin 实现

参数

struct dma_buf_attachment *attach

要锁定的附件

描述

锁定支持 DMA-buf 的 BO,使其无法再移动。

void amdgpu_dma_buf_unpin(struct dma_buf_attachment *attach)

dma_buf_ops.unpin 实现

参数

struct dma_buf_attachment *attach

要解锁的附件

描述

解锁先前锁定的 BO 以使其再次可移动。

struct sg_table *amdgpu_dma_buf_map(struct dma_buf_attachment *attach, enum dma_data_direction dir)

dma_buf_ops.map_dma_buf 实现

参数

struct dma_buf_attachment *attach

DMA-buf 附件

enum dma_data_direction dir

DMA 方向

描述

确保目标设备可以访问共享 DMA 缓冲区。目前,只需将其锁定到 GTT 域,所有 DMA 设备都应该可以访问它。

返回

sg_table 填充了要使用的 DMA 地址或带有负错误代码的 ERR_PTR。

void amdgpu_dma_buf_unmap(struct dma_buf_attachment *attach, struct sg_table *sgt, enum dma_data_direction dir)

dma_buf_ops.unmap_dma_buf 实现

参数

struct dma_buf_attachment *attach

DMA-buf 附件

struct sg_table *sgt

要取消映射的 sg_table

enum dma_data_direction dir

DMA 方向

描述

当共享 DMA 缓冲区不再需要被另一个设备访问时,将调用此函数。目前,只需从 GTT 中解锁缓冲区。

int amdgpu_dma_buf_begin_cpu_access(struct dma_buf *dma_buf, enum dma_data_direction direction)

dma_buf_ops.begin_cpu_access 实现

参数

struct dma_buf *dma_buf

共享 DMA 缓冲区

enum dma_data_direction direction

DMA 传输方向

描述

在 CPU 访问共享 DMA 缓冲区的内存之前调用此函数。如果是读取访问,则尽可能将缓冲区移动到 GTT 域,以获得最佳 CPU 读取性能。

返回

成功时为 0,失败时为负错误代码。

struct dma_buf *amdgpu_gem_prime_export(struct drm_gem_object *gobj, int flags)

drm_driver.gem_prime_export 实现

参数

struct drm_gem_object *gobj

GEM BO

int flags

DRM_CLOEXEC 和 DRM_RDWR 等标志。

描述

主要工作由drm_gem_prime_export 帮助程序完成。

返回

表示来自给定设备的 GEM BO 的共享 DMA 缓冲区。

struct drm_gem_object *amdgpu_dma_buf_create_obj(struct drm_device *dev, struct dma_buf *dma_buf)

创建用于 DMA-buf 导入的 BO

参数

struct drm_device *dev

DRM 设备

struct dma_buf *dma_buf

DMA-buf

描述

为 DMA-buf 导入创建空的 SG BO。

返回

给定 DRM 设备的新 GEM BO,表示给定 DMA-buf 附件和分散/聚集表描述的内存。

void amdgpu_dma_buf_move_notify(struct dma_buf_attachment *attach)

attach.move_notify 实现

参数

struct dma_buf_attachment *attach

DMA-buf 附件

描述

使 DMA-buf 附件失效,确保我们在下次使用之前重新创建映射。

struct drm_gem_object *amdgpu_gem_prime_import(struct drm_device *dev, struct dma_buf *dma_buf)

drm_driver.gem_prime_import 实现

参数

struct drm_device *dev

DRM 设备

struct dma_buf *dma_buf

共享 DMA 缓冲区

描述

将 dma_buf 导入到驱动程序中,并可能创建一个新的 GEM 对象。

返回

表示给定设备的共享 DMA 缓冲区的 GEM BO。

bool amdgpu_dmabuf_is_xgmi_accessible(struct amdgpu_device *adev, struct amdgpu_bo *bo)

检查 xgmi 是否可用于 P2P 传输

参数

struct amdgpu_device *adev

导入器的 amdgpu_device 指针

struct amdgpu_bo *bo

amdgpu 缓冲区对象

返回

如果可以通过 xgmi 访问 dmabuf,则为 True,否则为 False。

MMU 通知程序

对于一致的 userptr 处理,注册一个 MMU 通知程序,以通知驱动程序进程的页表更新。

当有人尝试使页表失效时,我们会阻止更新,直到问题页面上的所有操作都完成,然后这些页面被标记为已访问,如果不是只读访问,也会被标记为脏页。

使用问题 userptr 的新命令提交会延迟,直到所有页表失效都完成,并且我们再次看到一致的进程地址空间。

bool amdgpu_hmm_invalidate_gfx(struct mmu_interval_notifier *mni, const struct mmu_notifier_range *range, unsigned long cur_seq)

回调以通知有关 mm 更改

参数

struct mmu_interval_notifier *mni

范围 (mm) 即将更新

const struct mmu_notifier_range *range

有关失效的详细信息

unsigned long cur_seq

要传递给 mmu_interval_set_seq() 的值

描述

阻止对 BO 的操作完成,并将页面标记为已访问,并可能标记为脏页。

bool amdgpu_hmm_invalidate_hsa(struct mmu_interval_notifier *mni, const struct mmu_notifier_range *range, unsigned long cur_seq)

回调以通知有关 mm 更改

参数

struct mmu_interval_notifier *mni

范围 (mm) 即将更新

const struct mmu_notifier_range *range

有关失效的详细信息

unsigned long cur_seq

要传递给 mmu_interval_set_seq() 的值

描述

我们暂时逐出附加到此范围的 BO。这需要逐出进程的所有用户模式队列。

int amdgpu_hmm_register(struct amdgpu_bo *bo, unsigned long addr)

注册 BO 以进行通知程序更新

参数

struct amdgpu_bo *bo

amdgpu 缓冲区对象

unsigned long addr

我们应该监视的 userptr addr

描述

在指定地址为给定 BO 注册 mmu_notifier。成功时返回 0,如果出现任何问题,则返回 -ERRNO。

void amdgpu_hmm_unregister(struct amdgpu_bo *bo)

注销 BO 以进行通知程序更新

参数

struct amdgpu_bo *bo

amdgpu 缓冲区对象

描述

从缓冲区对象中删除 mmu 通知程序的任何注册更新。

AMDGPU 虚拟内存

GPUVM 是 GPU 上提供的 MMU 功能。GPUVM 类似于旧 asic 上的传统 GART,但是,与其为整个 GPU 提供单个全局 GART 表,不如在任何给定时间都可以有多个 GPUVM 页表处于活动状态。GPUVM 页表可以包含 VRAM 页面和系统页面的混合(内存和 MMIO),并且系统页面可以映射为 snooped(缓存的系统页面)或 unsnooped(未缓存的系统页面)。

每个活动的 GPUVM 都有一个与之关联的 ID,并且每个 VMID 都有一个页表链接。执行命令缓冲区时,内核会告诉引擎要为该命令缓冲区使用哪个 VMID。VMID 在提交命令时动态分配。用户空间驱动程序维护自己的地址空间,并且内核会在提交命令缓冲区并分配 VMID 时相应地设置其页面表。硬件最多支持 16 个活动 GPUVM。

每个 GPUVM 都由 1-2 或 1-5 级页表表示,具体取决于 ASIC 系列。GPUVM 支持每个页面上的 RWX 属性以及加密和缓存属性等其他功能。

VMID 0 是特殊的。它是内核驱动程序使用的 GPUVM。除了由页表管理的 aperture 之外,VMID 0 还有几个其他 aperture。有一个用于直接访问 VRAM 的 aperture,并且有一个传统的 AGP aperture,它只是将访问直接转发到匹配的系统物理地址(或者存在 IOMMU 时的 IOVA)。这些 aperture 提供对这些内存的直接访问,而不会产生页表的开销。VMID 0 由内核驱动程序用于内存管理等任务。

GPU 客户端(即 GPU 上的引擎)使用 GPUVM VMID 来访问内存。对于用户应用程序,每个应用程序都可以有自己唯一的 GPUVM 地址空间。应用程序管理地址空间,内核驱动程序管理每个进程的 GPUVM 页表。如果 GPU 客户端访问无效页面,它将生成 GPU 页错误,类似于访问 CPU 上的无效页面。

struct amdgpu_prt_cb

帮助程序,用于从 fence 回调禁用部分驻留纹理功能

定义:

struct amdgpu_prt_cb {
    struct amdgpu_device *adev;
    struct dma_fence_cb cb;
};

成员

adev

amdgpu 设备

cb

回调

struct amdgpu_vm_tlb_seq_struct

帮助程序,用于递增 TLB 刷新序列

定义:

struct amdgpu_vm_tlb_seq_struct {
    struct amdgpu_vm *vm;
    struct dma_fence_cb cb;
};

成员

vm

指向 amdgpu_vm 结构的指针,用于设置 fence 序列

cb

回调

int amdgpu_vm_set_pasid(struct amdgpu_device *adev, struct amdgpu_vm *vm, u32 pasid)

管理 pasid 和 vm 指针映射

参数

struct amdgpu_device *adev

amdgpu_device 指针

struct amdgpu_vm *vm

amdgpu_vm 指针

u32 pasid

VM 在此 GPU 上使用的 pasid

描述

设置此 VM 在此 GPU 上使用的 pasid,也可以通过传入零来删除 pasid。

void amdgpu_vm_bo_evicted(struct amdgpu_vm_bo_base *vm_bo)

vm_bo 被驱逐

参数

struct amdgpu_vm_bo_base *vm_bo

被驱逐的 vm_bo

描述

PD/PT 和每个 VM BO 的状态,它们不在它们应该在的位置。

void amdgpu_vm_bo_moved(struct amdgpu_vm_bo_base *vm_bo)

vm_bo 已移动

参数

struct amdgpu_vm_bo_base *vm_bo

已移动的 vm_bo

描述

每个 VM BO 的状态,它们已移动,但该更改尚未反映在页表中。

void amdgpu_vm_bo_idle(struct amdgpu_vm_bo_base *vm_bo)

vm_bo 空闲

参数

struct amdgpu_vm_bo_base *vm_bo

现在空闲的 vm_bo

描述

PD/PT 和每个 VM BO 的状态,它们已经过状态机,现在处于空闲状态。

void amdgpu_vm_bo_invalidated(struct amdgpu_vm_bo_base *vm_bo)

vm_bo 已失效

参数

struct amdgpu_vm_bo_base *vm_bo

现在失效的 vm_bo

描述

普通 BO 的状态,它们已失效,并且该更改尚未反映在 PT 中。

void amdgpu_vm_bo_evicted_user(struct amdgpu_vm_bo_base *vm_bo)

vm_bo 被驱逐

参数

struct amdgpu_vm_bo_base *vm_bo

被驱逐的 vm_bo

描述

用户模式队列使用的 BO 的状态,它们不在它们应该在的位置。

void amdgpu_vm_bo_relocated(struct amdgpu_vm_bo_base *vm_bo)

vm_bo 已重定位

参数

struct amdgpu_vm_bo_base *vm_bo

已重定位的 vm_bo

描述

PD/PT 的状态,它们需要更新其父 PD。对于根 PD,只需移动到空闲状态。

void amdgpu_vm_bo_done(struct amdgpu_vm_bo_base *vm_bo)

vm_bo 已完成

参数

struct amdgpu_vm_bo_base *vm_bo

现在完成的 vm_bo

描述

普通 BO 的状态,它们已失效,并且该更改已在 PT 中更新。

void amdgpu_vm_bo_reset_state_machine(struct amdgpu_vm *vm)

重置 vm_bo 状态机

参数

struct amdgpu_vm *vm

要重置状态机的 VM

描述

将 VM 中的所有 vm_bo 对象移动到一种状态,在该状态下它们将在验证期间再次更新。

void amdgpu_vm_update_shared(struct amdgpu_vm_bo_base *base)

用于更新共享内存统计信息的助手函数

参数

struct amdgpu_vm_bo_base *base

用于跟踪 VM 中 BO 使用情况的基本结构

描述

获取 vm status_lock 并更新共享内存统计信息。如果基本统计信息已更改(例如,缓冲区已移动),则也需要调用 amdgpu_vm_update_stats。

void amdgpu_vm_bo_update_shared(struct amdgpu_bo *bo)

当 bo 被共享/取消共享时的回调

参数

struct amdgpu_bo *bo

amdgpu 缓冲区对象

描述

如果需要,更新所有 vm 的每个 VM 统计信息,从私有更改为共享,反之亦然。

void amdgpu_vm_update_stats_locked(struct amdgpu_vm_bo_base *base, struct ttm_resource *res, int sign)

用于更新普通内存统计信息的助手函数

参数

struct amdgpu_vm_bo_base *base

用于跟踪 VM 中 BO 使用情况的基本结构

struct ttm_resource *res

ttm_resource 用于统计,可能或可能不是 bo->tbo.resource

int sign

如果我们应该从统计信息中添加 (+1) 或减去 (-1)

描述

调用方需要持有 vm status_lock。当需要同时进行多次更新时很有用。

void amdgpu_vm_update_stats(struct amdgpu_vm_bo_base *base, struct ttm_resource *res, int sign)

用于更新普通内存统计信息的助手函数

参数

struct amdgpu_vm_bo_base *base

用于跟踪 VM 中 BO 使用情况的基本结构

struct ttm_resource *res

ttm_resource 用于统计,可能或可能不是 bo->tbo.resource

int sign

如果我们应该从统计信息中添加 (+1) 或减去 (-1)

描述

当 bo 被添加/删除/移动时,更新基本内存统计信息。

void amdgpu_vm_bo_base_init(struct amdgpu_vm_bo_base *base, struct amdgpu_vm *vm, struct amdgpu_bo *bo)

将 bo 添加到与 vm 关联的 bos 列表

参数

struct amdgpu_vm_bo_base *base

用于跟踪 VM 中 BO 使用情况的基本结构

struct amdgpu_vm *vm

要将 bo 添加到的 vm

struct amdgpu_bo *bo

amdgpu 缓冲区对象

描述

初始化 bo_va_base 结构并将其添加到适当的列表中

int amdgpu_vm_lock_pd(struct amdgpu_vm *vm, struct drm_exec *exec, unsigned int num_fences)

在 drm_exec 中锁定 PD

参数

struct amdgpu_vm *vm

提供 BO 的 vm

struct drm_exec *exec

drm 执行上下文

unsigned int num_fences

要保留的额外 fence 数量

描述

在 DRM 执行上下文中锁定 VM 根 PD。

void amdgpu_vm_move_to_lru_tail(struct amdgpu_device *adev, struct amdgpu_vm *vm)

将所有 BO 移动到 LRU 的末尾

参数

struct amdgpu_device *adev

amdgpu 设备指针

struct amdgpu_vm *vm

提供 BO 的 vm

描述

将所有 BO 移动到 LRU 的末尾,并记住它们的位置以将它们放在一起。

uint64_t amdgpu_vm_generation(struct amdgpu_device *adev, struct amdgpu_vm *vm)

返回页表重新生成计数器

参数

struct amdgpu_device *adev

amdgpu_device

struct amdgpu_vm *vm

要检查的可选 VM,可能为 NULL

描述

返回页表重新生成令牌,以允许检查提交是否仍然有效以使用此 VM。VM 参数可能为 NULL,在这种情况下,将仅使用 VRAM 丢失计数器。

int amdgpu_vm_validate(struct amdgpu_device *adev, struct amdgpu_vm *vm, struct ww_acquire_ctx *ticket, int (*validate)(void *p, struct amdgpu_bo *bo), void *param)

验证 VM 中跟踪的已驱逐 BO

参数

struct amdgpu_device *adev

amdgpu 设备指针

struct amdgpu_vm *vm

提供 BO 的 vm

struct ww_acquire_ctx *ticket

用于保留 VM 的可选保留票证

int (*validate)(void *p, struct amdgpu_bo *bo)

执行验证的回调

void *param

验证回调的参数

描述

如有必要,在命令提交时验证页表 BO 和每个 VM BO。如果给定了票证,还尝试验证已驱逐的用户队列 BO。它们必须已使用给定的票证保留。

返回

验证结果。

bool amdgpu_vm_ready(struct amdgpu_vm *vm)

检查 VM 是否已准备好进行更新

参数

struct amdgpu_vm *vm

要检查的 VM

描述

检查所有 VM PD/PT 是否已准备好进行更新

返回

如果 VM 未被驱逐,则为 True。

void amdgpu_vm_check_compute_bug(struct amdgpu_device *adev)

检查 ASIC 是否有计算 VM 错误

参数

struct amdgpu_device *adev

amdgpu_device 指针

bool amdgpu_vm_need_pipeline_sync(struct amdgpu_ring *ring, struct amdgpu_job *job)

检查作业是否需要管道同步。

参数

struct amdgpu_ring *ring

将在其上提交作业的环

struct amdgpu_job *job

要提交的作业

返回

如果需要同步,则为 True。

int amdgpu_vm_flush(struct amdgpu_ring *ring, struct amdgpu_job *job, bool need_pipe_sync)

硬件刷新 VM

参数

struct amdgpu_ring *ring

用于刷新的环

struct amdgpu_job *job

相关作业

bool need_pipe_sync

是否需要管道同步

描述

在必要时发出 VM 刷新。

返回

成功时为 0,否则为 errno。

struct amdgpu_bo_va *amdgpu_vm_bo_find(struct amdgpu_vm *vm, struct amdgpu_bo *bo)

查找特定 vm 和 bo 的 bo_va

参数

struct amdgpu_vm *vm

请求的 vm

struct amdgpu_bo *bo

请求的缓冲区对象

描述

在请求的 vm 中查找 bo。在 bos vm 列表中搜索请求的 vm。返回找到的 bo_va,如果未找到,则返回 NULL

对象必须保留!

返回

找到的 bo_va 或 NULL。

uint64_t amdgpu_vm_map_gart(const dma_addr_t *pages_addr, uint64_t addr)

解析 addr 的 gart 映射

参数

const dma_addr_t *pages_addr

用于查找的可选 DMA 地址

uint64_t addr

未映射的 addr

描述

查找 pte 解析到的页面的物理地址。

返回

页表条目的指针。

int amdgpu_vm_update_pdes(struct amdgpu_device *adev, struct amdgpu_vm *vm, bool immediate)

确保所有目录都有效

参数

struct amdgpu_device *adev

amdgpu_device 指针

struct amdgpu_vm *vm

请求的 vm

bool immediate

立即提交到分页队列

描述

确保所有目录都是最新的。

返回

成功则为 0,失败则为错误。

void amdgpu_vm_tlb_seq_cb(struct dma_fence *fence, struct dma_fence_cb *cb)

确保增加 tlb 序列

参数

struct dma_fence *fence

未使用

struct dma_fence_cb *cb

回调结构

描述

增加 tlb 序列以确保未来的 CS 执行 VM 刷新。

void amdgpu_vm_tlb_flush(struct amdgpu_vm_update_params *params, struct dma_fence **fence, struct amdgpu_vm_tlb_seq_struct *tlb_cb)

准备 TLB 刷新

参数

struct amdgpu_vm_update_params *params

更新参数

struct dma_fence **fence

与 TLB 刷新同步的输入 fence

struct amdgpu_vm_tlb_seq_struct *tlb_cb

回调结构

描述

增加 tlb 序列以确保未来的 CS 执行 VM 刷新。

int amdgpu_vm_update_range(struct amdgpu_device *adev, struct amdgpu_vm *vm, bool immediate, bool unlocked, bool flush_tlb, bool allow_override, struct amdgpu_sync *sync, uint64_t start, uint64_t last, uint64_t flags, uint64_t offset, uint64_t vram_base, struct ttm_resource *res, dma_addr_t *pages_addr, struct dma_fence **fence)

更新 vm 页表中的范围

参数

struct amdgpu_device *adev

用于命令的 amdgpu_device 指针

struct amdgpu_vm *vm

要更新范围的 VM

bool immediate

页面错误中的立即提交

bool unlocked

MM 回调期间的解锁失效

bool flush_tlb

更新完成后触发 tlb 失效

bool allow_override

更改本地 NUMA 节点的 MTYPE

struct amdgpu_sync *sync

我们需要同步的 fence

uint64_t start

映射范围的开始

uint64_t last

上次映射的条目

uint64_t flags

条目的标志

uint64_t offset

节点和 pages_addr 中的偏移量

uint64_t vram_base

vram 映射的基础

struct ttm_resource *res

要映射的 ttm_resource

dma_addr_t *pages_addr

用于映射的 DMA 地址

struct dma_fence **fence

可选的结果 fence

描述

填充 startlast 之间的页表条目。

返回

成功则为 0,失败则为负错误代码。

int amdgpu_vm_bo_update(struct amdgpu_device *adev, struct amdgpu_bo_va *bo_va, bool clear)

更新 vm 页表中的所有 BO 映射

参数

struct amdgpu_device *adev

amdgpu_device 指针

struct amdgpu_bo_va *bo_va

请求的 BO 和 VM 对象

bool clear

如果为 true,则清除条目

描述

填充 bo_va 的页表条目。

返回

成功则为 0,失败则为 -EINVAL。

void amdgpu_vm_update_prt_state(struct amdgpu_device *adev)

更新全局 PRT 状态

参数

struct amdgpu_device *adev

amdgpu_device 指针

void amdgpu_vm_prt_get(struct amdgpu_device *adev)

添加 PRT 用户

参数

struct amdgpu_device *adev

amdgpu_device 指针

void amdgpu_vm_prt_put(struct amdgpu_device *adev)

删除 PRT 用户

参数

struct amdgpu_device *adev

amdgpu_device 指针

void amdgpu_vm_prt_cb(struct dma_fence *fence, struct dma_fence_cb *_cb)

用于更新 PRT 状态的回调

参数

struct dma_fence *fence

回调的 fence

struct dma_fence_cb *_cb

回调函数

void amdgpu_vm_add_prt_cb(struct amdgpu_device *adev, struct dma_fence *fence)

添加用于更新 PRT 状态的回调

参数

struct amdgpu_device *adev

amdgpu_device 指针

struct dma_fence *fence

回调的 fence

void amdgpu_vm_free_mapping(struct amdgpu_device *adev, struct amdgpu_vm *vm, struct amdgpu_bo_va_mapping *mapping, struct dma_fence *fence)

释放映射

参数

struct amdgpu_device *adev

amdgpu_device 指针

struct amdgpu_vm *vm

请求的 vm

struct amdgpu_bo_va_mapping *mapping

要释放的映射

struct dma_fence *fence

取消映射操作的 fence

描述

释放映射,并确保我们减少 PRT 使用计数(如果适用)。

void amdgpu_vm_prt_fini(struct amdgpu_device *adev, struct amdgpu_vm *vm)

完成所有 prt 映射

参数

struct amdgpu_device *adev

amdgpu_device 指针

struct amdgpu_vm *vm

请求的 vm

描述

注册清理回调以在 VM 死后禁用 PRT 支持。

int amdgpu_vm_clear_freed(struct amdgpu_device *adev, struct amdgpu_vm *vm, struct dma_fence **fence)

清除 PT 中已释放的 BO

参数

struct amdgpu_device *adev

amdgpu_device 指针

struct amdgpu_vm *vm

请求的 vm

struct dma_fence **fence

可选的结果 fence(如果不需要执行任何操作或发生错误,则保持不变)

描述

确保所有已释放的 BO 在 PT 中都被清除。PT 必须被预留,并且互斥锁必须被锁定!

返回

成功返回 0。

int amdgpu_vm_handle_moved(struct amdgpu_device *adev, struct amdgpu_vm *vm, struct ww_acquire_ctx *ticket)

处理 PT 中移动的 BO

参数

struct amdgpu_device *adev

amdgpu_device 指针

struct amdgpu_vm *vm

请求的 vm

struct ww_acquire_ctx *ticket

用于保留 VM 的可选保留票证

描述

确保所有移动的 BO 在 PT 中都被更新。

PT 必须被预留!

返回

成功返回 0。

int amdgpu_vm_flush_compute_tlb(struct amdgpu_device *adev, struct amdgpu_vm *vm, uint32_t flush_type, uint32_t xcc_mask)

刷新计算 VM 上的 TLB

参数

struct amdgpu_device *adev

amdgpu_device 指针

struct amdgpu_vm *vm

请求的 vm

uint32_t flush_type

刷新类型

uint32_t xcc_mask

需要刷新 TLB 的计算分区所属的 XCC 掩码。

描述

如果需要,刷新计算 VM 的 TLB。

返回

成功返回 0。

struct amdgpu_bo_va *amdgpu_vm_bo_add(struct amdgpu_device *adev, struct amdgpu_vm *vm, struct amdgpu_bo *bo)

将 bo 添加到特定的 vm

参数

struct amdgpu_device *adev

amdgpu_device 指针

struct amdgpu_vm *vm

请求的 vm

struct amdgpu_bo *bo

amdgpu 缓冲区对象

描述

将 **bo** 添加到请求的 vm 中。将 **bo** 添加到与 vm 关联的 bo 列表中

对象必须保留!

返回

新添加的 bo_va,失败则返回 NULL

void amdgpu_vm_bo_insert_map(struct amdgpu_device *adev, struct amdgpu_bo_va *bo_va, struct amdgpu_bo_va_mapping *mapping)

插入新的映射

参数

struct amdgpu_device *adev

amdgpu_device 指针

struct amdgpu_bo_va *bo_va

bo_va 用于存储地址

struct amdgpu_bo_va_mapping *mapping

要插入的映射

描述

将新的映射插入到所有结构中。

int amdgpu_vm_bo_map(struct amdgpu_device *adev, struct amdgpu_bo_va *bo_va, uint64_t saddr, uint64_t offset, uint64_t size, uint64_t flags)

将 bo 映射到 vm 内部

参数

struct amdgpu_device *adev

amdgpu_device 指针

struct amdgpu_bo_va *bo_va

bo_va 用于存储地址

uint64_t saddr

bo 映射的位置

uint64_t offset

bo 中请求的偏移量

uint64_t size

bo 大小,以字节为单位

uint64_t flags

页面的属性(读/写/有效/等等)

描述

在指定的地址将 BO 的映射添加到 VM 中。

对象必须在外部预留和取消预留!

返回

成功则为 0,失败则为错误。

int amdgpu_vm_bo_replace_map(struct amdgpu_device *adev, struct amdgpu_bo_va *bo_va, uint64_t saddr, uint64_t offset, uint64_t size, uint64_t flags)

将 bo 映射到 vm 内部,替换现有的映射

参数

struct amdgpu_device *adev

amdgpu_device 指针

struct amdgpu_bo_va *bo_va

bo_va 用于存储地址

uint64_t saddr

bo 映射的位置

uint64_t offset

bo 中请求的偏移量

uint64_t size

bo 大小,以字节为单位

uint64_t flags

页面的属性(读/写/有效/等等)

描述

在指定的地址将 BO 的映射添加到 VM 中。在此过程中替换现有的映射。

对象必须在外部预留和取消预留!

返回

成功则为 0,失败则为错误。

int amdgpu_vm_bo_unmap(struct amdgpu_device *adev, struct amdgpu_bo_va *bo_va, uint64_t saddr)

从 vm 中移除 bo 映射

参数

struct amdgpu_device *adev

amdgpu_device 指针

struct amdgpu_bo_va *bo_va

bo_va 用于从中移除地址

uint64_t saddr

BO 映射的位置

描述

从 VM 中移除在指定的地址的 BO 映射。

对象必须在外部预留和取消预留!

返回

成功则为 0,失败则为错误。

int amdgpu_vm_bo_clear_mappings(struct amdgpu_device *adev, struct amdgpu_vm *vm, uint64_t saddr, uint64_t size)

移除特定范围内的所有映射

参数

struct amdgpu_device *adev

amdgpu_device 指针

struct amdgpu_vm *vm

要使用的 VM 结构

uint64_t saddr

范围的起点

uint64_t size

范围的大小

描述

移除一个范围内的所有映射,并适当地拆分它们。

返回

成功则为 0,失败则为错误。

struct amdgpu_bo_va_mapping *amdgpu_vm_bo_lookup_mapping(struct amdgpu_vm *vm, uint64_t addr)

按地址查找映射

参数

struct amdgpu_vm *vm

请求的 VM

uint64_t addr

地址

描述

通过地址查找映射。

返回

与 addr 匹配的 amdgpu_bo_va_mapping,如果没有则返回 NULL

void amdgpu_vm_bo_trace_cs(struct amdgpu_vm *vm, struct ww_acquire_ctx *ticket)

跟踪所有预留的映射

参数

struct amdgpu_vm *vm

请求的 vm

struct ww_acquire_ctx *ticket

CS ticket

描述

跟踪命令提交期间预留的 BO 的所有映射。

void amdgpu_vm_bo_del(struct amdgpu_device *adev, struct amdgpu_bo_va *bo_va)

从特定的 vm 中移除 bo

参数

struct amdgpu_device *adev

amdgpu_device 指针

struct amdgpu_bo_va *bo_va

请求的 bo_va

描述

从请求的 vm 中移除 **bo_va->bo**。

对象必须被预留!

bool amdgpu_vm_evictable(struct amdgpu_bo *bo)

检查我们是否可以驱逐 VM

参数

struct amdgpu_bo *bo

VM 的页表。

描述

检查是否可以驱逐 VM。

void amdgpu_vm_bo_invalidate(struct amdgpu_bo *bo, bool evicted)

将 bo 标记为无效

参数

struct amdgpu_bo *bo

amdgpu 缓冲区对象

bool evicted

BO 是否被驱逐

描述

将 **bo** 标记为无效。

void amdgpu_vm_bo_move(struct amdgpu_bo *bo, struct ttm_resource *new_mem, bool evicted)

处理 BO 移动

参数

struct amdgpu_bo *bo

amdgpu 缓冲区对象

struct ttm_resource *new_mem

BO 移动的新位置

bool evicted

BO 是否被驱逐

描述

更新新位置的内存统计信息,并将 **bo** 标记为无效。

uint32_t amdgpu_vm_get_block_size(uint64_t vm_size)

以 2 的幂计算 VM 页表大小

参数

uint64_t vm_size

VM 大小

返回

VM 页表,以 2 的幂表示

void amdgpu_vm_adjust_size(struct amdgpu_device *adev, uint32_t min_vm_size, uint32_t fragment_size_default, unsigned max_level, unsigned max_bits)

调整 vm 大小、块大小和片段大小

参数

struct amdgpu_device *adev

amdgpu_device 指针

uint32_t min_vm_size

如果设置为 auto,则最小 vm 大小(GB)

uint32_t fragment_size_default

默认 PTE 片段大小

unsigned max_level

最大 VMPT 级别

unsigned max_bits

地址空间的最大位数

long amdgpu_vm_wait_idle(struct amdgpu_vm *vm, long timeout)

等待 VM 变为 idle 状态

参数

struct amdgpu_vm *vm

要等待的 VM 对象

long timeout

等待 VM 变为 idle 状态的超时时间

void amdgpu_vm_put_task_info(struct amdgpu_task_info *task_info)

减少 vm task_info 指针的引用计数

参数

struct amdgpu_task_info *task_info

正在讨论的 task_info 结构。

描述

在最后一次 put 操作时释放 vm task_info 指针

struct amdgpu_task_info *amdgpu_vm_get_task_info_vm(struct amdgpu_vm *vm)

提取 vm 的任务信息。

参数

struct amdgpu_vm *vm

要从中获取信息的 VM

描述

返回引用计数的 task_info 结构,必须使用 amdgpu_vm_put_task_info 减少其引用计数。

struct amdgpu_task_info *amdgpu_vm_get_task_info_pasid(struct amdgpu_device *adev, u32 pasid)

提取 PASID 的任务信息。

参数

struct amdgpu_device *adev

drm 设备指针

u32 pasid

VM 的 PASID 标识符

描述

返回引用计数的 task_info 结构,必须使用 amdgpu_vm_put_task_info 减少其引用计数。

void amdgpu_vm_set_task_info(struct amdgpu_vm *vm)

设置 VM 的任务信息。

参数

struct amdgpu_vm *vm

要设置信息的 vm

int amdgpu_vm_init(struct amdgpu_device *adev, struct amdgpu_vm *vm, int32_t xcp_id)

初始化 vm 实例

参数

struct amdgpu_device *adev

amdgpu_device 指针

struct amdgpu_vm *vm

请求的 vm

int32_t xcp_id

GPU 分区选择 id

描述

初始化 **vm** 字段。

返回

成功则为 0,失败则为错误。

int amdgpu_vm_make_compute(struct amdgpu_device *adev, struct amdgpu_vm *vm)

将 GFX VM 转换为计算 VM

参数

struct amdgpu_device *adev

amdgpu_device 指针

struct amdgpu_vm *vm

请求的 vm

描述

这仅适用于没有添加任何 BO 且尚未分配页表的 GFX VM。

更改以下 VM 参数:- use_cpu_for_update - pte_supports_ats

重新初始化页目录以反映更改的 ATS 设置。

返回

成功返回 0,错误返回 -errno。

void amdgpu_vm_fini(struct amdgpu_device *adev, struct amdgpu_vm *vm)

拆卸 vm 实例

参数

struct amdgpu_device *adev

amdgpu_device 指针

struct amdgpu_vm *vm

请求的 vm

描述

拆卸 **vm**。取消绑定 VM 并从 vm bo 列表中移除所有 bo

void amdgpu_vm_manager_init(struct amdgpu_device *adev)

初始化 VM 管理器

参数

struct amdgpu_device *adev

amdgpu_device 指针

描述

初始化 VM 管理器结构

void amdgpu_vm_manager_fini(struct amdgpu_device *adev)

清理 VM 管理器

参数

struct amdgpu_device *adev

amdgpu_device 指针

描述

清理 VM 管理器并释放资源。

int amdgpu_vm_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)

管理 vm hub 的 VMID 预留。

参数

struct drm_device *dev

drm 设备指针

void *data

drm_amdgpu_vm

struct drm_file *filp

drm 文件指针

返回

成功返回 0,错误返回 -errno。

bool amdgpu_vm_handle_fault(struct amdgpu_device *adev, u32 pasid, u32 vmid, u32 node_id, uint64_t addr, uint64_t ts, bool write_fault)

优雅地处理 VM 故障。

参数

struct amdgpu_device *adev

amdgpu 设备指针

u32 pasid

VM 的 PASID

u32 vmid

VMID,仅用于 GFX 9.4.3。

u32 node_id

IH cookie 中接收的 Node_id。仅适用于 GFX 9.4.3。

uint64_t addr

故障地址

uint64_t ts

故障的时间戳

bool write_fault

true 表示写故障,false 表示读故障

描述

尝试优雅地处理 VM 故障。如果故障已处理且不应再报告,则返回 true。

void amdgpu_debugfs_vm_bo_info(struct amdgpu_vm *vm, struct seq_file *m)

打印 VM 的 BO 信息

参数

struct amdgpu_vm *vm

请求打印 BO 信息的 VM

struct seq_file *m

debugfs 文件

描述

在 VM 的 debugfs 文件中打印 BO 信息

void amdgpu_vm_update_fault_cache(struct amdgpu_device *adev, unsigned int pasid, uint64_t addr, uint32_t status, unsigned int vmhub)

更新缓存的故障信息。

参数

struct amdgpu_device *adev

amdgpu 设备指针

unsigned int pasid

VM 的 PASID

uint64_t addr

故障地址

uint32_t status

GPUVM 故障状态寄存器

unsigned int vmhub

哪个 vmhub 发生了故障

描述

缓存故障信息,供用户空间以后在调试中使用。

bool amdgpu_vm_is_bo_always_valid(struct amdgpu_vm *vm, struct amdgpu_bo *bo)

检查 BO 是否 VM 始终有效

参数

struct amdgpu_vm *vm

要测试的 VM。

struct amdgpu_bo *bo

要测试的 BO。

描述

如果 BO 与根 PD 共享 dma_resv 对象,并且保证在 VM 内部始终有效,则返回 true。

中断处理

GPU 硬件中生成的中断会引发中断请求,这些请求会传递给 amdgpu IRQ 处理程序,该处理程序负责检测中断的来源和类型,并分派匹配的处理程序。如果处理中断需要调用可能休眠的内核函数,则处理会被分派给工作处理程序。

如果模块参数未禁用 MSI 功能,则将启用 MSI 支持。

对于可能由另一个驱动程序驱动的 GPU 中断源,将使用 IRQ 域支持(在虚拟 IRQ 和硬件 IRQ 之间进行映射)。

void amdgpu_irq_disable_all(struct amdgpu_device *adev)

禁用*所有*中断

参数

struct amdgpu_device *adev

amdgpu 设备指针

描述

禁用来自所有来源的所有类型的中断。

irqreturn_t amdgpu_irq_handler(int irq, void *arg)

IRQ 处理程序

参数

int irq

IRQ 编号(未使用)

void *arg

指向 DRM 设备的指针

描述

amdgpu 驱动程序(所有 ASIC)的 IRQ 处理程序。

返回

处理 IRQ 的结果,由 irqreturn_t 定义

void amdgpu_irq_handle_ih1(struct work_struct *work)

启动 IH1 的处理

参数

struct work_struct *work

struct amdgpu_irq 中的工作结构

描述

启动处理 IH 环 1。

void amdgpu_irq_handle_ih2(struct work_struct *work)

启动 IH2 的处理

参数

struct work_struct *work

struct amdgpu_irq 中的工作结构

描述

启动 IH 环 2 的处理。

void amdgpu_irq_handle_ih_soft(struct work_struct *work)

启动 ih_soft 的处理

参数

struct work_struct *work

struct amdgpu_irq 中的工作结构

描述

启动 IH 软环的处理。

bool amdgpu_msi_ok(struct amdgpu_device *adev)

检查是否启用了 MSI 功能

参数

struct amdgpu_device *adev

amdgpu 设备指针(未使用)

描述

检查是否已通过模块参数禁用 MSI 功能(所有 ASIC)。

返回

如果允许启用 MSI,则为 *true*,否则为 *false*

int amdgpu_irq_init(struct amdgpu_device *adev)

初始化中断处理

参数

struct amdgpu_device *adev

amdgpu 设备指针

描述

设置热插拔和重置中断的工作函数,启用 MSI 功能,初始化垂直消隐、热插拔和重置中断处理。

返回

成功时为 0,失败时为错误代码

void amdgpu_irq_fini_sw(struct amdgpu_device *adev)

关闭中断处理

参数

struct amdgpu_device *adev

amdgpu 设备指针

描述

拆卸热插拔和重置中断的工作函数,禁用 MSI 功能,关闭垂直消隐、热插拔和重置中断处理,关闭来自所有源的中断(所有 ASIC)。

int amdgpu_irq_add_id(struct amdgpu_device *adev, unsigned int client_id, unsigned int src_id, struct amdgpu_irq_src *source)

注册 IRQ 源

参数

struct amdgpu_device *adev

amdgpu 设备指针

unsigned int client_id

客户端 ID

unsigned int src_id

源 ID

struct amdgpu_irq_src *source

IRQ 源指针

描述

在客户端上注册 IRQ 源。

返回

成功时为 0,否则为错误代码

void amdgpu_irq_dispatch(struct amdgpu_device *adev, struct amdgpu_ih_ring *ih)

将 IRQ 分派到 IP 块

参数

struct amdgpu_device *adev

amdgpu 设备指针

struct amdgpu_ih_ring *ih

中断环实例

描述

将 IRQ 分派到 IP 块。

void amdgpu_irq_delegate(struct amdgpu_device *adev, struct amdgpu_iv_entry *entry, unsigned int num_dw)

将 IV 委托给软 IH 环

参数

struct amdgpu_device *adev

amdgpu 设备指针

struct amdgpu_iv_entry *entry

IV 条目

unsigned int num_dw

IV 的大小

描述

将 IV 委托给软 IH 环并安排对其进行处理。 如果由于某种原因硬件委托给 IH1 或 IH2 不起作用,则使用此方法。

int amdgpu_irq_update(struct amdgpu_device *adev, struct amdgpu_irq_src *src, unsigned int type)

更新硬件中断状态

参数

struct amdgpu_device *adev

amdgpu 设备指针

struct amdgpu_irq_src *src

中断源指针

unsigned int type

中断类型

描述

更新特定源的中断状态(所有 ASIC)。

void amdgpu_irq_gpu_reset_resume_helper(struct amdgpu_device *adev)

更新所有源的中断状态

参数

struct amdgpu_device *adev

amdgpu 设备指针

描述

重置后恢复时,更新所有源上所有类型中断的状态。

int amdgpu_irq_get(struct amdgpu_device *adev, struct amdgpu_irq_src *src, unsigned int type)

启用中断

参数

struct amdgpu_device *adev

amdgpu 设备指针

struct amdgpu_irq_src *src

中断源指针

unsigned int type

中断类型

描述

在指定源上启用指定类型的中断(所有 ASIC)。

返回

成功时为 0,否则为错误代码

int amdgpu_irq_put(struct amdgpu_device *adev, struct amdgpu_irq_src *src, unsigned int type)

禁用中断

参数

struct amdgpu_device *adev

amdgpu 设备指针

struct amdgpu_irq_src *src

中断源指针

unsigned int type

中断类型

描述

在指定源上启用指定类型的中断(所有 ASIC)。

返回

成功时为 0,否则为错误代码

bool amdgpu_irq_enabled(struct amdgpu_device *adev, struct amdgpu_irq_src *src, unsigned int type)

检查是否已启用中断

参数

struct amdgpu_device *adev

amdgpu 设备指针

struct amdgpu_irq_src *src

中断源指针

unsigned int type

中断类型

描述

检查给定类型的中断是否已在给定源上启用。

返回

如果已启用中断,则为 *true*;如果已禁用中断或参数无效,则为 *false*

int amdgpu_irqdomain_map(struct irq_domain *d, unsigned int irq, irq_hw_number_t hwirq)

创建虚拟 IRQ 编号和硬件 IRQ 编号之间的映射

参数

struct irq_domain *d

amdgpu IRQ 域指针(未使用)

unsigned int irq

虚拟 IRQ 编号

irq_hw_number_t hwirq

硬件 IRQ 编号

描述

当前实现将简单的中断处理程序分配给给定的虚拟 IRQ。

返回

成功时为 0,否则为错误代码

int amdgpu_irq_add_domain(struct amdgpu_device *adev)

创建线性 IRQ 域

参数

struct amdgpu_device *adev

amdgpu 设备指针

描述

为 GPU 中断源创建 IRQ 域,这些中断源可能由另一个驱动程序驱动(例如,ACP)。

返回

成功时为 0,否则为错误代码

void amdgpu_irq_remove_domain(struct amdgpu_device *adev)

移除 IRQ 域

参数

struct amdgpu_device *adev

amdgpu 设备指针

描述

移除 GPU 中断源的 IRQ 域,这些中断源可能由另一个驱动程序驱动(例如,ACP)。

unsigned int amdgpu_irq_create_mapping(struct amdgpu_device *adev, unsigned int src_id)

创建域 Linux IRQ 之间的映射

参数

struct amdgpu_device *adev

amdgpu 设备指针

unsigned int src_id

IH 源 ID

描述

创建域 IRQ(GPU IH src id)和 Linux IRQ 之间的映射。 将其用于生成 GPU 中断但由其他驱动程序驱动的组件(例如,ACP)。

返回

Linux IRQ

IP 块

GPU 由 IP(知识产权)块组成。 这些 IP 块提供各种功能:显示、图形、视频解码等。 构成特定 GPU 的 IP 块在 GPU 的相应 SoC 文件中列出。 amdgpu_device.c 在初始化时获取正在使用的 GPU 的 IP 块列表。 然后,它可以对此列表进行操作以执行标准驱动程序操作,例如:初始化、完成、暂停、恢复等。

IP 块实现的命名使用以下约定:<功能>_v<版本>(例如:gfx_v6_0)。

enum amd_ip_block_type

用于按功能对 IP 块进行分类。

常量

AMD_IP_BLOCK_TYPE_COMMON

GPU 系列

AMD_IP_BLOCK_TYPE_GMC

图形存储器控制器

AMD_IP_BLOCK_TYPE_IH

中断处理程序

AMD_IP_BLOCK_TYPE_SMC

系统管理控制器

AMD_IP_BLOCK_TYPE_PSP

平台安全处理器

AMD_IP_BLOCK_TYPE_DCE

显示和合成引擎

AMD_IP_BLOCK_TYPE_GFX

图形和计算引擎

AMD_IP_BLOCK_TYPE_SDMA

系统 DMA 引擎

AMD_IP_BLOCK_TYPE_UVD

统一视频解码器

AMD_IP_BLOCK_TYPE_VCE

视频压缩引擎

AMD_IP_BLOCK_TYPE_ACP

音频协处理器

AMD_IP_BLOCK_TYPE_VCN

视频核心/编解码器下一代

AMD_IP_BLOCK_TYPE_MES

微引擎调度器

AMD_IP_BLOCK_TYPE_JPEG

JPEG 引擎

AMD_IP_BLOCK_TYPE_VPE

视频处理引擎

AMD_IP_BLOCK_TYPE_UMSCH_MM

多媒体用户模式调度器

AMD_IP_BLOCK_TYPE_ISP

图像信号处理器

AMD_IP_BLOCK_TYPE_NUM

IP 块类型的总数

enum DC_DEBUG_MASK

可用于调试显示核心 IP 的位

常量

DC_DISABLE_PIPE_SPLIT

如果设置,则禁用管道拆分

DC_DISABLE_STUTTER

如果设置,则禁用内存口吃模式

DC_DISABLE_DSC

如果设置,则禁用显示流压缩

DC_DISABLE_CLOCK_GATING

如果设置,则禁用时钟门控优化

DC_DISABLE_PSR

如果设置,则禁用面板自刷新 v1 和 PSR-SU

DC_FORCE_SUBVP_MCLK_SWITCH

如果设置,则强制在 subvp 中进行 mclk 切换,即使可以在垂直消隐中进行 mclk 切换

DC_DISABLE_MPO

如果设置,则禁用多平面卸载

DC_ENABLE_DPIA_TRACE

如果设置,则为 DPIA 启用跟踪日志记录

DC_ENABLE_DML2

如果设置,则强制使用 DML2,即使 DCN 版本没有默认为此。

DC_DISABLE_PSR_SU

如果设置,则禁用 PSR SU

DC_DISABLE_REPLAY

如果设置,则禁用面板重放

DC_DISABLE_IPS

如果设置,则始终禁用所有空闲电源状态。 如果设置了多个 IPS 调试位,则最低位优先。 例如,如果设置了 DC_FORCE_IPS_ENABLE 和 DC_DISABLE_IPS_DYNAMIC,则 DC_DISABLE_IPS_DYNAMIC 优先。

DC_DISABLE_IPS_DYNAMIC

如果设置,则始终禁用所有 IPS,*除非*驱动程序进入挂起状态。

DC_DISABLE_IPS2_DYNAMIC

如果设置,如果启用了显示器,则禁用 IPS2(允许 IPS1)。 否则,启用所有 IPS。

DC_FORCE_IPS_ENABLE

如果设置,则始终强制启用所有 IPS。

DC_DISABLE_ACPI_EDID

如果设置,则不要尝试从 ACPI _DDC 方法获取 eDP 显示器的 EDID。

DC_DISABLE_HDMI_CEC

如果设置,则禁用 amdgpu 驱动程序中的 HDMI-CEC 功能。

DC_DISABLE_SUBVP_FAMS

如果设置,则禁用 amdgpu 驱动程序中的 DCN 子视口和固件辅助存储时钟切换 (FAMS) 功能。

DC_DISABLE_CUSTOM_BRIGHTNESS_CURVE

如果设置,则禁用对自定义亮度曲线的支持

DC_HDCP_LC_FORCE_FW_ENABLE

如果设置,则使用 HDCP 局部性检查 FW 路径,无论报告的 HW 功能如何。

DC_HDCP_LC_ENABLE_SW_FALLBACK

如果设置,在 HDCP 局部性检查 FW 路径失败时,使用旧版 SW 路径重试。

DC_SKIP_DETECTION_LT

如果设置,则跳过检测链路训练

struct amd_ip_funcs

用于管理 amdgpu IP 块的通用挂钩

定义:

struct amd_ip_funcs {
    char *name;
    int (*early_init)(struct amdgpu_ip_block *ip_block);
    int (*late_init)(struct amdgpu_ip_block *ip_block);
    int (*sw_init)(struct amdgpu_ip_block *ip_block);
    int (*sw_fini)(struct amdgpu_ip_block *ip_block);
    int (*early_fini)(struct amdgpu_ip_block *ip_block);
    int (*hw_init)(struct amdgpu_ip_block *ip_block);
    int (*hw_fini)(struct amdgpu_ip_block *ip_block);
    void (*late_fini)(struct amdgpu_ip_block *ip_block);
    int (*prepare_suspend)(struct amdgpu_ip_block *ip_block);
    int (*suspend)(struct amdgpu_ip_block *ip_block);
    int (*resume)(struct amdgpu_ip_block *ip_block);
    bool (*is_idle)(struct amdgpu_ip_block *ip_block);
    int (*wait_for_idle)(struct amdgpu_ip_block *ip_block);
    bool (*check_soft_reset)(struct amdgpu_ip_block *ip_block);
    int (*pre_soft_reset)(struct amdgpu_ip_block *ip_block);
    int (*soft_reset)(struct amdgpu_ip_block *ip_block);
    int (*post_soft_reset)(struct amdgpu_ip_block *ip_block);
    int (*set_clockgating_state)(struct amdgpu_ip_block *ip_block, enum amd_clockgating_state state);
    int (*set_powergating_state)(struct amdgpu_ip_block *ip_block, enum amd_powergating_state state);
    void (*get_clockgating_state)(struct amdgpu_ip_block *ip_block, u64 *flags);
    void (*dump_ip_state)(struct amdgpu_ip_block *ip_block);
    void (*print_ip_state)(struct amdgpu_ip_block *ip_block, struct drm_printer *p);
};

成员

name

IP 块的名称

early_init

设置早期驱动程序状态(sw_init 之前),不配置 hw - 可选

late_init

设置后期驱动程序/hw 状态(hw_init 后)- 可选

sw_init

设置驱动程序状态,不配置 hw

sw_fini

拆卸驱动程序状态,不配置 hw

early_fini

从驱动程序分离 dev 之前拆卸内容

hw_init

设置 hw 状态

hw_fini

拆卸 hw 状态

late_fini

最终清理

prepare_suspend

处理 IP 特定更改以准备挂起(例如,分配任何所需的内存)

suspend

处理 IP 特定 hw/sw 更改以进行挂起

resume

处理 IP 特定 hw/sw 更改以进行恢复

is_idle

返回当前 IP 块空闲状态

wait_for_idle

轮询以确定是否空闲

check_soft_reset

检查软重置 IP 块

pre_soft_reset

预软重置 IP 块

soft_reset

软重置 IP 块

post_soft_reset

后软重置 IP 块

set_clockgating_state

启用/禁用 IP 块的 cg

set_powergating_state

启用/禁用 IP 块的 pg

get_clockgating_state

获取当前时钟门控状态

dump_ip_state

在 GPU 挂起期间转储 ASIC 的 IP 状态

print_ip_state

在 devcoredump 中打印 ASIC 的每个 IP 的 IP 状态

描述

这些挂钩提供了一个接口,用于控制 IP 块的运行状态。 在获取正在使用的 GPU 的 IP 块列表后,驱动程序可以通过遍历此列表并调用每个 IP 块中的挂钩来进行芯片范围的状态更改。 对此列表进行排序,以确保驱动程序以安全的顺序初始化 IP 块。