[ARM 11차 B조] 14.05.31 스터디 후기
2014년 5월 31일 7주차 스터디 후기
1. Study history
- 5월 31일(7주차) 12:00 ~ 6:00 성수 서울앱창업센터에서 진행, 14명 참석
- arch/arm/boot/compressed/head.S 진행 중
- 6월 7일(8주차) 스터디 휴식
2. 이슈사항
추가적인 이슈사항이나 고쳐야 할 부분 있을경우 댓글로 달아주세요. 수정해서 올리겠습니다.
-1. 재배치 관련 이슈사항
모기향책과 기타 참고자료들로 정리해봤습니다. 댓글로 태클점 주세요.
mov r4, pc
and r4, r4, #0xf8000000
add r4, r4, #TEXT_OFFSET
/* 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(device tree binary).
*/
mov r0, pc
cmp r0, r4
@if r0 < r4 {
ldrcc r0, LC0+32 @ r0 < r4 일 때 LC0+32 = _end - restart + 16K(page_table) + 1M(DTB)
addcc r0, r0, pc
cmpcc r4, r0
@ if r4 < r0
orrcc r4, r4, #1 @ remember we skipped cache_on
}
@ if r4 >= r0
blcs cache_on
위의 값에서 압축해제된 커널을 올릴 주소를 r4에 넣어줍니다. 해당 주소와 현재 pc와 비교해서 재배치의 수행
여부를 결정하게 됩니다. 여기서 재배치가 결정되면 cache_on을 나중으로 미루게 됩니다.
참고1: http://www.iamroot.org/xe/Kernel_10_ARM/186592#comment_186806
참고2: http://www.iamroot.org/xe/index.php?mid=Kernel_10_ARM&document_srl=180812#comment_181518
+---------------------+
| |
|zImage | <- 재배치 검사할 때의 pc(r0)
+---------------------+--0x--C0_0000
|빈공간? |
+---------------------+--0x--00_----
|압축풀린 커널이|
|올라갈 공간 |
+---------------------+--0x--00_8000 <- r4(압축해제된 커널의 위치)
|TEXT_OFFSET | -page_directory(16k)
| |
+---------------------+
그럼 pc값이 커널의 위치보다 작아질 일이 없을것 같은데 왜 해당 코드를 넣었는지 이해가 안갑니다. 부트로더에서 실수로 _TEXT_BASE를 잘못 대입했을 때를 대비해서 넣어둔 코드인가요? 주석내용을 보면 pagetable과 관련된 이슈로 넣어둔것 같은데 잘 모르겠내요.
-2. 재배치 이 후 LC0 위치 조절
위의 재배치 문제가 발생할 경우 재배치 이 후 restart를 한번 더 실행하게 된다. 재배치를 수행했다면 _edata(bss시작 주소)와 압축 풀린 커널 사이즈가 있는 주소(r10)의 위치를 조절해주게 된다.
adr r0, LC0
ldmia r0, {r1, r2, r3, r6, r10, r11, r12}
ldr sp, [r0, #28]
sub r0, r0, r1 @ calculate the delta offset
add r6, r6, r0 @ _edata
add r10, r10, r0 @ inflated kernel size location
-3. 리틀-엔디안 방식으로 인한 로드 방법
해당 코드에서 로드하는 r10은 LC0에서 받아온 값으로 압축 풀린 커널의 크기가 들어있는 메모리의 주소이다. 해당 사이즈를 받아와서 나중에 어딘가에 쓰기 위해 저장을 해두는 것 같은데, 리틀 엔디안의 경우 메모리에서 레지스터로 값을 로드할 경우 상위 주소와 하위 주소가 다른 문제가 생긴다.
예를 들어 커널 사이즈 0x12345678가 리틀 엔디안 방식에서 메모리에 저장된다면 0x78563412로 저장됩니다. 이 상태에서 빅엔디안에서 해당 메모리에 있는 값을 r9로 불러온다면, 0x78563412 그대로 불러와지게 되기 때문에 아래와 같은 루틴으로 원하는 값을 레지스터에 적재한다.
참고 홈페이지를 보시면 더 자세한 설명이 있습니다. ㅎ
ldrb r9, [r10, #0] @ r9 = 0x00000078
ldrb lr, [r10, #1] @ lr = 0x00000056
orr r9, r9, lr, lsl #8 @ r9 = 0x00005678
ldrb lr, [r10, #2] @ lr = 0x00000034
ldrb r10, [r10, #3] @ r10 = 0x00000012
orr r9, r9, lr, lsl #16 @ r9 = 0x00345678
orr r9, r9, r10, lsl #24 @ r9 = 0x12345678
참고: http://www.iamroot.org/xe/Kernel_8_ARM/60066#comment_60161
3. 참고 + 질문
혹시 참고가 될까 해서 올려드립니다. 추가적인 참고자료 및 의문점도 댓글로 부탁드립니다.
-1. arch/arm/boot/compressed/vmware 덤프로 알아본 LC0
공부하다가 LC0에 저장된 값들 _end, _edata같은녀석들이 먼가 싶어서 이것 저것 찾아본 결과입니다. 맞는지 잘 모르겠어서 검증차 올려둡니다. 그리고 질문도 더해서요. ㅎ
#arm-linux-eabi-objdump arch/arm/boot/compressed/vmware
...
000002d8 <LC0>:
2d8: 000002d8 002a3638 002a3660 002a3638 ....86*.`6*.86*.
2e8: 002a35e9 002a35fc 002a3630 002a4660 .5*..5*.06*.`F*.
2f8: 003a7598 e320f000 .u:... .
LC0에서 _end와 _edata는 3번째와 4번째에 들어가있습니다. 덤프파일을 보면 _end: 002a3660, _edata: 002a3638와 같습니다. 해당 값들은 섹션 헤더에서 .stack과 .bss의 주소로 나옵니다. 그렇다면 재배치에서 사용하는 LC0의 _end -restart + 16Kb + 1Mb값은 스택 시작주소에서 restart를 뺀값으로 보이는데 재배치해줄때 스택 사이즈는 제외한다는 말처럼 보입니다.
그리고 5번째에는 inputdata - 4가 들어간다고 합니다. 압축된 커널의 끝에 압축 해제된 커널의 사이즈가 붙어있다는 문구가 있길래 살펴보니 살펴보면 002a35e9가 들어가 있으며, 해당 주소는 piggydata 시작주소 + piggydata size - 4를 한 값과 같습니다.
하나씩 맞춰가는 재미가 있내요 ㅋ; 여기서 의문점이 생겨서 질문 드려요.
질문1. vmware덤프 파일에서 user_stack섹션으로 공간이 잡아진 부분이 보이는데 해당 부분은 필요없다는 말일까요?
질문2. off는 elf파일에서 해당 오프셋만큼의 위치에 해당 섹션이 존재한다는 말인가요?