ARM System Developer's Guide  

- Designing and Optimizaing System Software




#####

Protected Regions

Initializing the MPU, Caches, and Write Buffer

Demonstration of an MPU System




#### 13. 메모리 보호 장치 (MPU, Memory Protection Units)


- protection : 원치 않는 액세스로부터 시스템 자원과 태스크들을 막아주는 것


- 시스템 자원 액세스를 제어하는 방법 : unprotected(비보호), protected(보호)

 unprotected systems

 소프트웨어에만 의존하여 시스템 자원을 보호

 protected systems

 하으뒈어와 소프트웨어 둘다에 의존하여 시스템 자원을 보호

* 프로세서의 기능과 제어 시스템의 요구사항에 맞춰 제어 방법을 선택


# Unprotected Embedded Systems

- 동작 중 메모리와 주변장치를 사용하돋록 강요하는 전용 하느웨어가 없음

- 시스템 자원을 액세스하기 위해 각 태스크들이 다른 모든 태스크와 동기를 맞춰야 함


# Protected Embedded Systems

- 시스템 자원의 액세스를 확인하고 제한하는 정용 하드웨어를 가짐

- 전용 하드웨어는 자원의 소유권을 가짐 (하드웨어 레벨에서 자원들을 모니터링하고 제어하는 특별한 권한)

- 소프트웨어 루틴보다 시스템을 더 잘 관리할 수 있음


# MPU : 능동적으로 시스템 자원을 보호하는 하드웨어

- 보호 시스템의 주요 보호대상 자원 : 메모리 시스템, 주변장치

- ARM의 주변장치는 일반적으로 메모리 매핑이 되어 있어 MPU는 두 자원을 보호하기 위해 동일한 방법을 제공(region을 이용)


# Region(영역) : 메모리 영역과 관련되어 있는 속성들의 집합

프로세서 코어는 몇몇의 CP15 레지스서 안에 속성값들을 저장(각 영역은 0-7의 번호로 규정)

- 메모리 경계는, 시작주소와 4KB와 4GB사이의 2의 지수로 설정되는 크기두 속성 값을 사용해 설정됨

=> 이 영역에 접근권한, 캐시쓰기정책(캐시 및 write buffer)와 같은 추가의 속성을 할당

* 접근권한 : RW, RO, no-access, 추가권한 : 현재 프로세서 모드(유저/특권 모드)

- 프로세서의 메인메모리 영역에 대한 접근 제어 : 

프로세서의 접근권한 및 현재 프로세서 모드를 비교하여 메모리 액세서를 허용하거나 abort 신호를 발생하여 메모리 액세스를 차단

- abort 신호 : exception 처리로 abort  handler로 분기하도록 한 후 처리를 위해 적절한 서비스 루틴으로 분기

* abort type : prefetch abort, data abort



### 13.1. Protected Regions


- ARM740T, ARM940T, ARM946E-S, ARM1026EJ-S


ARM940T

- 16개의 Protected Regions

- 명령어 메모리와 데이터 메모리를 제어하기 위한 분리된 영역을 가짐

- 코어는 명령어와 데이터 영역에ㅐ 대해 다른 영역 크기와 시작주소를 할당할 수 있음

- region 번호 : 0-7 사이의 번호로 할당되지만 명령어 영역과 데이터 영역의 pair로 이루어짐(8개씩)


ARM740T, ARM946E-S, ARM1026EJ-S

- 8개의 Protected Regions

- 명령어 영역과 데이터 영역이 통합

=> 데이터영역과 명령어영역은 크기와 시작주소를 설정하기 위해 똑같은 레지스터를 사용

메모리 접근 권한과 캐시 정책

ARM740T : 명령어와 데이터 액세스를 동일하게 적용 

ARM946E-S, ARM1026EJ-S : 명령어 액세스와 데이터 액세스를 독립적으로 설정 가능

- region 번호 : 코어가 폰노이만 아키텍처인지 하버디 아키텍처인지에 상관없이 독립적이며, 

각 영역은 0-7 사이의 번호로 할당


> region 제어를 위한 몇가지 규칙 <

1. 영역은 다른 영역에 overlap 될 수 있음

2. 영역은 영역에 할당되어 있는 특권에 독립적인 우선순위가 할당

3. 영역이 overlap 되면, 가장 높은 우선순위를 가진 영역 속성이 다른 영역에 대해 우선순위를 가짐.

* 우선순위는 overlap된 영역내의 주소에 대해서만 적용

4. 영역의 시작주소는 그 크기의 배수여야 함

5. 영역의 크기는 4KB-4GB 사이의 2의 지승의 값이여야 함(4KB, 8KB, 16KB, 32KB, 64KB, ...., 2GB, 4GB)

