日期:2014-05-16 浏览次数:20770 次
内核的入口是stext,这是在arch/arm/kernel/vmlinux.lds.S中指定的。而符号stext是在arch/arm/kernel/head.S中定义的。整个初始化分为两个阶段,首先是在head.S中用汇编代码执行一些平台相关的初始化,完成后跳转到start_kernel函数用C语言代码执行剩余的通用初始化部分。整个初始化流程图如下图所示:
一、 启动条件
通常从系统上电到运行到linux kenel这部分的任务是由boot loader来完成。Boot loader在跳转到kernel之前要完成一些限制条件:
1、CPU必须处于SVC(supervisor)模式,并且IRQ和FIQ中断必须是禁止的;
2、MMU(内存管理单元)必须是关闭的, 此时虚拟地址对应物理地址;
3、数据cache(Data cache)必须是关闭的;
4、指令cache(Instruction cache)没有强制要求;
5、CPU通用寄存器0(r0)必须是0;
6、CPU通用寄存器1(r1)必须是ARM Linux machine type;
7、CPU通用寄存器2(r2)必须是kernel parameter list的物理地址;
二、 汇编代码初始化部分
汇编代码部分主要完成的工作如下所示,下文只是概述head.S中各个函数完成的主要
功能,具体的技术细节,本文不再赘述。
? 确定processor type
? 确定machine type
? 创建页表
? 调用平台特定的__cpu_flush函数
? 开启mmu
? 切换数据
? 最终跳转到start_kernel
三、 C语言代码初始化部分
C语言代码初始化部分主要负责建立结点和内存域的数据结构、初始化页表、初始化用
于内存管理的伙伴系统。在启动过程中,尽管内存管理模块尚未初始化完成,但内核仍然需要分配内存以创建各种数据结构。bootmem分配器用于在启动阶段分配内存。所有涉及的实现都是在start_kernel函数中实现的,其中涉及到内存初始化的函数如下:
1、 build_all_zonelist用于结点和内存域的初始化。
在linux系统中,内存划分结点,每个结点关联到系统中的一个处理器。各个结点又划分内存域,主要包括ZONE_DMA、ZONE_NOR