Fundamentals 39 min read

Early I/O Memory Mapping (early_ioremap) in the Linux Kernel

The article explains the purpose, implementation, and usage of early I/O memory mapping (early_ioremap) in the Linux kernel, detailing its initialization, fixmap foundations, code flow, and differences from regular ioremap, with examples and kernel source snippets.

Deepin Linux
Deepin Linux
Deepin Linux
Early I/O Memory Mapping (early_ioremap) in the Linux Kernel

Everyone knows that computer hardware interacts with the system through I/O interfaces, and memory‑mapped I/O maps device physical addresses into the system's memory space so the kernel can access hardware directly. Early I/O memory mapping (early ioremap) provides a bridge during kernel boot, allowing devices to be recognized and configured before the full memory management subsystem is ready.

1. Overview of Early I/O Memory Mapping

In Linux, memory management is the "logistics center" of the system. Early ioremap acts as a small workshop that builds a fast communication bridge between hardware devices and the kernel during the initial boot phase, enabling rapid device identification and configuration.

I/O devices can be accessed via two methods:

Port‑mapped I/O (PMIO)

Memory‑mapped I/O (MMIO)

Memory‑mapped I/O places device registers into the system's address space, allowing the CPU to use normal memory instructions to read/write them, unlike port‑mapped I/O which requires special IN/OUT instructions on x86.

2. Foundations: Memory Management and I/O Operations

2.1 Virtual and Physical Addresses

Physical addresses refer to actual hardware locations, while virtual addresses provide a contiguous, process‑isolated view. The MMU translates virtual addresses to physical ones using page tables.

2.2 Peripheral Register Access

Peripheral registers (control, status, data) are accessed like memory. Architectures differ: x86 uses a separate I/O address space (PMIO) with IN/OUT instructions, while ARM and others use MMIO, allowing uniform memory‑style access.

3. The Main Actor: early ioremap Details

3.1 Origin: Early Kernel Boot Constraints

During the earliest boot stage, the memory manager is not fully set up, and most of the page tables are missing. Functions like ioremap and kmalloc cannot be used, so early ioremap provides a temporary mapping mechanism.

3.2 fixmap: The Backbone

fixmap is a fixed virtual address region determined at compile time. On ARM it typically occupies 0xffc00000‑0xfff00000. It is divided into segments such as FDT (device tree), console (early debug), and BITMAP (temporary boot‑time mappings).

The initialization function early_ioremap_init builds a basic page‑table framework and populates the fixmap area with a temporary page table ( bm_pte ).

// file: arch/x86/mm/ioremap.c
void __init early_ioremap_init(void)
{
    pmd_t *pmd;
    int i;
    // ... initialization code ...
}

Key structures:

// file: arch/x86/include/asm/pgtable_types.h
typedef struct { pmdval_t pmd; } pmd_t;

Arrays such as slot_virt[FIX_BTMAPS_SLOTS] hold the start virtual address of each temporary slot.

3.3 Initialization and Usage

The function early_ioremap_init is called from setup_arch :

// file: arch/x86/kernel/setup.c
void __init setup_arch(char **cmdline_p)
{
    ...
    early_ioremap_init();
    ...
}

When a driver needs early access, it calls early_ioremap :

#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <asm/io.h>

#define GPIO_BASE_PHYS 0x11000000
#define GPIO_CON_OFFSET 0x02E0
#define GPIO_DAT_OFFSET 0x02E4

static void __iomem *gpio_base_virt;

static int __init led_init(void)
{
    gpio_base_virt = early_ioremap(GPIO_BASE_PHYS, 0x1000);
    if (!gpio_base_virt)
        return -ENOMEM;
    writel(0x1111, gpio_base_virt + GPIO_CON_OFFSET);
    writel(0x0, gpio_base_virt + GPIO_DAT_OFFSET);
    return 0;
}

static void __exit led_exit(void)
{
    writel(0xF, gpio_base_virt + GPIO_DAT_OFFSET);
    early_iounmap(gpio_base_virt);
}

module_init(led_init);
module_exit(led_exit);
MODULE_LICENSE("GPL");

early_ioremap ultimately calls __early_ioremap , which selects a free slot, aligns the mapping to page boundaries, checks size limits, and populates the fixmap entries with early_set_fixmap . After mapping, it returns the virtual address (offset + slot_virt[slot]) .

4. Early I/O Mapping Interface Functions

4.1 early_ioremap

// file: arch/x86/mm/ioremap.c
void __init __iomem *early_ioremap(resource_size_t phys_addr, unsigned long size)
{
    return __early_ioremap(phys_addr, size, PAGE_KERNEL_IO);
}

The helper __early_ioremap performs slot allocation, alignment, size validation, and writes fixmap entries via early_set_fixmap . It also flushes the TLB for the new mapping:

static inline void __init __early_set_fixmap(enum fixed_addresses idx,
                        phys_addr_t phys, pgprot_t prot)
{
    // set page table entry and flush TLB
    set_pte(pte, pfn_pte(phys >> PAGE_SHIFT, prot));
    __flush_tlb_one(addr);
}

4.2 early_iounmap

// file: arch/x86/mm/ioremap.c
void __init early_iounmap(void __iomem *addr, unsigned long size)
{
    // locate slot, verify size, clear fixmap entries, free slot
    early_clear_fixmap(idx);
    prev_map[slot] = NULL;
}

It reverses the mapping by clearing the corresponding fixmap entries and releasing the slot.

5. Comparison with Regular ioremap

Both functions map physical I/O addresses to virtual addresses, but regular ioremap is used after the full memory manager is operational, offering flexible size and location, while early ioremap works only within the pre‑allocated fixmap region during boot, providing a lightweight, low‑overhead solution for critical early devices.

6. Conclusion

Early ioremap is a crucial component of the Linux kernel boot process, enabling hardware initialization before the complete paging system is available. Understanding its internals—fixmap, slot management, and TLB handling—offers insight into low‑level kernel design and opens opportunities for future optimizations in boot‑time memory mapping.

I/OLinux Kernelboot processearly_ioremapfixmapmemory-mapping
Deepin Linux
Written by

Deepin Linux

Research areas: Windows & Linux platforms, C/C++ backend development, embedded systems and Linux kernel, etc.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.