arm linux 内核启动,ARM Linux内核启动(1)

通过分析可知ARM-linux内核的启动分为两个过程,首先,自解压内核到内存中;其次,跳转到解压缩之后的内核运行。压缩内核的启动部分在 linux/arch/arm/boot/compressed/head.S和arch\arm\boot\compressed\misc.c两个文件中。而分压缩内核的启动部分,是真正的linux内核的入口,在linux/arch/arm/kernel/head.S文件中。源码如下:我们一段段的列出:

/*

* Kernel startup entry point.

* ---------------------------

*

* This is normally called from the decompressor code.  The requirements

* are: MMU = off, D-cache = off, I-cache = dont care, r0 = 0,

* r1 = machine nr.进入时的条件

*

* This code is mostly position independent, so if you link the kernel at

* 0xc0008000, you call this at __pa(0xc0008000).

*

* See linux/arch/arm/tools/mach-types for the complete list of machine

* numbers for r1.

*

* We're trying to keep crap to a minimum; DO NOT add any machine specific

* crap here - that's what the boot loader (or in extreme, well justified

* circumstances, zImage) is for.

*/

__INIT

.typestext, #function

ENTRY(stext)

movr12, r0

movr0, #PSR_F_BIT | PSR_I_BIT | MODE_SVC@ make sure svc mode确定SVC模式

msrcpsr_c, r0@ and all irqs disabled关闭所有中断

bl__lookup_processor_type跳转到查找处理器函数段

teqr10, #0@ invalid processor?判断是否是无效处理器

moveqr0, #'p'@ yes, error 'p'

beq__error

bl__lookup_architecture_type跳转到查找结构函数段

teqr7, #0@ invalid architecture?

moveqr0, #'a'@ yes, error 'a'

beq__error

bl__create_page_tables建立页表

/*

* The following calls CPU specific code in a position independent

* manner.  See arch/arm/mm/proc-*.S for details.r10 = base of

* xxx_proc_info structure selected by __lookup_architecture_type

* above. On return, the CPU will be ready for the MMU to be

* turned on, and r0 will hold the CPU control register value.

*/注释说的很详细。此时CPU已经准备好打开MMU,r0保存CPU控制寄存器的值

adrlr, __turn_mmu_on@ return (PIC) address

addpc, r10, #12

.type__switch_data, %object

__switch_data:

.long__mmap_switched

.long__data_loc@ r2

.long__data_start@ r3

.long__bss_start@ r4

.long_end@ r5

.longprocessor_id@ r6

.long__machine_arch_type@ r7

.longcr_alignment@ r8

.longinit_thread_union+8192@ sp

/*

*Enable the MMU. This completely changes the structure of the visible

* memory space.  这将完全改变可见存储空间的结构

*/

.align 5

.type__turn_mmu_on, %function

__turn_mmu_on:

ldrlr, __switch_data

#ifdef CONFIG_ALIGNMENT_TRAP

orrr0, r0, #2@ ...........A.

#endif

mcrp15, 0, r0, c1, c0, 0@ write control reg

mrcp15, 0, r3, c0, c0, 0@ read id reg

movr3, r3

movr3, r3

movpc, lr

/*

* The following fragment of code is executed with the MMU on, and uses

* absolute addresses; this is not position independent.下面代码在MMU打开的情况下运行,用绝对地址,与位置无关

*

*  r0  = processor control register

*  r1  = machine ID机器ID

*  r9  = processor ID处理器ID

*  r12 = value of r0 when kernel was called (currently always zero)

*/

这里主要是为调用c函数start_kernel做准备。

.align 5

__mmap_switched:

adrr2, __switch_data + 4

ldmiar2, {r2, r3, r4, r5, r6, r7, r8, sp}

cmpr2, r3@ Copy data segment if needed

1:cmpne r3, r4

ldrnefp, [r2], #4

strnefp, [r3], #4

bne1b

movfp, #0@ Clear BSS (and zero fp)

1:cmp r4, r5

strccfp, [r4],#4

bcc1b

strr9, [r6]@ Save processor ID

strr1, [r7]@ Save machine type

bicr2, r0, #2@ Clear 'A' bit

stmiar8, {r0, r2}@ Save control register values

bstart_kernel

内核编译连接过程的连接脚本是vmlinux.lds文件,ARM是arch\arm\kernel\vmlinux.lds.S,列出部分,如下所示:

OUTPUT_ARCH(arm)

ENTRY(stext)

#ifndef __ARMEB__

jiffies = jiffies_64;

#else

jiffies = jiffies_64 + 4;

#endif

SECTIONS

{

. = TEXTADDR;内核启动的虚拟地址,为0xc0008000

.init : { /* Init code and data*/

_stext = .;

_sinittext = .;

*(.init.text)

_einittext = .;

__proc_info_begin = .;

*(.proc.info)

__proc_info_end = .;

__arch_info_begin = .;

*(.arch.info)

__arch_info_end = .;

__tagtable_begin = .;

*(.taglist)

__tagtable_end = .;

. = ALIGN(16);

__setup_start = .;

*(.init.setup)

__setup_end = .;

__early_begin = .;

*(__early_param)

__early_end = .;

__initcall_start = .;

*(.initcall1.init)

*(.initcall2.init)

*(.initcall3.init)

*(.initcall4.init)

*(.initcall5.init)

*(.initcall6.init)

*(.initcall7.init)

__initcall_end = .;

__con_initcall_start = .;

*(.con_initcall.init)

__con_initcall_end = .;

__security_initcall_start = .;

*(.security_initcall.init)

__security_initcall_end = .;

. = ALIGN(32);

__initramfs_start = .;

usr/built-in.o(.init.ramfs)

__initramfs_end = .;

. = ALIGN(64);

__per_cpu_start = .;

*(.data.percpu)

__per_cpu_end = .;

#ifndef CONFIG_XIP_KERNEL

__init_begin = _stext;

*(.init.data)

. = ALIGN(4096);

__init_end = .;

#endif

zImage是由生成的vmlinux再经过压缩生成的,此时的连接脚本是\arch\arm\boot\compressed\vmlinux.lds,内容如下:

*/

OUTPUT_ARCH(arm)

ENTRY(_start)

SECTIONS

{

. = TEXT_START;内核RAM启动的偏移地址,这个地址是物理地址。

在\arch\arm\boot\compressed\Makefile中有如下

SEDFLAGS= s/TEXT_START/$(ZTEXTADDR)/;s/BSS_START/$(ZBSSADDR)/使得TEXT_START=ZTEXTADDR。  _text = .;

.text : {

_start = .;

*(.start)

*(.text)

*(.fixup)

*(.gnu.warning)

*(.rodata)

*(.rodata.*)

*(.glue_7)

*(.glue_7t)

*(.piggydata)

. = ALIGN(4);

}

这篇先到这里,下篇再说。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值