3.2.3 从头初始化到身体

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做好交接工作:

  1. preserve_boot_args 从前任拿到交接材料“引导参数”
  2. el2_setup 摆正自己的位置,调低姿态,降到EL1异常等级
  3. set_cpu_boot_mode_flag 把前任的状态存档

3.2.4 宇之内存的空分复用

        宇者,上下四方,空间为宇。盘古为了开天辟地,必须分开空间和时间。在空间维度,要对内存空间进行切分,即基于MMU的空分复用。

        内核要支持多任务运行,每个任务都有内存空间的需求,但是内存大小是有限的,多个任务必须共享内存。最简单粗暴的办法就是给每个任务分一块地盘,但是任务和任务是有区别的,有的任务贪心,不断malloc,很快就会发现自己的地盘不够用;有的任务谨小慎微,地盘根本用不完都荒废了。演化到最后,公认的最成功的设计就是基于分页的虚拟内存机制。

        虚拟内存,主打的是一个欺骗。它欺骗进程,告诉它你有一块超大的内存空间可以用,并且已经帮你切分成一个一个大小一致的小块(即页面,一般是4KB),方便取用。但是这块内存空间是虚拟的,当进程想要真正访问虚拟内存空间的时候,是需要兑现诺言的。

        兑现诺言的方法是搞一个虚拟内存和物理内存空间的映射表(页表)。把物理内存空间也切分成小块,大小和虚拟内存的页面一致。进程访问虚拟内存的某个地址时,这个地址总是属于一个虚拟页面,映射表能完成从虚拟页面到物理页面的查找,这样虚拟转成了现实。

        内核和CPU一起合作来兑现诺言。CPU提供一个硬件单元MMU,用于完成虚拟内存地址到物理内存地址的转换,而内核要对MMU硬件进行初始化,为每个进程填充页表。为了让进程听话,内核身先士卒,自身也不能搞特殊化,也得活在虚拟内存空间中,只不过内核算是既得利益者,它独占了一大片的物理内存页面。

        回到ENTRY(stext),内核要立即开始对MMU进行初始化:

  1. __create_page_tables 近水楼台,创建恒等映射页表idmap_pg_dir和内核镜像页表swapper_pg_dir
  2. __cpu_setup 搞定CPU MMU硬件,做必要的硬件设定
  3. __primary_switch 调用__enable_mmu打开MMU,虚拟内存机制开始运作,最后跳转到__primary_switched

        特别要注意的是内核镜像页表swapper_pg_dir,在后面会用上的。

        具体的函数很多书籍都有详解,与I-pipe基本没有关联,就不再详细展开了。

点击查看系列文章 =》 Interrupt Pipeline系列文章大纲-CSDN博客

原创不易,需要大家多多鼓励!您的关注、点赞、收藏就是我的创作动力!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值