NVDLA用户态驱动代码整理二


前言

本系列内容力求将nvdla的用户态驱动整理清楚,如果有分析不对的请指出。

前面已经花了不少章节详细解释NVDLA内核态驱动代码,链接分别如下:
系列文章1:NVDLA内核态驱动代码整理一
系列文章2:NVDLA内核态驱动代码整理二
系列文章3:NVDLA内核态驱动代码整理三
系列文章4:NVDLA内核态驱动代码整理四
系列文章5:NVDLA内核态驱动代码整理五
系列文章6:NVDLA内核态驱动代码整理六
系列文章7:NVDLA内核态驱动代码整理七
系列文章8:NVDLA内核态驱动代码整理八
系列文章8:NVDLA内核态驱动代码整理汇总篇

欢迎阅读硬件信号和架构分析系列文章1:
架构开篇介绍文章:NVDLA内核态驱动代码整理三
系列文章1:NVDLA硬件信号和架构设计整理一
系列文章2:NVDLA硬件信号和架构设计整理二
系列文章3:NVDLA硬件信号和架构设计整理三

这是用户态解读的第二篇,也是收官之作。(不过后面有机会解读行为级代码的时候另说,可能会花大把时间搞明白RTL的寄存器是啥规范!)


一、Runtime.cpp代码解读

按照官网的描述,使用运行时接口进行推测任务需要完成以下步骤:

1、Create NVDLA runtime instance
# 包括IRuntime *nvdla::createRuntime()函数

2、Get NVDLA device information
# 包括NvU16 nvdla::IRuntime::getMaxDevices()函数、NvU16 nvdla::IRuntime::getNumDevices()函数

3、Load network data
# 包括NvError nvdla::IRuntime::load(const NvU8 *buf, int instance)函数

4、Get input and output tensors information
# 包括NvError nvdla::IRuntime::getNumInputTensors(int *input_tensors)函数、NvError nvdla::IRuntime::getInputTensorDesc(int id, NvDlaTensor *tensors)函数、NvError nvdla::IRuntime::getNumOutputTensors(int *output_tensors)函数、NvError nvdla::IRuntime::getOutputTensorDesc(int id, NvDlaTensor *tensors)函数

5、Update input and output tensors information
# 包括NvError nvdla::IRuntime::setInputTensorDesc(int id, const NvDlaTensor *tensors)函数、NvError nvdla::IRuntime::setOutputTensorDesc(int id, const NvDlaTensor *tensors)函数

6、Allocate memory for input and output tensors
# 包括NvDlaError allocateSystemMemory(void **h_mem, NvU64 size, void **pData)函数

7、Bind memory handle with tensor
# 包括NvError nvdla::IRuntime::bindInputTensor(int id, void *hMem)函数、NvError nvdla::IRuntime::bindOutputTensor(int id, void *hMem)函数

8、Submit task for inference
# 包括NvError nvdla::IRuntime::submit()函数

9、Unload network resources
# 包括NvError nvdla::IRuntime::unload(int instance)函数

我们掌握到这一层足矣!

二、nvdla.c函数整理

本来打算机械式逐个解释nvdla.c的函数,后来想到其实这个文件内的所有函数直接看函数名就可以理解。尽管用户态函数确实定义十分清楚,但是我们始终没有搞明白几件事情!因此接下来我打算就几件事情拨开nvdla.c函数的某些有意思的点。

关于nvdla_os.c的函数不再赘述。直接看函数名就可以理解函数功能,和Runtime.cppnvdla.c类似。

三、由nvdla.c引发的几个问题

这3个问题分别是怎么联系用户态和内核态?明明我只insmod了一个.ko,但为什么出现了2个不同结构体下的fd?为什么memsetmmap没有同时出现在fops内?可能这三个问题会帮助理解一部分究竟什么是用户态?

3.1 两个不同的结构体都有fd,但只insmod了1个ko?

在这里插入图片描述
关于第1个结构体:NvDlaMemHandleRec,使用情况如下:
在这里插入图片描述
关于第2个结构体:NvDlaMemHandle,使用情况如下:
在这里插入图片描述
(以上2个结构体完全一致!)
关于第3个结构体:NvDlaHandleRec,使用情况如下:无
关于第4个结构体:NvDlaHandle,使用情况如下:无
(以上2个结构体完全一致!)
关于第5个结构体:NvDlaContextRec,使用情况如下:无
关于第6个结构体:NvDlaContext,使用情况如下:
在这里插入图片描述
关于第7个结构体:NvDlaDeviceHandle,使用情况如下:
在这里插入图片描述
(以上3个结构体完全一致!)
所以答案显而易见,有两套fd,那哪一套对应哪一套?
先做个整理:

