内存管理-7-memblock子系统-1-初探
基于msm-5.4
一、memblock简介
现实的物理内存是被截的一段一段的了,并不是一马平川的。伙伴系统要进行初始化,就需要知道哪些区域是可用的,哪些区域已经被占用了、被保留了,剩余的才可以用于伙伴系统的初始化。因此需要一个早期的内存管理机制,即 memblock 机制.
全局变量: struct memblock memblock;
可用物理内存:memblock.memory 数组
reserve的物理内存:memblock.reserved 数组
内核镜像(.init段除外)、dtb、u-boot、页表。
GPU、Camera、音视频编解码的保留物理内存。
保留的区域有很多,驱动需要占用内存,内核启动自己的镜像也会占用一部分预留内存,u-boot启动完后也一直驻留在内存中,reboot时还会跳转到u-boot中去执行。
.init只在内核初始化时运行一次,运行完后可以清理掉,可以节省一部分内存。
二、memblock接口
1. 文件接口
/sys/kernel/debug/memblock/memory /sys/kernel/debug/memblock/reserved /proc/kmsg: memblock=debug
分别对应memory区和reserved区每个区块的物理起始和结束地址,第三个是启动参数,用于打开memblock的调试信息。
2. 函数接口
int memblock_add(phys_addr_t base, phys_addr_t size); int memblock_remove(phys_addr_t base, phys_addr_t size); for_each_mem_range int memblock_reserve(phys_addr_t base, phys_addr_t size); int memblock_free(phys_addr_t base, phys_addr_t size);
这些regions添加后的状态:
三、memblock初始化
1. 执行路径
start_kernel setup_arch setup_machine_fdt early_init_dt_scan early_init_dt_scan_memory arm64_memblock_init early_init_fdt_scan_reserved_mem /* 添加/删除就是初始化这两个全局数组 */ static struct memblock_region memblock_memory_init_regions[INIT_MEMBLOCK_REGIONS]; //128 static struct memblock_region memblock_reserved_init_regions[INIT_MEMBLOCK_RESERVED_REGIONS]; //161
early_init_dt_scan_memory() 中会检索 device_type="memory" 设备树节点。
early_init_fdt_scan_reserved_mem() 中会检索根节点下的名为 "reserved-memory" 设备树一级子节点。
除了这两个函数外,还有其它路径会调用memblock的接口函数进行添加。
下一步会将memory这个空闲的内存块信息释放给伙伴系统。
四、memblock内存释放
对于reserved区域的内存块,在释放到伙伴系统时,会设置reserved属性,这样这些页面在伙伴系统中就保留下来了。
1. 释放调用路径
start_kernel setup_arch setup_machine_fdt early_init_dt_scan early_init_dt_scan_memory arm64_memblock_init early_init_fdt_scan_reserved_mem mm_init mem_init memblock_free_all //这里
memblock_free_all() 会将所有没有使用的内存放到伙伴系统的freelist中。
for_each_reserved_mem_region(i, p_start, p_end)
for_each_free_mem_range(i, nid, flags, p_start, p_end, p_nid)
将内存释放到伙伴系统后,就等于伙伴系统接管了物理内存的管理。
2. 释放代码走读
unsigned long __init memblock_free_all(void) //memblock.c { unsigned long pages; /* 释放所有低端内存到伙伴系统 */ pages = free_low_memory_core_early(); /* 计算释放的总的page数(这里不包含被预留占用的,会比实际的物理内存小一些的) */ totalram_pages_add(pages); //计算释放的总的page数 return pages; } static unsigned long __init free_low_memory_core_early(void) //memblock.c { phys_addr_t start, end; /* 遍历保存每个region的起始和结束地址 */ /* 遍历memblock.reserved中的regions, 将region中的页面属性设置为reserved*/ for_each_reserved_mem_region(i, &start, &end) reserve_bootmem_region(start, end); //但是没有释放到伙伴系统#### /* 遍历memblock.memory中的regions, 以region为单位,释放内存到伙伴系统 */ for_each_free_mem_range(i, NUMA_NO_NODE, MEMBLOCK_NONE, &start, &end, NULL) count += __free_memory_core(start, end); return count; } /* * __free_memory_core --> __free_pages_memory --> memblock_free_pages --> __free_pages_core --> __free_pages --> * free_the_page --> __free_pages_ok --> free_one_page --> __free_one_page --> add_to_free_area_tail */ /* 将page根据order、zone、migrate_type 添加到指定的链表中 */ static inline void add_to_free_area_tail(struct page *page, struct free_area *area, int migratetype) { list_add_tail(&page->lru, &area->free_list[migratetype]); area->nr_free++; }
五、.init内存释放
1. memblock中reserved的区域
内核的代码段(.text/.data/.bss,.init除外).
initrd
dtb
设备树中的reversed-momery区域(CMA除外)
临时页表
驱动reserved momery的初始化
2. .init段释放路径
//include/linux/init.h #define __init __section(.init.text) __cold __latent_entropy __noinitretpoline __nocfi __init修饰的代码只在内核初始化过程中调用一次,之后就再也不会使用了。释放掉可以节省一部分内存。 start_kernel setup_arch setup_machine_fdt early_init_dt_scan early_init_dt_scan_memory //memblock.memory初始化 arm64_memblock_init early_init_fdt_scan_reserved_mem //memblock.reserved初始化 mm_init mem_init memblock_free_all //释放到伙伴系统 arch_call_rest_init rest_init kernel_init free_initmem //这里释放.init段内存
3. 释放到伙伴系统中
/* 将 .init.text 段占据的内存释放到伙伴系统 */ void free_initmem(void) { free_reserved_area(lm_alias(__init_begin), lm_alias(__init_end), 0, "unused kernel"); unmap_kernel_range((u64)__init_begin, (u64)(__init_end - __init_begin)); } /* * free_reserved_area --> free_reserved_page --> __free_reserved_page --> __free_page --> __free_pages --> * free_the_page --> __free_pages_ok --> free_one_page */
posted on 2024-07-03 10:20 Hello-World3 阅读(134) 评论(0) 编辑 收藏 举报