Skip to main content

Linux Kernel Memory Mapping: Understanding ioremap

·759 words·4 mins
Linux Kernel Device Drivers Memory Management Embedded Systems
Table of Contents

Linux Kernel Memory Mapping: Understanding ioremap

In the Linux kernel, ioremap is a fundamental function used to map device I/O physical addresses—typically hardware registers—into the kernel’s virtual address space.

Because the Linux kernel operates in virtual memory, it cannot directly access raw physical addresses. Instead, functions like ioremap create a virtual mapping so that kernel drivers can safely interact with hardware.

For ARM-based embedded systems and many other architectures, ioremap is the standard mechanism used by device drivers to access memory-mapped I/O registers.


🧭 How to Use ioremap
#

The ioremap function maps a physical address range into the kernel’s virtual address space.

It takes two parameters:

  • Physical address – the starting hardware register address
  • Size – the length of the memory region to map

The function returns a pointer of type:


void __iomem *

This annotation reminds developers that the pointer refers to I/O memory, not normal RAM.

Basic Usage Flow
#

Map the Physical Address
#

First, map the device register’s physical address into kernel virtual memory.

// Map a physical register address to a kernel virtual address
void __iomem *addr = ioremap(phys_addr, size);

After this call succeeds, addr points to the mapped virtual address that corresponds to the device register.

Access the Hardware Register
#

The Linux kernel provides helper macros such as readl() and writel() to safely access I/O memory. These helpers enforce proper memory barriers and ensure correct ordering for hardware operations.

u32 val = readl(addr);          // Read register value
val |= (0x1 << ENABLE_SHIFT);   // Modify specific bit
writel(val, addr);              // Write value back

Direct pointer dereferencing should be avoided for device registers because it may bypass required memory ordering rules.

Release the Mapping
#

Once the mapping is no longer needed, it should be removed using iounmap().

iounmap(addr);

This releases the virtual address range previously allocated by ioremap.


⚙️ Internal Implementation Logic
#

Internally, ioremap works in two major steps: allocating virtual address space and creating page table mappings.

Allocating Virtual Address Space
#

The Linux kernel reserves virtual memory for ioremap from the vmalloc area.

This region is specifically designed for dynamically created virtual mappings that do not require contiguous physical memory.

Internally, the kernel calls a function similar to the following:

area = get_vm_area_caller(size, VM_IOREMAP, caller);

This step finds a suitable free region in the vmalloc virtual address range.

Creating Page Table Entries
#

Once the virtual region is reserved, the kernel updates the kernel page tables to map that virtual range to the requested physical I/O address range.

err = ioremap_page_range(addr, addr + size, phys_addr, prot);

This establishes the translation:

Kernel Virtual Address  →  Device Physical Address

After this mapping is installed, the kernel can access the device registers through the returned virtual pointer.


🔄 ioremap vs vmalloc
#

Although both ioremap and vmalloc use the vmalloc virtual address space, their purposes are very different.

Feature vmalloc ioremap
Source Allocates new physical pages from the kernel memory allocator Maps existing device physical addresses
Purpose Provides contiguous virtual RAM for kernel use Enables access to hardware registers or device memory
Physical Layout Backed by scattered physical pages Maps a predefined physical device region
Typical Usage Kernel buffers, large memory blocks Device drivers, MMIO registers

In short:

  • vmalloc creates memory
  • ioremap exposes hardware

🧩 Why ioremap Is Necessary
#

Modern operating systems rely on virtual memory abstraction to isolate processes and manage memory safely.

Hardware devices, however, exist in the physical address space. Without a mechanism like ioremap, kernel drivers would have to manipulate physical addresses directly, which would break the virtual memory model.

By mapping device registers into kernel virtual space, ioremap allows drivers to:

  • Safely access memory-mapped hardware registers
  • Maintain consistent memory protection
  • Integrate device access into the kernel’s virtual memory system

🧠 Summary
#

ioremap acts as the bridge between the Linux kernel’s virtual memory environment and the physical address space of hardware devices.

Its workflow can be summarized as:

  1. Reserve a virtual address range from the vmalloc area
  2. Map that virtual region to the device’s physical I/O addresses
  3. Access registers using safe helper macros like readl() and writel()
  4. Release the mapping with iounmap() when finished

Without ioremap, kernel drivers would not be able to safely interact with memory-mapped hardware devices while maintaining the kernel’s virtual memory abstraction.


🚀 Looking Ahead: ioremap Variants
#

The Linux kernel also provides specialized variants such as:

  • ioremap_nocache
  • ioremap_wc
  • ioremap_cache

Each controls CPU caching behavior for mapped I/O regions and can significantly affect device performance.

Understanding when to use each variant is an important next step for optimizing Linux device driver performance.

Related

QNX Device Driver Programming with Resource Managers
·824 words·4 mins
QNX RTOS Device Drivers Embedded Systems
Embedded C Explained: Double Pointers and Memory Models
·625 words·3 mins
C Language Pointers Embedded Systems Memory Management
Understanding Peripheral Drivers Through the Linux Kernel Device Model
·725 words·4 mins
Linux Kernel Device Drivers Kobject Device Model Embedded Linux