Get physical buffer address under Linux

I am running the Linux 3.3 kernel on Xilinx Microblaze with full MMU. The task that I perform requires that I know the following: I need to create a text file (buffer) and find the physical address of this buffer, and I do not want the kernel to write this file to intermittent memory areas.

the reason I need this is because I have a DMA mechanism that transfers data from a given address of physical memory, so I need to force Linux to create a spooled file in that exact memory location so that DMA is immediately transferred to it when writing data to this file Engine to another hardware core

More details:

my system is equipped with 512 MB DDR3 RAM connected to the system through a Multi-Xilinx memory controller (MPMC). The base address of this memory controller is 0x90000000, all the blocks in the system access memory through this controller, including MicroBlaze, the DMA module that I have, uses a special interface called Native Personality Interface (NPI) to communicate with the memory at a very low level, resulting in very high performance.

This DMA DMI module was originally designed for use in a very basic embedded kernel called "xilkernel" that did not support virtual memory, none of the MMUs were part of MicroBlaze, so the programmer could see where the OS code would be and select the address of the physical memory such as 0x91800000 as the source address from which DMA will be transmitted, then the programmer can put the file in that exact address and start the system

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

+6
source share
2 answers

There are certain functions for processing buffers for an interface with a DMA controller. These functions take care not only of address translation, but also of the coherence of the cache with memory, such as flash cache (write data to memory before sending) and cache invalid (invalidate cache before receiving).

(1) To allocate a buffer, get both the virtual address and the 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 allocated buffer, and the dma_handle pointer stores the physical address of the allocated buffer.

(2) To transfer one buffer allocated to a device:

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

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

(3) To receive one buffer from a device:

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

The dir parameter is DMA_FROM_DEVICE.

Note: To use the three functions related to dma, you must register the device on one specific bus that has dma_map_ops, or these three functions cannot be used.

+5
source

I need to force Linux to create a spooled file in this exact memory location

It's impossible. (Actually, you created the XY question.)

Since you have hardware that "transfers data from a given physical memory address", you must ensure that the Linux kernel does not use this memory area as part of the memory pool. You must tell the kernel when it is loading so as not to use this memory area. You cannot "restore" or allocate buffers in this particular area of ​​physical memory as soon as it becomes part of the memory space controlled by the kernel.

The most common method for excluding memory space is to use the memmap= parameter on the kernel command line.

 memmap=nn[KMG]$ss[KMG] [KNL,ACPI] Mark specific memory as reserved. Region of memory to be used, from ss to ss+nn. Example: Exclude memory from 0x18690000-0x1869ffff memmap=64K$0x18690000 or memmap=0x10000$0x18690000 

Some architectures, such as ARM with its ATAG, have other less visible and more secure methods for reserving physical memory areas.

Somehow you need to specify the address and size of this memory area to the device driver. This can be obtained by parsing the command line or (thumbs down) using #define s.

The driver must declare its use of the memory area by calling request_mem_region() .
A driver can map this memory to a virtual address space by calling ioreamp() .

Since the driver is provided or already knows the physical address, this has already been done. Since physical memory has been allocated, memory is therefore contiguous. You need to configure MMU to disable caching in this memory area. Then the memory area will be "DMAable".

+4
source

Source: https://habr.com/ru/post/947157/


All Articles