驱动对应fd结构体1结构体2
1NvDlaMemHandleRecNvDlaMemHandle
2NvDlaContextNvDlaDeviceHandle

两套fd究竟怎么来的?先观察在加载opendla.ko时打印的输出情况:
在这里插入图片描述
我们在这里介绍DRM时看到一张久违的图片:
在这里插入图片描述
DRM框架成功加载后,会创建一个设备文件/dev/dri/card0,上层用户应用可以通过该文件节点,获取显卡的各种操作。【不过始终无法解释一个问题:为什么用户态中/dev/dri/renderD128open的时候加载了,DRMcard0却不需要加载,但是其中一步close关闭了?我怀疑有一种可能就是renderD128这个opendla的驱动已经包含了DRMcard0驱动!】
这也就解释了为什么出现了两个fd

3.2 怎么联系用户态和内核态?

想到这个问题的原因是,用户态也有和内核态一样的open等操作。那到底是怎么回事?
ioctl函数出发,从用户态再看到内核态。先找找该文件下的ioctl出现的情况:
第一处:
在这里插入图片描述
其中宏DRM_IOCTL_NVDLA_GEM_CREATE指的是:
在这里插入图片描述
第二处:
在这里插入图片描述
然而此处的宏DRM_IOCTL_PRIME_HANDLE_TO_FD并不在上述截图中,而是在drm.h中:
在这里插入图片描述
第三处:
在这里插入图片描述
根据linux官方对于ioctl的解释:
在这里插入图片描述
ioctl()系统调用用于操纵特殊文件的底层设备参数。特别是,许多字符特殊文件(例如终端)的操作特性可以通过ioctl()请求进行控制。参数fd必须是一个打开的文件描述符。第2个参数是一个与设备相关的请求代码。第3个参数是一个untyped的内存指针。通常,成功时返回零。一些ioctl()请求将返回值用作输出参数,并在成功时返回非负值。发生错误时,返回-1,并设置errno以指示错误。
在这里插入图片描述
所以用户态传入的参数本质上补充第二个参数:
在这里插入图片描述
在这里插入图片描述
继续追溯宏函数:
在这里插入图片描述
在linux官网继续追溯:
在这里插入图片描述
继续:
在这里插入图片描述
基本上可以确认本质就是四个参数做移位!那么用户态ioctl怎么对应内核态ioctl
在内核态找到ioctl
在这里插入图片描述
随后该nvdla_drm_ioctls提交给nvdla_drm_driver结构体:
在这里插入图片描述
注意尽管在用户态代码中出现memsetmalloc这些函数,结合fs.h中的file operation结构体基本可以确认这些函数不是file operation中的。
在这里插入图片描述
ioctl或许是一个特例,我们再看看open是怎么一回事?
在这里插入图片描述
用户态的open函数=>高级版本抽象的do_sys_open函数=>借助file operation下的特定文件系统类型open函数。
在这里插入图片描述
所以调用链就是:用户态open调用=>内核态do_sys_open函数=>文件系统的open函数。
自此,案件已破!

3.3 memset/malloc和mmap没有同时出现在fops内?

在这里插入图片描述
到这里为止,大部分问题我们已经搞明白了!从看NVDLA的代码以来,一直很疑惑内核态和用户态到底是怎么关联的?我也遇到过各种奇奇怪怪的bug,但所幸有着自己的耐心一路推过去。也有各种各样的疑惑,有时候疑惑满脑子,有种剪不断、理还乱的感觉,还好,认知内各种各样的问题都一一去尝试解释。可以说,这一章的内容,突破了同辈们在搭建NVDLA过程中实现全栈建立的已有知识范畴,加入了我自己的理解和感悟!如果您对我的想法有疑惑或者质疑,欢迎提出,非常乐意交流。


总结

总结,撒花,欢迎阅读!

  • 23
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

DentionY

谢谢您的支持

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

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

打赏作者

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

抵扣说明:

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

余额充值