6. 정의된 영역 밖에 있는 메인메모리의 영역에 액세스를 시도하면, abort를 발생

- 명령어를 페치하고 있었다면 prefetch abort가 발생,

- 데이터를 위한 메모리 요청이었다면 data abort가 발생



## 13.1.1. Overlapping Regions

- Overlapping : 한 영역에 할당되어 있는 메모리 공간의 일부가 다른 메모리 영역에 할당되어있는 메모리 공간 안에 있는경우

* 접근 권한은 할당 할 때 overlap을 지원하지ㅏ 않는 영역보다 큰 유연성을 제공


ex. 가정 : 0x000000000 주소에서 시작하는 256KB의 메모리에서, user mode로 액세스가 불가능하도록 특권 시스템 영역에서 보호 중


특권영역의 코드와 데이터 스택이 벡터테이블 0x00000000에서 시작하는 32KB의 영역안에 맞춰져 있음

남은 공간은 user 공간으로 할당되어 있음

- overlap 영역과 함께 시스템은  256KB의 유저영역과 32KB의 특권 영영의 두 영역을 사용

- 특권영역 1은 속성이 유저역역 0보다 우선순위가 높음


## 13.1.2. Background Regions

- 큰 메모리 영역에 동일한 속성을 할당하는 데 사용되는 가장 낮은 우선순위의 영역

- 더 높은 우선순위를 가진 다른 영역들은,

 정의된 background 영역보다 적은 영역의 속성을 변경하기 위해서 background 영역에 overlapping 됨.

=> 더 높은 우선순위의 영역은 background 영역의 속성 일부를 변경하면 됨

- background 영역의 또 다른 부분은 다른 영역의 제어하에 활성화 됨

=> 원치 않는 액세스로 부터 몇몇 사용되지 않은 메모리 영역을 보호함


- 커다란 특권 영역을 정의하고 있을 때, background 영역이 오버랩되어 더 작은 비특권 영역을 정의할 수 있음

- 더 작은 비특권 영역은 다른 유저 공간을 나타내기 위해 background 영역의 다른 영역으로 이동 할 수 있음

이전에 관리되던 영역은 background 영역에 의해 보호됨

=> user 영역은 특권 배경의 다른 부분을 액세스 하지만, user 레벨 속성을 갖는 윈도우로 동작


> 3개의 간단한 태스크 보호 방법 < 

- 영역 3은 active task의 보호 속성을 정의

- background 영역 0은 non-active한 태스크로의 액세스를 통제

- task 1이 active 할 때, background 영역은 task 1로부터 task 2와 task 3을 보호

- task 2가 active 할 때, background 영역은 task 2로부터 task 1과 task 3을 보호

task 3이 active 할 때, background 영역은 task 3로부터 task 1과 task 2를 보호

=> 영역 0이 특권모드로써 더 높은 특권을 가지고는 있지만, 영역 3이 우선순위가 더욱 높기 때문



### 13.2. Initializing the MPU, Caches, and Write Buffer


MPU, Caches, Write Buffer의 초기화를 위해, 제어 시스템은 타겟이 동작하는 동안 필요로하는 보호 영역을 정의해야 함

- 최소한 보호 장치를 enable하기 전 적어도 하나의 데이터 영역과 하나의 명령어 영역을 정의해야 함

- 제어 시스템은 기본 CP15 레지스터인 c1, c2, c3, c4, c5, c6의 값을 설정하여 MPU를 설정


> MPU 동작 제어를 위한 CP15의 레지스터들

* c1 : 기본 컨트롤 레지스터


- c2, c3으로 영역의 cache와 write buffer의 속성이 설정

- c5 : 영역 접근 권한 제어

- c6 : 각 영역의 위치와 크기를 정의하며 8 or 16개의 보조 레지스터를 가짐


> MPU, caches, write-buffer의 초기화 수행 단계

1. CP15:c6를 사용하여 명령어 및 데이터 영역의 크기와 위치를 정의

2. CP15:c5를 사용하여 각 영역에 대한 접근 권한을 설정

3. 캐시를 위해서는 CP15:c2, write-buffer를 위해서는 CP15:c3를 사용하여 각 영역을 위한 cache, write-buffer의 속성을 지정

4. CP15:c1을 사용하여 캐시와 MPU를 enable.


# 13.2.1. Defining Region Size and Location

- CP15:c6:c0:0 - CP15:c6:c7:0 까지의 8개의 보조 레지스터 중 하나의 값을 설정하여 각 영역의 크기와 주소 범위를 정의

=> 보조 코프로세서 레지스터 숫자는 각 영역의 ID에 매핑

