Linux内存初始化之sparse内存模型(二)

时间:2024-05-22 19:39:09

1.Linux内存模型

前面已经分析把物理内存添加到memblock以及给物理内存建立页表映射,这里我们分析sparse内存模型

在linux内核中支持3中内存模型,分别是flat memory model,Discontiguous memory model和sparse memory model。所谓memory model,其实就是从cpu的角度看,其物理内存的分布情况,在linux kernel中,使用什么的方式来管理这些物理内存

sparse内存框架图

Linux内存初始化之sparse内存模型(二)

2 sparse初始化分析

函数调用关系:start_kernel->setup_arch->paging_init->bootmem_init->sparse_init

主要是给每个section分配一个pageblock bitmap位图

每个section又可以分为若干个pageblock,每个pageblock的状态占4bit,所以一个section的pageblock bitmap大小为:

unsigned long usemap_size(void)
{
	unsigned long size_bytes;
	size_bytes = roundup(SECTION_BLOCKFLAGS_BITS, 8) / 8;
	size_bytes = roundup(size_bytes, sizeof(unsigned long));
	return size_bytes;
}
其中SECTION_BLOCKFLAGS_BITS表示一个section中的pageblock bit数量
#define SECTION_BLOCKFLAGS_BITS \
	((1UL << (PFN_SECTION_SHIFT - pageblock_order)) * NR_PAGEBLOCK_BITS)
NR_PAGEBLOCK_BITS值为4,pageblock_order值为10
void __init sparse_init(void)
{
	unsigned long pnum;
	struct page *map;
	unsigned long *usemap;
	unsigned long **usemap_map;
	int size;

	size = sizeof(unsigned long *) * NR_MEM_SECTIONS;
        /*为每个section分配一个内存,用户保存bitmap内存地址 */
	usemap_map = memblock_virt_alloc(size, 0);
	if (!usemap_map)
		panic("can not allocate usemap_map\n");
     /*分配section的pageblock bitmap位图内存 */
	alloc_usemap_and_memmap(sparse_early_usemaps_alloc_node,(void *)usemap_map);

	for (pnum = 0; pnum < NR_MEM_SECTIONS; pnum++) {
		if (!present_section_nr(pnum))
			continue;

		usemap = usemap_map[pnum];
		if (!usemap)
			continue;
                /*映射page虚拟地址???? */
		map = sparse_early_mem_map_alloc(pnum);
		if (!map)
			continue;
               /*标记section为map状态 */
		sparse_init_one_section(__nr_to_section(pnum), pnum, map,usemap);
	}
	memblock_free_early(__pa(usemap_map), size);
}

section的初始化

static int __meminit sparse_init_one_section(struct mem_section *ms,
		unsigned long pnum, struct page *mem_map,
		unsigned long *pageblock_bitmap)
{
	if (!present_section(ms))
		return -EINVAL;

	ms->section_mem_map &= ~SECTION_MAP_MASK;
        /*标记section为map状态 */
	ms->section_mem_map |= sparse_encode_mem_map(mem_map, pnum) |
							SECTION_HAS_MEM_MAP;
 	/*section的bitmap */
      ms->pageblock_flags = pageblock_bitmap;

	return 1;
}