LINUX中的MACH定義之MACHINE_START / MACHINE_END
田海立@CSDN
2011/08/18
本文講解LINUX中用MACHINE_START/MACHINE_END定義的MACH,並給出定義的各個成員函數在初始化過程中被調用的時機。
1. 定義一個MACH
LINUX中MACHINE定義是用MACHINE_START()/MACHINE_END兩個宏來實現的,比如MSM的實現(arch/arm/mach-msm/board-halibut.c):
MACHINE_START(HALIBUT,"Halibut Board (QCT SURF7200A)") .boot_params = 0x10000100, .map_io = halibut_map_io, .init_irq = halibut_init_irq, .init_machine = halibut_init, .timer = &msm_timer,MACHINE_END
2. MACHINE_START / MACHINE_END定義
上面的定義中,用到了這兩個宏MACHINE_START/MACHINE_END,下面是它們具體的定義(在arch/arm/include/asm/mach/arch.h中):
#defineMACHINE_START(_type,_name) \static const structmachine_desc __mach_desc_##_type \ __used \ __attribute__((__section__(".arch.info.init")))= { \ .nr = MACH_TYPE_##_type, \ .name = _name, #define MACHINE_END \};
struct machine_desc也是定義在arch/arm/include/asm/mach/arch.h
struct machine_desc { /* * Note! The firstfour elements are used * by assembler codein head.S, head-common.S */ unsigned int nr; /* architecture number */ 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);};
3. MACH HALIBUT的定義
把1中定義的MACH展開之後,得到:
struct machine_desc __mach_desc_HALIBUT{__used __attribute__((__section__(".arch.info.init")))= { .nr = MACH_TYPE_HALIBUT, .name = "HalibutBoard (QCT SURF7200A)", .boot_params = 0x10000100, .map_io = halibut_map_io, .init_irq = halibut_init_irq, .init_machine = halibut_init, .timer = &msm_timer,};
總結一下:MACHINE_START主要是定義了"struct machine_desc"的類型,放在 section(".arch.info.init"),是初始化資料,Kernel 起來之後將被丟棄。
4. 成員函數被調用的時機
在setup_arch() [setup.c#758~760]中init_irq, timer & init_machine分別被賦值給下列變數:
init_arch_irq = mdesc->init_irq;
system_timer = mdesc->timer;
init_machine = mdesc->init_machine;
而這三個函數指標是在下列情境中被調用的:
1) start_kernel()[main.c#589]-> init_IRQ() [irq.c] ->init_arch_irq();
2) start_kernel()[main.c#595]->time_init () [time.c] ->system_time->init();
3) customize_machine()[setup.c#692] -> init_machine();
customize_machine是被放在arch_initcall段的,按照順序被調用。xxx_initcall段內的函數是按下列順序被調用的:start_kernel() [main.c#682] -> rest_init() [啟動核心線程]-> kernel_init() –> do_basic_setup()-> do_initcalls();
map_io是在下列順序中被調用
4) start_kernel()[main.c#546]-> setup_arch () [setup.c#745] -> paging_init() [mmu.c#1028] -> devicemaps_init()[mmu.c#993] -> map_io()
從它們在start_kernel()中被調用的順序,可知它們執行的先後為:map_io; init_irq; timer->time_init; init_machine。
*** 歡迎轉載,並請註明原文來自http://blog.csdn.net/thl789/article/details/6699259 ***