Linux allocates memory at specific physical address - linux

I am testing a PCI Endpoint driver, I would like to do simple copy from the PCI RootPort side to the PCI Endpoint side. In PCI Endpoint side, we have address translation from PCI address to CPU physical address. We can configure the CPU physical address in the translation so that it maps to the specific DRAM region. The problem is how can we allocate a memory buffer at that specific CPU physical address to make sure the write from RootPort side really works?
Any recommendations are appreciated. Thanks a lot!

You need to first reserve the physical memory area. The easiest but ugly way to do that is to pass a "mem=" parameter to the kernel command line that precludes the physical memory range you are interested in from kernel memory management and then use ioremap() to get a virtual mapping of that.
For example if your machine has 256 Mb of RAM use mem=255M to reserve the last Mb to your uses and then map it via ioermap()
NOTE: original answer fixed based on feedback from #Adrian Cox.

If you can remap the translation on the fly, then you should work like any driver that uses DMA. Your basic reference for this is Chapter 15 of LDD3, plus the Linux DMA API.
What you are allocating is a DMA coherent buffer, via dma_alloc_coherent. On most platforms you should be able to pass in a null struct device pointer and get a generic DMA address. This will give you both a kernel virtual address to access the data, and a dma address which is the CPU physical address to map through your translation layer.
If your address translation is not very flexible, you may need to modify the platform code for your endpoint to reserve this buffer early on, in order to meet address alignment requirements. This is a bit more complicated, but there is an update of the bigphysarea patch to recent kernels that may help as a starting point.

Related

Is it possible to partially virtualize the physical address space?

I'm currently working on systems that include embedded Linux and FPGAs. We've various IP cores that support the AXI-Bus. To communicate with the IP cores of PL (programable logic), we need to map them onto the address space of the PS (processing system). For example, for the widely used Zynq PS the address space is as follows (UG585 - Section 4.1: Address Map)
0x0000_0000 to 0x7FFF_FFFF: Mapped to the physical memory. Either external DDR or on-chip memory
0x8000_0000 to 0xBFFF_FFFF: Mapped to the PL explained above
0xE000_0000 to 0xFFFF_FFFF: Various other devices on the chip
As you can see, only the first 1GB of the address space is reserved to the physical memory, and the rest is occupied by the devices either in PL or PS. So, if possible, the virtualization range can be applied only for the first 1GB to allow faster access to devices on the chip by skipping the MMU.
I know that by doing such a modification we allow any kind of process to access the physical devices of the system without any control of its privileges. So, the questions are
Is it possible to partially virtualize the physical address space in Linux or any other OS?
If it is possible, would it be rational to do it?

procfs is located in memory, but where? Is it possible to obtain its address for DMA?

I'm developing on an FPGA/SoC and need to access procfs via DMA. I understand it's a pseudo filesystem located in memory, and am wondering if it's possible to obtain its address (similar to how the syscall table address is accessible in System.map) I'd like to have access to memory utilization and other stats.
You already got the answer from #Barmar comment. I just want to add some more information about procfs.
Actually pesudo is something pretend to. It means pesudo filesystem that doesn't have actual files, it has virtual entries that the filesystem available to access.
Is it possible to obtain address of DMA?
Answer is yes.
There are several kinds of addresses involved in the DMA API, and it’s important to understand the differences.
The kernel normally uses virtual addresses. Any address returned by kmalloc(), vmalloc(), and similar interfaces is a virtual address and can be stored in a void *.
From a device’s point of view, DMA uses the bus address space, but it may be restricted to a subset of that space. For example, even if a system supports 64-bit addresses for main memory and PCI BARs, it may use an IOMMU so devices only need to use 32-bit DMA addresses.
Read this kernel document for more info about DMA-API-HOWTO.txt

Application processor memory map

