6. 切换数据
在 arch/arm/kernel/head-common.S 中:
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
声明:本文内容来自网络转载或用户投稿,文章版权归原作者和原出处所有。文中观点,不代表本站立场。若有侵权请联系本站删除(kf@86ic.com)https://www.86ic.net/bandaoti/275638.html