解决memory management_memory怎么读「建议收藏」

解决memory management_memory怎么读「建议收藏」DMADMA(Directmemoryaccess) 特性允许在CPU参与的情况下外设访问DDR。如常见的ARM SOC,CPUcore通过AXImaster,经常NOC(Networkonachipe)路由到DDRAXISLAVE接口,实现DDR访问。在SO

大家好,欢迎来到IT知识分享网。

DMA

DMA(Direct memory access) 特性允许在CPU参与的情况下外设访问DDR。如常见的ARM SOCCPU core通过AXI master,经常NOC(Network on a chipe)路由到DDR AXI SLAVE接口,实现DDR访问。在SOC没有DMA特性下,如果DDR需要和外设之间搬移数据,只能通过CPU 指令,这样会耗费大量的CPU时间。如果有DMACPU配置好source addressdestination address,还有搬移数据的长度,DMAC(DMA controller)会在CPU不参与下搬移数据,CPU可以做其他工作,在完成后有中断通知到CPU,进行相应的处理。有些DMAC还支持link listt模式,一次搬移多个不连续的DDR请求。

通常情况下SOC下的负载IPSD/SDIO/eMMC controller[chapter 26], USB Controller[chapter 31]都自带专有的DMAC。其他相对简单的IP如串口、SPI共用内部的通用DMAC[chapter 19](general purpose direct memory access)DMACCPU访问DDR大概架构如下。其中CPUDMAC都有AXI master访问DDR,同时CPU可以通过APB总线配置DMAC相关寄存器。

解决memory management_memory怎么读「建议收藏」

简单CPUDMAC访问DDR架构图

通过图1可以看到CPU访问DDRDMAC有一点不同时,路径上经过CacheCache是为了加速DDR访问的一种缓存机制。因为有cache存在,CPUDMAC看到的同一个DDR地址空间可能不一致。有两种情况导致不一致,第一种是CPU写,DDR读。第二种是DDR写, CPU读。第一种的不一致例子如DDR 0x80000000地址处值为0CPU往该地址写入值为2,因为cacheWrite-back特性同时Cache可用,2只存在Cache中不会flushDDR上,所以DMACDDR看到的值还是0。第二种不一致和类似。对于这种SOC需要CPU相关指令clean cache , invalid cacheARM V7架构有一个Accelerator Coherency Port (ACP)接口,DMACCPU都通过Cache访问DDR达到缓存一致的效果,避免CPU操作cacheACP位于图2中虚线箭头,为了区别ACP请求和普通DDR请求,经过ACP口的地址可以和普通的DDR地址不一致,NOC通过地址路由到相关的接口。这个地址的偏移ARM平台可以通过设备数的dma-ranges指定。如stm32mp151设备数的相关配置

 

mlahb {

compatible = “simple-bus”;

#address-cells = <1>;

#size-cells = <1>;

dma-ranges = <0x00000000 0x38000000 0x10000>,

<0x10000000 0x10000000 0x60000>,

<0x30000000 0x30000000 0x60000>;

}

 

解决memory management_memory怎么读「建议收藏」

带有ACP接口的DMAC

因为ARM PTE页表policy可以设置成Strongly-ordered(no-cache)特性,CPU访问绕过Cache,因此就没有数据不一致的问题。图3中虚线为CPU绕过Cache直接访问DDR,不存在数据不一致问题。

解决memory management_memory怎么读「建议收藏」

3 stronger-order policyDMACCPU访问路径

IOMMU

从上面的介绍可以看到,CPUDMAC会同时访问内存,如果DMAC软件BUG造成越界写DDR,从CPU角度很难发现问题。对于不支持link list模式的DMAC搬移大量的数据时,可能由于系统内存碎片导致申请不到一大段连续内存,导致请求失败。鉴于这些原因在DMACDDR之间引入IOMMUARM也实现的IOMMU功能叫做SMMU。图IOMMUDMAC架构图。

解决memory management_memory怎么读「建议收藏」

带有IOMMUDMAC架构图

IOMMUCPU侧的MMU类似机制,对于DDR请求会根据页表做相应的映射,再请求到页表对应DDR的物理地址。所以设定好DMAC IOMMU页表,可以固定DDR请求的物理地址,避免访问非法DDR物理地址。对于非法的范围,出发相应的异常中断。

Linux DMA架构

