ARM linux的启动部分源代码简略分析
itched的地址,实际上__mmap_switched是一个arch/arm/kernel/head-common.S中定义的例程。接着来看这个例程的定义,在arch/arm/kernel/head-common.S文件中:
__mmap_switched:
adr r3, __switch_data + 4
ldmia r3!, {r4, r5, r6, r7}
cmp r4, r5 @ Copy data segment if needed
1: cmpne r5, r6
ldrne fp, [r4], #4
strne fp, [r5], #4
bne 1b
mov fp, #0 @ Clear BSS (and zero fp)
1: cmp r6, r7
strcc fp, [r6],#4
bcc 1b
ldmia r3, {r4, r5, r6, r7, sp}
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
ENDPROC(__mmap_switched)
这个例程完成如下工作:
1、使r3指向__switch_data变量的第二个字段(从1开始计数)。
2、执行了一条加载指令,也就是在r4, r5, r6, r7寄存器中分别加载4个符号__data_loc,_data, __bss_start ,_end的地址,这四个符号都是在链接脚本arch/arm/kernel/vmlinux.lds.S中出现的,标识了镜像各个段的地址,我们应该不难猜出他们所代表的段。
3、如果需要的话则数据段(数据段和BSS段是紧邻的)。
4、初始化BSS段,全部清零,BSS是未初始化的全局变量区域。
5、又看到一条加载指令,同样在一组寄存器中加载借个符号的地址,r4中为processor_id,r5中为__machine_arch_type, r6中为__atags_pointer, r7中为cr_alignment ,sp中为init_thread_union + THREAD_START_SP。
6、接着我们看到下面的几条语句,则是用前面获取的信息来初始化那些全局变量r9,机器号被保存到processor_id处;r1寄存器的值,机器号,被保存到变量__machine_arch_type中,其他的也一样。
7、重新设置堆栈指针,指向init_task的堆栈。init_task是系统的第一个任务,init_task的堆栈在taskstructure的后8K,我们后面会看到。
8、最后就要跳到C代码的 start_kernel。
b start_kernel
到此为止,汇编部分的初始化代码就结束了
O,My God.初始化代码的汇编部分终于结束。从而进入了与体系结构无关的Linux内核部分。start_kernel()会调用一系列初始化函数来设置中断,执行进一步的内存配置。
现在让我们来回忆一下目前的系统状态:
临时页表已经建立,在0X30004000处,映射了映像文件大小空间,虚地址0XC000000被映射到0X30000000。CACHE,MMU 都已经打开。堆栈用的是任务init_task的堆栈。
如果以为到了c代码可以松一口气的话,就大错特措了,linux的c也不比汇编好懂多少,相反倒掩盖了汇编的一些和机器相关的部分,有时候更难懂。其实作 为编写操作系统的c代码,只不过是汇编的另一种写法,和机器代码的联系是很紧密的。另外,这些start_kernel()中调用的C函数,每一个都具有举足轻重的地位,它们中的许多都肩负着初始化内核中的某个子系统的重要使命,而Linux内核中每一个子系统都错综复杂,牵涉到各种软件、硬件的复杂算法,所以理解起来倒真的是挺困难的。
start_kernel函数在init/main.c中定义:
528 asmlinkage void __init start_kernel(void)
529 {
530 char * command_line;
531 extern struct kernel_param __start___param[], __stop___param[];
532
533 smp_setup_processor_id();
534
535 /*
536 * Need to run as early as possible, to initialize the
537 * lockdep hash:
538 */
539 lockdep_init();
540 debug_objects_early_init();
541
542 /*
543 * Set up the the initial canary ASAP:
544 */
545 boot_init_stack_canary();
546
547 cgroup_init_early();
548
549 local_irq_disable();
550 early_boot_irqs_off();
551 early_init_irq_lock_class();
552
553 /*
554 * Interrupts are still disabled. Do necessary setups, then
555 * enable them
556 */
557 lock_kernel();
558 tick_init();
559 boot_cpu_init();
560 page_address_init();
561 printk(KERN_NOTICE "%s", linux_banner);
562 setup_arch(&command_line);
563 mm_init_owner(&init_mm, &init_task);
564 setup_command_line(command_line);
565 setup_nr_cpu_ids();
566 setup_per_cpu_areas();
567 smp_prepare_boot_cpu(); /* arch-specific boot-cpu hooks */
568
569 build_all_zonelists();
570 page_alloc_init();
571
572 printk(KERN_NOTICE "Kernel command line: %s\n", boot_command_line);
573 parse_early_param();
574 parse_args("Booting kernel", static_command_line,
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)