Linux内核启动分析(一)——head.S

之前我们说到u-boot的最终目的是将内核从flash中读出,并且启动内核。那么内核一旦开始启动之后,就没有u-boot什么事情了,控制权就交给了内核,那么先来明确一下内核要做的事情:运行用户程序,而要想运行用户程序,就得先挂接到文件系统上。下面分析内核的启动流程:

head.S主要做的事情是处理u-boot传入的参数,具体如下:

1、判断是否支持这个CPU

2、判断是否支持这个单板(对比机器ID)

3、建立一级页表

4、使能MMU

5、跳到start_kernel函数

下面具体分析这个流程:

Linux内核启动分析(一)——head.S_第1张图片

这是在内核文件下arch\arm\kernel目录下的head.S文件,也是内核启动的第一个文件。

79行,通过设置CPSR寄存器来确保处理器进入管理模式,并且禁止中断。

81行,通过读取CP15寄存器C0获得CPUid 

82调用__lookup_processor_type这个函数确认内核是否支持当前CPU,如果支持,r5寄存器会返回一个用来描述这个处理器的结构体的地址,否则r5=0

83行,先把这个r5的值保存到r10中

85行,调用__lookup_machine_type这个函数确认内核是否支持当前开发板,如果支持,r5寄存器会返回一个用来描述这个开发板的结构体的地址,否则r5=0

__lookup_processor_type和__lookup_machine_type这两个判断任何一个出现错误,内核都会停止启动,并且跳转到显示错误的函数如54、87

而一旦两个判断都通过,那么就会执行88行,生成页表。

下面主要来看一下__lookup_processor_type和__lookup_machine_type这个两个函数是如何具体实现的。

Linux内核启动分析(一)——head.S_第2张图片

147行,r3=178代码的物理地址

148行,r5=__proc_info_beginr6=__proc_info_end,虚拟地址,r7=178行代码的虚地

149行,物理地址和虚拟地址的差值

150行,__proc_info_begin对应的物理地址

151行,__proc_info_end对应的物理地址

152行,r3r4=__proc_info_list结构中的cpu_valcpu_mask

153行,r4=r4&r9=cpu_mask&传入的CPU ID

154行,比较

155行,如果相等,表示找到匹配的__proc_info_list结构,跳到160

156行,r5指向下一个__proc_info_list结构

157行,是否已经比较完所有的__proc_info_list结构?

158行,没有则继续比较

159行,比较完毕,但是没有匹配的__proc_info_list结构,r5=0

160行,返回

在启动mmu之前,使用的都是物理地址,而内核却是用虚拟地址连接的,所以在访问__proc_info_list结构之前,先将它的虚拟地址转换成物理地址,147~151代码实现

Linux内核启动分析(一)——head.S_第3张图片

r3=178行代码的物理地址

R4=178行代码的虚拟地址,

148行,r5=__arch_info_beginr6=__arch_info_end,虚拟地址,r4=178行代码的虚地

149行,物理地址和虚拟地址的差值

150行,__arch_info_begin对应的物理地址

151行,__arch_info_end对应的物理地址

152行,r5machine_desc结构地址

153行,r4=r4&r9=cpu_mask&传入的CPU ID

154行,比较

155行,如果相等,表示找到匹配的__proc_info_list结构,跳到160

156行,r5指向下一个__proc_info_list结构

157行,是否已经比较完所有的__proc_info_list结构?

158行,没有则继续比较

159行,比较完毕,但是没有匹配的__proc_info_list结构,r5=0

160行,返回

当这个两个判断都满足的时候,建立页表,接着启动MMU我们可以看到下面的这条语句:

Linux内核启动分析(一)——head.S_第4张图片

97~99行,启动MMU之后会跳转到_swich_data这个函数,具体的代码就不一一分析了,不过可以跟踪流程如下:

_swich_data——>__mmap_switched——>start_kernel其中最重要的是start_kernel这个函数,这是内核启动的第一个C语言函数。


到这里可以先来总结一下head.S主要做的事情:

1、通过分析u-boot启动流程,我们知道u-boot在启动内核之前,会吧一些参数传给内核(具体过程请参考u-boot启动流程的分析)。而这些传入的是机器ID和其他参数。在head.S中,就是利用u-boot传入的机器ID来判断内核是否支持这个CPU和这个开发板。

2、如果1中的两个条件都满足,则会建立页表,并且启动MMU

在这里简单介绍一下什么是MMU:

MMU也就是memory management  uint,也就是内存管理单元。它负责虚拟地址到物理地址的映射,并且提供内存机制的内存访问权限检查。

为什么要启动MMU?

由于内核使用的是虚拟地址连接,所以启动MMU,更方便地实现虚拟地址到物理地址的映射。

3、启动MMU之后,内核流程会跳转到start_kernel函数,在这个函数中将会处理u-boot传入的其他参数。

下次接着分析


你可能感兴趣的:(Linux)