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:
vmalloccreates memoryioremapexposes 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:
- Reserve a virtual address range from the vmalloc area
- Map that virtual region to the device’s physical I/O addresses
- Access registers using safe helper macros like
readl()andwritel() - 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_nocacheioremap_wcioremap_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.