微波EDA网,见证研发工程师的成长!
首页 > 硬件设计 > 嵌入式设计 > ARM Linux启动代码分析

ARM Linux启动代码分析

时间:11-09 来源:互联网 点击:
前言

在学习、分析之前首先要弄明白一个问题:为什么要分析启动代码

因为启动代码绝大部分都是用汇编语言写的,对于没学过或者不熟悉汇编语言的同学确实有一定难度,但是如果你想真正深入地学习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值是存放的是一个物理地址,为什么是物理地址?为了搞清楚这个问题,下面简

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top