Memory Management Unit

ARM Cortex-A Series Programmer’s Guide10. Memory Management Unit 장을 한글로 옮깁니다. Cortex-A8 프로세서에 포함되지 않은 Large Phsical Address Extension(LPAE) 부분은 생략되었습니다.


용어:


각각의 독립된 태스크가 개별적인 가상 메모리 공간을 점유하게 하는 것이 Memory Management Unit(MMU)의 주요 기능이다. 가상 메모리 시스템은 가상주소를 주 메모리의 물리주소로 변환하는 주소 재배치 역할을 한다. 이 주소 변환은 MMU 하드웨어에 의해 행해지고, 더불어 접근권한과 타입, 그리고 각 영역에 대한 캐시 정책을 제어한다.

MMU는 태스크가 물리주소나 다른 프로그램에 대한 정보없이 독립적으로 동작할 수 있도록 한다. 이는 각 프로그램이 동일한 가상주소를 사용할 수 있게 해줄뿐만 아니라 메모리의 실제 배열이 어떻든간에 연속된 메모리로 취급할 수 있게 한다. 가상주소는 메모리의 물리적 주소 공간과는 별개의 공간이다. 가상주소는 프로그래머와 컴파일러, 링커가 실행하는 공간인 반면, 물리적 주소는 하드웨어 시스템에서 사용하는 실제적 공간이다.

이 다른 두 공간을 서로 변환해주는 것이 MMU의 주 기능이고 이를 감독하는 것은 운영체제의 역할이다. MMU가 비활성일 때 가상주소는 물리주소와 1:1 대응한다. MMU가 주소를 변환하지 못하면 abort 예외를 발생한다. 이로써 요구페이징이 가능하다.

10.1 Virtual Memory

각 태스크는 각자의 가상 메모리 공간을 갖는다. 커널은 코드와 데이터를 실제 메모리에 적재하지만 프로그램은 그 위치에 대해 알 필요가 없다.

MMU의 역할은 페이지 테이블page table을 이용한 주소 변환이다. 페이지 테이블은 물리주소에 대한 각 항목entry의 나열이다. 페이지 테이블 항목page table entry은 가상주소로 조직되어 있고, 가상주소를 물리주소로 변환하기 위한 정보 뿐만 아니라 그 영역에 대한 접근권한과 속성을 포함한다.

ARM MMU는 멀티 레벨 페이지 테이블을 지원한다: L1, L2. 주소 변환을 위해 페이지 테이블에 접근하는 것을 page table walking이라고 한다.

10.2 Level 1 page tables

L1 페이지 테이블의 베이스 주소는 Translation Table Base Address(TTBA)라고 불린다. 32비트 레지스터로 4GB 주소 공간을 지정할 수 있다. CP15 c2에 저장되며, L1 페이지 테이블이 메모리 내에 16KB를 차지하므로 16KB 경계로 정렬되어야 한다.

L1 페이지 테이블 내의 각 항목은 4바이트 크기를 갖는다. 각 항목은 1MB짜리 물리공간을 지시하거나 L2 페이지 테이블의 베이스 주소를 지시한다. L1 페이지 테이블에는 4096개의 항목이 존재한다.

가상주소의 상위 12비트는 변환 테이블의 인덱스로 사용된다. 아래 그림을 참고하라.

figure10-2

간단한 예를 하나 보자: L1 페이지 테이블 주소TTBA0x12300000, 가상주소 0x00100000로 접근이 있을 때, 가상주소의 상위 12비트 값이 0x001이므로 L1 페이지 테이블의 1번째 항목을 참조한다. (한 항목은 4바이트를 차지하므로 1번째 항목의 위치는 0x001 * 4 bytes = 0x004이다.)

따라서 해당 항목의 주소는 0x12300000 + 0x004 = 0x12300004가 된다.

아래는 L1 페이지 테이블 항목의 포맷이다.

figure10-3

L1 페이지 테이블 항목은 다음 네가지 중 하나의 타입이다:

  1. fault page enrty - abort 예외를 발생시킨다. 접근 종류에 따라 prefetch거나 data abort일 수 있다. 가상주소가 전개되지 않았음을(unmapped) 뜻한다.
  2. 1MB page enrty - 1MB 크기 영역의 물리주소를 가리킨다.
  3. L2 page table entry - L2 페이지 테이블의 베이스 주소를 가리킨다. 1MB의 영역을 더 잘게 나눌 수 있다.
  4. A 16MB supersection - This is a special kind of 1MB section entry, which requires 16 entries in the page table, but can reduce the number of entries allocated in the Translation Lookaside Buffer for this region.

