从Linux调试信息分析linux启动流程

http://hi.baidu.com/daoguchengshu/item/f77c383fda19d46b7d034be0 


刚开始,看网上内核移植,驱动添加等等,都是在xx文件添加xx结构体,不知其所以然。

 

没办法,看样子还是得自己一句一句分析,才能理解深刻。

 

        内核版本是2.6.37.4,找了XC2240的zImage分析,看内核的启动流程,分析移植工作要做的和

各文件之间的调用关系。

 

      内核从int/main.c的start_kernel函数开始启动: 

 

Linux version 2.6.37.4 () (gcc version 4.1.2) #1 Tue Feb 28 00:30:28 HKT 2012

    这行之前还有几句,先不管,那是bootloader和解压内核的。

    上面一句调试信息是在 start_kernel中的printk(KERN_NOTICE "%s", linux_banner)调用时打印出来,打印的linux_banner即是上面的字符串,到底如何从linux_banner参数得到上述字符串,我也没搞明白,这应该是每个linux都会打印的,会去读编译内核时的电脑信息等,跟移植内核没有关系。

 

 

CPU:ARM920T [41129200] revision 0 (ARMv4T),cr=c0007177

start_kernel,第613行,调用setup_arch(&command_line)函数,setup_arch函数在arch/arm/kernel中,如下:

01 void__initsetup_arch(char**cmdline_p)
02 {
03    structtag*tags=(structtag*)&init_tags;
04    structmachine_desc*mdesc;
05    char*from=default_command_line;
06 
07    unwind_init();
08 
09    setup_processor();
10    mdesc=setup_machine(machine_arch_type);
11    machine_name=mdesc->name;
12 
13    if(mdesc->soft_reboot)
14        reboot_setup("s");
15 
16    if(__atags_pointer)
17        tags=phys_to_virt(__atags_pointer);
18    elseif(mdesc->boot_params)
19        tags=phys_to_virt(mdesc->boot_params);
20 
21 #if defined(CONFIG_DEPRECATED_PARAM_STRUCT)
22    /*
23     * If we have the old style parameters, convert them to
24     * a tag list.
25     */
26    if(tags->hdr.tag!=ATAG_CORE)
27        convert_to_tag_list(tags);
28 #endif
29    if(tags->hdr.tag!=ATAG_CORE)
30        tags=(structtag*)&init_tags;
31 
32    if(mdesc->fixup)
33        mdesc->fixup(mdesc,tags,&from,&meminfo);
34 
35    if(tags->hdr.tag==ATAG_CORE) {
36        if(meminfo.nr_banks!=0)
37            squash_mem_tags(tags);
38        save_atags(tags);
39        parse_tags(tags);
40    }
41 
42    init_mm.start_code=(unsignedlong) _text;
43    init_mm.end_code  =(unsignedlong) _etext;
44    init_mm.end_data  =(unsignedlong) _edata;
45    init_mm.brk      =(unsignedlong) _end;
46 
47    /* parse_early_param needs a boot_command_line */
48    strlcpy(boot_command_line,from,COMMAND_LINE_SIZE);
49 
50    /* populate cmd_line too for later use, preserving boot_command_line */
51    strlcpy(cmd_line,boot_command_line,COMMAND_LINE_SIZE);
52    *cmdline_p=cmd_line;
53 
54    parse_early_param();
55 
56    arm_memblock_init(&meminfo,mdesc);
57 
58    paging_init(mdesc);
59    request_standard_resources(&meminfo,mdesc);
60 
61 #ifdef CONFIG_SMP
62    if(is_smp())
63        smp_init_cpus();
64 #endif
65    reserve_crashkernel();
66 
67    cpu_init();
68    tcm_init();
69 
70    /*
71     * Set up various architecture-specific pointers
72     */
73    arch_nr_irqs=mdesc->nr_irqs;
74    init_arch_irq=mdesc->init_irq;
75    system_timer=mdesc->timer;
76    init_machine=mdesc->init_machine;
77 
78 #ifdef CONFIG_VT
79 #if defined(CONFIG_VGA_CONSOLE)
80    conswitchp=&vga_con;
81 #elif defined(CONFIG_DUMMY_CONSOLE)
82    conswitchp=&dummy_con;
83 #endif
84 #endif
85    early_trap_init();
86 }

第9行,调用了 setup_processor()函数,读CPU的一些信息,如下:

