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); //<font color=red>关键代码</font>
  1. 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;  // 说明
  1. 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);
  1. 从上看出,其实这里所谓的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.

在这里插入图片描述
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值