新聞中心

        EEPW首頁 > 嵌入式系統 > 設計應用 > linux啟動流程導讀(arm為例)

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

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

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

        本文引用地址:http://www.104case.com/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 關閉普通中斷,快速中斷,使能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 鏈接地址-實際地址=偏移量

        ==========

        繼續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環境。



        關鍵詞: linux啟動流程ar

        評論


        技術專區

        關閉
        主站蜘蛛池模板: 梅河口市| 舒兰市| 清水县| 平泉县| 四平市| 武安市| 稻城县| 庐江县| 兴宁市| 玉环县| 平乐县| 德令哈市| 枝江市| 诏安县| 聊城市| 花垣县| 修水县| 无锡市| 乌海市| 曲阳县| 云林县| 温泉县| 遵义县| 永顺县| 新绛县| 凯里市| 谷城县| 台北市| 普宁市| 崇仁县| 油尖旺区| 东丽区| 绵竹市| 榆社县| 周宁县| 泸定县| 尼木县| 昌吉市| 满城县| 河北省| 沽源县|