- 각 영역의 시작주소는 그 크기의 배수인 주소로 정렬

ex. 영역의 크기 128KB, 0x20000의 배수가 되는 어떤 주소에서 시작


> 8개의 보조 레지스터 CP15:c6:c0 - CP15:c6:c7의 포맷과 비트필드



- base address : 상위 [31-12], 비트필드의 배수여야 함.

- 비트필드 : [5-1]

- E 필드 : [0]. 영역을 enable/disable

=> 영역은 정의 된 후 E비트가 0으로 disable되어 있다가, 1로 설정되면 enable 됨

- 사용하지 않는 비트들은 0으로 설정되어야 함

- 영역의 크기는 "size = 2^(N+1)" 또는 영역크기 인코딩 값(표 13.4)을 참고        
????, N(크기)의 2배수 값이 base address가 되야한 다는 게 이해가 잘..안됨
- N : 크기 설정을 위해 지수 값 설정.(4KB~4GB를 의미하는 11~31의 정수값)


- ARM740T, ARM946E-S. ARM1026EJ-S는 8개의 영역을 갖고,

 CP15:c6:cX 안의 보조 레지스터에 값을 설정하여 한 영역의 크기와 위치를 결정


ex. 영역 3을 시작위치 : 0x300000, 크기 : 256KB 로 설정하기


MOV    r1, #0x300000           ;시작 위치 : 0x300000

ORR     r1, r1, #0x11<<1        ;크기 : 256KB

MCR    p15, 0, r1, r6, c3, 0    ; CP15 보조 레지스터 값 쓰기



- ARM940T는 8개의 데이터영역과 8개의 명령어 영역을 각각 가짐

명령어 영역과 데이터 영역을 선택하기 위해 추가로 "opcode2"를 가짐


ex. 데이터 영역 5, 명령어 영역 5의 크기와 위치 읽기(2개의 MRC명령어가 필요함)


MCR    p15, 0, r2, c6, c5, 0    ; r2 = base address / size, 데이터 영역 5   => r2에 데이터 영역 5의 크기와 시작주소 로드

MCR    p15, 0, r3, c6, c5, 1    ; r3 = base address / size, 명령어 영역 5   => r3에 명령어 영역 5의 크기와 시작주소 로드


> Example 13.1 <

: 영역의 시작주소, 크기, E bit를 설정하는 방법


* C 프로토 타입

void regionSet(unsigned region, unsigned address, unsigned sizeN, unsigned enable);

enable : 속성 변경 중에는 비활성화, 변경이 완료되면 활성화


- 명령어 영역과 데이터 영역을 위해 동일한 크기와 시작주소 정보를 설정하여 ARM940T 영역을 하나로 통합

=> ARM940T용과 다른 코어용의 두 부분으로 분리하여 매크로를 작성

=> SET_REGION 매크로 : 동일한 루틴으로 4개의 MPU 코어를 지원,

정의된 영역을 위해 CP15:c6 보조 레지스터에 값을 설정하여 시작주소, 크기, 활성상태를 설정 


- address, sizeN, enable의 영역 속성을 c6f라는 unsigned 정수에 통합

- SET_REGION매크로로 만들어진 8개의 regionSet 루틴 중 하나로 분기


# 13.2.2. Access Permission

- 접근권한 방식의 2가지 : 표준 설정 방식, 확장 설정 방식


> CP15 레지스터 6 접근권한 


ARM740T, ARM940T, ARM946E-S, ARM1026EJ-S : 표준 설정 방식 지원

- 최신의 ARM946E-S, ARM1026EJ-S : 확장 설정 방식도 지원하며 2가지 레벨의 권한도 지원

- 확장설정 비트 필드 AP : 12개의 추가 권한 값을 지원하며, 비트 중 2개만 현재 할당되어 사용

- 정의되지 않은 인코드 값의 사용은 예기치 못한 동작을 발생


> 레지스터에 접근권한 부여

: CP15:c5 안의 보조 레지스터에 값을 설정


- 표준 AP 설정 : CP15:c5:c0:0, CP15:c5:c0:1

- 확장 AP 설정 : CP15:c5:c0:2 or CP15:c5:c0:3


> AP 레지스터를 위한 레지스터의 권한 비트 할당과 CP15 레지스터 5 접근권한 레지스터 포맷


- 확장 권한을 지원하는 프로세서는 표준 권한을 위해 작성된 소프트웨어에서 실행이 가능

- AP 레지스터 마지막으로 쓰여진 것이 표준 AP 레지스터라면 코어는 확장 권한을 사용 ???????????????

