原文地址:http://www.eetop.cn/blog/html/45/11145-1512.html
================================
Author: taoyuetao
Email:[email protected]
Blog:http://www.eetop.cn/blog/?11145
2007-03-08
================================
前一篇介紹了彙編函數__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 four elements are used
* by assembler code in head-armv.S
*/
unsigned intnr;/* architecture number*/
unsigned intphys_ram;/* start of physical ram */
unsigned intphys_io;/* start of physical io*/
unsigned intio_pg_offst;/* byte offset for io page table entry*/
const char*name;/* architecture name*/
unsigned intparam_offset;/* parameter page*/
unsigned intvideo_start;/* start of video RAM*/
unsigned intvideo_end;/* end of video RAM*/
unsigned intreserve_lp0 :1;/* never has lp0*/,
unsigned intreserve_lp1 :1;/* never has lp1*/
unsigned intreserve_lp2 :1;/* never has lp2*/
unsigned intsoft_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);
};
這個結構一般都定義在(以arm平臺爲例)kernel/arch/arm/mach-xxx/xxx.c中,是用宏來定義的,以mainstone的開發板爲例:
定義在kernel/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
這些宏也定義在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"))) = { /
.nr = MACH_TYPE_##_type, /
.name = _name,
展開之後結構的是:
__mach_desc_MAINSTONE = {
.nr = MACH_TYPE_MAINSTIONE,
.name = "Intel DBBVA0 Development Platform",
中間的1行__attribute__((__section__(".arch.info"))) = {說明將這個結構放到指定的段.arch.info中,這和前面的
.proc.info是一個意思,__attribute__((__section__的含義參考GNU
手冊。後面的宏都是類似的含義,這裏就不再一一
介紹。下面開始說明源碼:
第1行實現r4指向2b的地址,2b如__lookup_processor_type介紹的第19行,將machine_desc結構中的數據存放到r2, r3, r5, r6, r7。
讀取__mach_desc_MAINSTONE結構中的nr參數到r5中,如第7行,比較r5和r1中的機器編號是否相同,如第8行,
r5中的nr值MACH_TYPE_MAINSTONE定義在kernel/include/asm-arm/mach-types.h中:
#define MACH_TYPE_MAINSTONE 303
r1中的值是由bootloader
傳遞過來的,這在<<linux啓動流程分析(1)---bootloader啓動內核過程>>中有說明,
如果機器編號相同,跳到15行執行,r5=intphys_ram,r6=intphys_io,r7=intio_pg_offst,並返回。如果
不同則將地址指針增加,在跳到7行繼續查找,如10--12行的代碼,如果檢索完所有的machine_desc仍然沒
有找到則將r7清零並返回。
/*
* 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:
* r2, r3, r4 corrupted
* r5 = physical start address of RAM
* r6 = physical address of IO
* r7 = byte offset into page tables for IO
*/
1 __lookup_architecture_type:
2 adr r4, 2b
3 ldmia r4, {r2, r3, r5, r6, r7} @ throw away r2, r3
4 sub r5, r4, r5 @ convert addresses
5 add r4, r6, r5 @ to our address space
6 add r7, r7, r5
7 1: ldr r5, [r4] @ get machine type
8 teq r5, r1
9 beq 2f
10 add r4, r4, #SIZEOF_MACHINE_DESC
11 cmp r4, r7
12 blt 1b
13 mov r7, #0 @ unknown architecture
14 mov pc, lr
15 2: ldmib r4, {r5, r6, r7} @ found, get results
16 mov pc, lr