페이지 테이블 매핑 시 zImage+DTB 코드가 파괴될 가능성이 있는 경우 캐시 on 보류
이 루틴에서는 캐시 사용 가능 유무를 결정하고 캐시 사용 가능한 경에만 캐시를 활성화 시키고 그렇지 않은 경우 캐시 사용을 잠시 유보시킨다.
- compressed 커널은 relocatable 코드로 만들어져서 어디에 위치하든 동작할 수 있게 되어 있다.
- 재배치를 조금이라도 빠르게 수행하기 위해 MMU를 켜고 캐시를 사용하는데 한 가지 체크를 해보아야 할 것이 있다.
- 캐시를 사용하기 위해서는 MMU를 켜야 하고 그 전에 페이지 테이블(PTE 또는 PT)을 생성해 줘야한다.
- 페이지 테이블은 decompressed 커널의 주소 바로 아래에 위치한다. 그렇기 때문에 압축된 커널(zImage)+DTB 영역과 decompressed 커널 영역 하단에 위치한 페이지 테이블이 겹치는 경우엔 캐시를 사용하지 않아야 한다.
- 캐시를 사용하는 경우 임시로 생성되는 페이지 테이블의 위치가 압축된 커널(zImage)+DTB 영역과 겹치기 때문에 압축된 커널(zImage)+DTB의 일부를 손상시키면서 문제가 발생하게 된다.
- 캐시 사용을 유보하는 코드는 linux-3.11.0에서 추가되었다.
- rpi2: step 1 조건으로 cache를 활성화 시킨다.
.text #ifdef CONFIG_AUTO_ZRELADDR @ determine final kernel image address mov r4, pc and r4, r4, #0xf8000000 add r4, r4, #TEXT_OFFSET #else ldr r4, =zreladdr #endif /* * Set up a page table only if it won't overwrite ourself. * That means r4 < pc || r4 - 16k page directory > &_end. * Given that r4 > &_end is most unfrequent, we add a rough * additional 1MB of room for a possible appended DTB. */ mov r0, pc cmp r0, r4 ldrcc r0, LC0+32 addcc r0, r0, pc cmpcc r4, r0 orrcc r4, r4, #1 @ remember we skipped cache_on blcs cache_on
- CONFIG_AUTO_ZRELADDR 옵션이 사용될 경우 decompressed 커널이 시작할 물리 주소를 자동계산한다.
- r4 = BASE_ADDR + 0x0000_8000(rpi2의 #TEXT_OFFSET)
- Base address의 align은 128M 간격으로 설정됨.
- cmp r0, r4
- compressed 커널(zImage)에서 동작하는 현재의 위치가 decompressed 커널 영역보다 상단에 떨어져 위치하는 지 비교한다.
- 현재 동작 주소 r0가 decompressed r4(커널 시작 주소)와 비교하여 상위에 있는지 비교
- 이러한 경우 향후 실행해야 할 compressed 커널(zImage)의 코드가 페이지 테이블의 상단이므로 페이지 테이블을 매핑하더라도 실행할 코드가 파괴되지 않는다고 판단하여 조건문 cc를 모두 무시하고 blcs cache_on 명령을 수행하여 캐시를 활성화 시킨다.
- compressed 커널(zImage)에서 동작하는 현재의 위치가 decompressed 커널 영역보다 상단에 떨어져 위치하는 지 비교한다.
- cmpcc r4, r0
- compressed 커널(zImage)가 decompressed 커널 영역보다 하단에 떨어져 위치하는 지 비교한다.
- r0(중복 체크를 위해 계산된 이미지의 끝부분) <= r4(zreladdr)인지 비교
- 페이지 테이블 영역이 겹치지 않는다고 판단하면 blcs cache_on을 수행하여 캐시를 활성화 시킨다.
- orrcc r4, r4, #1
- 캐시 사용을 유보한 사실을 r4의 LSB 1비트를 사용하여 보관하여 나중에 코드 재배치가 끝난 후 압축을 푸는 루틴을 실행하기 전에 유보된 캐시를 on 시킨다.
- 0=cache on status, 1 =cache off status(캐시 설정이 유보된 상태)
- 캐시 사용을 유보한 사실을 r4의 LSB 1비트를 사용하여 보관하여 나중에 코드 재배치가 끝난 후 압축을 푸는 루틴을 실행하기 전에 유보된 캐시를 on 시킨다.
LC0 객체
.align 2 .type LC0, #object LC0: .word LC0 @ r1 .word __bss_start @ r2 .word _end @ r3 .word _edata @ r6 .word input_data_end - 4 @ r10 (inflated size location) .word _got_start @ r11 .word _got_end @ ip .word .L_user_stack_end @ sp .word _end - restart + 16384 + 1024*1024 .size LC0, . - LC0
- .align 2
- 4 바이트 정렬
- .type LC0, #object
- LC0 레이블 위치를 객체로 정의
- __bss_start
- compressed 커널에서 bss 영역의 시작 주소
- _end
- compressed 커널의 끝 주소 (bss 영역 포함)
- _edata
- compressed 커널에서 data영역의 끝 주소
- input_data_end -4
- decompressed 커널의 길이가 담겨 있는 곳의 주소
- _got_start
- compressed 커널에서 got 영역의 시작 주소
- _got_end
- compressed 커널에서 got 영역의 끝 주소
- .L_user_stack_end
- compressed 커널의 스택 주소(아래로 커지므로 스택의 상단 주소)
- _end – restart + 16K + 1M
- zImage+DTB와 페이지 테이블의 중복 비교에 사용할 주소 값
- compressed 커널의 끝 주소 + 16K PTE + 1M DTB 영역
- .size
- LC0 객체 사이즈 지정
참고
- start: | 문c
- 영역 검사를 하여 하단부가 중복된 경우만 캐시 on 보류 – (현재 글)
- cache_on: | 문c
- cache_clean_flush: | 문c
- 영역 검사를 하여 하단부가 중복된 경우만 캐시 on 보류 – (현재 글)
- restart: | 문c
- wont_overwrite: | 문c