=> 표준 AP 레지스터에 쓰이는 것은 확장 AP 영역 엔트리의 [2:3]비트가 0을 클리어 함을 의미. 

확장 AP 레지스터에도 업데이트 되기 때문 ??


# 표준 AP

- 레지스터 CP15:c5:c0:0, CP15:c5:c0:1 안의 두 비트를 사용


CP15:c5:c0:0 : 데이터를 위한 AP를 설정

CP15:c5:c0:1 : 명령어영역을 설정


- 명령어와 데이터메모리를 위한 표준 AP를 읽기 위해, 2개의 레지스터를 읽어야 하므로 두개의 MRC 명령어를 사용


MRC    p15, 0, r1, c5, c0, 0        ; 데이터 영역 표준 AP. r1에 데이터 영역 메모리를 위한 AP 정보를 저장

MRC    p15, 0, r2, c5, c0, 1        ; 명령어 영역 표준 AP. r2에 명령어 영역 메모리를 위한 AP 정보를 저장


# 확장 AP

레지스터 CP15:c5:c0:2, CP15:c5:c0:3 안의 4개의 비트 사용


하나의 레지스터 : 8개의 영역을 위한 명령어 정보를 저장

또 하나의 레지스터 : 데이터 정보를 저장


CP15:c5:c0:2 : 데이터 영역을 위한 AP 설정

CP15:c5:c0:3 : 명령어 영역을 위한 AP 설정


- 데이터 영역 및 명령어 영역 확장 AP를 얻기위해,  2개의 레지스터를 읽어야 하므로 두개의 MRC 명령어를 사용


MRC    p15, 0, r3, c5, c0, 2       ; 데이터 영역 표준 AP. r3에 데이터 영역 AP 저장

MRC    p15, 0, r4, c5, c0, 3       ; 명령어 영역 표준 AP. r4에 명령어 영역 AP 저장


> Example 13.2 & 13.3 <

: 접근 권한을 사용하는 예


표준 AP 비트를 설정하기 위한 2가지 표준 AP 루틴


void regionSetISAP(unsigned region, unsigned ap);

void regionSetDSAP(unsigned region, unsigned ap);


region : 영역 번호

ap : 영역에 의해 제어되는 명령어나 데이터 메모리를 위한 표준 AP


> Example 13.2 <

: 접근 권한을 사용하는 예(표준 AP)


void regionSetISAP(unsigned region, unsigned ap)

{

unsigned c5f, shift;


shift = 2 * region;                                    /*  영역의 큭를 권한 비트필드 안에 저장되어있는 비트 수의 배수로 정의  */

__asm{ MRC    p15, 0, c5f, c5, c0, 1 }    /*  표준 I AP 로드  */

c5f = c5f &~ (0x3 << shift);                    /*  이전 AP 비트 클리어  */

c5f = c5f | (ap << shift);                          /*  새로운 AP 비트 설정  */

__asm{ MCR   p15, 0, c5f, c5, c0, 1 }    /*  표준 I AP 저장  */

}


void regionSetISAP(unsigned region, unsigned ap)

{

unsigned c5f, shift;


shift = 2 * region;                                    /*  영역의 크기를 권한 비트필드 안에 저장되어있는 비트 수의 배수로 정의  */

__asm{ MRC    p15, 0, c5f, c5, c0, 0 }    /*  표준 D AP 로드  */

c5f = c5f &~ (0x3 << shift);                    /*  이전 AP 비트 클리어  */

c5f = c5f | (ap << shift);                          /*  새로운 AP 비트 설정  */

__asm{ MCR   p15, 0, c5f, c5, c0, 0 }    /*  표준 DI AP 저장  */

}


> Example 13.3 <

: 접근 권한을 사용하는 예(확장 AP)


void regionSetIEAP(unsigned region, unsigned ap);

void regionSetDEAP(unsigned region, unsigned ap);


region : 영역 번호

ap : 영역에 의해 제어되는 명령어나 데이터 메모리를 위한 표준 AP


void regionSetIEAP(unsigned region, unsigned ap)

{

unsigned c5f, shift;


shift = 4 * region;                                    /*  영역의 크기를 권한 비트필드 안에 저장되어있는 비트 수의 배수로 정의  */

__asm{ MRC    p15, 0, c5f, c5, c0, 3 }    /*  확장 D AP 로드  */

c5f = c5f &~ (0x3 << shift);                    /*  이전 AP 비트 클리어  */

c5f = c5f | (ap << shift);                          /*  새로운 AP 비트 설정  */

__asm{ MCR   p15, 0, c5f, c5, c0, 3 }    /*  확장 D AP 저장  */

}


void regionSetIEAP(unsigned region, unsigned ap)

