该阶段完成了
1. 根据 memblock 的 reserved 成员 reserve 不需要填充的页表 // reserve_bootmem_region
2. 通过 在 全物理内存内 互补 memblock 的 reserved,得到未使用的物理内存,填充需要填充的页表 // __free_memory_core
3. 至此 , buddy 初始化完成
4. 用(内存地址,内存大小,申请块大小)填充 kmalloc_caches[type([0-1])][idx([6-d])]
5. 至此 , slab 初始化完成
6. 将 在vmalloc区间的 已经使用的虚拟内存地址A(主要是io设备) 注册到 vmap_area_root
7. 通过 在 全虚拟内存(非vmalloc区间)内 互补 A , 得到虚拟地址空间,注册到 free_vmap_area_root
8. 至此 , vmalloc 初始化完成
// 现在已经不打印 虚拟内存布局 了
// 请查看 1c31d4e96b8c205fe3aa8e73e930a0ccbf4b9a2b
其实 setup_arch 中也有 关于 mem 的部分
setup_arch 中 与mem 相关的部分
2. 匹配 板级 mdesc , 并解析 atags(包括core cmdline mem)
5. 初始化 各种类型的 描述符表
6. 添加 各种(kernel/initrd/设备树/atags/设备树中预留的/)预留的内存到 memblock
7. 对 即将存储页表的地址 清0
8. 针对 多项内容(lowmem/设备树/vectors/各项设备)填充页表
10. 申请内存,用于存储 很多个struct page
11. 初始化所有的 struct page
可以这么说 , setup_arch 中完成了
1. 虚拟页表的创建(lowmem/设备树/vectors/各项设备)
2. memblock 的初始化 // 在 setup_arch 的末尾,已经可以 通过 memblock_alloc 来 申请内存了
3. buddy初始化的第一部分 // 所有低端内存的 struct page 已经准备好了
在这篇文章中,主要关注下面的函数
page_address_init
// null
setup_arch
// 之前已经讨论过
build_all_zonelists
// 打印信息
// Built 1 zonelists, mobility grouping on. Total pages: 65024
mm_init
// 打印信息
// mem auto-init: stack:off, heap alloc:off, heap free:off
// Memory: 243936K/262144K available (5120K kernel code, 6569K rwdata, 732K rodata, 1024K init, 2134K bss, 18208K reserved, 0K cma-reserved)
// SLUB: HWalign=64, Order=0-3, MinObjects=0, CPUs=1, Nodes=1
build_all_zonelists
build_all_zonelists
build_all_zonelists_init
__build_all_zonelists
for_each_online_node(nid) build_zonelists(pgdat);
zonerefs = pgdat->node_zonelists[ZONELIST_FALLBACK]._zonerefs;
nr_zones = build_zonerefs_node(pgdat, zonerefs);
zone = pgdat->node_zones + zone_type;
zoneref_set_zone(zone, &zonerefs[nr_zones++]);
zoneref->zone = zone;
zoneref->zone_idx = zone_idx(zone);
zonerefs += nr_zones;
for_each_possible_cpu(cpu) pageset_init(&per_cpu(boot_pageset, cpu));
mminit_verify_zonelist
cpuset_init_current_mems_allowed
vm_total_pages = nr_free_zone_pages(gfp_zone(GFP_HIGHUSER_MOVABLE)); // fe00
page_group_by_mobility_disabled = 0;
mm_init
mm_init
page_ext_init_flatmem
// null
init_mem_debugging_and_hardening
// TODO
report_meminit
// pr_info
mem_init
set_max_mapnr(pfn_to_page(max_pfn) - mem_map);
max_mapnr = pfn_to_page(max_pfn) - mem_map;
/* this will put all unused low memory onto the freelists */
memblock_free_all
free_unused_memmap // 稀疏内存相关,释放不存在的地址
free_memmap
reset_all_zones_managed_pages
pages = free_low_memory_core_early
// reserve all the struct page
for_each_reserved_mem_range(i, &start, &end) reserve_bootmem_region(start, end); // reserve_bootmem_region 执行了 16次
for (; start_pfn < end_pfn; start_pfn++)
init_reserved_page(start_pfn);
INIT_LIST_HEAD(&page->lru);
__SetPageReserved(page);
/*
// 这 16 个 是 memblock 中的 reserved 成员
为 kernel/页表/struct page/vectors 预留的
还有 io map/request_standard_resources 过程中申请的内存
reserve_bootmem_region // 16次,之所以是16次,是因为之前调用了 memblock_alloc 16次
start_pfn:50004,end_pfn:50008 // 标记这段地址已经被使用,用作页表
page:cfdf5080
page:cfdf50a0
page:cfdf50c0
page:cfdf50e0
start_pfn:50100,end_pfn:51081 // 标记这段地址已经被使用,用作 kernel中的 (__pa(KERNEL_START), KERNEL_END - KERNEL_START)
page:cfdf7000
...
page:cfe16000
start_pfn:5fdbc,end_pfn:5fdf4
page:cfff0780
...
page:cfff0e60
start_pfn:5fdf5,end_pfn:5fffc // 标记这段地址已经被使用,用作 struct page
page:cfff0ea0
...
page:cfff4f60
start_pfn:5fffc,end_pfn:5fffd
page:cfff4f80
start_pfn:5fffc,end_pfn:5fffd
page:cfff4f80
start_pfn:5fffc,end_pfn:5fffd
page:cfff4f80
start_pfn:5fffc,end_pfn:5fffd
page:cfff4f80
start_pfn:5fffc,end_pfn:5fffd
page:cfff4f80
start_pfn:5fffc,end_pfn:5fffd
page:cfff4f80
start_pfn:5fffc,end_pfn:5fffd
page:cfff4f80
start_pfn:5fffc,end_pfn:5fffd
page:cfff4f80
start_pfn:5fffc,end_pfn:5fffd
page:cfff4f80
start_pfn:5fffc,end_pfn:5fffd
page:cfff4f80
start_pfn:5fffc,end_pfn:5fffd
page:cfff4f80
start_pfn:5fffc,end_pfn:60000 // 标记这段被 vectors 和 其他等 占用
page:cfff4f80
...
page:cfff4fe0
*/
// free mem
for_each_free_mem_range __free_memory_core(start, end);
__free_pages_memory(start_pfn, end_pfn); // __free_pages_memory 执行了 4次
memblock_free_pages(pfn_to_page(start), start, order);
__free_pages_core
__free_pages_ok
free_one_page
__free_one_page
add_to_free_list(page, zone, order, migratetype);
/*
__free_pages_memory 执行了4次
// 之所以是4次,是因为 总的内存 减去 memblock_alloc 的内存 ,只剩下4块连续的 free 内存
start_pfn:50000,end_pfn:50004 // 标记这段内存没被使用
pfn_to_page(start):cfdf5000, start:50000, order:2
start_pfn:50008,end_pfn:50100 // 标记这段内存没被使用,虽然这段是属于kernel的,但是不属于 kernel 的 (__pa(KERNEL_START), KERNEL_END - KERNEL_START)
pfn_to_page(start):cfdf5100, start:50008, order:3
pfn_to_page(start):cfdf5200, start:50010, order:4
pfn_to_page(start):cfdf5400, start:50020, order:5
pfn_to_page(start):cfdf5800, start:50040, order:6
pfn_to_page(start):cfdf6000, start:50080, order:7
start_pfn:51081,end_pfn:5fdbc
pfn_to_page(start):cfe16020, start:51081, order:0
pfn_to_page(start):cfe16040, start:51082, order:1
pfn_to_page(start):cfe16080, start:51084, order:2
pfn_to_page(start):cfe16100, start:51088, order:3
pfn_to_page(start):cfe16200, start:51090, order:4
pfn_to_page(start):cfe16400, start:510a0, order:5
pfn_to_page(start):cfe16800, start:510c0, order:6
pfn_to_page(start):cfe17000, start:51100, order:8
pfn_to_page(start):cfe19000, start:51200, order:9
pfn_to_page(start):cfe1d000, start:51400, order:a
pfn_to_page(start):cfe25000, start:51800, order:a
pfn_to_page(start):cfe2d000, start:51c00, order:a
pfn_to_page(start):cfe35000, start:52000, order:a
pfn_to_page(start):cfe3d000, start:52400, order:a
pfn_to_page(start):cfe45000, start:52800, order:a
pfn_to_page(start):cfe4d000, start:52c00, order:a
pfn_to_page(start):cfe55000, start:53000, order:a
pfn_to_page(start):cfe5d000, start:53400, order:a
pfn_to_page(start):cfe65000, start:53800, order:a
pfn_to_page(start):cfe6d000, start:53c00, order:a
pfn_to_page(start):cfe75000, start:54000, order:a
pfn_to_page(start):cfe7d000, start:54400, order:a
pfn_to_page(start):cfe85000, start:54800, order:a
pfn_to_page(start):cfe8d000, start:54c00, order:a
pfn_to_page(start):cfe95000, start:55000, order:a
pfn_to_page(start):cfe9d000, start:55400, order:a
pfn_to_page(start):cfea5000, start:55800, order:a
pfn_to_page(start):cfead000, start:55c00, order:a
pfn_to_page(start):cfeb5000, start:56000, order:a
pfn_to_page(start):cfebd000, start:56400, order:a
pfn_to_page(start):cfec5000, start:56800, order:a
pfn_to_page(start):cfecd000, start:56c00, order:a
pfn_to_page(start):cfed5000, start:57000, order:a
pfn_to_page(start):cfedd000, start:57400, order:a
pfn_to_page(start):cfee5000, start:57800, order:a
pfn_to_page(start):cfeed000, start:57c00, order:a
pfn_to_page(start):cfef5000, start:58000, order:a
pfn_to_page(start):cfefd000, start:58400, order:a
pfn_to_page(start):cff05000, start:58800, order:a
pfn_to_page(start):cff0d000, start:58c00, order:a
pfn_to_page(start):cff15000, start:59000, order:a
pfn_to_page(start):cff1d000, start:59400, order:a
pfn_to_page(start):cff25000, start:59800, order:a
pfn_to_page(start):cff2d000, start:59c00, order:a
pfn_to_page(start):cff35000, start:5a000, order:a
pfn_to_page(start):cff3d000, start:5a400, order:a
pfn_to_page(start):cff45000, start:5a800, order:a
pfn_to_page(start):cff4d000, start:5ac00, order:a
pfn_to_page(start):cff55000, start:5b000, order:a
pfn_to_page(start):cff5d000, start:5b400, order:a
pfn_to_page(start):cff65000, start:5b800, order:a
pfn_to_page(start):cff6d000, start:5bc00, order:a
pfn_to_page(start):cff75000, start:5c000, order:a
pfn_to_page(start):cff7d000, start:5c400, order:a
pfn_to_page(start):cff85000, start:5c800, order:a
pfn_to_page(start):cff8d000, start:5cc00, order:a
pfn_to_page(start):cff95000, start:5d000, order:a
pfn_to_page(start):cff9d000, start:5d400, order:a
pfn_to_page(start):cffa5000, start:5d800, order:a
pfn_to_page(start):cffad000, start:5dc00, order:a
pfn_to_page(start):cffb5000, start:5e000, order:a
pfn_to_page(start):cffbd000, start:5e400, order:a
pfn_to_page(start):cffc5000, start:5e800, order:a
pfn_to_page(start):cffcd000, start:5ec00, order:a
pfn_to_page(start):cffd5000, start:5f000, order:a
pfn_to_page(start):cffdd000, start:5f400, order:a
pfn_to_page(start):cffe5000, start:5f800, order:a
pfn_to_page(start):cffed000, start:5fc00, order:8
pfn_to_page(start):cffef000, start:5fd00, order:7
pfn_to_page(start):cfff0000, start:5fd80, order:5
pfn_to_page(start):cfff0400, start:5fda0, order:4
pfn_to_page(start):cfff0600, start:5fdb0, order:3
pfn_to_page(start):cfff0700, start:5fdb8, order:2
start_pfn:5fdf4,end_pfn:5fdf5 // 标记这段内存没被使用
pfn_to_page(start):cfff0e80, start:5fdf4, order:0
*/
/*
至此,50000000 - 60000000 已经被 struct page 记录完毕
50000 000 - 50004 000 : free // 0x5000 0100 应该有 atags ,但是memblock 没预留这段内存,因为 atags 已经解析完了,没用了
50004 000 - 50008 000 : reserved // 页表/段表
50008 000 - 50100 000 : free
50100 000 - 51081 000 : reserved // kernel 的 (__pa(KERNEL_START), KERNEL_END - KERNEL_START)
51081 000 - 5fdbc 000 : free
5fdbc 000 - 5fdf4 000 : reserved // 过程中 memblock_alloc 过的内存
5fdf4 000 - 5fdf5 000 : free
5fdf5 000 - 5fffc 000 : reserved // struct page
5fffc 000 - 60000 000 : reserved // vectors等
*/
totalram_pages_add(pages);
_totalram_pages = _totalram_pages + pages ; // _totalram_pages 初始化为0
free_highpages
// null
mem_init_print_info
pr_info("Memory: %luK/%luK available (%luK kernel code
// 这个过程初始化 好的 内存管理器 是 buddy
// 怎么向 buddy 申请内存
// alloc_pages/alloc_page
上一篇:OK6410A 开发板 (八) 12 linux-5.11 OK6410A start_kernel 打印角度 第一阶段 irq
下一篇:OK6410A 开发板 (八) 10 linux-5.11 OK6410A start_kernel 打印角度 第一阶段 setup_arch
推荐阅读最新更新时间:2024-11-20 00:06
设计资源 培训 开发板 精华推荐
- LTC3815IUFE 1.2V/6A 2MHz 降压稳压器的典型应用电路
- ZR431FTA 可调精密齐纳并联稳压器的典型应用
- NRF24L01无线模块(程序+原理图+芯片资料)
- LT1767EMS8-3.3 12V 至 3.3V 降压转换器的典型应用电路
- 使用 Analog Devices 的 LTP5901IPC-IPMA 的参考设计
- CH340N_USB_TTL自动下载器
- 用于便携式的 12 位、1 通道 DAC
- MAXREFDES67#:通用输入微型PLC
- IS31AP4991-GRLS2-EB,IS31AP4991A 演示板,具有低电平有效关断模式的 1.1W AB 类音频功率放大器
- AD9680-LF500EBZ、9680CE02B 评估板,适用于高达 1GHz 输入带宽的 AD9680-500 高速 ADC