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

前一篇介绍了汇编函数__lookup_processor_type

这一篇介绍__lookup_architecture_type函数

函数__lookup_architecture_type介绍:
每个机器(一般指的是某一个电路板)都有自己的特殊结构,如物理内存地址,物理I/O地址,显存起始地址等等,
这个结构为struct machine_desc,定义在asm-arm/mach/arch.h:
struct machine_desc {

    /*

     * Note! The first five elements are used

     * by assembler code in head-armv.S

     */

    unsigned int        nr;     /* architecture number  */

    unsigned int        phys_ram;   /* start of physical ram */

    unsigned int        phys_io;    /* start of physical io */

    unsigned int        io_pg_offst;    /* byte offset for io

                         * page tabe entry  */

 

    const char      *name;      /* architecture name    */

    unsigned long       boot_params;    /* tagged list      */

 

    unsigned int        video_start;    /* start of video RAM   */

    unsigned int        video_end;  /* end of video RAM */

 

    unsigned int        reserve_lp0 :1; /* never has lp0    */

    unsigned int        reserve_lp1 :1; /* never has lp1    */

    unsigned int        reserve_lp2 :1; /* never has lp2    */

    unsigned int        soft_reboot :1; /* soft reboot      */

    void            (*fixup)(struct machine_desc *,

                     struct tag *, char **,

                     struct meminfo *);

    void            (*map_io)(void);/* IO mapping function  */

    void            (*init_irq)(void);

    struct sys_timer    *timer;     /* system tick timer    */

    void            (*init_machine)(void);

};

这个结构一般都定义在(arm平台为例)kernel\arch\arm\mach-xxx\xxx.c中,是用宏来定义的,以s3c2410的开发板为例:
定义在kernel\arch\arm\mach-s3c2410\mach-smdk2410.c文件中,如下所示:
MACHINE_START(SMDK2410, "SMDK2410") /* @TODO: request a new identifier and switch to SMDK2410 */

    /* Maintainer: Jonas Dietsche */

    .phys_ram   = S3C2410_SDRAM_PA,

    .phys_io    = S3C2410_PA_UART,

    .io_pg_offst    = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,

    .boot_params    = S3C2410_SDRAM_PA + 0x100,

    .map_io     = smdk2410_map_io,

    .init_irq   = smdk2410_init_irq,

    .timer      = &s3c24xx_timer,

MACHINE_END

这些宏也定义在kernel/include/asm-arm/mach/arch.h中,以MACHINE_START为例:
#define MACHINE_START(_type,_name)      \

const struct machine_desc __mach_desc_##_type   \

 __attribute__((__section__(".arch.info.init"))) = {    \

    .nr     = MACH_TYPE_##_type,    \

    .name       = _name,

 

#define MACHINE_END             \

};

展开之后结构的是:
__mach_desc_SMDK2410= {
 .nr = MACH_TYPE_SMDK2410,
 .name = "SMDK2410",

中间的1__attribute__((__section__(".arch.info"))) = {说明将这个结构放到指定的段.arch.info中,这和前面的
.proc.info
是一个意思,__attribute__((__section__的含义参考GNU手册。后面的宏都是类似的含义,这里就不再一一介绍。

 

下面开始说明源码:

1行实现r3指向3b的地址,3b__lookup_processor_type介绍的第19行,

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

R5= __arch_info_beginr6= __arch_info_endr4=19行的地址

用仿真器查看:

R5= 0xc0018694

R6= 0xc00186cc

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

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

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

7行读取__mach_desc_ SMDK2410结构中的nr参数到r3中,

8行比较r3r1中的机器编号是否相同,
r3
中的nrMACH_TYPE_SMDK2410定义在kernel\include\asm-arm\mach-types.h中:
#define MACH_TYPE_SMDK2410             193

r1中的值是由bootloader传递过来的,这在<<linux启动流程分析(1)---bootloader启动内核过程>>中有说明,如果机器编号相同,跳到14行返回。如果不同则将地址指针增加,在跳到7行继续查找,见10--12行的代码,如果检索完所有的machine_desc仍然没有找到则将r5清零并返回。

/*

 * Lookup machine architecture in the linker-build list of architectures.

 * Note that we can't use the absolute addresses for the __arch_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.

 *

 *  r1 = machine architecture number

 * Returns:

 *  r3, r4, r6 corrupted

 *  r5 = mach_info pointer in physical address space

 */

    .type   __lookup_machine_type, %function

1:  __lookup_machine_type:

2:      adr r3, 3b

3:      ldmia   r3, {r4, r5, r6}

4:      sub r3, r3, r4          @ get offset between virt&phys

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

6:      add r6, r6, r3          @ physical address space

7:  1:  ldr r3, [r5, #MACHINFO_TYPE]    @ get machine type

8:      teq r3, r1              @ matches loader number?

9:      beq 2f              @ found

10:     add r5, r5, #SIZEOF_MACHINE_DESC    @ next machine_desc

11:     cmp r5, r6

12:     blo 1b

13:     mov r5, #0              @ unknown machine

14  2:  mov pc, lr


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