Kernel下的DMA 地址映射详解

       在网上查看了各路大牛的DMA资料,但一直未解决我的问题和疑问;

我的问题就是:这个DMA Buf地址区间在哪,是如何划分的。大部分资料都是

DMA的抽象层,没有讲到具体,比如这个dma_map_single这个函数。这个

phys_addr到底是从哪里来的,是如何受到保护的,以及这个映射关系和dma_unmap_single

取消映射之间,是否涉及到phys_addr的关联。

xfer->tx_dma = dma_map_single(dev, (void *)xfer->tx_buf,

     xfer->len, DMA_TO_DEVICE);

 

   跟踪代码,

  1 .  phys_addr_t map_single(struct device *hwdev, phys_addr_t phys, size_t size,

      enum dma_data_direction dir) {

     dma_addr_t start_dma_addr = phys_to_dma(hwdev, io_tlb_start); //关键代码

  2.  phys_addr_t swiotlb_tbl_map_single(struct device *hwdev, 

     { ......

io_tlb_list[i] = 0;
for (i = index - 1; (OFFSET(i, IO_TLB_SEGSIZE) != IO_TLB_SEGSIZE - 1) && io_tlb_list[i]; i--)
io_tlb_list[i] = ++count;

tlb_addr = io_tlb_start + (index << IO_TLB_SHIFT); //关键代码,说明这里

  有一个单独的dma内存区域,而且维护了一张list.

      for (i = 0; i < nslots; i++)
io_tlb_orig_addr[index+i] = orig_addr + (i << IO_TLB_SHIFT);

   swiotlb_late_init_with_tbl{
bytes = nslabs << IO_TLB_SHIFT;
io_tlb_nslabs = nslabs;

io_tlb_start = virt_to_phys(tlb);

        return tlb_addr;  // 说明

 

  3.  swiotlb_bounce{ ......

         else if (dir == DMA_TO_DEVICE) {

memcpy(vaddr, phys_to_virt(orig_addr), size);  //这里表明的意思是,需要把内容重新

拷贝到dma_phys映射的vir_ddr上,否则就没有数据。另外最重要的一点是,DMA和

RAM的地址是独立、并列,同级的关系,是一个编址的问题

} else {
memcpy(phys_to_virt(orig_addr), vaddr, size);

  4.  从上看出,其实这里所谓的dma操作都是一些逻辑性的,没涉及到phys部分,也就说理论上

dma可以随意映射ram任何地址。Kernel里面搞这么复杂,还是因为kernel里涉及各方面的内存

分配和堆栈空间,便于管理;另外有个重要的原因是,phys addr被dma映射后,其他的进程是

不知道的,而且各dma进程之间也是不清楚的,这样会导致严重的混乱问题,所以从这个原理上

看,对DMA的ram地址进行一定发分区管理是非常明智和实用的。抓个开机log

<6>[    0.000000] cma: CMA: reserved 16 MiB at 0x00000000f5000000 for default region
<7>[    0.000000] On node 0 totalpages: 1537024
<7>[    0.000000]   DMA zone: 13824 pages used for memmap
<7>[    0.000000]   DMA zone: 0 pages reserved
<7>[    0.000000]   DMA zone: 750592 pages, LIFO batch:31
<7>[    0.000000]   Normal zone: 13824 pages used for memmap
<7>[    0.000000]   Normal zone: 786432 pages, LIFO batch:31

<6>[    0.000000] psci: probing for conduit method from DT.

 

Kernel下的DMA 地址映射详解_第1张图片

Kernel下的DMA 地址映射详解_第2张图片

你可能感兴趣的:(Kernel下的DMA 地址映射详解)