Look at real operating systems to see how they size memory. (11)

ええと、ePAPR specifications オトしてきて確認。memory な記述としては

memory {"device_type"=memory, reg=<0x0 0x20000000>}

みたいなソレらしい。
確かに early_init_dt_scan_memory 手続きでは

    /* We are scanning "memory" nodes only */
    if (type == NULL) {
        /*
         * The longtrail doesn't have a device_type on the
         * /memory node, so look for the node called /memory@0.
         */
        if (depth != 1 || strcmp(uname, "memory@0") != 0)
            return 0;
    } else if (strcmp(type, "memory") != 0)
        return 0;

みたいなフィルタがあるし

    reg = of_get_flat_dt_prop(node, "linux,usable-memory", &l);
    if (reg == NULL)
        reg = of_get_flat_dt_prop(node, "reg", &l);
    if (reg == NULL)
        return 0;

みたいなことしてます。が __be32 って何なのだろうな。
ここはスルーとして核心部分もなんとなく分かった気がする。

    while ((endp - reg) >= (dt_root_addr_cells + dt_root_size_cells)) {
        u64 base, size;

        base = dt_mem_next_cell(dt_root_addr_cells, &reg);
        size = dt_mem_next_cell(dt_root_size_cells, &reg);

        if (size == 0)
            continue;
        pr_debug(" - %llx ,  %llx\n", (unsigned long long)base,
            (unsigned long long)size);

        early_init_dt_add_memory_arch(base, size);
    }

上記によれば

  • dt_root_{addr, size}_cells は 1 または 2
  • 繰り返しの中で reg が増分される
    • dt_mem_next_cell 手続きで増分のはず
  • early_init_dt_add_memory_arch 手続きの実体は arch/arm/kernel/setup.c にある arm_add_memory 手続き
    • meminfo.bank に登録
    • meminfo は arch/arm/mm/init.c で定義

以下。

/*
 * This keeps memory configuration data used by a couple memory
 * initialization functions, as well as show_mem() for the skipping
 * of holes in the memory map.  It is populated by arm_add_memory().
 */
struct meminfo meminfo;

これでこのシリーズは終了。fdt とか勉強になりました。