1. DMA MAP API在驱动中的使用
DMA MAP建立起物理地址PA和IO设备的虚拟地址IOVA之间的映射,当IO设备通过SMMU访IOVA实际会访问到对应的物理地址PA。完成访问后DMA UNMAP取消映射。
在IO设备驱动中DMA MAP/UNMAP使用如下图所示:
数据如何在CPU和IO device之间的传递和处理?
(1)CPU通过MMU建立起数据的物理地址PA到数据的虚拟地址之间的映射,CPU通过访问VA从而访问到数据(比如CPU填充数据到内存中);
(2)IO设备驱动得到数据的PA,并通过DMA MAP将数据的物理地址PA和IOVA建立映射,然后IO设备驱动将IOVA传递给SMMU设备;
(3)SMMU将IOVA转换为PA,从而对PA处的数据的处理;
(4)完成数据处理后,通过DMA UNMAP取消IOVA到PA的映射;
2 DMA MAP/UNMAP API分类
2.1 一致性DMA
之前介绍过COHERENT特性,对于一致性DMA,可以保证CPU和IO设备看到的物理地址是一致,因为CPU侧存在CACHE,一致性DMA可通过关CACHE或硬件来保证CPU和IO设备看到的物理地址是一致。函数dma_alloc_coherent()为一致性DMA。一致性DMA通常为静态的,建立起一致性映射后,一般在系统结束时取消映射。
2.2 流式DMA
流式DMA为动态的,每次都会建立映射,然后取消映射。由于CPU侧存在CACHE,需要软件或硬件来维护一致性。流式DMA包括dma_map_sg/dma_map_single()等。
目前很多现在SOC如kunpeng920都是硬件来保证coherent一致性。
2.3 DMA MAP API简介
先简单介绍下面几个函数的作用,后述对每个函数的实现对较为详细的分析。
DMA MAP API |
描述 |
dma_alloc_coherent(dev, size, dma_handle, gfp) |
分配size大小的一致性映射,返回IOVA和VA |
dma_map_sg(d, s, n, r) |
将scatther gather建立映射 |
dma_map_page(d, p, o, s, r) |
将一个物理页建立映射 |
dma_map_single() |
将一块连续物理区域建立映射 |
这些函数都会将物理区域与连续的IOVA建立起映射,差别在于物理区域的组织方式不一样,对于*_sg来説,是多个连续的物理区域,*_page是一个物理页,*_single是一块连续的物理区域,这三个函数的物理区域都是提前分配好的。但函数dma_alloc_coherent()则是在分配物理区域的同时,建立物理区域与IOVA的映射,同时返回VA。