なんとなく気になるので

メモっておく事に。
# unpack_to_rootfs 手続きが難解なので (ry

__init と解放

こんなカンジで定義されているナニ

static int __init populate_rootfs(void)
{
	char *err = unpack_to_rootfs(__initramfs_start,
			 __initramfs_end - __initramfs_start, 0);
	if (err)
		panic(err);

__init は include/linux/init.h にて定義されてて以下。

#define __init		__attribute__ ((__section__ (".init.text")))
#define __initdata	__attribute__ ((__section__ (".init.data")))

ld script の arch/i386/kernel/vmlinux.lds.S の一部を以下に。

  /* will be freed after init
   * Following ALIGN() is required to make sure no other data falls on the
   * same page where __smp_alt_end is pointing as that page might be freed
   * after boot. Always make sure that ALIGN() directive is present after
   * the section which contains __smp_alt_end.
   */
  . = ALIGN(4096);
  
  /* will be freed after init */
  . = ALIGN(4096);              /* Init code and data */
  .init.text : AT(ADDR(.init.text) - LOAD_OFFSET) {
        __init_begin = .;
        _sinittext = .;
        *(.init.text)
        _einittext = .;
  }
  .init.data : AT(ADDR(.init.data) - LOAD_OFFSET) { *(.init.data) }
  . = ALIGN(16);
  .init.setup : AT(ADDR(.init.setup) - LOAD_OFFSET) {
        __setup_start = .;
        *(.init.setup)
        __setup_end = .;
   }
  .initcall.init : AT(ADDR(.initcall.init) - LOAD_OFFSET) {
        __initcall_start = .;
        INITCALLS
        __initcall_end = .;
  }
(以下略

で、上記がざっくり解放な根拠は init/main.c にて定義されている init 手続きから呼び出されている free_initmem 手続きとの事。

void free_initmem(void)
{
	free_init_pages("unused kernel memory",
			(unsigned long)(&__init_begin),
			(unsigned long)(&__init_end));
}

詳細は略としておそらくは __init_begin から __init_end までがざっくり解放される、と見て間違いはないはず。
ちなみに __init_begin は以下の箇所で

  /* will be freed after init */
  . = ALIGN(4096);              /* Init code and data */
  .init.text : AT(ADDR(.init.text) - LOAD_OFFSET) {
        __init_begin = .;
        _sinittext = .;
        *(.init.text)
        _einittext = .;
  }

__init_end は以下となっている模様。

  .data.percpu  : AT(ADDR(.data.percpu) - LOAD_OFFSET) {
        __per_cpu_start = .;
        *(.data.percpu)
        __per_cpu_end = .;
  }
  . = ALIGN(4096);
  /* freed after init ends here */
        
  .bss : AT(ADDR(.bss) - LOAD_OFFSET) {
        __init_end = .;
        __bss_start = .;                /* BSS */

.bss なセクションの先頭部分。あんまきちんと追い掛けるつもりはないのですが、free_init_pages の定義が以下 (arch/i386/mm/init.c)。

void free_init_pages(char *what, unsigned long begin, unsigned long end)
{
	unsigned long addr;

	for (addr = begin; addr < end; addr += PAGE_SIZE) {
		ClearPageReserved(virt_to_page(addr));
		init_page_count(virt_to_page(addr));
		memset((void *)addr, POISON_FREE_INITMEM, PAGE_SIZE);
		free_page(addr);
		totalram_pages++;
	}
	printk(KERN_INFO "Freeing %s: %ldk freed\n", what, (end - begin) >> 10);
}

ld script でも 4096 で ALIGN されてますが PAGE_SIZE の定義は include/asm-i386/page.h で以下。

/* PAGE_SHIFT determines the page size */
#define PAGE_SHIFT	12
#define PAGE_SIZE	(1UL << PAGE_SHIFT)
#define PAGE_MASK	(~(PAGE_SIZE-1))

PAGE_SIZE は 4096UL になるのが分かります。メモリ管理のあたりはそのうち読まなきゃなナニになるのだろうな、と。