内核启动前需要满足的条件(寄存器,CPU,Cache、MMU):
1. CPU寄存器的设置:
①R0 = 0
②R1为机器码
③R2为启动参数,标记列表在RAM中的起始地址
2.CPU工作模式
①必须禁止中断(IRQ和FIQ)
②CPU必须设置为SVC模式
3.Cache和MMU的设置
①MMU必须关闭
②指令Cache可以打开或关闭
③数据Cache必须关闭
Linux 内核启动过程
Linux的启动过程分为两部分:
1.架构、开发板相关的引导过程。
2.后续的通用启动过程。
ARM架构处理器上Linux内核vmlinux的启动过程,之所以说是vmlinux,是因为其他格式的内核在进行与vmlinux相同的流程之前会有一些独特的操作。比如:对于压缩格式的内核zImage,首先进行自解压得到vmlinux,然后执行vmlinux开始的“正常”启动流程。
引导阶段通常使用汇编语言编写,步骤:
1. 它首先检查内核是否支持当前的处理器架构
2. 然后检查是否支持当前开发板,通过检查后
3. 就为调用下一阶段的start_kernel函数做准备了
①连接内核时使用的是虚拟地址,所以要设置页表、使能MMU
②调用C函数start_kernel之前的常规工作,包括复制数据段,清楚BSS段,调用start_kernel函数
第二阶段的关键代码主要使用C语言编写。它进行内核初始化的全部工作,最后调用rest_init函数启动init过程,创建系统第一个进程:init进程。在第二阶段,仍有部分架构/开发板相关的代码,比如setup_arch函数用于进行架构/开发板相关的设置(比如重新设置页表,设置系统时钟,初始化串口等)。
head.s文件中:
ENTRY(stext)
__lookup_processor_type --->arch/arm/kernel/head.S
__lookup_machine_type ---> arch/arm/kernel/head-common.S
__create_page_tables ---> arch/arm/kernel/head.S
__cpu_flush ---> arch/arm/kernel/head.S
__enable_mmu ---> arch/arm/kernel/head.S
__switch_data --->arch/arm/kernel/head-common.S
start_kernel --->/init/main.c
start_kernel --->/init/main.c
rest_init --->/init/main.c
kernel_init --->/init/main.c
init_post --->/init/main.c
__lookup_processor_type: 确定内核是否支持该架构
__lookup_machine_type:确定内核是否支持该单板
__create_page_tables:建立一级页表
__arm920_setup:禁止ICache、Dcache
__enable_mmu:使能MMU
__mmap_switched:复制数据段,清楚BSS段,设置栈指针,保存CPU ID到processor_id变量,保存机器类型ID到__machine_arch_type变量,调用start_kerne
init/main.c的start_kernel函数
printk(linux_version):输出Linux版本信息
setup_arch:设置与体系结构相关的环境
...
console_init:初始化控制台
...
rest_init:启动init过程