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, ®); size = dt_mem_next_cell(dt_root_size_cells, ®); 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 とか勉強になりました。