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

ARM linux的启动部分源代码简略分析

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

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,

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

网站地图

Top