# Memory Management

	* memory map at boot time
	+-------------------------+ _ram_end(e.g. 0x2000ffff)
	| | initial kernel stack  |
	| |                       |
	| v                       |
	|-------------------------|
	| .bss                    |
	|-------------------------|
	| .data                   |
	|-------------------------|
	| .vector                 |
	+-------------------------+ _ram_start(e.g. 0x20000000)

	* task memory space
	+-------------+ mm.sp           -
	|   |         |                 ^
	|   |         |                 |
	|   |         |                 |
	|   | stack   | USER_STACK_SIZE |
	|   |         |                 |
	|   |         |                 |
	|   |         |                 |
	|   v         |                 |
	|   -         |               - |
	|   ^         |               ^ |
	|   | heap    |     HEAP_SIZE | |
	|   |         |               v v
	+-------------+ mm.base       - -

	+-------------+ mm.kernel.sp    -
	|   |         |                 ^
	|   | kernel  |                 |
	|   | stack   |      STACK_SIZE |
	|   |         |                 |
	|   v         |                 v
	+-------------+ mm.kernel.base  -

초기 커널 스택은 `_ram_end`을 시작으로 `STACK_SIZE`만큼 할당되어야 함. 초기
커널 스택에 해당하는 버디 `free_area`의 마지막 페이지들이 사용중으로 마크됨.

malloc()은 kmalloc()의 랩퍼일 뿐, 차후에 단편화를 고려한 slab과 같은 캐시를
구현하는 것도 고려해볼만..

~~시스템 부팅부터 init 태스크로 제어가 넘어가기 전까지 커널 스택이 보호되지
않고 버디 `free_area`에 들어가 있음. 초기화 막바지에 커널 스택은 init 태스크
스택으로 교체되기 때문에 문제는 없을 것으로 보이지만, 주의하고 있을 필요가
있음. 버디 초기화 시에 확실히 마크하고 init으로 제어가 넘어갈 때
free해야함!~~미뤄두었다가 피봤음.

~~AVR에 포팅할 것도 고려하고 있는데 페이징은 좀 무리인 듯. page 구조체 사이즈가
못해도 7바이트는 되어야 하는데 atmega128 sram이 4kb 밖에 안되니까.~~

~~그에 알맞은 메모리 관리자를 생각해보고 구현하자. 그리고 페이징 메모리
관리자와 새로운 메모리 관리자 모두 CONFIGURE 할 수 있도록. 페이징과 버디
할당자를 각 파일로 떼어낼 것.~~

폴트 발생시 `CONFIG_DEBUG` 옵션으로 컴파일 한 후 자세한 로그를 확인할 것.
시스템 운영에 필요한 최소한의 가용 메모리가 부족할 확률이 높음(kmalloc()).

## Buddy allocator

지수법칙을 활용한 메모리 할당자. 2의 누승에서 `n^2 = n + n` 이 된다. 쪼개진 이
두 개의 n을 버디라고 한다. 두개가 한 쌍인 버디는 하나의 상태비트를 갖는다.
상태비트는 버디가 할당되거나 해제될 때마다 토글된다. 즉, 비트 값이 0일 경우
한쌍인 두개의 버디는 모두 할당되었거나 해제된 상태이고, 비트 값이 1일 경우 둘
중 하나의 버디만 할당된 상태를 뜻한다.

할당시 요청한 크기의 버디가 없다면 상위 버디 하나를 쪼개어 할당하고 남는 한
쪽의 버디는 하위 버디 리스트에 추가한다.

해제시 해당 크기의 버디 리스트에 추가하는데 이때 상태비트를 확인하여 비트 값이
0인 경우(두개의 버디 모두가 해제된 경우) 두 버디를 합쳐 상위 버디 리스트에
추가한다. 상위 버디 리스트로 합칠 수 있는만큼 반복한다.

버디 할당자는 페이징 메모리 관리자 하에서 동작한다.

## First fit allocator

연속된 주소 공간을 하나의 구간chunk으로 가용한 구간들을 서로 연결 관리한다.
메모리 할당 요청이 일어나면 요청 크기를 만족하는 구간을 찾을 때까지 처음부터
검색한다. 찾은 구간이 동일한 크기일 경우 변경사항 없이 해당 구간을 할당하고,
그보다 큰 구간일 경우 쪼갠 나머지를 다시 `free_area` 영역으로 연결한다.

할당된 메모리가 다시 `free_area` 영역으로 연결하면서 해제를 수행한다. 단편화를
고려하여 해제된 구간은 다음 구간과 연속된 메모리 어드레스를 갖는지 확인한 후
연속된 구간이라면 두 구간을 합친다. 연속된 구간이 나타나지 않을 때까지
반복한다.

	 ----------------------     ----------------------
	| meta | ///////////// | - | meta | ///////////// | - ...
	 ----------------------     ----------------------
	^HEAD

할당은 낮은주소-높은주소 순으로 이루어지기 때문에 할당/해제 두 경우 모두 head
포인터를 적절히 변경해주어야 한다.

~~페이징 대용뿐만 아니라 유저용 `malloc()`으로 사용. 커널로부터 `kmalloc()`으로
확보된 메모리의 2차 할당자로. 고비용의 인터럽트 금지 부분을 제거하고,
해제함수에서 내부 단편화를 고려한 루프문도 제거할 것.~~

## Paging

	_ram_start(e.g. 0x20000000)                                _ram_end
	^----------------------------------------------------------^
	| kernel data | mem_map | bitmap |//////////////////////////|
	 -----------------------------------------------------------
	              ^mem_map

	page flags:
	31 30 29 ...... 26 17 16 15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00
	 -----------------------------------------------------------------------
	| reserved              |   ORDER   |           PAGE_FLAGS*             |
	 -----------------------------------------------------------------------

	  *PAGE_FLAGS
	   -------------------------------------------------------
	  | NO | ELEMENT        | DESCRIPTION                     |
	   -------------------------------------------------------
	  |  1 | PAGE_BUDDY     | page(s) allocated by buddy      |
	  |  2 |                |                                 |
	  |  3 |                |                                 |
	  |  4 |                |                                 |
	  |      ...                                              |
	  | 12 |                |                                 |
	   -------------------------------------------------------

	   PAGE_BUDDY flag set by `alloc_pages()` and cleared by `free()`,
	   checking if it is really allocated by buddy allocator.

`mem_map`은 시스템 전체 메모리를 관리하기 위한 메타정보를 저장한 배열이고, 전체
메모리에서 zone 단위로 나눠 사용할 수 있다.
