Linux启动中setup_arch分析

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


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值