[ 注:内核版本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 ]