ARM Linux启动代码分析
在学习、分析之前首先要弄明白一个问题:为什么要分析启动代码?
因为启动代码绝大部分都是用汇编语言写的,对于没学过或者不熟悉汇编语言的同学确实有一定难度,但是如果你想真正深入地学习Linux,那么读、分析某一个体系结构(比如ARM)的启动代码或者其他底层代码是必不可少的。当分析之后会发现这是有很多好处的:分析启动代码可以加深对汇编语言的理解;可以学习汇编语言的使用技巧;可以学习如何编写位置无关的代码,可以知道从启动到start_kernel()函数之前内核到底干了什么事情,从而为后续其他内核子系统的学习打下基础。
废话不多说,下面基于s3c6410,以Linux-2.6.36版本为基础进行分析。ARM Linux的启动代码有两处,一处是经过压缩的,一处是没有经过压缩的,压缩的最终还是会调用没有压缩的,没有压缩的入口在arch/arm/kernel/head.S文件中,如下所示:
77 __HEAD78 ENTRY(stext)79 setmode PSR_F_BIT PSR_I_BIT SVC_MODE, r9 @ ensure svc mode80 @ and irqs disabled81 mrc p15, 0, r9, c0, c0 @ get processor id82 bl __lookup_processor_type @ r5=procinfo r9=cpuid83 movs r10, r5 @ invalid processor (r5=0)?84 beq __error_p @ yes, error p85 bl __lookup_machine_type @ r5=machinfo86 movs r8, r5 @ invalid machine (r5=0)?87 beq __error_a @ yes, error a88 bl __vet_atags89 bl __create_page_tables90 91 /*92 * The following calls CPU specific code in a position independent93 * manner. See arch/arm/mm/proc-*.S for details. r10 = base of94 * xxx_proc_info structure selected by __lookup_machine_type95 * above. On return, the CPU will be ready for the MMU to be96 * turned on, and r0 will hold the CPU control register value.97 */98 ldr r13, __switch_data @ address to jump to after99 @ mmu has been enabled00100 adr lr, BSYM(__enable_mmu) @ return (PIC) address00101 ARM( add pc, r10, #PROCINFO_INITFUNC )00102 THUMB( add r12, r10, #PROCINFO_INITFUNC )00103 THUMB( mov pc, r12 )00104 ENDPROC(stext)
79行就是要分析的第一行代码,设置CPU为管理模式,这也是CPU一上电所处的模式,关闭CPU普通中断和CPU快速中断。
81行,读协处理器p15获取CPU ID,结果存在r9寄存器里,待会会用到。
82行,跳转到__lookup_processor_type标号处,在arch/arm/kernel/head-common.S文件里定义:
00160 __lookup_processor_type:00161 adr r3, 3f00162 ldmia r3, {r5 - r7}00163 add r3, r3, #800164 sub r3, r3, r7 @ get offset between virt&phys00165 add r5, r5, r3 @ convert virt addresses to00166 add r6, r6, r3 @ physical address space00167 1: ldmia r5, {r3, r4} @ value, mask00168 and r4, r4, r9 @ mask wanted bits00169 teq r3, r400170 beq 2f00171 add r5, r5, #PROC_INFO_SZ @ sizeof(proc_info_list)00172 cmp r5, r600173 blo 1b00174 mov r5, #0 @ unknown processor00175 2: mov pc, lr00176 ENDPROC(__lookup_processor_type)……00193 .align 200194 3: .long __proc_info_begin00195 .long __proc_info_end00196 4: .long .00197 .long __arch_info_begin00198 .long __arch_info_end
在汇编语言中,标号代表的是地址,准确来说是链接地址。adr和ldr都是伪指令,它们两者的作用都是将标号处所代表的地址存放到寄存器中。但是adr采用基于PC值的相对地址(PC+偏移值),而ldr采用的是绝对地址(直接采用标号的值),另外adr要求指令与标号位于同一个段中。
161行,因此当前PC值是存放的是一个物理地址,为什么是物理地址?为了搞清楚这个问题,下面简
ARMLinux启动代 相关文章:
- Windows CE 进程、线程和内存管理(11-09)
- RedHatLinux新手入门教程(5)(11-12)
- uClinux介绍(11-09)
- openwebmailV1.60安装教学(11-12)
- Linux嵌入式系统开发平台选型探讨(11-09)
- Windows CE 进程、线程和内存管理(二)(11-09)