KBASE_IOCTL -- MEM_ALLOC_EX 解析
这篇文章详解 kbase_ioctl
中的 KBASE_IOCTL_MEM_ALLOC_EX
命令。最新的 mali GPU 支持了 CSF,因此这篇的讲解基于 MALI_USE_CSF
使能的配置。
1 | static long kbase_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) |
KBASE_HANDLE_IOCTL_INOUT
表示 KBASE_IOCTL_MEM_ALLOC_EX
是有输入并且有输出的 cmd,输入输出都是 uarg
。在 KBASE_HANDLE_IOCTL_INOUT
中先将 uarg
通过 copy_from_user(¶m, uarg, sizeof(param));
拷贝到一个临时变量 union kbase_ioctl_mem_alloc_ex param
中,然后调用 ret = kbase_api_mem_alloc_ex(kctx, param);
,再调用 copy_to_user(uarg, ¶m, sizeof(param));
将 param
拷贝到 uarg
中,最终返回 ret
(如果在两处 copy 中出错,则返回 -EFAULT
)。
以上是 KBASE_IOCTL_MEM_ALLOC_EX
的粗略流程,具体内容在 kbase_api_mem_alloc_ex
函数中,接下来详解这个函数。
union kbase_ioctl_mem_alloc_ex
上面说到 KBASE_IOCTL_MEM_ALLOC_EX
用户态传进来的参数和内核返回用户的数据都是 union kbase_ioctl_mem_alloc_ex
类型表示的,那么首先来看下这个类型:
1 | /** |
从联合体结合注释很简便看出,in
部分对应入参,out
部分对应出参。
in
va_pages
: 虚拟空间大小commit_pages
: 需要分配的物理页extension
: 每次 GPU fault 需要额外分配的页面数flags
fixed_address
: 如果flags
中带了BASE_MEM_FIXED
标志,则考虑用fixed_address
作为 GPU 虚拟空间地址分配extras
: 保留
out
flags
gpu_va
: 返回的 GPU 虚拟空间地址
kbase_mem_allow_alloc
由于 mali 的 user space 驱动是闭源的,所以我也只能靠猜测 mali 驱动是如何使用的。
kbase_api_mem_alloc_ex
一开始就调用了 kbase_mem_allow_alloc(kctx)
来判断这个 kctx
可不可以分配空间:
1 | /** |
粗看这个函数,只是判断了 kctx->process_mm
,那这个 process_mm
是什么呢?
1 | /* |
根据注释看,process_mm
是哪个进程创建了这个 kctx
,它的值就是这个进程的 mm
成员。用处是用来跟踪这个进程在 GPU 中分配的内存。
再看 kbase_mem_allow_alloc
注释,如果 process_mm
还未设置或者发出 ioctl
命令的进程是设置 process_mm
的进程 fork
出来的子进程,分配是不允许的。换句话来说,只允许已经设置了 process_mm
的进程来分配。注释中还说到, process_mm
是在设置 tracking page
时设置的,这个 tracking page
是什么呢?按照 process_mm
的含义,估计就是用来跟踪进程 GPU 分配情况的。来搜索下 process_mm
具体是怎么设置的:
1 | static int kbase_tracking_page_setup(struct kbase_context *kctx, struct vm_area_struct *vma) |
这个函数的调用流程如下:
graph A("mmap=>operation: mmap 时调用 .mmap 钩子 kbase_mmap(filp, vma);") -->B("kbase_context_mmap(kctx, vma);") B --> C{根据 vm_pgoff 的值来做不同的操作} C -->|"vma->vm_pgoff == PFN_DOWN(BASE_MEM_MAP_TRACKING_HANDLE)"| D["kbase_tracking_page_setup(kctx, vma);"]