LinuxDMA的架构如下图5..对于内存申请,IOMMU映射,Cache的操作通过inlclude/linux/dma-mapping.h相关接口。include/linux/dmaengine.h为使用通用DMAC相关接口。对于自带DMACIP,只需要关注include/linux/dma-mapping.h相关接口。

解决memory management_memory怎么读「建议收藏」

5 linux DMA架构

通用的DMAC会通过DMA Engine导出统一的API。通用的处理流程如下。具体可参考dmates.c

 

Allocate a DMA slave channel

Set slave and controller specific parameters

Get a descriptor for transaction

Submit the transaction

Issue pending requests and wait for callback notification

 

其中申请给DMA使用的内存有两种类型,一种Consistent DMA mappings ,另外一种是Streaming DMA mappings Consistent DMA mappings也称作coherent DMA mapping,也就是驱动先申请一段stronger order内存,绕过cache达到数据一致性。Streaming DMA mappings使用的DDR normal policycache的内存,所以需要clean/invalid cache操作达到数据一致性。

Consistent DMA mapping API

这类接口适合驱动初始化时候分配好,后续的DMA相关操作固定使用申请的内存。申请接口为dma_alloc_coherent,释放接口为dma_free_coherent

static inline void *dma_alloc_coherent(struct device *dev, size_t size,

dma_addr_t *dma_handle, gfp_t gfp)

返回值为CPU 范围的地址, dma_handleDMAC操作地址。主要的流程如下

dma_alloc_coherent ->dma_mmap_attrs->dev->dma_ops->alloc

 

dma_alloc_coherent

->dma_mmap_attrs

–>dev->dma_ops->alloc

 

其中dev->dma_ops是在platform bus绑定platform device 解析其device tree设置的,相应的流程如下

 

driver_probe_device

->platform_dma_configure

->of_dma_configure

—>of_dma_get_range //dma-ranges map

—>of_dma_is_coherent // coherent

—>of_iommu_configure_device // get iommu_ops

—>arch_setup_dma_ops

—->arm_setup_iommu_dma_ops

—–>arm_iommu_create_mapping

—–>arm_get_iommu_dma_map_ops // iommu_coherent_ops

 

其中arm_get_iommu_dma_map_ops会根据device tree中时候配置coherent,决定返回值。这里说的coherent也就是这个DMAC支持ACP,对于带有cacheDDR也不需要操作cache。这里分析不带coherent配置相关接口,也就是iommu_ops。继续上述的dev->dma_ops->alloc接口arm_iommu_alloc_attrs

 

arm_iommu_alloc_attrs

->__arm_iommu_alloc_attrs

–>__iommu_alloc_buffer

–>__iommu_create_mapping //创建DMA address DDR地址映射,配置IOMMU 页表

–>dma_common_pages_remap //通过vmap接口创建stronger order内存映射

 

dma_common_pages_remap中的pte页表的配置通过__get_dma_pgprot。可以看到pte的配置是L_PTE_MT_UNCACHED

 

static inline pgprot_t __get_dma_pgprot(unsigned long attrs, pgprot_t prot)

{

prot = (attrs & DMA_ATTR_WRITE_COMBINE) ?

pgprot_writecombine(prot) :

pgprot_dmacoherent(prot);

return prot;

}

 

#define pgprot_dmacoherent(prot) \

__pgprot_modify(prot, L_PTE_MT_MASK, L_PTE_MT_UNCACHED | L_PTE_XN)

#endif

 

 

Streaming DMA mapping API

Streaming DMA mapping适用于内存已分配好,操作相应的cacheIOMMU mapDMAC使用。例如用户态发送TCP/IP数据,数据包是协议栈通过alloc_skb分配的normal policy的带cache的内存,再发起DMA操作前需要操作cache

dma_map_single 对内存分配操作cache,再进行IOMMU map操作返回DMA address

static inline dma_addr_t dma_map_single_attrs(struct device *dev, void *ptr,

size_t size, enum dma_data_direction dir, unsigned long attrs)

 

dma_map_single_attrs

->dev->dma_ops->alloc //Consistent DMA mapping probe driver设定的

arm_iommu_map_page

–>__dma_page_cpu_to_dev //通过dir确定clean/invalid cache

–>arm_coherent_iommu_map_page //构建IOMMU映射,返回DMA address

 

免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://yundeesoft.com/29156.html

(0)

相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注微信