前文:AMD KFD的BO设计分析系列10-1:doorbell bo的相关内核实现 整体分析了内核的doorbell使用流程。本文重点分析doorbell bo的创建、mmap流程。
1. 整体流程
AMDGPU_GEM_DOMAIN_DOORBELL 是 AMDGPU 驱动专门为 doorbell(门铃)机制分配显存对象(BO, Buffer Object)时使用的内存域。doorbell 是一种用于 CPU 与 GPU 间高效通信的机制,通常映射为一段 BAR 区域,CPU 通过写入 doorbell 寄存器通知 GPU 触发某些操作(如提交命令、唤醒队列等)。
下面详细分析在 AMDGPU_GEM_DOMAIN_DOORBELL 域下amdgpu_bo_create_kernel 分配 BO 的实现流程。首先可以看到这个bo是一个kernel bo。
2. bo创建
int amdgpu_bo_create_kernel(struct amdgpu_device *adev,
size_t size, size_t align, u32 domain,
struct amdgpu_bo **bo_ptr,
uint64_t *gpu_addr, void **cpu_addr)
{
...
// 创建 BO 对象,设置 domain = DOORBELL
struct amdgpu_bo *bo = amdgpu_bo_create(adev, size, align, domain, ...);
...
return 0;
}
doorbell注册memory manager是通过amdgpu_ttm_init_on_chip,调用参数和该函数的实现如下:
amdgpu_ttm_init_on_chip(adev, AMDGPU_PL_DOORBELL,
adev->doorbell.size / PAGE_SIZE);
static int amdgpu_ttm_init_on_chip(struct amdgpu_device *adev,
unsigned int type,
uint64_t size_in_page)
{
return ttm_range_man_init(&adev->mman.bdev, type,
false, size_in_page);
}
可以看到doorbell的物理区域的管理用了ttm框架自带的管理器---ttm_range_manager。这个管理器中使用了drm_mm作为空间分配器,drm_mm怎么分配的,请参见:linux drm子系统分析。
3 doorbell bo 的mmap
doorbell bo的mmap入口在kfd chardev设备的mmap接口中,如下。逻辑很简单,就是取到该process的doorbell区域的实际物理地址(每个processs的doorbell区域是一个相对于doorbell bar base的偏移)。取得地址后,就直接调用io_remap_pfn_range函数了。
static int kfd_mmap(struct file *filep, struct vm_area_struct *vma)
{
...
mmap_offset = vma->vm_pgoff << PAGE_SHIFT;
switch (mmap_offset & KFD_MMAP_TYPE_MASK) {
case KFD_MMAP_TYPE_DOORBELL:
if (!dev)
return -ENODEV;
return kfd_doorbell_mmap(dev, process, vma);
...
}
}
int kfd_doorbell_mmap(struct kfd_node *dev,
struct kfd_process *process,
struct vm_area_struct *vma)
{
phys_addr_t address;
vm_flags_set(vma, VM_IO | VM_DONTCOPY | VM_DONTEXPAND | VM_NORESERVE |
VM_DONTDUMP | VM_PFNMAP);
vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
/* Calculate physical address of doorbell */
address = kfd_get_process_doorbells(pdd);
return io_remap_pfn_range(vma,
vma->vm_start,
address >> PAGE_SHIFT,
kfd_doorbell_process_slice(dev->kfd),
vma->vm_page_prot);
}
就这么简单。后面就是用户态直接写数据进去通知GPU该干活了。
796

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



