[ 注:内核版本Linux-2.6.30 ]
setup_arch执行是由start_kernel来调用的:
start_kernel [ init/main.c ] --> setup_arch(&command_line) [arch/arm/kernel/setup.c ]
void __init setup_arch(char **cmdline_p) { struct tag *tags = (struct tag *)&init_tags; struct machine_desc *mdesc; char *from = default_command_line; /* [Voice] configuration in defconfig file */ unwind_init(); setup_processor(); mdesc = setup_machine(machine_arch_type); /* [Voice] This get from include/generated/mach-types.h */ machine_name = mdesc->name; if (mdesc->soft_reboot) reboot_setup("s"); if (__atags_pointer) /* [Voice] unsigned int __atags_pointer __initdata;*/ tags = phys_to_virt(__atags_pointer); else if (mdesc->boot_params) tags = phys_to_virt(mdesc->boot_params); /* * If we have the old style parameters, convert them to * a tag list. */ if (tags->hdr.tag != ATAG_CORE) convert_to_tag_list(tags); if (tags->hdr.tag != ATAG_CORE) tags = (struct tag *)&init_tags; if (mdesc->fixup) mdesc->fixup(mdesc, tags, &from, &meminfo); if (tags->hdr.tag == ATAG_CORE) { if (meminfo.nr_banks != 0) squash_mem_tags(tags); save_atags(tags); parse_tags(tags); } init_mm.start_code = (unsigned long) _text; init_mm.end_code = (unsigned long) _etext; init_mm.end_data = (unsigned long) _edata; init_mm.brk = (unsigned long) _end; memcpy(boot_command_line, from, COMMAND_LINE_SIZE); boot_command_line[COMMAND_LINE_SIZE-1] = '\0'; parse_cmdline(cmdline_p, from); paging_init(mdesc); request_standard_resources(&meminfo, mdesc); #ifdef CONFIG_SMP smp_init_cpus(); #endif cpu_init(); /* * Set up various architecture-specific pointers */ init_arch_irq = mdesc->init_irq; system_timer = mdesc->timer; init_machine = mdesc->init_machine; #ifdef CONFIG_VT #if defined(CONFIG_VGA_CONSOLE) conswitchp = &vga_con; #elif defined(CONFIG_DUMMY_CONSOLE) conswitchp = &dummy_con; #endif #endif early_trap_init(); }
1. default_command_line
static char default_command_line[COMMAND_LINE_SIZE] __initdata = CONFIG_CMDLINE;
其中的CONFIG_CMDLINE来自于board的默认配置选项。
2. setup_processor();
首先读取cpuid,read_cpuid_id() --> read_cpuid(CPUID_ID), 其中CPUID_ID为0, 而read_cpuid为一个汇编代码。如下:
#define read_cpuid(reg) \ ({ \ unsigned int __val; \ asm("mrc p15, 0, %0, c0, c0, " __stringify(reg) \ : "=r" (__val) \ : \ : "cc"); \ __val; \ })
然后执行lookup_processor_type(); 其定义在:[ arch/arm/kernel/head-common.S ]
cpu_name, elf_platform, elf_hwcap 变量得到赋值。
接着是: cacheid_init()
读取CPU的cachetype和arch结构,如果arch结构小于ARMv6,则cacheid = CACHEID_VIVT。
最后执行:cpu_proc_init()
[此处比较迷茫]
3. mdesc = setup_machine(machine_arch_type)
machine_arch_type来自于文件:include/generated/mach-types.h [ 此文件是生成文件 ]
这个只是对应一个number,然后通过这个number去查找到相关信息。每一种板子对应于一个特定的number。然后相关的描述来于MACHINE_START和MACHINE_END。
接着:setup_machine --> lookup_machine_type(nr) [ 定义于head.S ]
machine_name 变量得到赋值。
4. phys_to_virt(mdesc->bootparams)
phys_to_virt(mdesc->bootparams) --> __phys_to_virt((usigned long)(x)) --> ((x) - PHYS_OFFSET + PAGE_OFFSET)
#ifndef PHYS_OFFSET
#define PHYS_OFFSET (CONFIG_DRAM_BASE)
#endif
#ifndef PAGE_OFFSET
#define PAGE_OFFSET (PHYS_OFFSET)
#endif
5. _text, _etext, _edata, _end
这四个参数来自于文件:[ arch/arm/kernel/vmlinux.lds.S ]
init_mm部份参数得到赋值。
6. parse_cmdline(cmdline_p, from)
7. paging_init(mdesc)
pageing_init() sets up the page tables, initialises the zone memory maps, and sets up the zero page, bad page and bad page tables.
8. request_standard_resources(&meminfo, mdesc)
9. cpu_init()
10. CONFIG_VT && CONFIG_DUMMY_CONSOLE
conswitchp = &dummy_con; [ conswitchp ==> drivers/char/vt.c;dummy_con ==> driver/video/console/dummycon.c ]
11. early_trap_init() [ arch/arm/kernel/traps.c ]