Skip to content

ioremap()

Overview

Memory-Mapped I/O (MMIO) allows hardware peripherals to expose registers through physical memory addresses.

Unlike normal RAM, these physical addresses correspond to hardware devices rather than system memory.

Linux drivers cannot directly access MMIO physical addresses. Instead, they must create a kernel virtual mapping using ioremap().

After mapping, drivers access device registers through the returned virtual address using APIs such as readl() and writel().


Why ioremap()?

Modern operating systems use virtual memory.

Kernel code normally operates on virtual addresses, while hardware peripherals expose fixed physical addresses.

For example:

Physical Address

0xFE200000
GPIO Controller Registers

Instead of directly accessing this physical address, Linux performs:

Physical Address
ioremap()
Kernel Virtual Address

The returned virtual address is then used throughout the driver.


Linux MMIO Architecture

In Linux, ioremap() establishes a page-table mapping between a virtual address and a physical MMIO region.

Whenever the driver accesses the mapped address, the CPU MMU performs address translation automatically.

Driver

Kernel Virtual Address
        MMU
Physical Address
Hardware Registers

The driver never performs this translation itself.


Simulator Architecture

The simulator cannot modify kernel page tables.

Instead, it implements a simplified MMIO mapping layer entirely in userspace.

            +----------------------+
            |     io_region        |
            +----------------------+
            | Physical Address     |
            | Size                 |
            | Backing Storage      |
            +----------+-----------+
                       |
                       |
            +----------v-----------+
            |    io_mapping        |
            +----------------------+
            | Virtual Address      |
            | Physical Address     |
            | Size                 |
            +----------+-----------+
                       |
           io_mapping_translate()
                       |
             Backing Storage Pointer

Unlike Linux, the simulator introduces backing storage.

This storage is allocated from heap memory and simulates hardware registers.


MMIO Region

A region represents a physical MMIO device.

io_region_register(0x10000000, 0x1000);

Each registered region owns:

  • Physical base address
  • Region size
  • Simulated backing storage

Multiple virtual mappings may reference the same region.


Virtual Mapping

Drivers create virtual mappings using ioremap().

base = ioremap(0x10000000, 0x100);

The simulator allocates virtual addresses independently of the backing storage.

For example:

Physical Address          Virtual Address

0x10000000      --->      0x20000000
0x10000800      --->      0x20001000

Mappings are allocated in page-sized increments, similar to Linux.


Address Translation

The simulated virtual address cannot be dereferenced directly.

Instead:

Virtual Address
Find Mapping
Calculate Mapping Offset
Calculate Region Offset
Backing Storage

The translation computes:

storage
+ region_offset
+ mapping_offset

This replaces the work normally performed by the MMU.


Mapping Lifecycle

The ownership model follows the Linux driver model.

io_region_register()
ioremap()
MMIO Access
iounmap()
io_region_unregister()

A region cannot be removed while active mappings still exist.


Linux vs Simulator

Linux Simulator
Hardware registers Backing storage
Physical address Physical address
Page table Mapping list
MMU io_mapping_translate()
Kernel virtual address Simulated virtual address
readl() directly accesses MMIO readl() translates to backing storage

Key Points

  • MMIO devices are accessed through memory addresses rather than I/O ports.
  • ioremap() converts a physical MMIO address into a kernel virtual address.
  • Linux relies on the MMU to perform address translation automatically.
  • The simulator replaces the MMU with io_mapping_translate().
  • Backing storage exists only in the simulator to emulate hardware registers.
  • Multiple virtual mappings may reference the same physical MMIO region.