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?
Related
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.
I know access to ports in I/O address spaces requires specific IN/OUT instructions and they are not part of Physical memory( RAM) but I have not understood Where is the I/O address space actually located (Physically)? (some sort of RAM in )I/O controller? Reserved side of physical memory?
On the early X86 processors (and also the 8080, Z80 etc) I/O address space was on the same data and address bus as the memory, but was accessed by activating a dedicated IO-request pin on the CPU
So electrically I/O was in parallell with the RAM
Thses days the CPU speaks HDMI and PCIe directly so much of the I/O space is either internal to the CPU (eg: the VGA I/O interface) or accessed over th serial bus that is PCIe
PCIe is also used for memory mapped I/O so in that respect IO is still accessed over mostly the same electrical interfaces as memory mapped IO . but not over the same IO pins that are used for RAM any more,
A list of I/O addresses can be found in Ralf Browns x86/MSDOS Interrupt List:
http://www.pobox.com/~ralf
http://www.pobox.com/~ralf/files.html
ftp://ftp.cs.cmu.edu/afs/cs.cmu.edu/user/ralf/pub/
inter61d.zip: "PORTS.A", "PORTS.B", "PORTS.C"
First, you should understand that a device can be programmed to respond to any address, even if that address is not part of physical memory. This is done by programming their memory decoders. In short, the memory for I/O devices is located on the device. The I/O space provided to the device usually maps the memory which is on the device, i.e., each I/O device provides it's own memory.
Well, in the old days, there were certain "well-known" addresses, for instance, 0x3f8, 0x2f8 for com (serial) ports, 0xCF8-0xCFC for PCI config space. These addresses do not use any physical memory, a separate I/O signal is asserted to indicate such. These devices memory decoders were programmed at the factory to respond to these addresses only when the I/O pin is asserted.
But this became obsolete. Even in the later days of PCI, most devices were initially configured through IO space, but then their memory decoders were programmed to respond to a memory-mapped address in the virtual space above physical memory. When memory decoders are programmed, not only is the base address provided but also the size of that address space is provided as well to avoid collisions between devices. The memory is located on the device, not in the host computer's RAM or chipset.
For PCI-express, I believe now the acpi table is consulted for the memory-mapped space and i/o instructions are essentially deprecated. Serial ports are not usually included on modern hardware. And even if they were it would be implemented on a PCI or PCIe device.
How does xen handle E820 memory map for domU kernels? In my specific problem I am trying to map Non-Volatile RAM to domU kernels. The dom0 memory map returns the following relevant parts.
100000000-17fffffff : System RAM (4GB to 6GB)
180000000-37fffffff : reserved (6GB to 14GB)
The second line corrosponds to the NVRAM which is a region from 6GB to 14GB in the dom0 kernel. How can I map this NVRAM region to the domU kernel which does not map this region at all.
Ultimately I want to the nvram region to be available in other domU VMs so any solutions or advice would be highly helpful.
P.S. :: If I attempt to write to this region from the domU kernel will Xen intercept this write operation. Actually this is just a memory region write which should not be a problem, but it might appear as a hardware access.
Guest domains in Xen have two different models for x86:
1. Hardware Virtual Machine (HVM) : It takes benefit of Intel VT or AMD SVM extensions to enable true virtualization on x86 platform
2. Paravirtualized (PV) : This mode adds modifications in the source code of the operating system to get rid of the x86 virtualization problems and also add performance boost to the system.
These two different models handle the E820 memory map differently. E820 memory map basically gives an OS the physical address space to operate on along with the location of I/O devices. In PV mode I/O devices are available through Xenstore. The domain builder only provides a console device during boot to the pv guest. All other I/O devices have to be mapped by the guest. The guest in this mode starts execution in protected mode instead of real mode for x86. The domain builder maps the start_info pages into the guest domain's physical address space. This start_info pages contain most of the information to initialize a kernel such as number of available pages, number of CPUs, console information, Xenstore etc. E820 memory map in this context would just consist of the number of available memory pages because BIOS is not emulated and I/O device information is provided separately through Xenstore.
On the otherhand, in HVM guest BIOS and other devices have to be emulated by Xen. This mode should support any unmodified OS, thus we cannot use the previous method. BIOS emulation is done via code borrowed from Bochs, while devices are emulated using QEMU code. Here an OS is provided with an E820 memory map, build by the domain builder. The HVM domain builder would typically pass the memory layout information to the Bochs emulator which then performs the required task.
To get hold of the NVRAM pages you will have to build a separate MMU for NVRAM. This MMU should handle all the NVM pages and allocate/free it on demand just like the RAM pages. It is a lot of work.
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
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.