{

unsigned c5f, shift;


shift = 4 * region;                                    /*  영역의 큭를 권한 비트필드 안에 저장되어있는 비트 수의 배수로 정의  */

__asm{ MRC    p15, 0, c5f, c5, c0, 2 }    /*  확장 I AP 로드  */

c5f = c5f &~ (0x3 << shift);                    /*  이전 AP 비트 클리어  */

c5f = c5f | (ap << shift);                          /*  새로운 AP 비트 설정  */

__asm{ MCR   p15, 0, c5f, c5, c0, 2 }    /*  확장 I AP 저장  */

}



## 13.2.3. Setting Region Cache and Write Buffer Attributes


- CP15:c2:c0:0, CP15:c2:c0:1 : D캐시와 I캐시의 영역 속성값을 저장

- CP15:c3:c0:0 : 영역 쓰기 버퍼 속성을 저장, 메모리 데이터 영역에 제공


> CP15:c2 캐시와 CP15:c3 write buffer 영역 레지스터


> CP15:c2 및 CP15:c3 레지스터를 위한 비트필드 할당


CP15:c2:c0:1 : 8개의 명령어 영역을 위한 캐시 설정 데이터를 포함

CP15:c2:c0:0 : 8개의 데이터 영역을 포함

=> 둘 다  동일한 비트필드 인코딩 사용


> cache-bit : 캐시가 영역 내에 주어진 주소를 위해 활성화할지의 여부를 결정

-  ARM740T, ARM940T는 cache-bit에 상관없이 항상 캐시가 사용되므로

캐시의 정책이 cached->noncached로 변경되는 영역에서는 캐시를 flush(무조건), clean(가능하면) 해주는 것이 좋음

=> MPU 시스템은 캐시 정책이 write-through 방식에서 noncached 방식으로 변경될 때 항상 캐시를 flush 해야 함

=> write-back 방식에서는 캐시 flush와 clean을 모두 해야 함

- ARM946E-S 에서 cache-bit이 0이면 캐시안에 물리적 정보는 캐시로 복원되지 않고 외부 메모리 액세스가 수행됨

=> 캐시가 비활성화 되어 있을 때는 캐시를 flush하는데 필요한 요구사항을 줄여주지만, 오래된 영역에 대한 clean은 계속 적용 됨


CP15:c3:c0:0 : 8개의 영역 write buffer는 각 영역에 대한 write buffer의 활성화/비활성화를 조작


> 데이터 영역 설정 시 영역의 정책 결정

: write buffer bit, cache bit

 write buffer bit

 - 영역을 쓰기 위한 write buffer 활성화/비활성화 설정

 - 영역의 cache write policy를 설정

 cache bit

 - write buffer bit의 용도를 설정


 cache bit

  write buffer bit

 

 0

 0

 write buffer 비활성화 

 0

 1

 write buffer 활성화 

 1   

 0  

 write-through policy 적용

 1 1

 write-back policy 적용

(* cache와 write buffer 모두 활성화되고 write buffer bit은 캐시의 쓰기 정책을 판단)



> Example 13.4 <

: cache와 write buffer 활성화/비활성화 방법


- 인라인 어셈블러 사용

- cache와 write-buffer의 제어를 하나의 루틴 호출로 통합

- 캐시 쓰기 정책을 결정하기 위해서는 데이터 cache와 write buffer bit들을 모두 참조

- 명령어 cache bit은 단독 사용

* cache와 write-buffer의 상태를 각 영역을 위한 하나의 값으로 통합하면 영역 정보를 RCB로 모으는 것을 보다 쉽게 처리

(RCB : Region Control Block, 13.3.3절)


void regionSetCB(unsigned region, unsigned CB);

(region : 영역의 번호, CB : cache 속성 + write buffer 속성)



## 13.2.4. Enabling Regions and the MPU


# 초기화 과정

- 영역의 시작주소, 크기, E bit를 설정

- 접근권한 설정

- cache와 write buffer 활성화/비활성화

- 활성 영역을 enable : regionSet 루틴을 이용

- MPU, caches, write buffer를 enable : CP15:c1:c0:0안의 비트값을 수정

(CP15:c1:c0 안에 있는 MPU, caches, write buffer의 위치는 ARM940T, ARM946E-S, ARM1026EJ-S과 동일)


> Enable-bit의 위치


> CP15 컨트롤 레지스터 1에서의 보호 장치 활성 비트

> Example 13.5 < 

: MPU, caches를 enable하기 위해 "changeControl" 루틴을 사용

(but, changeControl 루틴은 CP15:c1:c0:0 레지스터 안에 있는 값들을 변경할 수 있음)???? 