01 staticvoid__initsetup_processor(void)
02 {
03    structproc_info_list*list;
04 
05    /*
06     * locate processor in the list of supported processor
07     * types.  The linker builds this table for us from the
08     * entries in arch/arm/mm/proc-*.S
09     */
10    list=lookup_processor_type(read_cpuid_id());
11    if(!list) {
12        printk("CPU configuration botched (ID %08x), unable "
13               "to continue.\n",read_cpuid_id());
14        while(1);
15    }
16 
17    cpu_name=list->cpu_name;
18 
19 #ifdef MULTI_CPU
20    processor=*list->proc;
21 #endif
22 #ifdef MULTI_TLB
23    cpu_tlb=*list->tlb;
24 #endif
25 #ifdef MULTI_USER
26    cpu_user=*list->user;
27 #endif
28 #ifdef MULTI_CACHE
29    cpu_cache=*list->cache;
30 #endif
31 
32    printk("CPU: %s [%08x] revision %d (ARMv%s), cr=%08lx\n",
33           cpu_name,read_cpuid_id(),read_cpuid_id() &15,
34           proc_arch[cpu_architecture()],cr_alignment);
35 
36    sprintf(init_utsname()->machine,"%s%c",list->arch_name,ENDIANNESS);
37    sprintf(elf_platform,"%s%c",list->elf_name,ENDIANNESS);
38    elf_hwcap=list->elf_hwcap;
39 #ifndef CONFIG_ARM_THUMB
40    elf_hwcap&=~HWCAP_THUMB;
41 #endif
42 
43    feat_v6_fixup();
44 
45    cacheid_init();
46    cpu_proc_init();
47 }

在这个函数中第32行,cpuname, read_cpuid()等,读变量或函数返回值,打印出CPU信息,即是开头的CPU:ARM920T [41129200] revision 0 (ARMv4T),cr=c0007177 打印信息。这也跟移植的关系不大,主要是我们移植的时候配置好CPU就行了。

 

 

CPU:VIVTdatacache,VIVTinstructioncache

再看上面的setup_processor函数,后面调用了cacheid_init()函数,这个函数具体干嘛的,现在不明白,后面分析,这个函数如下:

01 staticvoid__initcacheid_init(void)
02 {
03    unsignedintcachetype=read_cpuid_cachetype();
04    unsignedintarch=cpu_architecture();
05 
06    if(arch>=CPU_ARCH_ARMv6) {
07        if((cachetype&(7<<29)) ==4<<29) {
08            /* ARMv7 register format */
09            cacheid=CACHEID_VIPT_NONALIASING;
10            if((cachetype&(3<<14)) ==1<<14)
11                cacheid|=CACHEID_ASID_TAGGED;
12            elseif(cpu_has_aliasing_icache(CPU_ARCH_ARMv7))
13                cacheid|=CACHEID_VIPT_I_ALIASING;
14        }elseif(cachetype&(1<<23)) {
15            cacheid=CACHEID_VIPT_ALIASING;
16        }else{
17            cacheid=CACHEID_VIPT_NONALIASING;
18            if(cpu_has_aliasing_icache(CPU_ARCH_ARMv6))
19                cacheid|=CACHEID_VIPT_I_ALIASING;
20        }
21    }else{
22        cacheid=CACHEID_VIVT;
23    }
24 
25    printk("CPU: %s data cache, %s instruction cache\n",
26        cache_is_vivt() ?"VIVT":
27        cache_is_vipt_aliasing() ?"VIPT aliasing":
28        cache_is_vipt_nonaliasing() ?"VIPT nonaliasing":"unknown",
29        cache_is_vivt() ?"VIVT":
30        icache_is_vivt_asid_tagged() ?"VIVT ASID tagged":
31        icache_is_vipt_aliasing() ?"VIPT aliasing":
32        cache_is_vipt_nonaliasing() ?"VIPT nonaliasing":"unknown");
33 }

第25行即是输出打印信息。到这里跟移植关系也不太大。

 

Machine:WGC2440

       返回setup_arch函数,第10行调用setup_machine(machine_arch_type)函数,参数是machine_arch_type, 将返回值传递给mdesc变量。

       这里虽然跟移植有关系,不过跟具体的平台关系不大,我们设置好平台机器号就好了。

        achine_arch_type来自于文件:include/generated/mach-types.h [ 此文件是生成文件 ]。这个只是对应一个number,然后通过这个number去查找到相关信息。每一种板子对应于一个特定的number。然后相关的描述来于MACHINE_START宏。

       取得该板子的机器码后,在setup_machine函数中会打印出机器名称。如下:

01 staticstructmachine_desc*__initsetup_machine(unsignedintnr)
02 {
03    structmachine_desc*list;
04 
05    /*
06     * locate machine in the list of supported machines.
07     */
08    list=lookup_machine_type(nr);
09    if(!list) {
10        printk("Machine configuration botched (nr %d), unable "
11               "to continue.\n",nr);
12        while(1);
13    }
14 
15    printk("Machine: %s\n",list->name);
16 
17    returnlist;
18 }

第15行打印出机器名,这里是WGC2440。

       这个名字来自arch/arm/mach-s3c2440/mach-wgc2440.c文件中的MACHINE_START宏,这个宏后面再分析,跟机器码有关。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值