linux-2.6.22.6分析(二)启动流程之第一阶段

内核的启动也可以分为两个阶段

第一阶段是用汇编写的,主要是判断是否支持CPU、单板、创建页表等

第二阶段是用C语言写的,主要是处理u-boot传递的参数,挂接根文件系统,调用应用程序等

 

本节简要分析启动流程的第一阶段,代码是内核链接的第一个文件arch/arm/kernel/head.S

1、判断内核是否支持cpu

	mrc	p15, 0, r9, c0, c0		@ get processor id	
	bl	__lookup_processor_type		@ r5=procinfo r9=cpuid	 	

	/* 读取机器 id,判断内核是否支持	*/	
	movs	r10, r5				@ invalid processor (r5=0)?
	beq	__error_p			@ yes, error 'p'		

 

2、判断内核是否支持单板

要支持某块单板,要在内核的arch目录下提供一个machine_desc结构体,它的段属性是.arch.info.init,在判断是否支持单板的时候,内核会从这个段中查找相应结构体,如果找到,则表明支持单板

	bl	__lookup_machine_type		@ r5=machinfo
	movs	r8, r5				@ invalid machine (r5=0)?
	beq	__error_a			@ yes, error 'a'

其中__lookup_machine_type函数位于同目录下的head-common.S中,该文件部分代码如下

3:	.long	.	/*虚拟地址*/
	.long	__arch_info_begin		/*机器ID起始地址*/
	.long	__arch_info_end		/*机器ID结束地址*/

/*__arch_info_begin、__arch_info_end定义在链接脚本:*/
  __arch_info_begin = .;
  *(.arch.info.init)
 __arch_info_end = .;


__lookup_machine_type:
	/* 获得代码段标号3的地址(实际的物理地址),存入r3*/	
	adr	r3, 3b
	/* 取r3、r3+4、r3+8地内容存入r4、r5、r6 */
	ldmia	r3, {r4, r5, r6}	//r4、r5、r6都是虚拟地址
	/* 计算偏移量 */
	sub	r3, r3, r4			@ get offset between virt&phys
	/* 根据偏移量,把虚拟地址转换成实际地址 */
	add	r5, r5, r3			@ convert virt addresses to
	add	r6, r6, r3			@ physical address space
	/* 比较机器id */
1:	ldr	r3, [r5, #MACHINFO_TYPE]	@ get machine type
	teq	r3, r1				@ matches loader number?
	beq	2f				@ found
	add	r5, r5, #SIZEOF_MACHINE_DESC	@ next machine_desc
	cmp	r5, r6
	blo	1b
	mov	r5, #0				@ unknown machine
2:	mov	pc, lr

 

以arch/arm/mach-s3c2440/mach-smdk2440.c为例,其中定义的machine_desc结构体是:

MACHINE_START(S3C2440, "SMDK2440")
	/* Maintainer: Ben Dooks <ben@fluff.org> */
	.phys_io	= S3C2410_PA_UART,
	.io_pg_offst	= (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,
	.boot_params	= S3C2410_SDRAM_PA + 0x100,

	.init_irq	= s3c24xx_init_irq,
	.map_io		= smdk2440_map_io,
	.init_machine	= smdk2440_machine_init,
	.timer		= &s3c24xx_timer,
MACHINE_END

所用到的宏定义于include/asm-arm/mach/arch.h:

#define MACHINE_START(_type,_name)			\
static const struct machine_desc __mach_desc_##_type	\
 __used							\
 __attribute__((__section__(".arch.info.init"))) = {	\
	.nr		= MACH_TYPE_##_type,		\
	.name		= _name,

#define MACHINE_END				\
};

 

将宏展开后:

static const struct machine_desc __mach_desc_S3C2440	\
 __used							\
 __attribute__((__section__(".arch.info.init"))) = {	\
	.nr		= MACH_TYPE_S3C2440,		\
	.name		= “SMDK2440”,

	.phys_io	= S3C2410_PA_UART,
	.io_pg_offst	= (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,
	.boot_params	= S3C2410_SDRAM_PA + 0x100,

	.init_irq	= s3c24xx_init_irq,
	.map_io		= smdk2440_map_io,
	.init_machine	= smdk2440_machine_init,
	.timer		= &s3c24xx_timer,
};

其中

.nr就是单板的ID,用于使内核支持该单板

 

3、创建页表

	bl	__create_page_tables

 

4、保存__mmap_switched的地址,使能mmu后跳转过去

	ldr	r13, __switch_data		@ address to jump to after
        /*使能mmu*/
	adr	lr, __enable_mmu		@ return (PIC) address

其中__switch_data:

__switch_data:
	.long	__mmap_switched
	.long	__data_loc			@ r4
	.long	__data_start			@ r5
	.long	__bss_start			@ r6
	.long	_end				@ r7
	.long	processor_id			@ r4
	.long	__machine_arch_type		@ r5
	.long	cr_alignment			@ r6
	.long	init_thread_union + THREAD_START_SP @ sp

 

而在__mmap_switched程序段,内核会调用start_kernel,进入启动的第二阶段

__mmap_switched:
	adr	r3, __switch_data + 4
        /* 拷贝数据段 */
	ldmia	r3!, {r4, r5, r6, r7}
	cmp	r4, r5				@ Copy data segment if needed
1:	cmpne	r5, r6
	ldrne	fp, [r4], #4
	strne	fp, [r5], #4
	bne	1b

        /* 清除bss段 */
	mov	fp, #0				@ Clear BSS (and zero fp)
1:	cmp	r6, r7
	strcc	fp, [r6],#4
	bcc	1b

        /* 保存CPU id、单板 id,清除累加器,保存控制寄存器的值 */
	ldmia	r3, {r4, r5, r6, sp}
	str	r9, [r4]			@ Save processor ID
	str	r1, [r5]			@ Save machine type
	bic	r4, r0, #CR_A			@ Clear 'A' bit
	stmia	r6, {r0, r4}			@ Save control register values
	b	start_kernel

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值