Chinaunix首页 | 论坛 | 博客
  • 博客访问: 963757
  • 博文数量: 173
  • 博客积分: 3436
  • 博客等级: 中校
  • 技术积分: 1886
  • 用 户 组: 普通用户
  • 注册时间: 2009-01-07 09:29
文章分类

全部博文(173)

文章存档

2016年(6)

2015年(10)

2014年(14)

2013年(8)

2012年(36)

2011年(63)

2010年(19)

2009年(17)

分类: LINUX

2011-02-22 21:32:24

ARM linux 内核启动分析(2) [原创 2007-06-11 10:50:25]


Author:    jimmy.li
Date:       2007-06-08
--------------------------------------

分支1__lookup_processor_type函数分析

 

内核中使用了一个结构struct proc_info_list,用来记录处理器相关的信息,该结构定义在kernel/include/asm-arm/procinfo.h头文件中。

/* arch/arm/kernel/head-armv.S */

 

/*

 * Note!  struct processor is always defined if we're

 * using MULTI_CPU, otherwise this entry is unused,

 * but still exists.

 *

 * NOTE! The following structure is defined by assembly

 * language, NOT C code.  For more information, check:

 *  arch/arm/mm/proc-*.S and arch/arm/kernel/head-armv.S

 */

struct proc_info_list {

        unsigned int            cpu_val;

        unsigned int            cpu_mask;

        unsigned long           __cpu_mmu_flags;        /* used by head-armv.S */

        unsigned long           __cpu_flush;            /* used by head-armv.S */

        const char              *arch_name;

        const char              *elf_name;

        unsigned int            elf_hwcap;

        struct proc_info_item   *info;

        struct processor        *proc;

};

在该结构定义的注释中说,proc_info_list的定义不是在C语言代码中,而是在汇编语言中实现的。arch/arm/mm/proc-xscale.S文件中定义了所有和xscale有关的proc_info_list,我们使用的pxa270定义如下:

/* arch/arm/mm/proc-xscale.S */

 

1027         .section ".proc.info", #alloc, #execinstr

1028

1029         .type   __80200_proc_info,#object

1030 __80200_proc_info:                 //每一个__xxx_proc_info就对应于proc_info_list

1031         .long   0x69052000         //cpu_val

1032         .long   0xfffffff0            //cpu_mask

1033 #if CACHE_WRITE_THROUGH

1034         .long   0x00000c0a      //__cpu_mmu_flags

1035 #else

1036         .long   0x00000c0e     //__cpu_mmu_flags

1037 #endif

1038         b       __xscale_setup   //__cpu_flush

1039         .long   cpu_arch_name   //arch_name

1040         .long   cpu_elf_name     //elf_name

1041         .long   HWCAP_SWP|HWCAP_HALF|HWCAP_THUMB|HWCAP_FAST_MULT|
HWCAP_EDSP|HWCAP_XSCALE     // elf_hwcap

1042         .long   cpu_80200_info       // info

1043         .long   xscale_processor_functions    //proc

1044         .size   __80200_proc_info, . - __80200_proc_info

1045

….        

1096        

1097     .type   __bva0_proc_info,#object

1098 __bva0_proc_info:              //pxa270 proc_info_list

1099     .long   0x69054110          @ Bulverde A0: 0x69054110, A1 : 0x69054111.

1100     .long   0xfffffff0          @ and this is the CPU id mask.

1101 #if CACHE_WRITE_THROUGH

1102     .long   0x00000c0a

1103 #else  

1104     .long   0x00000c0e

1105 #endif

1106     b   __xscale_setup

1107     .long   cpu_arch_name

1108     .long   cpu_elf_name

1109     .long   HWCAP_SWP|HWCAP_HALF|HWCAP_THUMB|HWCAP_FAST_MULT|
HWCAP_EDSP|HWCAP_XSCALE

1110     .long   cpu_bva0_info

1111     .long   xscale_processor_functions

1112     .size   __bva0_proc_info, . - __bva0_proc_info

 

在上述code中,由于定义了section,因此__bva0_proc_info等在编译时会放入.proc.info section中。根据vmlinux-armv.lds__arch_info_begin__arch_info_end就分别指向.proc.info section的起始和结束,换句话说,在__arrch_info_begin__arch_info_end所指向的区域,包含着若干个proc_info_list结构的数据。这个会在__lookup_processor_type中用到,下面来看一下__lookup_processor_type这个分支代码。

/* arch/arm/kernel/head-armv.S */

 

  477 __lookup_processor_type:

   478                 adr     r5, 2f           //把标号2(行498)的址址放入r5寄存器中

479                 ldmia   r5, {r7, r9, r10}  //r7 = __proc_info_end

                                            // r9 =  __proc_info_begin

                                            // r10 = 标号2(行498)的地址

   480                 sub     r5, r5, r10                     @ convert addresses

   481                 add     r7, r7, r5                      @ to our address space

   482                 add     r10, r9, r5

   483                 mrc     p15, 0, r9, c0, c0              @ get processor id

   484 1:              ldmia    r10, {r5, r6, r8}               @ value, mask, mmuflags

   485                 and     r6, r6, r9                      @ mask wanted bits

   486                 teq      r5, r6

   487                 moveq   pc, lr

   488                 add      r10, r10, #36                   @ sizeof(proc_info_list)

   489                 cmp     r10, r7

   490                 blt       1b

   491                 mov     r10, #0                         @ unknown processor

492                 mov     pc, lr

493

494 /*

495  * Look in include/asm-arm/procinfo.h and arch/arm/kernel/arch.[ch] for

496  * more information about the __proc_info and __arch_info structures.

497  */

498 2:              .long   __proc_info_end

499                 .long   __proc_info_begin

500                 .long   2b

501                 .long   __arch_info_begin

502                 .long   __arch_info_end

 

Line478:将line498的地址放到寄存器r5中,adr是小范围的地址读取伪指令。

Line479:将r5所指向的数据区的数据读出到r7r9r10。结果就是r7= __proc_info_endr9 = __proc_info_begin r10 = 标号2line498)的地址。

Line480~482r10 = __proc_info_begin

Line483mrc是一个协处理器寄存器到ARM寄存器的数据传送指令,它的指令格式是:MRC  coproc, opcode1, Rd, CRn {, opcode2}  对于读取Processor ID来说,coproc 15opcode10, CRn=0, opcode2=0Line483读取processor ID,并放入r9寄存器中。

Line484~490,是一个循环处理过程,由于r10一开始是指向__proc_info_begin的,前面提到__proc_info_begin指向.proc.info section的首地址,所以整个循环就是遍历.proc.info section,也就是遍历proc_info_list结构数组,比较(proc_info_list[i]->cpu_val == processor ID & proc_info_list[i]->cpu_mask)是否与当前运行的processor ID一致,如果有条件满足的则函数在line487返回(跳转到line189),此时r10是不为零的(因为函数返回后,要根据r10是否为0,来判断processor未知与否);如果遍历完整个.proc.info section都不满足的,则进入line491

Line491~492:置r10=0用来表示processor 未知,然后函数返回(跳转到line189)

阅读(1373) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~