前言:学习了PCIe设备端驱动之后并做了一个项目之后,有了很多疑惑。疑惑主要来自于,由于没有深入学习PCIe体系结构,所以总线从上电开始做的一系列工作对于我来说都是黑盒。设备端只是用几个简单的API就搞定,所以稍微复杂一点的映射关系就看不懂。所以学习了下PCIe体系结构,解答了以下几个疑惑。
问题1:为什么需要dma buffer地址映射。AMTU寄存器的作用。
问题2:可不可以用bar空间实现dma buffer
回答问题1先要搞明白“域”的概念,在PCIe通信链路上,其实存在着:存储器域、pcie总线域。
PCIe HOST主桥是一个很特别的桥片,其主要功能是隔离存储器系统的存储器域和处理器系统的PCI总线域,管理PCI总线域,并完成处理器与PCI设备间的数据交换。
那么有人就要问了,这跟为什么需要dma buffer地址映射有什么关系。其实这个dma地址映射就是存储器域到pcie总线域的映射的一种表现形式呀,下面我们来聊一聊。
dma buffer是在哪里开辟的?
答:一般是pcie驱动里开辟的,使用dma_alloc_coherent,返回虚拟地址。需要注意的是,这段地址在内存里属于CPU能直接访问到的存储器域,下面处理器需要将存储器域中的dma buffer 地址空间映射到pci总线的地址空间也就是pcie总线域。
有必要做这一步吗?
答:有必要,因为PCI设备进行DMA操作时,必须使用pcie总线域的地址,HOST主桥才能认领这个PCI总线事务。所以PCI设备进行DMA操作时,使用的目的地址或者源地址有时是PCI总线域的物理地址!
难怪写dma目的地址寄存器时内容是pcie设备的总线地址,原来是为了让HOST桥认领这个事务,再通过映射关系,访问到存储器域(也就是真正的dma buffer开辟的位置)。
另外,许多PowerPC处理器使用ATMU寄存器进行存储器域到PCI总线域,以及PCI总线域到存储器域的地址映射。ATMU寄存器中的outbound组完成存储器域地址转换成PCI总线域,而inbound寄存器组将pci总线域的地址转换为存储器域的地址。
最后我想直接使用bar映射后的空间开辟dma buffer应该也是可行的,这样减少了配置ATMU寄存器的步骤,但是要注意:1、内存对齐:DMA 操作通常要求内存是对齐的,因此你需要确保所分配的内存区域满足设备的对齐要求。2、地址映射:BAR 地址通常是物理地址,因此需要确保你正确处理虚拟地址与物理地址之间的映射。3、同步:DMA 操作可能需要进行缓存同步,确保在进行 DMA 传输之前和之后进行缓存的刷新。