void controlSet(unsigned value, unsigend mask);

(value : 변경할 비트를 포함하는 unsigned 정수 값, 

mask : 변경하기를 원하는 비트들을 선택하는데 사용. 

"value"와는 상관없이 1은 컨트롤 레지스터 안에 있는 비트를 변경, 0은 비트값이 변경되지 않고 그래도 유지되도록 함)


ex. MPU와 I캐시를 enabling, D캐시는 disabling        ????

=> [12]bit : 1,    [2]bit : 0,    [0]bit : 1

value : 0x00001001

mask : 0x00001005




### 13.3. Demonstration of an MPU System

: 고정된 메모리 맵을 사용하여 간단한 보호 시스템을 초기화하고 제어하기

(간단한 보호 멀티태스킹 시스템 안에서 동작하는 3개의 태스크를 enable)



## 13.3.1. 시스템 요구사항

- MPU를 가지는 ARM 코어

- 0x0에서 시작하고 0x40000으로 끝나는 256KB의 물리 메모리

- 0x10000000 ~ 0x12000000의 몇 MB 이상을 차지하는 메모리 매핑 된 몇가지 주변장치


* 모든 메모리 매핑된 주변장치는 보호를 필요로하는 하나의 메모리 영역으로 가정


- 시스템 소프트웨어는 크기가 64KB 이내

exception을 지원하기 위한 vector table, exception handler, data cache를 포함

- 시스템 소프트웨어는 user mode로 액세스 할 수 없음. system level의 권한을 갖음

=> user mode는 이 영역 안에 있는 코드나 데이터를 액세스 하기 위해 시스템 콜을 사용해야 함

- 크기가 64KB 이내인 공유 소프트웨어가 존재. 전체 시스템에 의해 액세스가 가능

user task 사이에 메시지를 보내기 위해 공통으로 사용되는 라이브러리와 데이터공간을 포함

- 시스템에서 독립적인 기능을 제어하는 3개의 user task가 존재. 

32KB 이내의 크기를 가짐. 실행될때는 각각 다른 2개의 task에 의한 액세스로부터 보호되어야 함

- 소프트웨어는 할당되어 있는 영역 내에서 소프트웨어 컴포넌트를 놓아두도록 연결


> 소프트웨어 메모리 맵


* 마지막 열에보면 영역은 4개임을 알 수 있음


> 영역 레이아웃을 나타내는 메모리 맵



## 13.3.2. 메모리맵을 사용하여 영역 할당하기


- Region 1 : 전체 메모리 공간을 사용할 수 있는 background 영역. 특권영역(어떤 user mode access라도 불가능)

명령어 캐시는 enabled, 데이터캐시는 write-back 방식으로 동작(??? why?)

가장 낮은 우선순위를 가짐

<기능> 

1. 0x0 ~ 0x10000사이의 64KB 공간을 제한적으로 액세스 하도록 함

2. 배경역역으로 동작하여 non-active한 user task를 위한 보호영역으로 동작

3. 배경 영역으로서는 디폴트로 전체 메모리 공간이 시스템 레벨의 액세스로 할당 되게 함

=> active한 user task에 인해 다른 user task가 액세스 되는 것을 보호


- Region 2 : 공유 시스템 자원을 액세스 하는 것을 제어

0x10000을 시작주소로 64KB의 크기를 가짐

공유 메모리 영역에 직접 매핑

보호된 영역 1의 일부분의 꼭대기에 위치하며 영역1보다 높은 우선순위를 가짐

user system 레빌의 메모리 액세스를 허용


- Region 3 : active한 task의 메모리 영역과 속성을 제어

context switching이 발생하는 동안 처럼,
     한 task에서 다른 task로 제어권이 넘어가면 OS는 영역 3이 실행중인 task의 메모리 영역과 overlap되도록 재정의를 수행함

새로운 task에 대한 위치가 다시 정해질 때, 이전 task는 영역 1의 일부가 되고 실행하는 task는 새롭게 영역 3이 됨

실행중인 task는 이전 task에 액세스 할 수 없음. (영역 1의 속성으로 보호되기 때문)


- Region 4 : 메모리 매핑된 주변장치의 공간

목적 : 해당 영역을 캐시와 버퍼를 사용하지 않는 영역으로 설정하는 것

이유? 캐시에 의해 발생되는 잘못된 데이터 문제와 write buffer를 사용할 대 포함 될 수 있는 시간이나 순서적 문제 때문에 

입력이나 출력 컨트롤 레지스터가 영향을 받지 않게 하기 위함



## 13.3.3. MPU의 초기화


# Region data type : 초기화 과정을 조직화 하기위해 만들어진 구조체