하위 두 비트[1:0]는 fault 항목인지 페이지 테이블 항목인지, 영역section 항목인지 결정한다. bit[18]은 normal section과 supersection을 구분한다.

section이나 supersection을 위한 페이지 테이블 항목은 접근권한AP와 캐시설정C, 버퍼설정B과 함께 가상주소를 변환하기 위한 물리주소의 베이스 주소(물리주소의 상위비트 분)를 갖고 있다.

아래 그림은 가상주소에서 L1 테이지 테이블의 1MB section 항목을 거쳐 물리주소로 변환되는 과정을 보인다.

figure10-4

그림 10-3에서 볼 수 있듯이 1MB section 메모리의 페이지 테이블 항목에서 상위 12비트는 물리주소의 상위 12비트로, 가상주소의 하위 20비트는 물리주소의 하위 20비트로 대치됨으로 변환이 완료된다.

A supersection is a 16MB piece of memory, which must have both its virtual and physical base address aligned to a 16MB boundary. As L1 page table entries each describe 1MB, we need 16 consecutive, identical entries within the table to mark a supersection. In Choice of page sizes on page 10-11, we describe why supersections can be useful.

10.3 Level 2 page tables

L2 페이지 테이블은 4바이트의 256개의 항목을 가진다. 즉, 메모리 상에 1KB를 차지하며, 1KB단위로 정렬되어야 한다. 각 항목은 4KB 크기의 가상주소를 같은 크기의 물리주소로 변환한다. 4KB 혹은, 64KB 페이지의 베이스 주소를 나타낼 수 있다.

L2 페이지 테이블에 사용되는 3가지 타입의 항목이 있다. 역시 하위 2비트로 구분된다.

  1. large page entry - 64KB page
  2. small page entry - 4KB page
  3. fault page enrty

다음 그림은 L2 페이지 테이블 항목의 포맷을 보여준다.

figure10-5

Type extension(TEX), Shareable(S), Access Permission(AP, APX) 비트는 ARMv7 메모리 모델에 필요한 속성을 설정한다. C와 B비트는 TEX비트와 함께 페이지 테이블 항목이 지시하는 메모리 영역의 캐시 정책을 결정한다. nG비트는 전역인지(모든 프로세스에게 허용) 아닌지를(특정 프로세스에만 허용) 결정한다. 자세한 사항은 10-12. Memory attributes on page 를 참고하라.

figure10-6

위 그림은 L1 페이지 테이블 항목에서 얻어낸 L2 페이지 테이블 베이스 주소와 가상주소의 8비트 [19:12]를 인덱스로 사용해 어떻게 L2 페이지 테이블에서 해당 항목을 얻어내는지 보여준다.

아래 그림은 2 단계 페이지 테이블의 주소변환 과정을 보인다. L1 페이지 테이블 베이스 주소는 CP15 TTB 레지스터에 저장된다. 가상주소의 비트[31:20]은 L1 페이지 테이블의 4096개의 항목을 인덱스하기 위해 사용된다. L1 페이지 테이블 항목은 L2 페이지 테이블 베이스 주소를 가리킨다. 가상주소의 비트[19:12]는 L2 페이지 테이블의 256개의 항목을 인덱스하는데 사용된다. L2 페이지 테이블 항목에는 물리주소의 상위비트를 갖고 있고 그 주소에 가상주소의 하위비트를 합치면 물리주소로의 변환이 완료된다.

figure10-7

10.4 The Translation Lookaside Buffer

한 번의 메모리 요청에 상대적으로 느린 외부 메모리로 세 번의 접근을 해야한다 - L1 page table walk, L2 page table walk, 실제 메모리 접근. 이는 시스템 성능을 크게 저하시키기 때문에 MMU에는 또다른 기능이 추가되어 있다.

Translation Lookaside Buffer (TLB) 라고 하는 캐시가 그것이다. 메모리 요청이 있으면 MMU는 TLB에 해당 메모리가 캐시되어 있는지 체크한다. 캐시되어 있다면 TBL hit로 해당 값이 바로 제공된다. 반면, TLB miss일 경우 page table walk가 수행된다. 새로 해석된 변환주소는 재사용을 위해 TLB에 캐시될 수 있다.

