compressed/head.S – start: 영역 검사를 하여 하단부가 중복된 경우만 캐시 on 보류

페이지 테이블 매핑 시 zImage+DTB 코드가 파괴될 가능성이 있는 경우 캐시 on 보류

decompress_head.s분석2

이 루틴에서는 캐시 사용 가능 유무를 결정하고 캐시 사용 가능한 경에만 캐시를 활성화 시키고 그렇지 않은 경우 캐시 사용을 잠시 유보시킨다.

  • 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 명령을 수행하여 캐시를 활성화 시킨다.
  • 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(캐시 설정이 유보된 상태)

 

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 객체 사이즈 지정

 

참고

댓글 남기기