Tiny4412 Linux 内核启动流程
Linux内核的启动分为压缩内核和非压缩内核两种,这里我们以压缩内核为例。压缩内核运行时,将运行一段解压缩程序,得到真正的内核镜像,然后跳转到内核镜像运行。此时,Linux进入非压缩内核入口,在非压缩内核入口中,完成各种初始化操作后跳转到C语言入口处运行。主要流程如下所示。
1.解压缩内核镜像
解压缩程序通常在arch/arm/boot/compressed/目录中
├── atags_to_fdt.c
├── big-endian.S
├── decompress.c
├── head.S
├── head-sa1100.S
├── head-shark.S
├── head-sharpsl.S
├── head-shmobile.S
├── head-vt8500.S
├── head-xscale.S
├── libfdt_env.h
├── ll_char_wr.S
├── Makefile
├── misc.c
├── mmcif-sh7372.c
├── ofw-shark.c
├── piggy.gzip.S
├── piggy.lzma.S
├── piggy.lzo.S
├── piggy.xzkern.S
├── sdhi-sh7372.c
├── sdhi-shmobile.c
├── sdhi-shmobile.h
├── string.c
└── vmlinux.lds.in
它们经过编译后,生成的内容独立于真正的Linux内核,这部分内容的功能就是初始化环境,解压缩和运行真正的Linux内核。在压缩内核启动时,首先进入arch/arm/boot/compressed目录中的compressed目录中的head.S文件。
start:
.type start,#function
.rept
mov r0, r0
.endr
ARM( mov r0, r0 )
ARM( b 1f )
THUMB( adr r12, BSYM(1f) )
THUMB( bx r12 )
.word 0x016f2818 @ Magic numbers to help the loader
.word start @ absolute load/run zImage address
.word _edata @ zImage end address
THUMB( .thumb )
: mov r7, r1 @ save architecture ID
mov r8, r2 @ save atags pointer
start是head.S的程序的开始,在此之前都是一些宏定义。在1标号处保存由bootloader传递过来的参数
#ifndef __ARM_ARCH_2__
/*
* Booting from Angel - need to enter SVC mode and disable
* FIQs/IRQs (numeric definitions from angel arm.h source).
* We only do this if we were in user mode on entry.
*/
@获取当前运行模式
mrs r2, cpsr @ get current mode
@测试是否为usr模式
tst r2, # @ not user?
bne not_angel
mov r0, #0x17 @ angel_SWIreason_EnterSVC
ARM( swi 0x123456 ) @ angel_SWI_ARM
THUMB( svc 0xab ) @ angel_SWI_THUMB
not_angel:
mrs r2, cpsr @ turn off interrupts to
orr r2, r2, #0xc0 @ prevent angel from running
msr cpsr_c, r2
#else
teqp pc, #0x0c000003 @ turn off interrupts
#endif
如果内核从angel运行进入的运行模式将是usr mode,这时需要进入svc mode ,并禁止所有FIQ和IRQ中断。这些只有在进入时处于用户模式的时候才会执行。正常情况下,将运行not_angel标号处关闭中断的代码。然后对内核代码进行重定向(telocate)--(这部分代码还没看懂-_-!!!),重定向完成之后会跳转到not_relocated标号处运行。
not_relocated: mov r0, #
: str r0, [r2], # @ clear bss
str r0, [r2], #
str r0, [r2], #
str r0, [r2], #
cmp r2, r3
blo 1b
/*
* The C runtime environment should now be setup sufficiently.
* Set up some pointers, and start decompressing.
* r4 = kernel execution address
* r7 = architecture ID
* r8 = atags pointer
*/
mov r0, r4
mov r1, sp @ malloc space above stack
add r2, sp, #0x10000 @ 64k max
mov r3, r7
bl decompress_kernel
bl cache_clean_flush
bl cache_off
mov r0, # @ must be zero
mov r1, r7 @ restore architecture number
mov r2, r8 @ restore atags pointer
ARM( mov pc, r4 ) @ call kernel
重定向完成之后,首先清bss段,这时所有初始化C语言运行环境都要做的,然后调用decompress_kernel解压内核,之后跳转到非压缩内核启动阶段。
2.汇编阶段启动流程
对于tiny4412而言,内核的链接脚本为arch/arm/kernel/vmlinux.lds,它是由arch/arm/kernel/vmlinux.lds.S生成的。在链接脚本中,我们可以找到内核的入口
OUTPUT_ARCH(arm)
ENTRY(stext)
jiffies = jiffies_64;
SECTIONS
{
可以看出内核的入口为stext,它在 linux/arch/arm/kernel/head.S 中被定义。
.arm
__HEAD
ENTRY(stext)
THUMB( adr r9, BSYM(1f) ) @ Kernel is always entered in ARM.
THUMB( bx r9 ) @ If this is a Thumb- kernel,
THUMB( .thumb ) @ switch to Thumb now.
THUMB(: )
@设定为SVC模式,关闭IRQ、FIQ
setmode PSR_F_BIT | PSR_I_BIT | SVC_MODE, r9 @ ensure svc mode
@ and irqs disabled
@检查CPU ID 是否匹配
mrc p15, , r9, c0, c0 @ get processor id
bl __lookup_processor_type @ r5=procinfo r9=cpuid
movs r10, r5 @ invalid processor (r5=)?
THUMB( it eq ) @ force fixup-able long branch encoding
beq __error_p @ yes, error 'p'
#ifdef CONFIG_ARM_LPAE
mrc p15, , r3, c0, c1, @ read ID_MMFR0
and r3, r3, #0xf @ extract VMSA support
cmp r3, # @ long-descriptor translation table format?
THUMB( it lo ) @ force fixup-able long branch encoding
blo __error_p @ only classic page table format
#endif
#ifndef CONFIG_XIP_KERNEL
adr r3, 2f
ldmia r3, {r4, r8}
sub r4, r3, r4 @ (PHYS_OFFSET - PAGE_OFFSET)
add r8, r8, r4 @ PHYS_OFFSET
#else
ldr r8, =PHYS_OFFSET @ always constant in this case
#endif
/*
* r1 = machine no, r2 = atags or dtb,
* r8 = phys_offset, r9 = cpuid, r10 = procinfo
*/
@检查bootloader传入的参数列表atags的合法性
bl __vet_atags
#ifdef CONFIG_SMP_ON_UP
bl __fixup_smp
#endif
#ifdef CONFIG_ARM_PATCH_PHYS_VIRT
bl __fixup_pv_table
#endif
@创建初始页表
bl __create_page_tables
/*
* The following calls CPU specific code in a position independent
* manner. See arch/arm/mm/proc-*.S for details. r10 = base of
* xxx_proc_info structure selected by __lookup_processor_type
* above. On return, the CPU will be ready for the MMU to be
* turned on, and r0 will hold the CPU control register value.
*/
@建立C语言环境(代码重定位、清bss段)
ldr r13, =__mmap_switched @ address to jump to after
@ mmu has been enabled
adr lr, BSYM(1f) @ return (PIC) address
mov r8, r4 @ set TTBR1 to swapper_pg_dir
ARM( add pc, r10, #PROCINFO_INITFUNC )
THUMB( add r12, r10, #PROCINFO_INITFUNC )
THUMB( mov pc, r12 )
@开启MMU
: b __enable_mmu
ENDPROC(stext)
__mmap_switched定义在arch/arm/kernel/head-common.S中
__mmap_switched:
adr r3, __mmap_switched_data
ldmia r3!, {r4, r5, r6, r7}
cmp r4, r5 @ Copy data segment if needed
: cmpne r5, r6
ldrne fp, [r4], #
strne fp, [r5], #
bne 1b
mov fp, # @ Clear BSS (and zero fp)
: cmp r6, r7
strcc fp, [r6],#
bcc 1b
ARM( ldmia r3, {r4, r5, r6, r7, sp})
THUMB( ldmia r3, {r4, r5, r6, r7} )
THUMB( ldr sp, [r3, #] )
str r9, [r4] @ Save processor ID
str r1, [r5] @ Save machine type
str r2, [r6] @ Save atags pointer
bic r4, r0, #CR_A @ Clear 'A' bit
stmia r7, {r0, r4} @ Save control register values
b start_kernel
3.C语言阶段启动流程
Tiny4412 Linux 内核启动流程的更多相关文章
- linux 内核启动流程
Linux内核启动流程详细分析: http://www.linuxidc.com/Linux/2014-10/108034.htm ARM Linux内核启动过程: http://blog.csdn. ...
- 【内核】linux内核启动流程详细分析
Linux内核启动流程 arch/arm/kernel/head-armv.S 该文件是内核最先执行的一个文件,包括内核入口ENTRY(stext)到start_kernel间的初始化代码, 主要作用 ...
- 【内核】linux内核启动流程详细分析【转】
转自:http://www.cnblogs.com/lcw/p/3337937.html Linux内核启动流程 arch/arm/kernel/head-armv.S 该文件是内核最先执行的一个文件 ...
- linux 内核启动流程分析,移植
分析 linux-2.6.22.6 内核启动流程 移植 linux-3.4.2 到 JZ2440 开发板 Linux内核源码百度云链接: https://pan.baidu.com/s/1m1ymGl ...
- Linux内核启动流程与模块机制
本文旨在简单的介绍一下Linux的启动流程与模块机制: Linux启动的C入口位于/Linux.2.6.22.6/init/main.c::start_kernel() 下图简要的描述了一下内核初始化 ...
- Linux内核启动流程(简介)
1. vmlinux.lds 首先分析 Linux 内核的连接脚本文件 arch/arm/kernel/vmlinux.lds,通过链接脚本可以找到 Linux 内核的第一行程序是从哪里执行的: 第 ...
- Linux内核启动流程分析(一)【转】
转自:http://blog.chinaunix.net/uid-25909619-id-3380535.html 很久以前分析的,一直在电脑的一个角落,今天发现贴出来和大家分享下.由于是word直接 ...
- linux内核启动流程[转]
启动流程一览 既然启动是很严肃的一件事,那我们就来了解一下整个启动的过程吧! 好让大家比较容易发现启动过程里面可能会发生问题的地方,以及出现问题后的解决之道! 不过,由於启动的过程中,那个启动管理程序 ...
- Linux内核启动流程分析(二)【转】
转自:http://blog.chinaunix.net/uid-25909619-id-3380544.html S3C2410 Linux 2.6.35.7启动分析(第二阶段) 接着上面的分析,第 ...
随机推荐
- Yum 命令语法
一.Yum 命令格式: yum <options> <command><package...> 二.参数说明 1.options: 1)-y:如果在工作过程中如要使 ...
- 转:Android命令Monkey压力测试,详解
停止Monkey命令: 1. ps命令 查找uiautomator的进程 打开cmd命令行窗口 输入: adb shell ps | grep monkey 返回来的第一个数字,即是monkey的进 ...
- phalcon: 开启模板缓存和缓存路径
/** * 设置view */ $di->set('view', function () use ($config) { $view = new \Phalcon\Mvc\View(); $vi ...
- 表格表格中获取不到button选择器
今天做一个表单提交,怎么也拿不到button的选择器,不管用$(“#btn_update”)还会getElementById("btn_update"),浏览器也是谷歌没问题,后来 ...
- 使用JMeter建立接口测试
[需求]某组机器是Android和iOS输入法接口服务器,有很多重要的接口,例如:升级,网络开关,热词等.现在有3台机器过保要下线,新申请了3台机器,需要验证一下这3台机器接口的正确性. [测试步骤] ...
- oracle for loop 简单
declare i NUMBER; begin loop INSERT INTO emp VALUES(i,i); end LOOP; END;
- React native 开发工具 VSCode
1.VSCODE下载地址:先下载VSCode软件 2.代码提示功能: 打开 VSCode ,然后 按住键盘 command+p,然后在vscode上面输入框 输入: "ext install ...
- 关于js序列化时间的方法
var time = new Date(); var otime = getMyDate(time); //将毫秒转换成 年月日+时分秒 格式的 (1970-01-11 00:00:00) funct ...
- (转)根据ImageView的大小来压缩Bitmap,避免OOM
本文转载于:http://www.cnblogs.com/tianzhijiexian/p/4254110.html Bitmap是引起OOM的罪魁祸首之一,当我们从网络上下载图片的时候无法知道网络图 ...
- Zeroc Ice 负载均衡之Icegrid simple
最近学习Icestorm的replicated例子,在本地计算机上面跑通了,但在两台机器上(一台服务器192.168.0.113,一台客户端192.168.0.188),怎么都跑不通.上网求助,大家给 ...