TLB 캐시 구조는 ARM 프로세서마다 다르기 때문에 전형적인 시스템에 대해 다루겠다. 명령 캐시와 데이터 캐시 가까이에 위치한 하나 또는 여러개의 micro-TLB가 있다. TLB hit 된 주소는 추가적인 메모리 접근과 사이클 패널티를 갖지 않는다. 하지만 micro-TLB는 소수의 항목만 저장할 수 있다(보통 8개의 명령과 8개의 데이터). 그래서 보다 큰(보통 64개의 항목) main TLB로 백업한다(micro-TLB hit보다 약간의 패널티를 갖는다). 아래 그림은 TLB 항목에 담긴 가상주소와 물리주소, 속성, 그리고 ASID를 보여준다. ASID에 대해서는 10.8.1 Address Space ID를 참고하라.

TLB는 다른 캐시와 같이 라인별로 저장한다. TLB 무효화를 제외한 이러한 일들은 프로그래머의 관여없이 이루어진다. 페이지 테이블 항목이 유효하다면 가상주소와 물리주소, 그리고 나머지 속성들이 TLB 항목에 저장된다. 페이지 테이블 항목이 유효하지 않은 경우에는 TLB가 업데이트 되지 않는다. ARM architecture는 유효 페이지 테이블 디스크립터만 캐시한다.

figure10-8

10.5 TLB coherency

운영체제가 페이지 테이블 항목을 변경했을 경우 TLB는 유효하지 않은 변환 값을 가질 수 있다. 따라서 TLB 항목을 무효화할 필요가 있다. CP15 연산으로 TLB 전체를 무효화하거나 낱개의 항목을 무효화할 수 있다. 예측 명령과 데이터 읽기는 page table walk를 수반하므로 유효 페이지 테이블 항목이 변경됐을 경우 TLB를 무효화해야 한다. 유효하지 않은 페이지 테이블 항목은 TLB에 캐시되지 않으므로 무효화 없이 변경할 수 있다.

리눅스 커널은 CP15 연산을 이용한 flush_tlb_all(), flush_tlb_range()와 같은 여러 함수를 보유하고 있다. 이러한 함수는 보통 디바이스 드라이버에 사용되지 않는다.

10.6 Choice of page sizes

작은 페이지 사이즈는 메모리 블럭을 보다 정밀하게 제어할 수 있고 페이지 내의 미사용 공간을 줄여 메모리 낭비를 막는 데 효과적이다. 태스크가 7KB의 데이터 공간을 필요로 할 경우, 64KB 페이지나 1MB 섹션에 비해 4KB 페이지에서 적은 미사용 메모리를 갖는다.

반면, 큰 페이지 사이즈를 사용할 경우 TLB의 각 항목은 보다 큰 영역의 메모리를 지시할 것이고 TLB hit 확률이 높아진다. 따라서 page table walks가 줄어들어 외부 메모리 접근에 따른 속도 부하를 줄일 수 있다. 이러한 이유로 16MB supersection이 큰 메모리에 사용될 수 있다.

10.7 Memory attributes

MMU가 페이지 테이블을 사용해 가상주소를 어떻게 물리주소로 변환하는지 보았다. 그러나 각 페이지에는 접근권한과 메모리 타입, 캐시 정책과 같은 몇가지 속성이 있다. 이에 대해 알아보자.

10.7.1 Memory Access Permissions

페이지 테이블 항목의 접근권한(AP와 APX)는 해당 페이지의 접근권한을 설정한다. 아래 표를 참고하라.

필요한 권한을 갖지 못한 상태에서 페이지에 접근할 시 abort가 일어난다. 데이터 접근에서는 data abort 예외가 발생할 것이고, 명령 패치에서는 aborted로 마크될 것이고 만약 실행전에 플러시되지 못한다면 prefetch abort 예외가 일어날 것이다.

오류 이유와 위치는 CP15의 fault address와 fault status 레지스터에 저장된다. 그리고 난 뒤 abort 핸들러는 페이지 테이블을 수정하거나 오류를 발생시킨 프로그램을 종료시키는 등의 적절한 조치를 할 수 있다.

table10-1

10.7.2 Memory types

이전 세대의 ARM 아키텍처에서는 프로그래머가 캐시와 write buffer를 설정하므로서 메모리 접근 행동을 결정할 수 있었다. 하지만 여러 단계의 캐시와 멀티 프로세서의 공유 메모리와 같은 현대의 복잡한 시스템에서 그것만으로는 부족하게 되었다. 따라서 ARMv6에 새로운 메모리 타입이 추가되었고 ARMv7에서 확장되었다.

