Content of /Proc/Iomem

Content of /proc/iomem


1) Is it possible to access a physical address which is not defined in /proc/iomem?

Yes.

Assuming an ARM processor which memory maps all directly-connected periperals, the driver could perform an ioremap() operation to map the physical memory to virtual memory for access.

But a properly written driver would first call request_mem_region() to ensure that it can use (and lay claim to) that physical address space.

The information in /proc/iomem comes from drivers calling request_mem_region().

2) If the physical address range of a device does not appear in /proc/iomem, does it mean that the device has not been utilized/initialized yet?

You would have to inspect the driver code to determine how well written the driver is.

Is there a request_mem_region() before the ioremap()?

Check the system log using the dmesg command; perhaps driver initialization failed.

Assuming that this is a statically-linked driver rather than a loadable module, then as each kernel device driver has its init() routine called you can get trace output by having added the option "initcall_debug" on the kernel command line. If you are using U-Boot, then this option should be added to the "bootargs" variable (which is used for the kernel command line).

How procfs outputs /proc/iomem?


  1. struct resource iomem_resource is what you're looking for, and it is defined and initialized in kernel/resource.c (via proc_create_seq_data()). In the same file, the instance struct seq_operations resource_op defines what happens when you, for example cat the file from userland.
  2. iomem_resource is a globally exported symbol, and is used throughout the kernel, drivers included, to request resources. You can find instances scattered across the kernel of devm_/request_resource() which take either iomem_resource or its sibling ioport_resource based on either fixed settings, or based on configurations. Examples of methods that take configurations are a) device trees which is prevalent in embedded settings, and b) E820 or UEFI, which can be found more on x86.

Starting with b) which was asked in the question, the file arch/x86/kernel/e820.c shows examples of how reserved memory gets inserted into /proc/iomem via insert_resource().
This excellent link has more details on the dynamics of requesting memory map details from the BIOS.

Another alternative sequence (which relies on CONFIG_OF) for how a device driver requests the needed resources is:

  1. The Open Firmware API is traversing the device tree, and finds a matching driver. For example via a struct of_device_id.
  2. The driver defines a struct platform_device which contains both the struct of_device_id and a probe function. This probing function is thus called.
  3. Inside the probe function, a call to platform_get_resource() is made which reads the reg property from the device tree. This property defines the physical memory map for a specific device.
  4. A call to devm_request_mem_region() is made (which is just a call to request_region()) to actually allocate the resources and add it to /proc/iomem.

Understanding /proc/iomem

You are running into the 3 GB barrier (which your BIOS has moved down to 2 GB).
Only 2 GB are used as system RAM; the other 2 GB of the physical address space are used for I/O devices.

The other memory is used as high memory, which cannot be used directly but must be mapped, page by page, into the virtual address space whenever it is to be accessed.

Is the System RAM displayed by /proc/iomem is like unallocated memory?


0000000-0000ffff : reserved      // Reserved = not used, not available for anything.
00010000-0009c3ff : System RAM // Regular memory - can be used to store code or data/
0009c400-0009ffff : reserved
000a0000-000bffff : PCI Bus 0000:00 // PCI device memory case
000a0000-000bffff : Video RAM area // (graphics/video memory in this)
000c0000-000c7fff : Video ROM // VGA BIOS memory
000d0000-000d0fff : Adapter ROM // General area for "boot ROM", e.g. Network boot
000d2000-000d3fff : reserved
000d4000-000d7fff : PCI Bus 0000:00 // Some other PCI device
000d8000-000dbfff : PCI Bus 0000:00 // as above
000dc000-000dffff : PCI Bus 0000:00
000e0000-000fffff : reserved
000f0000-000fffff : System ROM // System BIOS
00100000-bb27bfff : System RAM // Regular RAM
01000000-015b0afb : Kernel code // Kernel "code" uses this bit.
015b0afc-01878c3f : Kernel data // Kernel "data"
01939000-01a11fff : Kernel bss // Kernel "initialized to zero" data.
bb27c000-bb281fff : reserved
bb282000-bb3e9fff : System RAM
bb3ea000-bb40efff : reserved
bb40f000-bb46efff : System RAM
bb46f000-bb46ffff : reserved
bb470000-bb4f0fff : ACPI Non-volatile Storage // Advanced Control and Power Interface memory (doesn't got away when power is off!)
bb4f1000-bb70efff : reserved
bb70f000-bb716fff : System RAM
bb717000-bb71efff : reserved
bb71f000-bb77dfff : System RAM
bb77e000-bb79efff : ACPI Non-volatile Storage
bb79f000-bb7e1fff : System RAM
bb7e2000-bb7fefff : ACPI Tables
bb7ff000-bb7fffff : System RAM
bb800000-bfffffff : reserved
c0000000-dfffffff : PCI Bus 0000:00
c0000000-c04fffff : PCI Bus 0000:04 // PCI bus bridge device

