가상주소와 페이지 테이블 크기

· 977 words · 2 minute read

각 태스트(유저 레벨에서 프로세스라고 일컫는)에는 각각의 가상주소를 갖는다. 사용되는 가상주소는 메모리 상에서 MMU에 의해 물리 메모리로 접근이 가능한데 이 때 MMU에 ‘어떻게 가상 주소를 맵핑할 것인지’에 대한 정보를 전달해줘야 한다. 이러한 정보는 ‘페이지 테이블’이라는 것으로 표현되어 그 물리주소를 MMU에서 참고하는 레지스터 정보에 저장하게 된다. 포스팅에서 기준으로 삼은 아키텍처는 ARM64이다. ARM64 커널에서는 사용 가능한 페이지의 크기로서 4K, 16K, 64K 등을 사용하고 있고 가상주소 비트 수(VA_BITS)로서 36, 39, 42, 47, 48비트 등을 사용한다. 여기서 잠깐 짚고 넘어가자면 커널에서 가상주소를 전부 사용하지 않는다. 예를 들어, 64비트 환경에서는 주소 체계가 64비트 기반이므로 가상주소의 경우에도 64비트 0x0000000000000000 ~ 0xffffffffffffffff 를 모두 사용할 것 같지만 실제로는 그렇지 않다. 페이지 단위로 관리되고 있는 메모리 체계에서 커널은 VA_BITS 상수를 통해 전체 64비트 중에서 실제 가상주소로 사용하기 위한 비트 개수를 정의한다.

예를 들어, VA_BITS = 36의 경우 가상주소의 범위는 0xffff 0000 0000 0000 0000 ~ 0xffff ffff ffff ffff 가 된다. 즉, 페이지 테이블을 이용하여 2^36 = 64G 의 범위를 아우를 수 있으면 된다. 그런데 64G 가상주소를 위해 모든 페이지 엔트리를 나타내기에는 페이지 테이블의 크기가 커지기 때문에 페이지 테이블을 여러 레벨에 걸쳐 나타내게 된다. 다시 말해, 실제 36비트 중 페이지 엔트리로 사용할 비트를 제외한 나머지 (VA_BITS - log(PAGE_TABLE_ENTRY 크기) 비트를 이용해 64G 범위를 나타낼 수 있는 페이지 엔트리를 확보한다.

앞서 설명했던 VA_BITS = 36 일 때의 경우를 살펴보자.

VA_BITS

가상주소를 위한 36비트에서 pgd(11bits), 16K(14bits)를 제외한 나머지 11비트를 어떻게 이용하느냐에 따라, 64G의 범위를 다룰 수 있는지 여부를 판단할 수 있다. 이렇게 가상 주소 비트는 페이지 테이블의 레벨이 많아질수록, 테이블의 엔트리 수가 많아질수록 가상주소를 맵핑하기 위한 작업이 까다로워지고 더 많은 사이클을 필요로 하게 된다. 이 때문에 나온 개념이 TLB이며 적절한 캐시를 통해 오버헤드가 많아지지 않도록 처리하는 것이 중요하다.

최근에는 4-level paging에서 5-level paging으로 변화하고 있는 추세(https://lwn.net/Articles/717293/)이다. 레벨 4를 가지는 페이징 구조가 가지는 최대 메모리 크기 128 PiB를 넘어가기 때문에 가상 주소로 사용하는 VA_BITS를 늘려 지원하는 가상 메모리의 크기를 늘리기 위한 패치가 나온 상태이다.