ARM linux的启动部分源代码简略分析
rocessor *proc;
struct cpu_tlb_fns *tlb;
struct cpu_user_fns *user;
struct cpu_cache_fns *cache;
};
第一项是CPUid,将与协处理器中读出的id作比较,其余的字段也都是与处理器相关的信息,到下面初始化的过程中自然会用到。
另外,这个例程加载符地址的代码也是挺值得我辈学习的:
adr r3, 3f
加载一个符号的地址,这个符号在加载语句前面(下面)定义,forward嘛,这个符号为3,离这条语句最近的那个。在那个符号为3的位置我们看到这样的代码:
.align 2
3: .long __proc_info_begin
.long __proc_info_end
4: .long .
.long __arch_info_begin
.long __arch_info_end
搜索这两个符号的值,在文件arch/arm/kernel/vmlinux.lds.S中:
__proc_info_begin = .;
*(.proc.info.init)
__proc_info_end = .;
这两个符号分别是一种初始化的段的结束开始地址和结束地址。为了了解由struct proc_info_list结构体组成的段的实际构成,我们还是得要了解一下在系统中到底都有哪些变量是声明了要被放到这个段的。用关键字.proc.info.init来搜,全部都是arch/arm/mm/proc-*.S文件,这些都是特定于处理器的汇编语言文件,对于我们的mini2440, 自然是要看proc-arm920.S文件的,在其中可以看到这些内容:
.section ".proc.info.init", #alloc, #execinstr
.type __arm920_proc_info,#object
__arm920_proc_info:
.long 0x41009200
.long 0xff00fff0
.long PMD_TYPE_SECT | \
PMD_SECT_BUFFERABLE | \
PMD_SECT_CACHEABLE | \
PMD_BIT4 | \
PMD_SECT_AP_WRITE | \
PMD_SECT_AP_READ
.long PMD_TYPE_SECT | \
PMD_BIT4 | \
PMD_SECT_AP_WRITE | \
PMD_SECT_AP_READ
b __arm920_setup
.long cpu_arch_name
.long cpu_elf_name
.long HWCAP_SWP | HWCAP_HALF | HWCAP_THUMB
.long cpu_arm920_name
.long arm920_processor_functions
.long v4wbi_tlb_fns
.long v4wb_user_fns
#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
.long arm920_cache_fns
#else
.long v4wt_cache_fns
#endif
.size __arm920_proc_info, . - __arm920_proc_info
看到这儿我们再回国头去看__lookup_processor_type的代码:
ldmia r3, {r5 - r7}
add r3, r3, #8
sub r3, r3, r7
尽管符号3处只有两个有效值,但它加载了三个数,而第三个数,我们看到是这样定义的:
.long .
__lookup_processor_type中,给r3加上8,也就是让r3指向“.”的地址,然后用r3减r7来获取虚拟地址与物理地址的差,这样看来,“.”就应该是虚拟空间(编译地址)里那个数据的地址。
之后的代码获得__proc_info_begin和__arch_info_end这两个符号在物理空间中的地址:
add r5, r5, r3 @ convert virt addresses to
add r6, r6, r3
然后便是在那个段中逐个的检查struct proc_info_list结构体,以找到与我们的CPU相匹配的:
1: ldmia r5, {r3, r4} @ value, mask
and r4, r4, r9 @ mask wanted bits
teq r3, r4
beq 2f
add r5, r5, #PROC_INFO_SZ @ sizeof(proc_info_list)
cmp r5, r6
blo 1b
mov r5, #0 @ unknown processor
2: mov pc, lr
__lookup_processor_type例程会返回在文件arch/arm/mm/proc-arm920.S中定义的一个保存有与我们的处理器相关的信息的struct proc_info_list结构体的地址。
接下来我们继续看stext的代码:
bl __lookup_machine_type @ r5=machinfo
movs r8, r5 @ invalid machine (r5=0)?
beq __error_a @ yes, error a
在获得了处理器信息之后,则调用__lookup_machine_type来查找机器信息。这个例程同样也在arch/arm/kernel/head-common.S文件中定义。这个例程的定义如下:
__lookup_machine_type:
adr r3, 4b
ldmia r3, {r4, r5, r6}
sub r3, r3, r4 @ get offset between virt&phys
add r5, r5, r3 @ convert virt addresses to
add r6, r6, r3 @ physical address space
1: ldr r3, [r5, #MACHINFO_TYPE] @ get machine type
teq r3, r1 @ matches loader number?
beq 2f @ found
add r5, r5, #SIZEOF_MACHINE_DESC @ next machine_desc
cmp r5, r6
blo 1b
mov r5, #0 @ unknown machine
2: mov pc, lr
ENDPROC(__lookup_machine_type)
处理的过程和上面的__lookup_processor_type还是挺相似的。这个例程接收r1中传进来的机器号作为参数,然后,在一个由struct machine_desc结构体组成的段中查找和我们的机器号匹配的struct machine_desc结构体,这个结构体在arch/arm/include/asm/mach/arch.h文件中定义,用于保存机器的信息:
struc
ARMlinux启 相关文章:
- ARM Linux 更新启动画面(11-21)
- ARM Linux启动分析headarmv.S内幕(11-09)
- arm linux 启动流程(11-09)
- ARM Linux 的启动过程(11-09)
- arm linux 启动流程之 进入内核(11-09)
- ARM Linux启动代码分析(11-09)