1. leaq _text(%rip), %rdi 에서 %rdi에는 어떤 값이 들어가는가
정답은 0x1000000이 들어가는게 맞습니다
소스 바로 윗부분을 보면
leaq _text(%rip), %rax
shrq $MAX_PHYSMEM_BITS, %rax
jnz bad_address
이런 코드가 있는데 만약 첫줄 %rax에 0xFFFFFFFF80000000이 들어가게 되면 bad_address로 점프하게 됩니다
우리가 주석까지 달았는데 아무도 알아차리지 못했네요 ㅋㅋ
2.
leaq _text(%rip), %rbp
subq $_text - __START_KERNEL_map, %rbp
첫줄에서 %rbp는 0x1000000 이고
두번째 줄의 $_text는 0xFFFFFFFF80000000 이라 결국 %rbp에는 0이 들어간다는 가설이 있었습니다
%rbp는 커널이 relocate 된 경우에만 의미있는 값을 가지게 되기 때문
일단 1번을 토대로 메모리맵을 대충 그려보았는데 상당히 깔끔한 그림이 나왔습니다
우리가 고민했던 코드는 주석에도 나와있듯이 switchover를 위해
커널의 _text 부터 _end까지를 1:1로 매핑하는 페이지 테이블을 새로 설정해 주는 것입니다
early_level4_pgt의 앞쪽 부분은 level4로 이용하고
64개의 early_dynamic_pgts들 중
첫번째 early_dynamic_pgts는 level3,
두번째 early_dynamic_pgts는 level2처럼 사용합니다
따라서 실제 커널이 들어있는 페이지 프레임 주소가 저장되는 곳은 두번째 early_dynamic_pgts 입니다
그런데 커널이 relocate된 경우 그냥 엔트리를 설정해주면 테이블의 boundary를 넘어가는 문제가 생길 수가 있습니다
(early_level4_pgt는 앞에서 주소값이 46비트가 넘어가는지 미리 체크해주기 때문에 테이블의 크기를 넘지 않습니다)
그래서 이 경우 마치 큐처럼 테이블의 가장 마지막 엔트리에 다다르게 되면 첫번째 엔트리로 돌아가서
계속해서 매핑을 해주게 됩니다
이 부분이 주석에서 wraparound어쩌구 하던 부분인 것 같습니다
커널 코드가 들어있는 물리주소가 1G boundary를 넘게 되면 두번째 early_dynamic_pgts 가 순환하게 되고
커널 시작 주소(_text)가 512G boundary에 걸치게 되면 첫번째 early_dynamic_pgts 가 순환하게 됩니다
그 아래 코드는 위에서 했던것 처럼 level2_kernel_pgt에도 %rbp를 더해주는 작업을 하게 됩니다
#PF handler 부분은 아직 못찾아봤습니다 ㅋㅋ
자세한 내용은 다음주에 같이 생각해보는게 좋을 것 같습니다
그럼 좋은 주말 보내세요!
댓글 6
-
이성훈
2013.11.03 17:43
-
김택훈
2013.11.04 09:07
답변 감사합니다. 저도 1번, 2번에 대한 답변에 대한 내용은 동의합니다!
다음 스터디 때 dynamic pgt 관련하여 간단한 설명 부탁드립니다^^
-
도영주
2013.11.04 21:06
고생하셨네요~ Memory Map이 있으면 더 좋을 것 같은데,
올려주실 거라 기대하고 있겠습니다.^^;
-
이경욱
2013.11.05 21:01
간단하게 그려봤는데 오류가 있을수도 있음;
메모리의 마지막 _end는 정확히 말하면 _end - (_end % 2M)라고 할 수 있겠네요
-
pororo
2013.11.05 21:16
예전에 관련해서 그려놨던게 있습니다.
틀릴수도 있으니 참고 정도로 올려봅니다. -
이경욱
2013.11.05 21:21
감사합니다!! 다행히 제 그림과 같네요 ㅋㅋ
.
수고 하셨습니다.
1번이 명확하지 않아서 모두들 고민 했었는데 해결이 된 듯 하군요.
만약 어제 이야기처럼 가상주소가 들어가게 되면 bad address가 되겠네요..