Linux v6.6 · 개념과 코드 읽기

paging_init: RAM에 접근할 가상 주소 마련하기

이 코드는 어떤 문제를 푸나요?

RAM이 존재한다는 사실과 커널 포인터로 접근할 수 있다는 사실은 다릅니다. Linux v6.6의 paging_init은 최종 커널 매핑을 작성하고 TTBR1을 그 테이블로 교체한 뒤 초기 테이블 공간을 돌려줍니다. 주소를 해석하는 기준을 바꾸는 동안에도 코드가 계속 실행되어야 하므로 임시 매핑과 동일 주소 매핑이 필요합니다.

읽을 범위: v6.6 · arch/arm64/mm/mmu.c · paging_init 790–811행입니다. 아래에 이 범위의 원문과 각 줄의 설명을 실었습니다. 주제 전체의 흐름과 다른 경로는 기존 분석에서 함께 읽으실 수 있습니다.

먼저 알아둘 개념

선형 매핑

일정한 주소 변환 관계로 물리 RAM을 커널 가상 주소에 연결하는 영역입니다. 주소 구간을 잡는 것과 페이지 테이블 항목을 채우는 일을 함께 이해하셔야 합니다.

identity mapping

가상 주소 숫자와 물리 주소 숫자가 같은 매핑입니다. 주소 변환 체계를 바꾸는 낮은 수준의 코드에서 사용하며, 커널 전체가 항상 이 주소로 실행된다는 뜻은 아닙니다.

swapper_pg_dir

초기 커널 주소 공간의 최상위 페이지 테이블을 가리키는 심벌입니다. 이 인자를 전달하면 하위 함수가 어느 테이블을 갱신해야 하는지 알 수 있습니다.

처음 읽을 때

init_pg_dir, swapper_pg_dir, init_idmap_pg_dir를 서로 다른 표로 그려 보세요. 이전 부팅용 테이블, 새 커널 테이블, 전환을 도울 동일 주소 매핑의 역할을 구별하시면 됩니다.

더 깊이 살펴볼 때

pgd_set_fixmap의 임시 접근 주소와 cpu_replace_ttbr1의 전환 경로를 따라가 보세요. T0SZ 계산, 동일 주소 매핑과 TLB 관련 처리가 전환의 어느 시점에 필요한지 확인하는 연습입니다.

그림으로 보는 변화

paging_init: RAM에 접근할 가상 주소 마련하기의 단계별 개념 그림
각 단계에 화살표 의미와 생략 범위를 표시했습니다. 주소·숫자 예제는 실제 장치 값을 뜻하지 않습니다.
1단계 설명

1단계 고정

GIF 원본 열기

1. 수정할 테이블에 접근

pgd_set_fixmap → map_kernel / map_mem

화살표는 임시 매핑을 마련한 뒤 새 페이지 테이블을 작성하는 순서입니다.

2. 커널 주소 변환 기준 교체

cpu_replace_ttbr1 → init_mm.pgd 갱신

화살표는 하드웨어 변환 기준과 소프트웨어 관리 정보의 갱신 순서입니다. 원문은 초기 동일 주소 매핑을 전환에 사용합니다.

3. 이전 자원 회수와 후속 준비

init_pg_dir 해제 → memblock 확장 허용 → create_idmap

사용을 끝낸 부팅용 테이블을 회수합니다. 새 swapper_pg_dir를 해제하는 그림이 아닙니다.

paging_init를 한 줄씩 읽기

줄 번호는 v6.6 원문 기준입니다. 주석·빈 줄을 포함한 함수 전체를 먼저 보고, 그 아래에서 각 줄을 설명합니다.

void __init paging_init(void)
{
	pgd_t *pgdp = pgd_set_fixmap(__pa_symbol(swapper_pg_dir));
	extern pgd_t init_idmap_pg_dir[];

	idmap_t0sz = 63UL - __fls(__pa_symbol(_end) | GENMASK(VA_BITS_MIN - 1, 0));

	map_kernel(pgdp);
	map_mem(pgdp);

	pgd_clear_fixmap();

	cpu_replace_ttbr1(lm_alias(swapper_pg_dir), init_idmap_pg_dir);
	init_mm.pgd = swapper_pg_dir;

	memblock_phys_free(__pa_symbol(init_pg_dir),
			   __pa_symbol(init_pg_end) - __pa_symbol(init_pg_dir));

	memblock_allow_resize();

	create_idmap();
}
void __init paging_init(void)