시스템 동작중에 사용되는 영역의 속성값들을 포함

MPU를 사용할 때에는 필요하지 않고 단지 예시 소프트웨어를 지원하기 위해 만들어낸, 설계상 편의를 목적으로 함

RCB(Region Control Block)


- 초기화 소프트웨어는 MPU안에 영역을 설정하기 위해 RCB 안에 저장된 정보를 이용

- RCB안에 정의되어 있는 Region 구조체는 물리적 영역보다 많이 있을 수 있음

ex. 영역 3은 task를 위해서만 사용되지만, 각 user task를 위해 영역 3을 사용하는 Region 구조체에는 3개가 있어야 함


typedef struct {

unsigned int number;            // Region에 할당되어 있는 MPU 영역 번호

unsigned int type;                  // 사용되는 접근 권한의 유형 (STANDARD, EXTENDED)

unsigned int baseaddress;     // 영역의 시작주소

unsigned int size;                   // 영역의 크기

unsigned int IAP;                    // 접근권한

unsigned int DAP;                  // 접근권한

unsigned int CB;                     // cache, write buffer 설정

} region;


- RCB 안에 저장되어있는 6개의 Region


> RCB 안에 있는 엔트리들에 대해 만든 매크로


- 4개의 문자 조합을 이용해 데이터와 명령어 메모리로의 접근권한을 입력

처음 2개 : system access permission, 나머지 2개 : user access permission

(RW / RO/ NA(no access))


- cache와 write buffer의 정보 : 명령어 캐시와 데이터 캐시 정책을 위한 속성으로 매핑

처음 문자 : C or c. 영역을 위한 명령어 캐시 활성화/비활성화

다음 2개 문자 : 데이터캐시 정책과 write buffer의 컨트롤 결정. 

WT : write-through, WB : write-back, 

Cb : =WT, CB : =WB, cB : 캐시를 사용하지 않고 버퍼만 사용, cb : 캐시와 버퍼 모두 사용하지 않음



## 13.3.4. 영역 설정 및 초기화


- "configRegion" 루틴(초기화 다음 단계에 위치)  

: 영역을 설명하는 데이터를 가지고 CP15레지스터를 조작하기 위해 RCB에서 하나의 Region 구조체 엔트리를 얻어 옴


void configRegion(region *region);

(*region : 영역의 RCB를 가리키는 포인터 값으로 루틴내에서 Region의 멤버들을 초기화 하는 과정에서 데이터 입력값으로 사용)


> MPU, cache, write buffer 초기화


void configRegion(Region *region) 

 /* Step 1 - Define the size and location of the instruction */

 /* and data regions using CP15:c6 */

regionSet(region->number, region->baseaddress, region->size, R_DISABLE);


/* Step 2 - Set access permission for each region using CP15:c5 */

if (region->type == STANDARD) { 

regionSetISAP(region->number, region->IAP); 

regionSetDSAP(region->number, region->DAP); 

else if (region->type == EXTENDED) 

{

regionSetIEAP(region->number, region->IAP); 

regionSetDEAP(region->number, region->DAP); 


/* Step 3 - Set the cache and write buffer attributes */ 

/* for each region using CP15:c2 for cache */ 

/* and CP15:c3 for the write buffer. */ 

regionSetCB(region->number, region->CB); 


/* Step 4 - Enable the caches, write buffer and the MPU */ 

/* using CP15:c6 and CP15:c1 */ 

regionSet(region->number, region->baseaddress, region->size, region->enable); 

}



## 13.3.5. MPU 초기화


- 모든 영역을 설명하는 데이터를 저장하기 위해 RCB를 사용

- MPU를 초기화 하기위해 "initActiveRegions"라는 상위레벨의 루틴을 사용

: 시스템이 시작될 때 활성화된 각각의 영역을 위해 한번씩만 호출

- MPU를 enable 시킴으로써 마무리


void initActiveRegions();        // 입력 파라미터 없음


- 시스템이 시작할 때 활성화 되어있는 영역인 

kernelRegion, shareRegion, peripheralRegion, task1Region을 위해 configRegion을 한번 씩 호출


#define ENABLEMPU (0x1) 

#define ENABLEDCACHE (0x1 << 2) 

#define ENABLEICACHE (0x1 << 12) 

#define MASKMPU (0x1) 

#define MASKDCACHE (0x1 << 2) 

#define MASKICACHE (0x1 << 12) 


void initActiveRegions() 

unsigned value,mask; 

configRegion(&kernelRegion); 

configRegion(&sharedRegion); 

configRegion(&peripheralRegion);

 configRegion(&task1Region); 


value = ENABLEMPU | ENABLEDCACHE | ENABLEICACHE; 

mask = MASKMPU | MASKDCACHE | MASKICACHE; 

controlSet(value, mask); 

}


