# memblock: 사용할 RAM과 남겨 둘 RAM을 구분하기

v6.18.37 / mm/memblock.c

부팅 직후에는 일반 메모리 할당기가 아직 없습니다. 그렇지만 페이지 테이블과 커널 자료구조를 만들 RAM은 필요합니다. memblock은 RAM 구간과 예약 구간을 따로 기록하여, 이미 커널 이미지나 펌웨어가 쓰는 주소를 다시 나누어 주지 않도록 합니다. 여기서는 예약 정보를 등록하는 짧은 함수 전체를 읽습니다.

## __memblock_reserve

```c

int __init_memblock __memblock_reserve(phys_addr_t base, phys_addr_t size,
				       int nid, enum memblock_flags flags)
{
	phys_addr_t end = base + size - 1;

	memblock_dbg("%s: [%pa-%pa] nid=%d flags=%x %pS\n", __func__,
		     &base, &end, nid, flags, (void *)_RET_IP_);

	return memblock_add_range(&memblock.reserved, base, size, nid, flags);
}

```

### 928행

```c

int __init_memblock __memblock_reserve(phys_addr_t base, phys_addr_t size,

```

base부터 size바이트를 예약 목록에 넣는 함수입니다. phys_addr_t는 물리 주소를 담으며, 반환값은 등록 성공 여부를 나타냅니다.

### 929행

```c

				       int nid, enum memblock_flags flags)

```

nid는 NUMA 노드 정보이고 flags는 이 구간의 속성입니다. 주소만 기록하는 것이 아니라 이후 탐색과 병합에 필요한 정보도 함께 받습니다.

### 931행

```c

	phys_addr_t end = base + size - 1;

```

로그에서 마지막 바이트까지 보여 주려고 끝 주소를 계산합니다. 관리 범위를 반열린 구간으로 쓰면 base + size가 끝 경계입니다.

### 933행

```c

	memblock_dbg("%s: [%pa-%pa] nid=%d flags=%x %pS\n", __func__,

```

memblock 디버그 출력에 함수 이름과 예약 범위를 남깁니다. %pa는 물리 주소용 형식이며 주소값을 담은 변수의 포인터를 받습니다.

### 934행

```c

		     &base, &end, nid, flags, (void *)_RET_IP_);

```

시작·끝 주소, 노드, 속성, 호출 지점을 넘깁니다. _RET_IP_는 어느 초기화 코드가 이 RAM을 예약했는지 추적하는 데 사용됩니다.

### 936행

```c

	return memblock_add_range(&memblock.reserved, base, size, nid, flags);

```

memory 목록이 아니라 reserved 목록에 구간을 추가합니다. 겹침 처리와 필요한 목록 확장은 memblock_add_range가 담당하며 그 결과를 그대로 반환합니다.