arm64의 부팅 중 페이지 테이블 구성 함수입니다. v6.6에서는 커널 매핑 작성과 TTBR1 교체까지 이 함수에서 연결합니다.

	pgd_t *pgdp = pgd_set_fixmap(__pa_symbol(swapper_pg_dir));

swapper_pg_dir의 물리 주소를 구하고 fixmap의 임시 슬롯에 연결하여 수정 가능한 pgdp 주소를 얻습니다. 주소만 형 변환하는 것이 아니라 임시 매핑을 마련하는 호출입니다.

	extern pgd_t init_idmap_pg_dir[];

TTBR1 전환 중에 사용할 초기 동일 주소 매핑 테이블 심벌을 외부 선언합니다. 선언 자체가 테이블을 새로 만드는 것은 아닙니다.

	idmap_t0sz = 63UL - __fls(__pa_symbol(_end) | GENMASK(VA_BITS_MIN - 1, 0));

커널 끝 물리 주소와 최소 가상 주소 범위를 함께 고려해 동일 주소 매핑에 필요한 T0SZ 값을 계산합니다. __fls는 가장 높은 설정 비트를 찾아 필요한 주소 비트 수 판단에 사용됩니다.

	map_kernel(pgdp);

임시로 접근 가능한 커널 최상위 테이블에 커널 이미지의 코드·데이터 매핑을 작성합니다. 구간별 권한 등은 map_kernel이 처리합니다.

	map_mem(pgdp);

같은 테이블에 물리 RAM의 선형 매핑을 작성합니다. 커널 이미지 매핑과 일반 RAM 접근용 선형 매핑을 구분하셔야 합니다.

	pgd_clear_fixmap();

테이블 작성을 위해 사용한 임시 fixmap 슬롯을 해제합니다. 방금 작성한 커널 페이지 테이블 자체를 폐기하는 것이 아닙니다.

	cpu_replace_ttbr1(lm_alias(swapper_pg_dir), init_idmap_pg_dir);

초기 동일 주소 매핑을 사용하여 TTBR1을 새 커널 페이지 테이블로 교체합니다. lm_alias는 테이블에 대한 선형 매핑 쪽 주소를 제공하며 단순 포인터 대입보다 큰 주소 변환 전환입니다.

	init_mm.pgd = swapper_pg_dir;

초기 커널 mm 자료구조도 새 최상위 테이블을 가리키도록 맞춥니다. 하드웨어 기준과 소프트웨어 관리 정보를 일치시키는 단계입니다.

	memblock_phys_free(__pa_symbol(init_pg_dir),

전환 전 사용하던 init_pg_dir 메모리 구간을 memblock 예약에서 해제하기 시작합니다. 아래줄이 해제 크기를 계산합니다.

			   __pa_symbol(init_pg_end) - __pa_symbol(init_pg_dir));

init_pg_dir 시작부터 init_pg_end까지의 물리 주소 차이를 크기로 넘깁니다. swapper_pg_dir 자체를 해제하는 호출과 혼동하지 않으셔야 합니다.

	memblock_allow_resize();

이제 memblock의 내부 구간 배열이 필요할 때 확장될 수 있도록 허용합니다. 이 호출 자체가 모든 배열을 즉시 늘리지는 않습니다.

	create_idmap();

이후 낮은 수준의 주소 변환 전환 등에 사용할 동일 주소 매핑을 구성합니다. 앞에서 잠시 사용한 init_idmap_pg_dir와 사용 시점을 구별해서 읽으셔야 합니다.

함께 생각해 볼 질문

fixmap은 새 커널 주소 공간 전체인가요?

아닙니다. 여기서는 페이지 테이블을 수정하기 위한 임시 접근 슬롯으로 사용합니다. 실제 커널 매핑은 map_kernel과 map_mem이 작성합니다.

TTBR1을 교체하기 전에 테이블을 만드는 이유는 무엇인가요?

주소 변환 기준을 새 테이블로 바꾼 직후에도 커널의 코드와 데이터 접근이 가능해야 하기 때문입니다.

어느 테이블 메모리를 해제하나요?

init_pg_dir부터 init_pg_end까지의 이전 부팅용 테이블 공간입니다. 새로 활성화한 swapper_pg_dir를 해제하는 것이 아닙니다.

출처와 읽은 범위

Linux stable v6.6 · arch/arm64/mm/mmu.c

해당 버전 원본 파일 · 기존 코드 분석 · 설명 원고

맨 위로 ↑