=> 여기까지 시스템 초기화 완료!!!, 제어 시스템은 첫번재 태스크를 실행!!



## 13.3.6. 보호된 문맥전환

- 제어 시스템은 시스템 초기화가 완료 된 후 첫번재 태스트를 실행하며, 다른 태스크를 실행하기 위해 context switching을 수행

- RCB는 현재 task의 영역 문맥 정보를 포함하므로 CP15 레지스터로부터 영역 데이터를 저장할 필요가 없음


- (그림 13.7)에서 task 2로 변환하기 위해 OS는 region 3을 task 2의 메모리 영역으로 변경

- 현재 task와 다음 task 사이의 context switching을 수행하는 코드를 실행하기 전, 

초기화의 일부로 이 함수를 수행하기 위해 configRegion 루틴을 다시 사용 

- configRegion으로의 입력 값 : taask2Region


STMFD sp!, {r0-r3,r12,lr} 

BL configRegion 

LDMFD sp!, {r0-r3,r12,pc}     ; return


- C 함수


configRegion(&task2Region);



## 13.3.7. mpuSLOS

: SLOS(11장) 메모리 보호 장치를 추가한 제어시스템


> 기존 SLOS와의 차이점

mpuSLOS는 MPU를 완전히 사용

- applications는 커널과 분리되어 컴파일 디고 빌드된 다음 하나의 바이너리 파일에 통합

각 application은 다른 메모리 영역에서 실행되도록 링크 됨

- 3개의 applications은 각각 Static Application Loader 라는 루틴에 의해 32KB 크기의 분리된 고정 영역으로 로딩

이 주소는 Application의 시작 주소임

각 영역은 32KB의 크기를 가지므로 스택 포인터는 32KB의 상위값으로 설정

- applications는 device driver call에의해서만 하드웨어를 액세스

만약 application이 직접 하드웨어를 액세스 하려고 한다면 data abort가 발생 

(SLOS와 다른점. device가 application으로부터 직접 액세스 될 때는 data abort가 발생하지 않음)

- applications으로 분기하는 것은 spsr을 설정한 다음, 

MOVS 명령어를 사용하여 pc가 task1을 가리키는 엔트리포인터의 값으로 변경하는 작업을 포함

- 스케줄러가 호출될 경우에는 언제나 활성화된 영역2는 새로 실행되는 application을 반영하도록 변경 됨




### 13.4. Summary


# 메모리 protection

1.  unprotected : 태스크 상호 작용을 위한 규칙들을 관리하기 위해 소프트웨어적인 제어 루틴을 사용

2. protected : 태스크 상호작용을 관리하기 위해 하드웨어와 소프트웨어를 둘 다 사용.

=> 보호 시스템에서 접근권한이 침범을 받은 경우 하드웨어적으로 abort를 발생하여 메모리 영역을 보호함

소프트웨어는 발생한 abort 루틴을 처리하고 메모리 기반의 자원을 제어하도록 반응


# Region : ARM MPU가 시스템 보호를 위한 기본적으로 사용하는 struct

메모리 영역과 관련되어 있는 속성값들의 모임을 말함

# Backgroud Region : 영역은 overlap 될 수 있으므로,

현재 실행중인 태스크에 의한 원치않은 액세스로 부터 non-active한 상태의 task의 메모리를 보호하기위해 사용


# MPU를 초기화하는 단계

1. CP15:c5을 사용하여 명령어 및 데이터 영역의 크기와 위치를 설정

2. CP15:c5를 사용하여 각 영역에 대한 접근 권한을 설정

3. 각 영역을 위한 cache와 write buffer 속성을 지정

CP15:c2 : 캐시 설정

CP15:c3 : write buffer 설정

4. CP15:c6를 사용하여 활성화 영역을 Enabled

5. CP15:c1을 사용하여 cache, write buffer, MPU를 enabled


# 간단한 멀티태스킹 환경에서의 보호에 대한 예제

1. 보호 시스템 정의

2. 초기화

3. 초기화 후 보호시스템을 실행하는 데 필요한 태스크 변환 및 태스크로 영역할당 받기


# mpuSLOS






'System > Embedded' 카테고리의 다른 글

[ARM] 캐시 2  (0) 2015.11.12
[ARM] 캐시  (0) 2015.11.12
[ARM] 펌웨어  (0) 2015.11.12
[ARM] 익셉션과 인터럽트 처리 2  (0) 2015.11.10
[ARM] 익셉션과 인터럽트 처리  (0) 2015.11.10

+ Recent posts