本文简要描述了amdgpu bo的类型和用途,以及map、共享、同步等功能,看多了本专栏的文章,就会发现图形/计算的存储管理涉及存储子系统的方方面面,需久久为功是—— 唯有坚持技术深耕、实践复盘,才能在开发的产品中提升性能、保障稳定、达成预期。
1. amd bo类型和用途
AMDGPU 支持多种类型的 BO,分别服务于不同的使用场景:
-
用户空间 BO:通过 GEM/DRM ioctl 由应用程序分配,用于图形渲染、OpenCL/Vulkan 计算、ROCm训练/推理等。
-
内核空间 BO:驱动内部分配,用于 ring buffer、firmware、调度队列等,用户空间不可直接访问。
-
VM BO:专用于 GPU 虚拟内存页表管理。
-
ISP 用户 BO:用于 ISP(图像信号处理)等外部设备的 DMA-BUF 导入。
每种 BO 类型在分配、映射、销毁等环节有不同的参数和生命周期管理策略。这个是从使用场景分类BO类型,还有一个视角是:bo所在的物理空间的区域(内存分配位置)。内存分配位置视角更有技术研究价值,请参见:AMD KFD BO设计分析系列10:内存分配位置flags详解。
2. BO 的创建与分配流程
2.1 用户空间 BO 创建
用户空间通过 ioctl(如 DRM_IOCTL_AMDGPU_GEM_CREATE)请求分配 BO,驱动调用 amdgpu_bo_create_user
int amdgpu_bo_create_user(struct amdgpu_device *adev,
struct amdgpu_bo_param *bp,
struct amdgpu_bo_user **ubo_ptr)
{
bp->bo_ptr_size = sizeof(struct amdgpu_bo_user);
bp->destroy = &amdgpu_bo_user_destroy;
r = amdgpu_bo_create(adev, bp, &bo_ptr);
*ubo_ptr = to_amdgpu_bo_user(bo_ptr);
return r;
}
-
用途:为用户空间应用(如 OpenCL、Vulkan、图形程序、AI)分配 BO,用户可通过 GEM/DRM ioctl 访问和管理这些 BO。
-
参数:需要
amdgpu_bo_param,并指定bo_ptr_size为sizeof(struct amdgpu_bo_user),destroy 回调为amdgpu_bo_user_destroy。 -
实现:调用
amdgpu_bo_create创建 BO,并返回struct amdgpu_bo_user *。 - 特性:
-
支持元数据(metadata)、tiling flags 等用户空间属性。
-
生命周期由用户空间控制,通常与 GEM handle 绑定。
-
适合图形渲染、用户侧显存分配等场景。
-
2.2 内核空间 BO 创建
内核通过 amdgpu_bo_create_kernel 分配 BO,供驱动内部使用:
int amdgpu_bo_create_kernel(struct amdgpu_device *adev,
unsigned long size, int align,
u32 domain, struct amdgpu_bo **bo_ptr,
u64 *gpu_addr, void **cpu_addr)
{
r = amdgpu_bo_create_reserved(adev, size, align, domain, bo_ptr,
gpu_addr, cpu_addr);
if (*bo_ptr)
amdgpu_bo_unreserve(*bo_ptr);
return r;
}
-
用途:为内核驱动自身分配 BO,供驱动内部使用(如 ring buffer、firmware、内核任务等),用户空间不可直接访问。
-
参数:直接传递 BO 指针,destroy 回调为
amdgpu_bo_destroy,类型为ttm_bo_type_kernel。 -
实现:调用
amdgpu_bo_create_reserved创建并 pin 住 BO,随后 unreserve,返回struct amdgpu_bo *。 -
特性:
-
通常分配 VRAM 或 GTT,支持内核直接映射(可选)。
-
生命周期由内核管理,适合 GPU 驱动内部资源。
-
可选返回 GPU 地址和 CPU 映射地址。
-
2.3 VM BO 创建
用于 GPU 虚拟内存页表管理:
-
通常分配 VRAM,支持页表层级结构。
int amdgpu_bo_create_vm(struct amdgpu_device *adev,
struct amdgpu_bo_param *bp,
struct amdgpu_bo_vm **vmbo_ptr)
{
r = amdgpu_bo_create(adev, bp, &bo_ptr);
*vmbo_ptr = to_amdgpu_bo_vm(bo_ptr);
return r;
}
2.4 ISP 用户 BO 创建
用于 ISP 设备的 DMA-BUF 导入:
int amdgpu_bo_create_isp_user(struct amdgpu_device *adev,
struct dma_buf *dma_buf, u32 domain, struct amdgpu_bo **bo,
u64 *gpu_addr)
{
gem_obj = amdgpu_gem_prime_import(&adev->ddev, dma_buf);
*bo = gem_to_amdgpu_bo(gem_obj);
amdgpu_bo_reserve(*bo, false);
amdgpu_bo_pin(*bo, domain);
amdgpu_ttm_alloc_gart(&(*bo)->tbo);
*gpu_addr = amdgpu_bo_gpu_offset(*bo);
amdgpu_bo_unreserve(*bo);
return 0;
}
3. BO 的内存分配与域管理
BO 支持多种内存域(domain),如 VRAM、GTT、CPU、DOORBELL、GDS、GWS、OA 等。分配时通过 amdgpu_bo_placement_from_domain 设置 BO 的物理位置和属性:
void amdgpu_bo_placement_from_domain(struct amdgpu_bo *abo, u32 domain)
{
// 根据 domain 设置 TTM placement 和 flags
}
-
VRAM:GPU 专用显存,适合高带宽任务。
-
GTT:系统内存,通过 IOMMU 映射到 GPU。
-
DOORBELL:队列通知机制专用内存。
-
GDS/GWS/OA:特殊硬件资源。
4. BO 的映射与访问
4.1 GPU 地址映射
BO 分配后可通过 amdgpu_bo_gpu_offset 获取其在 GPU 地址空间的偏移,用于命令提交和显存访问。
4.2 CPU 地址映射
内核可通过 amdgpu_bo_kmap 映射 BO 到内核虚拟地址,实现 CPU 直接访问:
int amdgpu_bo_kmap(struct amdgpu_bo *bo, void **ptr)
{
// 调用 ttm_bo_kmap 设置内核虚拟映射
}
- 受 BO flags 控制,部分 BO 不允许 CPU 访问。
4.3 用户空间 mmap
用户空间可通过 mmap ioctl 映射 BO,实现显存直接访问,底层通过 DRM/GEM 和 TTM 管理页表和权限。
5. BO 的生命周期与同步机制
1. Pin/Unpin: BO 可通过 amdgpu_bo_pin 固定在物理内存,防止被驱逐或移动,适合帧缓冲等关键资源。
2. Fence 与同步:BO 支持 fence 机制,通过 amdgpu_bo_fence 关联 DMA fence,确保命令提交和内存访问的正确顺序。
3. 驱逐与回收: 当显存紧张或 BO 失效时,驱动可通过状态链表和锁机制驱逐 BO,释放资源。
4.bo共享:bo支持通过 DMA-BUF fd 导入导出,实现多进程、多设备间的显存共享。驱动通过 drm_gem_prime_import 和相关接口管理生命周期和映射关系。
5. 销毁与释放:BO 销毁时,调用 destroy 回调(如 amdgpu_bo_destroy 或 amdgpu_bo_user_destroy),释放所有资源并解除映射。
6. 总结对比
这里对user和kernel bo做了对比。
| 项目 | amdgpu_bo_create_user | amdgpu_bo_create_kernel |
|---|---|---|
| 用途 | 用户空间 BO | 内核空间 BO |
| 返回类型 | struct amdgpu_bo_user * | struct amdgpu_bo * |
| 生命周期 | 用户空间控制(GEM handle) | 内核控制 |
| destroy 回调 | amdgpu_bo_user_destroy | amdgpu_bo_destroy |
| 典型场景 | 图形渲染、用户显存、AI | ring buffer、firmware、内核任务 |
| 是否 pin/保留 | 通常不自动 pin | 自动 pin 并可选 CPU 映射 |
| 是否支持元数据/tiling flags | 支持 | 通常不支持 |
一句话总结:amdgpu_bo_create_user 用于分配用户空间可管理的 BO,amdgpu_bo_create_kernel 用于分配内核驱动内部使用的 BO,二者在生命周期、访问权限和分配方式上有本质区别。
技术交流,欢迎加入社区:GPUers。
1192

被折叠的 条评论
为什么被折叠?



