在Linux下获取缓冲区的物理地址 [英] get the physical address of a buffer under Linux

查看:183
本文介绍了在Linux下获取缓冲区的物理地址的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在Xilinx的Microblaze上运行Linux内核3.3,配备完整的MMU。我正在做的任务要求我知道以下内容:我需要创建一个文本文件(缓冲区)并找到这个缓冲区的物理地址,我不希望内核把这个文件写入不连续的内存区域。 / p>

我需要这个的原因是因为我有一个DMA引擎,从预设的物理内存地址中流出数据,所以我需要强制Linux在那个确切的内存中创建缓冲区文件位置,所以当我将数据写入该文件时,它立即由DMA引擎传输到另一个硬件核心。



更多详细信息:



我的系统有一个512 MB DDR3 RAM通过Xilinx多端口存储控制器(MPMC)连接到系统,该内存控制器的基址为0x90000000,系统通过该控制器访问存储器中的所有单元,包括MicroBlaze,我使用了一个名为Native Personality Interface(NPI)的特殊接口的DMA单元与内存进行非常低的通信,因此r造成非常高速的表现。



此NPI DMA单元最初设计用于不支持虚拟内存的称为xilkernel的非常基本的嵌入式内核,这两个MMU都不是MicroBlaze的一部分,所以程序员可以看到操作系统代码将驻留在哪里,并选择一个物理内存地址,例如0x91800000作为DMA将流入的源地址,然后程序员可以将文件放在该确切的地址中并运行系统



当我们需要迁移项目以使用Linux而不是xilkernel我们遇到这个问题,我有一个外部存储设备上的文件,我可以从Linux访问作为块设备,我需要移动每个文件到主内存(DDR3 RAM),并使DMA流成为文件。
当前来自固定地址的DMA流,但如果需要,我可以使其成为通用。

解决方案

接口与DMA控制器有特定的功能。这些功能不仅要处理地址转换,还要处理缓存与内存的一致性,如缓存刷新(在发送前将数据写入存储器)并缓存无效(接收之前使缓存无效)。



(1)要分配缓冲区,请同时获取虚拟地址和物理地址:

  void * dma_alloc_coherent struct device * dev,size_t size,
dma_addr_t * dma_handle,gfp_t flag)

功能的值是分配的缓冲区的虚拟地址,而dma_handle指针保存分配的缓冲区的物理地址。



(2)将一个分配给设备:

  dma_addr_t dma_map_single(struct device * dev,void * ptr,
size_t size,
enum dma_data_direction dir)

返回值是缓冲区的物理地址, nd参数dir是DMA_TO_DEVICE,ptr是缓冲区的虚拟地址;



(3)从设备接收一个缓冲区:

  void dma_unmap_single(struct device * dev,dma_addr_t addr,
size_t size,
enum dma_data_direction dir)

参数dir为DMA_FROM_DEVICE。



注意:
要使用三与dma有关的功能,应该将设备注册到具有dma_map_ops的特定总线,否则这三个功能将无法使用。


I am running Linux kernel 3.3 on Xilinx's Microblaze with full MMU. the task that I am doing requires me to know the following: I need to create a text file (buffer) and locate the physical address of this buffer and I don't want the kernel to write this file into discontinuous regions of memory.

the reason I need this because I have a DMA engine that streams data from a preset physical memory address, so I need to force Linux to create the buffer file at that exact memory location, so that when I write data into this file its immediately transmitted by the DMA Engine to another Hardware core

More details:

my system has a 512 MB DDR3 RAM connected to the system via "Xilinx' multi port memory controller (MPMC). the base address of this memory controller is 0x90000000, all units in the system access memory through this controller, including MicroBlaze, The DMA unit that I have uses a special interface called Native Personality Interface (NPI) to communicate with memory at a very low level, thus resulting a very high speed performance.

This NPI DMA unit was originally designed to be utilized under a very basic embedded kernel called "xilkernel" which did not support virtual memory, neither MMU was part of MicroBlaze, so the programmer could see where the OS code will reside and select a physical memory address such as 0x91800000 as the source address which DMA will stream from, then the programmer can place a file in that exact address and run the system

when we needed to the migrate the project to use Linux instead of xilkernel we ran into this issue, I have files on an external storage device which I can access as block device from Linux and I need move each file to main memory (DDR3 RAM) and make the DMA stream the file. currently the DMA streams from a fixed address but I can make it generic if needed.

解决方案

To handle buffers to interface with DMA controller, there are specific functions. These functions take care of not only the address translation but also the cache coherency with memory such as cache flush(write data to memory before sending) and cache invalidate(invalidate the cache before receiving).

(1) To allocate a buffer, get both the virtual address and physical address:

void *dma_alloc_coherent(struct device *dev, size_t size,
                         dma_addr_t *dma_handle, gfp_t flag)

the return value of the function is the virtual address of the buffer allocated, while the dma_handle pointer saves the physical address of the buffer allocated.

(2) To pass one buffer allocated to device:

dma_addr_t dma_map_single(struct device *dev, void *ptr,
                          size_t size,
                          enum dma_data_direction dir)

The return value is physical address of the buffer, and parameter dir is DMA_TO_DEVICE, ptr is the virtual address of the buffer;

(3) To receive one buffer from device:

void dma_unmap_single(struct device *dev, dma_addr_t addr,
                            size_t size,
                            enum dma_data_direction dir)

The parameter dir is DMA_FROM_DEVICE.

Note: To use the three functions related to dma, one should register a device to one specific bus which has the dma_map_ops, or else these three functions can not be used.

这篇关于在Linux下获取缓冲区的物理地址的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