Linux内存活动区域其实就是全局变量e820中的内存块做了相关的检查和对其处理后的区域。在管理区初始化等地方有用到。
数据结构
struct node_active_region { unsigned long start_pfn; unsigned long end_pfn; int nid; };
初始化
活动内存的初始化工作在setup_arch()->initmem_init()->e820_register_active_regions()中
/* Walk the e820 map and register active regions within a node */ void __init e820_register_active_regions(int nid, unsigned long start_pfn, unsigned long last_pfn) { unsigned long ei_startpfn; unsigned long ei_endpfn; int i; for (i = 0; i < e820.nr_map; i++) if (e820_find_active_region(&e820.map[i],/*从全局变量e820中查找活动区*/ start_pfn, last_pfn, &ei_startpfn, &ei_endpfn)) add_active_range(nid, ei_startpfn, ei_endpfn);/*加入活动区*/ }
/* * Finds an active region in the address range from start_pfn to last_pfn and * returns its range in ei_startpfn and ei_endpfn for the e820 entry. */ int __init e820_find_active_region(const struct e820entry *ei, unsigned long start_pfn, unsigned long last_pfn, unsigned long *ei_startpfn, unsigned long *ei_endpfn) { u64 align = PAGE_SIZE; *ei_startpfn = round_up(ei->addr, align) >> PAGE_SHIFT; *ei_endpfn = round_down(ei->addr + ei->size, align) >> PAGE_SHIFT; /* Skip map entries smaller than a page */ if (*ei_startpfn >= *ei_endpfn) return 0; /* Skip if map is outside the node */ if (ei->type != E820_RAM || *ei_endpfn <= start_pfn || *ei_startpfn >= last_pfn) return 0; /* Check for overlaps */ if (*ei_startpfn < start_pfn) *ei_startpfn = start_pfn; if (*ei_endpfn > last_pfn) *ei_endpfn = last_pfn; return 1; }
/*添加活动区域,需要对原有的进行检查*/ void __init add_active_range(unsigned int nid, unsigned long start_pfn, unsigned long end_pfn) { int i; mminit_dprintk(MMINIT_TRACE, "memory_register", "Entering add_active_range(%d, %#lx, %#lx) " "%d entries of %d used\n", nid, start_pfn, end_pfn, nr_nodemap_entries, MAX_ACTIVE_REGIONS); //not set macro mminit_validate_memmodel_limits(&start_pfn, &end_pfn); /* Merge with existing active regions if possible */ for (i = 0; i < nr_nodemap_entries; i++) { if (early_node_map[i].nid != nid) continue; /* Skip if an existing region covers this new one */ if (start_pfn >= early_node_map[i].start_pfn && end_pfn <= early_node_map[i].end_pfn) return; /* Merge forward if suitable */ if (start_pfn <= early_node_map[i].end_pfn && end_pfn > early_node_map[i].end_pfn) { early_node_map[i].end_pfn = end_pfn; return; } /* Merge backward if suitable */ if (start_pfn < early_node_map[i].end_pfn && end_pfn >= early_node_map[i].start_pfn) { early_node_map[i].start_pfn = start_pfn; return; } } /* Check that early_node_map is large enough */ if (i >= MAX_ACTIVE_REGIONS) { printk(KERN_CRIT "More than %d memory regions, truncating\n", MAX_ACTIVE_REGIONS); return; } early_node_map[i].nid = nid; early_node_map[i].start_pfn = start_pfn; early_node_map[i].end_pfn = end_pfn; nr_nodemap_entries = i + 1; }