Chinaunix首页 | 论坛 | 博客
  • 博客访问: 963754
  • 博文数量: 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:33:48

ARM linux 内核启动分析(3)

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

分支2: __lookup_architecture_type函数分析

 

       __lookup_processor_type类似,__loop_architecture_type会根据bootloader引导linux kernel时传递给r1寄存器的平台类型(machine ID),查找Linux kernl中是否有对这个平台的支持,查找的位置就是下面将会说到的.arch.info section中,这与__lookup_processor_type.proc.info sesction查找类似。

Kernel定义平台通常是使用MACHINE_START宏,其定义在include/asm-arm/mach/arch.h中:

#define MACHINE_START(_type,_name)              \

const struct machine_desc __mach_desc_##_type   \

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

        .nr             = MACH_TYPE_##_type,    \

        .name           = _name,

__attribute__((__section__(".arch.info"))) 的含义是把这个结构(struct machine_desc)放到.arch.info section

 

其中的struct machine_desc结构也是定义在asm-arm/mach/arch.h:

struct machine_desc {

        /*

         * Note! The first four 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 int            param_offset;   /* parameter page       */

 

        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 param_struct *, char **,

                                         struct meminfo *);

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

        void                    (*init_irq)(void);

};

asm-arm/mach/arch.h除了定义了MACHINE_START宏外,还定义了一系列的宏用来填充struct machine_desc结构的信息。如果我们要添加一个新的平台支持的话,一般都是在arch/arm/mach-xxx/目录下某一文件通过上述这些宏来定义平台信息,使之在编译时把struct machine_desc结构放到.arch.info section,以供__lookup_processor_type函数来查询是否与当前运行的平台匹配。

mainstone平台为例,在arch/arm/mach-pxa/mainstone.c中有:

MACHINE_START(MAINSTONE, "Intel DBBVA0 Development Platform")

        MAINTAINER("MontaVista Software Inc.")

        BOOT_MEM(0xa0000000, 0x40000000, io_p2v(0x40000000))

        FIXUP(fixup_mainstone)

        MAPIO(mainstone_map_io)

        INITIRQ(mainstone_init_irq)

MACHINE_END

经过宏替换后,相当于定义了编号为MACH_TYPE_MAINSTONE的平台,MACH_TYPE_MAINSTONEinclude/asm-arm/mach-types.h文件中被定义,此文件是编译内核时Makefile脚本根据arch/arm/tools/mach-types文件生成的,make clean会删除mach-types.h文件,所以,要想添加新的平台号的支持,需要修改arch/arm/tools/mach-types文件,而不能直接修改include/asm-arm/mach-types.h

 

接下来,来看实际的源码:

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

 

504 /*

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

506  * Note that we can't use the absolute addresses for the __arch_info

507  * lists since we aren't running with the MMU on (and therefore, we are

508  * not in the correct address space).  We have to calculate the offset.

509  *

510  *  r1 = machine architecture number

511  * Returns:

512  *  r2, r3, r4 corrupted

513  *  r5 = physical start address of RAM

514  *  r6 = physical address of IO

515  *  r7 = byte offset into page tables for IO

516  */

517 __lookup_architecture_type:

    518                 adr     r4, 2b

    519                 ldmia   r4, {r2, r3, r5, r6, r7}        @ throw away r2, r3

    520                 sub     r5, r4, r5                      @ convert addresses

    521                 add     r4, r6, r5                      @ to our address space

    522                 add     r7, r7, r5

    523 1:              ldr     r5, [r4]                        @ get machine type

    524                 teq     r5, r1

    525                 beq     2f

    526                 add     r4, r4, #SIZEOF_MACHINE_DESC

    527                 cmp     r4, r7

    528                 blt     1b

    529                 mov     r7, #0                          @ unknown architecture

    530                 mov     pc, lr

    531 2:              ldmib   r4, {r5, r6, r7}                @ found, get results

    532                 mov     pc, lr

 

Line518:把标号2的地址(2b指的是前面__lookup_processor_type代码处的标号2——line498)放入r4寄存器。

Line519:执行的结果是:r2=__proc_info_endr3=__proc_info_beginr5=标号2line498)的地址,r6= __arch_info_begin r7= __arch_info_end。在这里,主要是想获得__arch_info_start__arch_info_end的地址,所以r2, r3的值没有用处。

Line520~522执行的结果是r4=__arch_info_begin r7= __arch_info_end

Line523~528:是一个循环比较的过程,在.arch.info section中从__arch_info_begin开始的地址中获得machine ID,查找与r1中的值(bootloader 引导kernel时传递给r1machine ID)相匹配的机器类型信息。如果有匹配的,则进入line531,如果遍历完所有注册的机器信息都与r1的值不匹配,则进入line529

Line529530:置r7为0返回,作为平台不支持的标志。

Line531~532:从.arch.info section中获取平台信息,r5start of physical ram, r6start of physical ior7= byte offset into page tables for IO ,然后返回。

该段__lookup_architecture_type函数完成后,各寄存器情况如下:

r5 = 内存(SDRAM)的起始物理地址

r6 = IO的起始物理地址

r7 = IO虚拟地址在页表中的索引项

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