背景 工作中内存子系统相关的问题主要聚焦在内存分配、内存回收,本文记录内存初始化的学习过程,加深对linux内核子系统的理解。
源码版本 linux 5.10
架构 arm64
主要带着两个问题去学习:
1、内核是如何确认及获取物理内存大小的;
2、物理内存是如何被添加到buddy系统。
一、内核是如何确认及获取物理内存大小的
通过dts中配置的memory字段
内存 通过memblock_add添加到memblock中
start_kernel
setup_arch
setup_machine_fdt(__fdt_pointer)
early_init_dt_scan
early_init_dt_scan_nodes
early_init_dt_scan_memory
early_init_dt_add_memory_arch
memblock_add
memblock_add_range(&memblock.memory, base, size, MAX_NUMNODES, 0)
int __init early_init_dt_scan_memory(unsigned long node, const char *uname, int depth, void *data) { const char *type = of_get_flat_dt_prop(node, "device_type", NULL); const __be32 *reg, *endp; int l; bool hotpluggable; /* We are scanning "memory" nodes only */ if (type == NULL || 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; endp = reg + (l / sizeof(__be32)); hotpluggable = of_get_flat_dt_prop(node, "hotpluggable", NULL); pr_debug("memory scan node %s, reg size %d,\n", uname, l); 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); if (!hotpluggable) continue; if (early_init_dt_mark_hotplug_memory_arch(base, size)) pr_warn("failed to mark hotplug range 0x%llx - 0x%llx\n", base, base + size); } return 0; }struct memblock
struct memblock_type memory;
struct memblock_region *regions;
struct memblock_type memory;
struct memblock_region *regions;
二、内存如何添加到buddy子系统