fixmap.h의 fixed_addresses 처음에 나오는 VSYSCALL_START는 끝에서 -10M (0xFFFFFFFFFF600000) VSYSCALL_END는 -2M(0xFFFFFFFFFFE00000) 입니다.
여기서는 8M의 VSYSCALL 로 추측되는 부분을 페이지 단위로 쪼개줍니다.
VSYSCALL_LAST_PAGE,
VSYSCALL_FIRST_PAGE = VSYSCALL_LAST_PAGE
+ ((VSYSCALL_END-VSYSCALL_START) >> PAGE_SHIFT) - 1,
FIXADDR_TOP 32비트는 메모리 끝-1페이지(4KB)가 인데 64비트는 특이하게 VSYSCALL_END-1페이지 입니다.
이 enum fixed_addresses는 페이지 번호(인덱스)가 맞는것 같습니다.
이 고정된 공간은 TOP부터 메모리의 높은쪽에서 낮은쪽으로 페이지 번호(0,1,2...)가 매겨지는데 이 연산은 __fix_to_virt와 __virt_to_fix 매크로를 사용해 페이지 번호 <-> 가상주소를 변환합니다. 페이지 번호/ 메모리주소가 높을수록 메모리 공간에서는 낮은쪽에 위치합니다.
fixed_addressed를 살펴보면 VSYSCALL, APIC도 보이고 좀 헤맸던 __end_of_permanent_fixed_addresses와 FIX_BTMAP도 보이네요. __end_of_fixed_addresses가 끝에 또 보입니다.
페이징은 복잡하네요.
xor 나오는 곳에 주석을 달아봤습니다.
/* 이 루틴은 같은 PTE에 BITMAP 페이지(256)들이 같은 PTE블럭에 연속적으로 할당가능한지 체크한다.
* 공간이 충분하다면 연속해서 할당하고 모자라면 PTE블럭을 넘겨서 정렬한후 할당한다.
*
* (x ^ (x + small_block - 1)) & large_block 에서
* small_block이 large_block에 들어갈수 있다면 값이 넘치지 않으면 and도 0이 된다.
* x가 원래 large_block의 비트값을 가지는 경우도 있기에 자신과 xor해서 체크한다.
* large_block 단위로 넘치지 않았다면 xor결과 0이 되고 and 또한 0이 된다.
* (large_block은 2의 승수)
*
* 1이면 x + block - (x & (block - 1)) 은 블럭단위를 증가시키고
* (x & (block - 1))로 block보다 작은 값을 구한다.
* x의 block단위안에서 값을 빼면 블럭 단위로 정렬된다.
*
* 0이면 small_block이 들어가기에 공간이 충분하다. 주소를 그대로 사용한다.
**/
FIX_BTMAP_END =
(__end_of_permanent_fixed_addresses ^
(__end_of_permanent_fixed_addresses + TOTAL_FIX_BTMAPS - 1)) &
-PTRS_PER_PTE
? __end_of_permanent_fixed_addresses + TOTAL_FIX_BTMAPS -
(__end_of_permanent_fixed_addresses & (TOTAL_FIX_BTMAPS - 1))
: __end_of_permanent_fixed_addresses,
FIX_BTMAP_BEGIN = FIX_BTMAP_END + TOTAL_FIX_BTMAPS - 1,
여기서는 8M의 VSYSCALL 로 추측되는 부분을 페이지 단위로 쪼개줍니다.
VSYSCALL_LAST_PAGE,
VSYSCALL_FIRST_PAGE = VSYSCALL_LAST_PAGE
+ ((VSYSCALL_END-VSYSCALL_START) >> PAGE_SHIFT) - 1,
FIXADDR_TOP 32비트는 메모리 끝-1페이지(4KB)가 인데 64비트는 특이하게 VSYSCALL_END-1페이지 입니다.
이 enum fixed_addresses는 페이지 번호(인덱스)가 맞는것 같습니다.
이 고정된 공간은 TOP부터 메모리의 높은쪽에서 낮은쪽으로 페이지 번호(0,1,2...)가 매겨지는데 이 연산은 __fix_to_virt와 __virt_to_fix 매크로를 사용해 페이지 번호 <-> 가상주소를 변환합니다. 페이지 번호/ 메모리주소가 높을수록 메모리 공간에서는 낮은쪽에 위치합니다.
fixed_addressed를 살펴보면 VSYSCALL, APIC도 보이고 좀 헤맸던 __end_of_permanent_fixed_addresses와 FIX_BTMAP도 보이네요. __end_of_fixed_addresses가 끝에 또 보입니다.
페이징은 복잡하네요.
xor 나오는 곳에 주석을 달아봤습니다.
/* 이 루틴은 같은 PTE에 BITMAP 페이지(256)들이 같은 PTE블럭에 연속적으로 할당가능한지 체크한다.
* 공간이 충분하다면 연속해서 할당하고 모자라면 PTE블럭을 넘겨서 정렬한후 할당한다.
*
* (x ^ (x + small_block - 1)) & large_block 에서
* small_block이 large_block에 들어갈수 있다면 값이 넘치지 않으면 and도 0이 된다.
* x가 원래 large_block의 비트값을 가지는 경우도 있기에 자신과 xor해서 체크한다.
* large_block 단위로 넘치지 않았다면 xor결과 0이 되고 and 또한 0이 된다.
* (large_block은 2의 승수)
*
* 1이면 x + block - (x & (block - 1)) 은 블럭단위를 증가시키고
* (x & (block - 1))로 block보다 작은 값을 구한다.
* x의 block단위안에서 값을 빼면 블럭 단위로 정렬된다.
*
* 0이면 small_block이 들어가기에 공간이 충분하다. 주소를 그대로 사용한다.
**/
FIX_BTMAP_END =
(__end_of_permanent_fixed_addresses ^
(__end_of_permanent_fixed_addresses + TOTAL_FIX_BTMAPS - 1)) &
-PTRS_PER_PTE
? __end_of_permanent_fixed_addresses + TOTAL_FIX_BTMAPS -
(__end_of_permanent_fixed_addresses & (TOTAL_FIX_BTMAPS - 1))
: __end_of_permanent_fixed_addresses,
FIX_BTMAP_BEGIN = FIX_BTMAP_END + TOTAL_FIX_BTMAPS - 1,
댓글 0
.