AMD KFD BO设计分析系列10-2:doorbell bo的使用分析

前文: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该干活了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

DeeplyMind

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值