__mmap_switched:
/* * The following fragment of code is executed with the MMU on in MMU mode, * and uses absolute addresses; this is not position independent. * * r0 = cp#15 control register * r1 = machine ID * r2 = atags/dtb pointer * r9 = processor ID */ __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 cmp r7, #0 strne r0, [r7] @ Save control register values b start_kernel ENDPROC(__mmap_switched)
- ldmia r3!, {r4, r5, r6, r7}
- r4: __data_loc <- 커널 데이터 섹션 시작 가상주소
- r5: _sdata <- 위와 동일하지만 XIP 커널의 경우 RAM영역으로 바뀜
- rpi2: 0x8000_8000 <- 커널빌드시 결정 (vmlinux.lds.S)
- r6: __bss_start <- .bss 섹션 시작
- r7: _end <- .bss 섹션 끝
- __data_loc 와 _sdata의 주소가 다른 경우 데이터 섹션을 _sdata 주소로 옮긴다. 즉, XIP 커널이 동작중인 경우 데이터 영역을 kernel space의 시작부분 + TEXT_OFFSET 위치로 옮긴다. (data영역만 ROM -> RAM으로 옮긴다)
- .bss 영역을 0으로 초기화한다.
- start_kernel로 점프하기 전에 몇 개의 레지스터를 __mmap_switched_data 스트럭처의 5~7 번째 멤버가 가리키는 각 전역 변수 processor_id, __machine_arch_type 및 __atags_pointer에 저장한다.
- 보조코프로세서 CP15가 사용되는 경우 __mmap_switched_data 스트럭처의 8번째 멤버가 가리키는 전역 변수 cr_alignment에 SCTLR 값을 가진 r0을 저장한다.
- b start_kernel
- 여기서 start_kernel 함수로 이동하여 C언어로 작성된 커널 설정 루틴을 동작시킨다.
__mmap_switched_data:
.align 2 .type __mmap_switched_data, %object __mmap_switched_data: .long __data_loc @ r4 .long _sdata @ r5 .long __bss_start @ r6 .long _end @ r7 .long processor_id @ r4 .long __machine_arch_type @ r5 .long __atags_pointer @ r6 #ifdef CONFIG_CPU_CP15 .long cr_alignment @ r7 #else .long 0 @ r7 #endif .long init_thread_union + THREAD_START_SP @ sp .size __mmap_switched_data, . - __mmap_switched_data