Location of Port mapped I/O address space - linux

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.

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?

Linux Kernel Mapping Physical Memory for DMA

I'm developing on an embedded system that has a DSP and a CPU. There is a shared memory region between the DSP and CPU. The DSP processes data and signals to the CPU when data is ready. I'm running Linux on the CPU and have excluded the shared memory region from the kernel mapping.
I have Linux kernel driver code that can ioremap the physical address sent by the DSP. Using the returned virtual address, I can inspect the data and see that the data looks valid. I'm now having trouble trying to map the data so I can DMA it out of the CPU to a peripheral device. I want to avoid copying the data to a dma_alloc_coherent region to minimize latency.
I believe this is because there is an IOMMU between the memory and the device doing the DMA. What do I need to do in order to generate the dma address to physical address mapping?

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.

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

Linux allocates memory at specific physical address

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.

Resources