모든 메모리 영역은 아래의 상호 배타적인 세가지 타입 중 하나로 설정된다:

아래 표 10-2를 참고하라.

table10-2

세 메모리 타입에 대한 정보는 11-4 ARM memory ordering model을 참고하라.

아래 표 10-3은 페이지의 메모리 타입을 어떻게 설정하는지, 그리고 캐시 정책은 어떻게 설정하는지 나타낸다. 캐시 정책은 9장을 참고하고, 메모리 타입은 11장을 참고하라.

table10-3

표 10-3의 마지막 항목은 좀 더 설명이 필요하다. 보통의 캐시 메모리에서 TEX의 하위 2비트는 바깥 캐시를 설정하는데 사용되고, C와 B비트는 안쪽 캐시를 설정하는데 사용된다(바깥 캐시는 2,3차 캐시, 안쪽 캐시는 1차 캐시). 이로써 각각의 캐시에 서로 다른 캐시 정책을 수립할 수 있다. Cortex-A15와 Cortex-A8 프로세서에서는 페이지 테이블 항목의 안쪽 캐시 속성이 L1, L2 캐시 모두에 적용된다. 예전의 몇몇 프로세서에서 바깥 캐시는 write allocate를 지원한다. 따라서 이와같은 캐시 정책 설정은 그러한 프로세서에서 제대로 동작하기 위함이다.

10.7.3 Domains

ARM architecture는 메모리 영역을 도메인 ID로 태깅하는 기능을 갖고 있다. 하드웨어는 16개의 도메인 ID를 제공한다. Domain Access Control Register(DACR) CP15 c3에는 각 도메인당 권한 설정 2비트씩이 할당되어 있다. 이는 각 도메인이 no-access, manager 모드 또는 client 모드로 동작할 수 있게 한다. No-access 도메인이 설정된 페이지에 대한 접근은 페이지 권한과 상관없이 abort 예외를 일으킨다. Manager mode는 모든 페이지 권한을 무시하고 full access를 허용한다. Client mode는 도메인과 함께 페이지 퍼미션을 참조한다.

주의 : ARMv7 architecture 에서는 도메인 기능을 사용하지 않을 것을 권장하고 이는 곧 제거될 것이다. 하지만 접근권환을 확보하기 위해 섹션에 도메인 번호를 할당하고 client mode로 설정하는 것은 여전히 필수적이다.

10.8 Multi-tasking and OS usage of page tables

Cortex-A 시리즈 프로세서를 사용하는 대부분의 시스템에서는 여러 개의 프로그램 또는 태스크가 동시에 수행 중일 것이다. 각 태스크는 메모리에 독자적인 페이지 테이블을 가질 것이다. 전형적으로 가상-물리 주소 맵핑은 고정된 상태로 대부분의 메모리 시스템이 조직된다. 이는 운영체제의 코드와 데이터, 그리고 각 태스크에 사용된 페이지 테이블을 포함하는 데 사용된다.

프로그램이 시작될 때, 운영체제는 프로그램에 사용될 한 셋의 페이지 테이블 항목을 메모리에 할당한다. 프로그램에 추가적인 코드나 데이타 공간을 맵핑할 필요가 있을 시(malloc() 콜과 같은) 커널은 이 테이블을 수정할 수 있다. 태스크가 종료되고 프로그램이 더 이상 동작하지 않으면 커널은 관련 페이지 테이블 항목을 제거하고 새로운 프로그램을 위해 재사용할 수 있다. 이러한 방식으로 여러개의 태스크가 물리 메모리에 상주할 수 있다. 태스크 전환이 일어날 때, 커널은 페이지 테이블 항목을 다음 실행 스레드의 페이지로 전환한다. 휴지중인 태스크는 실행중인 태스크로부터 완전히 보호된다. 이는 커널 코드와 데이타는 물론 다른 사용자의 태스크로의 접근을 MMU가 방지함을 말한다.

페이지 테이블 항목이 변경된다면 어떤 가상주소로의 접근은 물리주소의 다른 위치로 변환될 수 있다. 이는 여러 문제를 발생시키고 ARM architecture는 이러한 성능저하를 줄이기 위한 몇가지 기능을 갖추고 있다.

