[LINUX] Whereabouts of memory (what happens to kernel / initrd / fdt?)

It's a small story, but I will briefly summarize what happens to kernel / initrd / fdt that was placed in physical memory at startup.

First of all, here is the code to see


When it starts up, it reserves more and more reserves.

--Kernel: Reserved --initrd: Discard after interpretation --fdt: (Maybe) remain reserve

You can see ...


void __init arm_memblock_init(const struct machine_desc *mdesc)
	/* Register the kernel text, kernel data and initrd with memblock. */
	memblock_reserve(__pa(KERNEL_START), KERNEL_END - KERNEL_START);★ Reserve Kernel

	arm_initrd_init();★ Reserve initrd

	arm_mm_memblock_reserve();★ Reserve page table

	/* reserve any platform specific memblock areas */
	if (mdesc->reserve)

	early_init_fdt_reserve_self();★ Reserve fdt area
	early_init_fdt_scan_reserved_mem();★ Reserve reserved memory in fdt

	/* reserve memory for DMA contiguous allocations */
	dma_contiguous_reserve(arm_dma_limit); ★dma reserve

	arm_memblock_steal_permitted = false;


 * Reserve the special regions of memory
void __init arm_mm_memblock_reserve(void)
     * Reserve the page tables.  These are already in use,
     * and can only be in node 0.
    memblock_reserve(__pa(swapper_pg_dir), SWAPPER_PG_DIR_SIZE);

#ifdef CONFIG_SA1111
     * Because of the SA1111 DMA bug, we want to preserve our
     * precious DMA-able memory...
    memblock_reserve(PHYS_OFFSET, __pa(swapper_pg_dir) - PHYS_OFFSET);

static void __init arm_initrd_init(void)
	phys_addr_t start;
	unsigned long size;

	initrd_start = initrd_end = 0;

	if (!phys_initrd_size)

	 * Round the memory region to page boundaries as per free_initrd_mem()
	 * This allows us to detect whether the pages overlapping the initrd
	 * are in use, but more importantly, reserves the entire set of pages
	 * as we don't want these pages allocated for other purposes.
	start = round_down(phys_initrd_start, PAGE_SIZE);
	size = phys_initrd_size + (phys_initrd_start - start);
	size = round_up(size, PAGE_SIZE);

	if (!memblock_is_region_memory(start, size)) {
		pr_err("INITRD: 0x%08llx+0x%08lx is not a memory region - disabling initrd\n",
		       (u64)start, size);

	if (memblock_is_region_reserved(start, size)) {
		pr_err("INITRD: 0x%08llx+0x%08lx overlaps in-use memory region - disabling initrd\n",
		       (u64)start, size);

	memblock_reserve(start, size);

	/* Now convert initrd to virtual addresses */
	initrd_start = __phys_to_virt(phys_initrd_start);
	initrd_end = initrd_start + phys_initrd_size;

Yeah, I feel like I've come to understand it.

The fdt relationship is implemented under driver / of. It seems that it is reserved.


 * early_init_fdt_reserve_self() - reserve the memory used by the FDT blob
void __init early_init_fdt_reserve_self(void)
    if (!initial_boot_params)

    /* Reserve the dtb region */

 * early_init_fdt_scan_reserved_mem() - create reserved memory regions
 * This function grabs memory from early allocator for device exclusive use
 * defined in device tree structures. It should be called by arch specific code
 * once the early allocator (i.e. memblock) has been fully activated.
void __init early_init_fdt_scan_reserved_mem(void)
    int n;
    u64 base, size;

    if (!initial_boot_params)

    /* Process header /memreserve/ fields */
    for (n = 0; ; n++) {
        fdt_get_mem_rsv(initial_boot_params, n, &base, &size);
        if (!size)
        early_init_dt_reserve_memory_arch(base, size, false);

    of_scan_flat_dt(__fdt_scan_reserved_mem, NULL);

So, it is called from init / initramfs.c, but it seems that initrd will be thrown away once rootfs is expanded.


static int __init populate_rootfs(void)
    /* Load the built in initramfs */
    char *err = unpack_to_rootfs(__initramfs_start, __initramfs_size);
    if (err)
        panic("%s", err); /* Failed to decompress INTERNAL initramfs */

    if (!initrd_start || IS_ENABLED(CONFIG_INITRAMFS_FORCE))
        goto done;

        printk(KERN_INFO "Trying to unpack rootfs image as initramfs...\n");
        printk(KERN_INFO "Unpacking initramfs...\n");

    err = unpack_to_rootfs((char *)initrd_start, initrd_end - initrd_start);
    if (err) {

     * If the initrd region is overlapped with crashkernel reserved region,
     * free only memory that is not part of crashkernel region.
    if (!do_retain_initrd && initrd_start && !kexec_free_initrd())
        free_initrd_mem(initrd_start, initrd_end);★ Here! !! !! !! !! !! !! !! !! !! !!
    initrd_start = 0;
    initrd_end = 0;

    return 0;

that's all.

Recommended Posts

Whereabouts of memory (what happens to kernel / initrd / fdt?)
What kind of Kernel is this Kernel?
What happens when I change the hyperparameters of SVM (RBF kernel)?
Try to make a kernel of Jupyter
What I did to save Python memory
What to do when PermissionError of tempfile.mkstemp occurs