新聞中心

EEPW首頁 > 嵌入式系統(tǒng) > 設(shè)計應(yīng)用 > linux啟動流程導(dǎo)讀(arm為例)

linux啟動流程導(dǎo)讀(arm為例)

作者: 時間:2016-11-20 來源:網(wǎng)絡(luò) 收藏
arm為例,分析一下kernel的啟動過程;

內(nèi)核版本:linux-3.2.tar.gz

本文引用地址:http://butianyuan.cn/article/201611/318983.htm

一、arch/arm/kernel/head.s


.arm

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

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

setmode PSR_F_BIT | PSR_I_BIT | SVC_MODE, r9 @ ensure svc mode 關(guān)閉普通中斷,快速中斷,使能svc模式
@ and irqs disabled
mrc p15, 0, r9, c0, c0 @ get processor id 獲得芯片ID
bl __lookup_processor_type @ r5=procinfo r9=cpuid 獲得處理器型號,r5 == id,#1
movs r10, r5 @ invalid processor (r5=0)? 校驗正確性,0錯誤
THUMB( it eq ) @ force fixup-able long branch encoding
beq __error_p @ yes, error p

#ifndef CONFIG_XIP_KERNEL
adr r3, 2f
ldmia r3, {r4, r8}
sub r4, r3, r4 @ (PHYS_OFFSET - PAGE_OFFSET)

add r8, r8, r4 @ PHYS_OFFSET

==========

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

==========


__CPUINIT
__lookup_processor_type:
adr r3, __lookup_processor_type_data @adr 相對偏移讀取,讀取下面type_data地址
ldmia r3, {r4 - r6} @將該地址存放的值 放入r4(.),r5(begin),r6(end)
sub r3, r3, r4 @ get offset between virt&phys 鏈接地址-實際地址=偏移量

==========

繼續(xù)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:
tst r2, #0x3 @ aligned? 不對其就返回
bne 1f

ldr r5, [r2, #0] @讀到r5
#ifdef CONFIG_OF_FLATTREE
ldr r6, =OF_DT_MAGIC @ is it a DTB? 過濾DTB
cmp r5, r6
beq 2f
#endif
cmp r5, #ATAG_CORE_SIZE @ is first tag ATAG_CORE? must be first
cmpne r5, #ATAG_CORE_SIZE_EMPTY
bne 1f
ldr r5, [r2, #4]
ldr r6, =ATAG_CORE
cmp r5, r6
bne 1f

2: mov pc, lr @ atag/dtb pointer is ok

1: mov r2, #0
mov pc, lr
ENDPROC(__vet_atags)

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

@#2:__create_page_tables

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


__create_page_tables:
pgtbl r4, r8 @ page table address

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



ldr r13, =__mmap_switched @ address to jump to after
@ mmu has been enabled
adr lr, BSYM(1f) @ return (PIC) address
mov r8, r4 @ set TTBR1 to swapper_pg_dir
ARM( add pc, r10, #PROCINFO_INITFUNC )
THUMB( add r12, r10, #PROCINFO_INITFUNC )
THUMB( mov pc, r12 )
1: b __enable_mmu

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

進入enable_mmu


__enable_mmu:
#if defined(CONFIG_ALIGNMENT_TRAP) && __LINUX_ARM_ARCH__ < 6
orr r0, r0, #CR_A
#else
bic r0, r0, #CR_A
#endif
#ifdef CONFIG_CPU_DCACHE_DISABLE
bic r0, r0, #CR_C
#endif
#ifdef CONFIG_CPU_BPREDICT_DISABLE
bic r0, r0, #CR_Z
#endif
#ifdef CONFIG_CPU_ICACHE_DISABLE
bic r0, r0, #CR_I
#endif
mov r5, #(domain_val(DOMAIN_USER, DOMAIN_MANAGER) |
domain_val(DOMAIN_KERNEL, DOMAIN_MANAGER) |
domain_val(DOMAIN_TABLE, DOMAIN_MANAGER) |
domain_val(DOMAIN_IO, DOMAIN_CLIENT))
mcr p15, 0, r5, c3, c0, 0 @ load domain access register
mcr p15, 0, r4, c2, c0, 0 @ load page table pointer
b __turn_mmu_on
ENDPROC(__enable_mmu)

==========


.align 5
__turn_mmu_on:
mov r0, r0
mcr p15, 0, r0, c1, c0, 0 @ write control reg
mrc p15, 0, r3, c0, c0, 0 @ read id reg
mov r3, r3
mov r3, r13 //跳回r13,=__mmap_switched
mov pc, r3
__enable_mmu_end:
ENDPROC(__turn_mmu_on)

==========

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


__INIT
__mmap_switched:
adr r3, __mmap_switched_data

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

mov fp, #0 @ Clear BSS (and zero fp)
1: cmp r6, r7
strcc fp, [r6],#4
bcc 1b

ARM( ldmia r3, {r4, r5, r6, r7, sp})
THUMB( ldmia r3, {r4, r5, r6, r7} )
THUMB( ldr sp, [r3, #16] )
str r9, [r4] @ Save processor ID
str r1, [r5] @ Save machine type
str r2, [r6] @ Save atags pointer
bic r4, r0, #CR_A @ Clear A bit
stmia r7, {r0, r4} @ Save control register values
b start_kernel
ENDPROC(__mmap_switched)

===========

絕對地址操作,copy data,bss清空,跳入start_kernel,進入c環(huán)境。



關(guān)鍵詞: linux啟動流程ar

評論


技術(shù)專區(qū)

關(guān)閉