Interrupt Pipeline系列文章大纲-CSDN博客
3.2 内核初始化(盘古开天地)
3.2.1 内核初始化的神话
3.2.2 从头 (Head)开始
3.2.3 从头初始化到身体
3.2.4 宇之内存的空分复用
3.2.5 宙之CPU的时分复用
3.2.6 盘古开天地start_kernel
3.2.3 从头初始化到身体
再看一下上一章找到的”头“:
__HEAD _head: /* * DO NOT MODIFY. Image header expected by Linux boot-loaders. */ #ifdef CONFIG_EFI /* * This add instruction has no meaningful effect except that * its opcode forms the magic "MZ" signature required by UEFI. */ add x13, x18, #0x16 b stext #else b stext // branch to kernel start, magic .long 0 // reserved #endif |
二话不说,直接跳转到stext。取前两个字母st,与身(shen)体(ti)的前2个字母相同,把stext理解为身体代码哈。这么理解后,由头到身还是挺生动的,盘古的形象开始清晰起来。
ENTRY(stext) bl preserve_boot_args bl el2_setup // Drop to EL1, w0=cpu_boot_mode adrp x23, __PHYS_OFFSET and x23, x23, MIN_KIMG_ALIGN - 1 // KASLR offset, defaults to 0 bl set_cpu_boot_mode_flag bl __create_page_tables /* * The following calls CPU setup code, see arch/arm64/mm/proc.S for * details. * On return, the CPU will be ready for the MMU to be turned on and * the TCR will have been set. */ bl __cpu_setup // initialise processor b __primary_switch ENDPROC(stext) |
从stext开始,Linux内核开始实质运行起来了,新官上任,接管CPU!最重要的任务就是和引导程序uboot做好交接工作:
- preserve_boot_args 从前任拿到交接材料“引导参数”
- el2_setup 摆正自己的位置,调低姿态,降到EL1异常等级
- set_cpu_boot_mode_flag 把前任的状态存档
3.2.4 宇之内存的空分复用
宇者,上下四方,空间为宇。盘古为了开天辟地,必须分开空间和时间。在空间维度,要对内存空间进行切分,即基于MMU的空分复用。
内核要支持多任务运行,每个任务都有内存空间的需求,但是内存大小是有限的,多个任务必须共享内存。最简单粗暴的办法就是给每个任务分一块地盘,但是任务和任务是有区别的,有的任务贪心,不断malloc,很快就会发现自己的地盘不够用;有的任务谨小慎微,地盘根本用不完都荒废了。演化到最后,公认的最成功的设计就是基于分页的虚拟内存机制。
虚拟内存,主打的是一个欺骗。它欺骗进程,告诉它你有一块超大的内存空间可以用,并且已经帮你切分成一个一个大小一致的小块(即页面,一般是4KB),方便取用。但是这块内存空间是虚拟的,当进程想要真正访问虚拟内存空间的时候,是需要兑现诺言的。
兑现诺言的方法是搞一个虚拟内存和物理内存空间的映射表(页表)。把物理内存空间也切分成小块,大小和虚拟内存的页面一致。进程访问虚拟内存的某个地址时,这个地址总是属于一个虚拟页面,映射表能完成从虚拟页面到物理页面的查找,这样虚拟转成了现实。
内核和CPU一起合作来兑现诺言。CPU提供一个硬件单元MMU,用于完成虚拟内存地址到物理内存地址的转换,而内核要对MMU硬件进行初始化,为每个进程填充页表。为了让进程听话,内核身先士卒,自身也不能搞特殊化,也得活在虚拟内存空间中,只不过内核算是既得利益者,它独占了一大片的物理内存页面。
回到ENTRY(stext),内核要立即开始对MMU进行初始化:
- __create_page_tables 近水楼台,创建恒等映射页表idmap_pg_dir和内核镜像页表swapper_pg_dir
- __cpu_setup 搞定CPU MMU硬件,做必要的硬件设定
- __primary_switch 调用__enable_mmu打开MMU,虚拟内存机制开始运作,最后跳转到__primary_switched
特别要注意的是内核镜像页表swapper_pg_dir,在后面会用上的。
具体的函数很多书籍都有详解,与I-pipe基本没有关联,就不再详细展开了。
点击查看系列文章 =》 Interrupt Pipeline系列文章大纲-CSDN博客
原创不易,需要大家多多鼓励!您的关注、点赞、收藏就是我的创作动力!