질문에 곧바로 답변을 드리기에 앞서 조금 넓게 설명을 하겠습니다.
예를 들어 48비트의 가상 주소 공간을 사용하는 커널을 빌드하였다고 가정합니다. (VA_BITS=48, 4K Page 기준)
다음은 빌드된 vmlinux의 섹션 부분의 일부입니다. 커널의 가상 공간 시작 주소를 특별히 변경하지 않으면 0xffff000008080000에서 시작됨을 알 수 있습니다.
Section Headers:
[Nr] Name Type Address Offset
Size EntSize Flags Link Info Align
[ 0] NULL 0000000000000000 00000000
0000000000000000 0000000000000000 0 0 0
[ 1] .head.text PROGBITS ffff000008080000 00010000
0000000000001000 0000000000000000 AX 0 0 4096
[ 2] .text PROGBITS ffff000008081000 00011000
000000000097ab30 0000000000000000 AX 0 0 2048
[ 3] .rodata PROGBITS ffff000008a00000 00990000
00000000004091a8 0000000000000000 WA 0 0 4096
[ 4] .eh_frame PROGBITS ffff000008e091a8 00d991a8
그리고 DRAM 물리 주소는 0x40000000부터 시작된다고 가정하고 데이터를 다음과 같이 준비하였습니다.
0x40000000 DRAM 시작 물리 주소
0x40080000 pa_start(커널 코드 물리 주소 시작)
DRAM은 시스템이 부팅될 때 해당 시스템에 의해 결정되지만 _text, _etext 주소는 다음과 같이 컴파일
타임에 결정됩니다.
0xffff000008080000 va_start = _text(커널 코드 가상 주소 시작)
0xffff000008a00000 va_end = _etext(커널 코드 끝)
0x00980000 size(커널 코드 사이즈)
커널 랜더마이즈를 사용하지 않는 경우 아래 값은 다음과 같습니다.
kimage_voffset = 0xfffeffffc8000000
va_start - kimage_voffset = pa_start
결론을 내보겠습니다.
DRAM에 대한 가상 주소 매핑은 PAGE_OFFSET(0xffff800000000000) 위에 있습니다.
그러나 커널 이미지는 PAGE_OFFSET 아래인 vmalloc 가상 주소 공간에 위치합니다.
이러한 이유로 arm64에서는 arm32와 다르게 가상 주소와 물리 주소의 변환을 하기 위해 커널 이미지에 대해서는 별도의 주소 변환 매크로 함수를 사용합니다.
일반적으로 사용하는 가상 주소와 물리 주소의 변환은 다음 매크로 함수를 사용합니다.
virt_to_phys() - 가상 주소 -> 물리 주소로 변환
phys_to_virt() - 물리 주소 -> 가상 주소로 변환
그러나 커널 이미지에 대해서는 다음과 같은 매크로 함수를 사용합니다.
virt_to_phys() - 가상 주소 -> 물리 주소로 변환 (위의 API와 동일합니다)
__phys_to_kimg() - 물리 주소 -> 이미지가 위치한 가상 주소로 변환
도움이 되시길 바랍니다.
감사합니다.
문영일 드림.
--
Google 그룹스 'Linux Kernel ARM' 그룹에 가입했으므로 본 메일이 전송되었습니다.
이 그룹에서 탈퇴하고 더 이상 이메일을 받지 않으려면 linux-kernel-a...@googlegroups.com에 이메일을 보내세요.
이 그룹에 게시하려면 linux-ke...@googlegroups.com(으)로 이메일을 보내세요.
https://groups.google.com/group/linux-kernel-arm에서 그룹을 방문하세요.
더 많은 옵션을 보려면 https://groups.google.com/d/optout을(를) 방문하세요.