Identify DMA memory in /proc/mtrr and /proc/iomem?

DMA (Direct Memory Access) is just where a device accesses memory itself (without asking CPU to feed the data to the device). For a (simplified) example of DMA; imagine a random process does a write(), and this bubbles its way up (through VFS, through file system, through any RAID layer, etc) until it reaches some kind of disk controller driver; then the disk controller driver tells its disk controller "transfer N bytes from this physical address to that place on the disk and let me know when the transfer has been done". Most devices (disk controllers, network cards, video cards, sound cards, USB controllers, ...) use DMA in some way. Under load, all the devices in your computer may be doing thousands of transfers (via. DMA) per second, potentially scattered across all usable RAM.

As far as I know; there are no files in /proc/ that would help (most likely because it changes too fast and too often to bother providing any, and there'd be very little reason for anyone to ever want to look at it).

The MTTRs are mostly irrelevant - they only control the CPU's caches and have no effect on DMA requests from devices.

The /proc/iomem is also irrelevant. It only shows which areas devices are using for their own registers and has nothing to do with RAM (and therefore has nothing to do with DMA).

Note 1: DMA doesn't have to be in the lower 32-bit (e.g. most PCI devices have supported 64-bit DMA/bus mastering for a decade or more); and for the rare devices that don't support 64-bit it's possible for Linux to use an IOMMU to remap their requests (so the device thinks it's using 32-bit addresses when it actually isn't).

Note 2: Once upon a time (a long time ago) there were "ISA DMA controller chips". Like the ISA bus itself; these were restricted to the first 16 MiB of the physical address space (and had other restrictions - e.g. not supporting transfers that cross a 64 KiB boundary). These chips haven't really had a reason to exist since floppy disk controllers became obsolete. You might have a /proc/dma describing these (but if you do it probably only says "cascade" to indicate how the chips connect, with no devices using them).

How is /proc/io* populated?


If you pick up some book on Linux device drivers, it will state something about iomem being populated by the driver calling request_region() or something like that.

The information in /proc/iomem comes from drivers calling request_mem_region().

See Content of /proc/iomem.

how does the device driver know where the hardware register is located

The address of a device register is typically specified by either the board (for an external peripheral) or SoC designer (for an integrated peripheral), and then conveyed in the board or SoC documentation. Some boards (e.g. PC ISA adapter boards) may allow address specification by some DIP switches.

The writer of the device driver then can

(a) hardcode the device address in the driver itself or a board file, or

(b) retrieve the device address using some bus configuration method (e.g. PCI configuration space), or

(c) retrieve the device address using a (handwritten) configuration list (e.g. Device Tree, FEX, ATAGs), or

(d) try to probe the device at runtime.

Note that conveying the system configuration and device addresses to device drivers is a longstanding issue.

The IBM PC's method of assigned addresses that were then hardcoded eventually led to the plug and play initiative for x86 PCs.

Issues with unique Linux kernel builds for each and every ARM board led to the adoption of Device Tree (from PowerPC) for that architecture.



Related Topics



Leave a reply



Submit