您的位置:首页 > 运维架构 > Linux

Linux启动中setup_arch分析

2011-09-02 15:46 609 查看
[ 注:内核版本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 ]
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