新闻中心

EEPW首页>嵌入式系统>设计应用> linux启动流程导读(arm为例)

linux启动流程导读(arm为例)

作者: 时间:2016-11-20 来源:网络 收藏
arm为例,分析一下kernel的启动过程;

内核版本:linux-3.2.tar.gz

本文引用地址://m.amcfsurvey.com/article/201611/318983.htm

一、arch/arm/kernel/head.s


.arm

__HEAD@#define __HEAD.section ".head.text","ax"
ENTRY(stext)

THUMB(adrr9, BSYM(1f))@ Kernel is always entered in ARM.
THUMB(bxr9)@ If this is a Thumb-2 kernel,
THUMB(.thumb)@ switch to Thumb now.
THUMB(1:)

setmodePSR_F_BIT | PSR_I_BIT | SVC_MODE, r9 @ ensure svc mode关闭普通中断,快速中断,使能svc模式
@ and irqs disabled
mrcp15, 0, r9, c0, c0@ get processor id获得芯片ID
bl__lookup_processor_type@ r5=procinfo r9=cpuid 获得处理器型号,r5 == id,#1
movsr10, r5@ invalid processor (r5=0)?校验正确性,0错误
THUMB( iteq )@ force fixup-able long branch encoding
beq__error_p@ yes, error p

#ifndef CONFIG_XIP_KERNEL
adrr3, 2f
ldmiar3, {r4, r8}
subr4, r3, r4@ (PHYS_OFFSET - PAGE_OFFSET)

addr8, r8, r4@ PHYS_OFFSET

==========

#1 :arch/arm/kernel/head-common.h

==========


__CPUINIT
__lookup_processor_type:
adrr3, __lookup_processor_type_data@adr 相对偏移读取,读取下面type_data地址
ldmiar3, {r4 - r6}@将该地址存放的值 放入r4(.),r5(begin),r6(end)
subr3, r3, r4@ get offset between virt&phys链接地址-实际地址=偏移量

==========

继续arch/arm/kernel/head.s

==========


bl__vet_atags@#1,head-common.s
#ifdef CONFIG_SMP_ON_UP
bl__fixup_smp@略
#endif
#ifdef CONFIG_ARM_PATCH_PHYS_VIRT
bl__fixup_pv_table@略
#endif
bl__create_page_tables@#2

==========

#1 :arch/arm/kernel/head-common.h

==========


__vet_atags:
tstr2, #0x3@ aligned? 不对其就返回
bne1f

ldrr5, [r2, #0]@读到r5
#ifdef CONFIG_OF_FLATTREE
ldrr6, =OF_DT_MAGIC@ is it a DTB?过滤DTB
cmpr5, r6
beq2f
#endif
cmpr5, #ATAG_CORE_SIZE@ is first tag ATAG_CORE? must be first
cmpner5, #ATAG_CORE_SIZE_EMPTY
bne1f
ldrr5, [r2, #4]
ldrr6, =ATAG_CORE
cmpr5, r6
bne1f

2:movpc, lr@ atag/dtb pointer is ok

1:movr2, #0
movpc, lr
ENDPROC(__vet_atags)

============

@#2:__create_page_tables

============


__create_page_tables:
pgtblr4, r8@ page table address

============



ldrr13, =__mmap_switched@ address to jump to after
@ mmu has been enabled
adrlr, BSYM(1f)@ return (PIC) address
movr8, r4@ set TTBR1 to swapper_pg_dir
ARM(addpc, r10, #PROCINFO_INITFUNC)
THUMB(addr12, r10, #PROCINFO_INITFUNC)
THUMB(movpc, r12)
1:b__enable_mmu

============

进入enable_mmu


__enable_mmu:
#if defined(CONFIG_ALIGNMENT_TRAP) && __LINUX_ARM_ARCH__ < 6
orrr0, r0, #CR_A
#else
bicr0, r0, #CR_A
#endif
#ifdef CONFIG_CPU_DCACHE_DISABLE
bicr0, r0, #CR_C
#endif
#ifdef CONFIG_CPU_BPREDICT_DISABLE
bicr0, r0, #CR_Z
#endif
#ifdef CONFIG_CPU_ICACHE_DISABLE
bicr0, r0, #CR_I
#endif
movr5, #(domain_val(DOMAIN_USER, DOMAIN_MANAGER) |
domain_val(DOMAIN_KERNEL, DOMAIN_MANAGER) |
domain_val(DOMAIN_TABLE, DOMAIN_MANAGER) |
domain_val(DOMAIN_IO, DOMAIN_CLIENT))
mcrp15, 0, r5, c3, c0, 0@ load domain access register
mcrp15, 0, r4, c2, c0, 0@ load page table pointer
b__turn_mmu_on
ENDPROC(__enable_mmu)

==========


.align5
__turn_mmu_on:
movr0, r0
mcrp15, 0, r0, c1, c0, 0@ write control reg
mrcp15, 0, r3, c0, c0, 0@ read id reg
movr3, r3
movr3, r13//跳回r13,=__mmap_switched
movpc, r3
__enable_mmu_end:
ENDPROC(__turn_mmu_on)

==========

#arch/arm/kernel/head-common.s


__INIT
__mmap_switched:
adrr3, __mmap_switched_data

ldmiar3!, {r4, r5, r6, r7}
cmpr4, r5@ Copy data segment if needed
1:cmpner5, r6
ldrnefp, [r4], #4
strnefp, [r5], #4
bne1b

movfp, #0@ Clear BSS (and zero fp)
1:cmpr6, r7
strccfp, [r6],#4
bcc1b

ARM(ldmiar3, {r4, r5, r6, r7, sp})
THUMB(ldmiar3, {r4, r5, r6, r7})
THUMB(ldrsp, [r3, #16])
strr9, [r4]@ Save processor ID
strr1, [r5]@ Save machine type
strr2, [r6]@ Save atags pointer
bicr4, r0, #CR_A@ Clear A bit
stmiar7, {r0, r4}@ Save control register values
bstart_kernel
ENDPROC(__mmap_switched)

===========

绝对地址操作,copy data,bss清空,跳入start_kernel,进入c环境。



关键词:linux启动流程ar

评论


技术专区

关闭