What information is contained in the memory map of application processor? Is it tells which subsystem can access which area of RAM or it means if CPU tries to access an address based on memory map it can be RAM address or a device address? I am referring this documentation
http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0515b/CIHIJJJA.html.
Here 0x00_0000_0000 to 0x00_0800_0000 is mapped to the boot region, what does that imply?
The style of memory map diagram you've linked to shows how the processor and peripherals will decode physical memory addresses. This is a normal diagram for any System-on-Chip device, though the precise layout will vary. The linked page actually lists which units of the SoC use this memory map for their address decoding, and it includes the ARM and the Mali graphics processor. In a Linux system, much of this information will be passed to the kernel in the device tree. It's important to remember that this tells us nothing about how the operating system chooses to organise the virtual memory addresses.
Interesting regions of this are:
DRAM - these addresses will be passed to the DRAM controller. There is no guarantee that the specific board being used has DRAM at all of that address space. The boot firmware will set up the DRAM controller and pass those details to the operating system.
PCIe - these addresses will be mapped to the PCIe controller, and ultimately to transfers on the PCIe links.
The boot region on this chip by default contains an on-chip boot rom and working space. On this particular chip there's added complexity caused by ARMs TrustZone security architecture, which means that application code loaded after boot may not have access to this region. On the development board it should be possible to override this mapping and boot from external devices.
The memory map contains an layout of the memory of your device.
It tells your OS, where the OS can place data and how it is accessed, as some areas may be only accessible in a privileged state.
Your boot image will be placed in the boot area.This defines among other things your entry point.

Virtual memory to physical memory

I'm working with a trustzone (ARM) and unlike memory access in linux, the trusted applet does not have access to the virtual-physical memory mapping. It deals strictly with physical memory.
How would I go about translating from virtual to physical addresses?
So if i understand you don't know which memory area your application can use as it is detached from the virtual address space set in the CPU?
In my opinion you have only two choices:
Somehow tell the OS that a section of memory (physical) is reserved for the application. Let's say from 0xfff0 to 0xffff
The Page Table with the mapping is usually at the end of the kernel in memory. Try to get that address and you can search it for a free adress space (memory block).

What is i/o port , i/o port address? Is that address a part of RAM?

What is i/o port , i/o port address? When a driver wants to communicate with hardware, for example the parallel port (0x378). That port address(0x378) is RAM address or something else?
This ultimately depends on the architecture of the system.
x86 processors and the 8080 (and ultimately 8008) from which they descend use a scheme called I/O mapping where a special control signal from the processor indicates that an access is to an I/O port rather than a regular memory location. A corresponding special instruction must be used for such access.
Many other processors - especially the ARM cores so widespread in mobile and embedded devices today - follow from a different design tradition in which I/O ports are memory mapped within the same unified address space as ordinary memory. This means that they appear as regular memory locations (in a special reserved address region) and are accessed with fairly normal instructions. One caveat however is that sometimes only specific width access is permitted - for example a 32-bit embedded ARM chip may require that a particular port be accessed using a 16-bit memory access instructions, even though a full 32-bit bus word is reserved for it.
Ultimately the information about a specific processor is found in its Data Sheet or Programmer's Manual. Systems with busses connecting off-chip peripherals - especially bridged busses - may add additional constraints.
Each I/O device connected to your computer is mapped to a unique I/O (Input/Output) address. These addresses are assigned to every I/O port on your computer, including USB, Firewire, Ethernet, VGA etc. In your computer there are 65,535 ports that are numbered from 0000h to FFFFh.
I/O addresses are controlled by the computer's motherboard, they do not use up any system memory, or RAM. Having a unique address assigned to each port allows your computer to easily recognize and locate devices attached to your computer. Whether it is a keyboard, mouse, monitor, printer, or any other device, the computer can locate it by its I/O address.
The two ways of connecting a peripheral to cpu is 1)through a dedicated I/O bus(port mapped I/O) 2)interfacing to processor via memory controller(Memory mapped I/O).
port mapped I/O devices are directly addressed by processor and need special instructions to achieve it.
Memory mapped I/O needs address translation ie.., Some of the physical addresses are dedicated to I/O. To read or write from these devices we can just use instructions generally as that of reading or writing into RAM locations.In brief we are completely abstracted from directly accessing the device status and control registers (and other registers if any) via memory controller.
That is what ioremap() function in kernel exactly does for the above implementation to happen ie.., mapping device address region into process's virtual address space.
The memory ,devices and cpu are connected to primary address bus.when bus sees certain addresses the addressing decoding circuitry knows that they are not the memory addresses but are generated to access a I/O device.
Besides note that port mapped devices can be accessed from user and kernel mode but memory mapped devices are mapped from kernel space only.
In nut shell the answer for the question you asked is -the address 0x378 will be a reserved physical ram address if it were to be a memory mapped one.
Try cat /proc/iomem if the address not here then it is a port mapped one for sure.
hope this clarifies you
#Gopikrishnaraju

Resources