ARM7에서 ARM9사이의 예전 ARM 프로세서는 가상 주소를 저장하는 캐시 태그를 사용했다. 페이지 테이블 맵핑이 변경된다면 캐시는 예전 페이지 테이블 정보를 갖게 된다. 이를 방지하기 위해 캐시는 무효화될 필요가 있다. 그러나 이는 큰 성능저하를 유발할 수 있다. 방금 무효화된 한 위치의 명령과 데이터는 바로 다시 외부 메모리로부터 re-fetch 될 필요가 있을 수 있기 때문이다. 그러나 Cortex-A 시리즈의 모든 프로세서는 physically tagged caches를 사용한다. 따라서 페이지 테이블 항목을 변경하면서 생기는 무결성 문제가 일어나지 않는다.

TLB 역시 변경되기 전의 페이지 테이블 항목을 캐시한 경우 무효화해 줄 필요가 있다.

10.8.1 Address Space ID

페이지 테이블의 nG비트가 셋되면 해당 페이지는 특정 프로그램과 관련됨을 뜻한다. MMU는 이 때 주소를 변환하기 위해 가상주소와 ASID 값을 사용한다.

ASID는 운영체제에 의해 각 독립적인 태스크에 할당된 번호이다. 이 값은 0-255 값을 가지고 현재 태스크의 값이 ASID 레지스터에 저장된다(CP15 c13). TLB가 업데이트 되고 해당 항목이 non-global로 마크되어 있을 때, ASID 값이 추가적으로 TLB 항목에 저장된다. 따라서 현재의 ASID와 항목에 저장된 ASID가 일치할 경우에만 TLB hit이 일어난다. 이것으로 우리는 nG마크된 하나의 동일한 페이지에 여러개의 유효한 TLB항목을 가질 수 있다(ASID 값만 다른). 이는 TLB의 플러시 작업을 건너뛰게 하므로 문맥전환의 오버헤드를 크게 줄이는 역할을 한다. The ASID forms part of a larger (32-bit) process ID register that can be used in task-aware debugging.

아래 그림은 가상주소 0에서 실행되는 A, B, C라는 세 개의 프로그램을 나타낸다. 각 프로그램은 물리 메모리에 서로 다른 위치에 저장된다. 특정 프로그램을 지시하는 ASID 값을 사용하므로써 언제나 가상주소 0에 유효한 TLB 항목을 여러개 가질 수 있다.

figure10-9

10.8.2 Page Table Base Register 0 and 1

여러 프로그램의 여러 페이지 테이블이 갖는 또다른 문제는 각 프로그램마다 독자적인 L1 페이지 테이블이 필요하다는 것이다(하나의 크기가 16KB인). 전형적으로 메모리의 한 구역만이 태스크에 할당되고, 커널은 늘 변하지 않는 공간에 존재할 것이므로 각 테이블의 대부분의 항목은 동일한 값을 갖는다. 게다가 global 페이지 테이블 항목을 변경하자면 모든 테이블에 그 변경사항을 적용해야 한다는 것이다.

이 문제를 개선하기 위해 또 하나의 페이지 테이블 레지스터를 사용할 수 있다. CP15TTBR0TTBR1, 두 개의 Translation Table Base Register를 포함한다. 제어 레지스터(TTB Control Register)는 0-7 값을 지정하기 위해 사용된다. 이 값은 가상주소의 상위 몇 비트를 체크할 것인지 결정하고 어느 TTBR 레지스터를 사용할지 결정한다.

TTB 제어 레지스터 값이 0일 때(default 값), 모든 가상주소는 TTBR0 레지스터에 의해 맵핑된다. TTB 제어 레지스터 값이 1-7일 때, 가상주소의 상위주소를 체크한다.

일례로 TTB 제어 레지스터 값이 7이라면, 하위 32MB는 TTBR0 레지스터로 참조될 것이며, 나머지 영역은 TTBR1 레지스터로 참조될 것이다. 결과적으로 TTBR0에 의해 지시된 프로그램 특정 페이지 테이블은 32개의 항목(128 바이트)을 포함한다. TTBR1에 의해 지시된 global 테이블은 단 하나로 유지되는 것이다.

0b0000|0000|0000|0000|0000|0000|0000|0000
        ^32MB  ^1MB ^64KB

이러한 특징은 운영체제가 CP15 명령을 이용해 TTBR0ASID 값을 문맥전환시 변경하므로써 기능한다. 단, non-atomic 연산이므로 신경을 써서 프로그램해야 한다. non-atomic 연산을 위한 권장 시퀀스를 Reference Manual에서 참고하라.

10.8.3 The Fast Context Switch Extension

deprecated. 생략.

10.9 Large Physical Address Extensions

생략.