新聞中心

        EEPW首頁 > 嵌入式系統 > 設計應用 > arm linux 從入口到start_kernel 代碼分析 - 7(end)

        arm linux 從入口到start_kernel 代碼分析 - 7(end)

        作者: 時間:2016-11-10 來源:網絡 收藏
        6. 切換數據

        在 arch/arm/kernel/head-common.S 中:

        本文引用地址:http://www.104case.com/article/201611/317207.htm

        00014: .type__switch_data, %object
        00015: __switch_data:
        00016: .long__mmap_switched
        00017: .long__data_loc@ r4
        00018: .long__data_start@ r5
        00019: .long__bss_start@ r6
        00020: .long_end@ r7
        00021: .longprocessor_id@ r4
        00022: .long__machine_arch_type@ r5
        00023: .longcr_alignment@ r6
        00024: .longinit_thread_union + THREAD_START_SP @ sp
        00025:
        00026:
        00034: .type__mmap_switched, %function
        00035: __mmap_switched:
        00036: adrr3, __switch_data + 4
        00037:
        00038: ldmiar3!, {r4, r5, r6, r7}
        00039: cmpr4, r5@ Copy data segment if needed
        00040: 1:cmpner5, r6
        00041: ldrnefp, [r4], #4
        00042: strnefp, [r5], #4
        00043: bne1b
        00044:
        00045: movfp, #0@ Clear BSS (and zero fp)
        00046: 1:cmpr6, r7
        00047: strccfp, [r6],#4
        00048: bcc1b
        00049:
        00050: ldmiar3, {r4, r5, r6, sp}
        00051: strr9, [r4]@ Save processor ID
        00052: strr1, [r5]@ Save machine type
        00053: bicr4, r0, #CR_A@ Clear A bit
        00054: stmiar6, {r0, r4}@ Save control register values
        00055: bstart_kernel

        第14, 15行: 函數聲明
        第16 - 24行: 定義了一些地址,例如第16行存儲的是 __mmap_switched 的地址, 第17行存儲的是 __data_loc 的地址 ......
        第34, 35行: 函數 __mmap_switched
        第36行: 取 __switch_data + 4的地址到r3. 從上文可以看到這個地址就是第17行的地址.
        第37行: 依次取出從第17行到第20行的地址,存儲到r4, r5, r6, r7 中. 并且累加r3的值.當執行完后, r3指向了第21行的位置.
        對照上文,我們可以得知:
        r4 - __data_loc
        r5 - __data_start
        r6 - __bss_start
        r7 - _end
        這幾個符號都是在 arch/arm/kernel/vmlinux.lds.S 中定義的變量:

        00102: #ifdef CONFIG_XIP_KERNEL
        00103: __data_loc = ALIGN(4);
        00104: . = PAGE_OFFSET + TEXT_OFFSET;
        00105: #else
        00106: . = ALIGN(THREAD_SIZE);
        00107: __data_loc = .;
        00108: #endif
        00109:
        00110: .data : AT(__data_loc) {
        00111: __data_start = .;
        00112:
        00113:
        00117: *(.init.task)

        ......

        00158: .bss : {
        00159: __bss_start = .;
        00160: *(.bss)
        00161: *(COMMON)
        00162: _end = .;
        00163: }

        對于這四個變量,我們簡單的介紹一下:
        __data_loc 是數據存放的位置
        __data_start 是數據開始的位置

        __bss_start 是bss開始的位置
        _end 是bss結束的位置, 也是內核結束的位置

        其中對第110行的指令講解一下: 這里定義了.data 段,后面的AT(__data_loc) 的意思是這部分的內容是在__data_loc中存儲的(要注意,儲存的位置和鏈接的位置是可以不相同的).
        關于 AT 詳細的信息請參考 ld.info




        第38行: 比較 __data_loc 和 __data_start
        第39 - 43行: 這幾行是判斷數據存儲的位置和數據的開始的位置是否相等,如果不相等,則需要搬運數據,從 __data_loc 將數據搬到 __data_start.
        其中 __bss_start 是bss的開始的位置,也標志了 data 結束的位置,因而用其作為判斷數據是否搬運完成.

        第45 - 48行: 是清除 bss 段的內容,將其都置成0. 這里使用 _end 來判斷 bss 的結束位置.
        第50行: 因為在第38行的時候,r3被更新到指向第21行的位置.因而這里取得r4, r5, r6, sp的值分別是:
        r4 - processor_id
        r5 - __machine_arch_type
        r6 - cr_alignment
        sp - init_thread_union + THREAD_START_SP

        processor_id 和 __machine_arch_type 這兩個變量是在 arch/arm/kernel/setup.c 中 第62, 63行中定義的.
        cr_alignment 是在 arch/arm/kernel/entry-armv.S 中定義的:

        00182: .globlcr_alignment
        00183: .globlcr_no_alignment
        00184: cr_alignment:
        00185: .space4
        00186: cr_no_alignment:
        00187: .space4

        init_thread_union 是 init進程的基地址. 在 arch/arm/kernel/init_task.c 中:

        00033: union thread_union init_thread_union
        00034: __attribute__((__section__(".init.task"))) =
        00035: { INIT_THREAD_INFO(init_task) };

        對照 vmlnux.lds.S 中的 的117行,我們可以知道init task是存放在 .data 段的開始8k, 并且是THREAD_SIZE(8k)對齊的
        第51行: 將r9中存放的 processor id (在arch/arm/kernel/head.S 75行) 賦值給變量 processor_id
        第52行: 將r1中存放的 machine id (見"啟動條件"一節)賦值給變量 __machine_arch_type
        第53行: 清除r0中的 CR_A 位并將值存到r4中. CR_A 是在 include/asm-arm/system.h 21行定義, 是cp15控制寄存器c1的Bit[1](alignment fault enable/disable)
        第54行: 這一行是存儲控制寄存器的值.
        從上面 arch/arm/kernel/entry-armv.S 的代碼我們可以得知.
        這一句是將r0存儲到了 cr_alignment 中,將r4存儲到了 cr_no_alignment 中.
        第55行: 最終跳轉到start_kernel



        評論


        技術專區

        關閉
        主站蜘蛛池模板: 南部县| 驻马店市| 息烽县| 赞皇县| 蒲江县| 平遥县| 珠海市| 大同市| 禹州市| 筠连县| 威远县| 东城区| 宁蒗| 和平区| 安康市| 改则县| 衡南县| 资兴市| 镇赉县| 凌源市| 岐山县| 汨罗市| 蒙城县| 西贡区| 河南省| 信丰县| 米林县| 常山县| 旺苍县| 昆山市| 讷河市| 广河县| 林口县| 桑植县| 昌宁县| 五峰| 西贡区| 盘锦市| 大安市| 溧水县| 虹口区|