分类: LINUX
2011-02-22 21:33:48
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_MAINSTONE在include/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
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_end,r3=__proc_info_begin,r5=标号2(line498)的地址,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时传递给r1为machine ID)相匹配的机器类型信息。如果有匹配的,则进入line531,如果遍历完所有注册的机器信息都与r1的值不匹配,则进入line529。
Line529~530:置r7为0返回,作为平台不支持的标志。
Line531~532:从.arch.info section中获取平台信息,r5=start of physical ram, r6=start of physical io,r7= byte offset into page tables for IO ,然后返回。
该段__lookup_architecture_type函数完成后,各寄存器情况如下:
r5 = 内存(SDRAM)的起始物理地址
r6 = IO的起始物理地址
r7 = IO虚拟地址在页表中的索引项