随笔-118  评论-133  文章-4  trackbacks-0
注:
    原文出自taoyuetao大侠的博客上:
http://www.eetop.cn/blog/html/45/11145_itemid_1396.html
    小弟参考之研究s3c2410相关代码,然后做了稍微的修改,作为一个学习笔记,方便以后的学习,也希望对后人有所帮助^_^

前面一篇文章,简单介绍了内核启动的汇编主流程,这篇介绍其中调用的汇编子函数__lookup_processor_type

函数__lookup_processor_type介绍:

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

/*

 * 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.S

 */

struct proc_info_list {

    unsigned int        cpu_val;

    unsigned int        cpu_mask;

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

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

    const char      *arch_name;

    const char      *elf_name;

    unsigned int        elf_hwcap;

    const char      *cpu_name;

    struct processor    *proc;

    struct cpu_tlb_fns  *tlb;

    struct cpu_user_fns *user;

    struct cpu_cache_fns    *cache;

};

arch/arm/mm/proc-arm920.S文件中定义了所有和arm920有关的proc_info_list,我们使用的arm920定义如下:

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

 

    .type   __arm920_proc_info,#object

__arm920_proc_info:

    .long   0x41009200

    .long   0xff00fff0

.

.

 

由于.section指示符,上面定义的__arm920_proc_info信息在编译的时候被放到了.proc.info段中,这是由linux的链接脚本文件arch/arm/kernel/vmlinux.lds指定的,参考如下:

SECTIONS

{

    . = TEXTADDR;

    .init : {           /* Init code and data       */

        _stext = .;

            _sinittext = .;

            *(.init.text)

            _einittext = .;

        __proc_info_begin = .;

            *(.proc.info.init)

        __proc_info_end = .;

                .

                .

 

这里的符号__proc_info_begin指向.proc.info的起始地址,而符号__proc_info_end指向.proc.info的结束地址。后面就会引用这两个符号,来指向.proc.info这个段。
    

下面来来看看函数的源代码,为了分析方便将函数按行进行编号,其中17-18行就是前面提到的对.proc.info的引用,
2行将19行的地址放到寄存器r3中,adr是小范围的地址读取伪指令。

3行将r3所指向的数据区的数据读出到r5r6r9,执行结果是

R5=__proc_info_beginr6=__proc_info_endr9=19行的地址

用仿真器查看:

r5=0xc0018664

r6=0xc0018694

r9=0xc0008324(为何是0xc0008324而不是0x30008324???)

4行算出虚、实地址的偏移,

5-6行的结果应该是r5指向__proc_info_begin的实地址,r6指向__proc_info_end的实地址。

7行读取cpuid,这是一个协处理器指令,将processor ID存储在r9中。

8行将r5指向的__arm920_proc_info开始的数据读出放到寄存器r3r4,结果r3=0x41009200 (cpu_val)r4=0xff00fff0 (cpu_mask)

9-10行将读出的id和结构中的id进行比较,如果id相同则返回,返回时r9存储
processor ID
,如果id不匹配,则将指针r10增加PROC_INFO_SZ (proc_info_list结构的长度,在这等于48),如果r5小于r6指定的地址,也就是
__proc_info_end
,则继续循环比较下一个proc_info_list中的id,如第11-14行的代码,如果查找到__proc_info_end,仍未找到一个匹配的id,则将r5清零并返回,如15-16行,也就是说如果函数执行成功则r5指向匹配的proc_info_list结构地址,如果函数返回错误则r50

 

/*

 * Read processor ID register (CP#15, CR0), and look up in the linker-built

 * supported processor list.  Note that we can't use the absolute addresses

 * for the __proc_info lists since we aren't running with the MMU on

 * (and therefore, we are not in the correct address space).  We have to

 * calculate the offset.

 *

 * Returns:

 *  r3, r4, r6 corrupted

 *  r5 = proc_info pointer in physical address space

 *  r9 = cpuid

 */

    .type   __lookup_processor_type, %function

1   __lookup_processor_type:

2       adr r3, 3f

3       ldmda   r3, {r5, r6, r9}

4       sub r3, r3, r9          @ get offset between virt&phys

5       add r5, r5, r3          @ convert virt addresses to

6       add r6, r6, r3          @ physical address space

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

8   1:  ldmia   r5, {r3, r4}            @ value, mask

9       and r4, r4, r9          @ mask wanted bits

10     teq r3, r4

11      beq 2f

12      add r5, r5, #PROC_INFO_SZ       @ sizeof(proc_info_list)

13      cmp r5, r6

14      blo 1b

15      mov r5, #0              @ unknown processor

16  2:  mov pc, lr
   
/*

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

 * more information about the __proc_info and __arch_info structures.

 */

17      .long   __proc_info_begin

18      .long   __proc_info_end

19  3:  .long   .

20      .long   __arch_info_begin

21      .long   __arch_info_end

 



posted on 2007-07-24 20:50 lfc 阅读(1567) 评论(0)  编辑 收藏 引用
只有注册用户登录后才能发表评论。