__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