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

x86-64 커널의 32비트 진입과 long mode·가상 주소 전환

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

x86-64 부팅에서는 임시 매핑을 오래 유지하는 것이 오히려 잘못된 접근을 숨길 수 있습니다. 아래에서는 v6.18.37의 reset_early_page_tables 전체를 읽습니다. 압축 해제와 long mode 진입 전체 중, 이미 초기 C 실행이 가능한 단계에서 임시 표를 정리하는 작은 부분을 대표로 선택했습니다.

읽을 범위: v6.18.37 · arch/x86/kernel/head64.c · reset_early_page_tables 71–76행입니다. 아래에 이 범위의 원문과 각 줄의 설명을 실었습니다. 주제 전체의 흐름과 다른 경로는 기존 분석에서 함께 읽으실 수 있습니다.

먼저 알아둘 개념

CR3

현재 주소 변환에 사용할 최상위 페이지 표의 물리 위치와 관련 제어를 담습니다.

커널 기호 매핑

커널 코드가 계속 실행되는 높은 가상 주소 매핑입니다. 아래 memset은 마지막 PGD 항목을 남깁니다.

메모리 암호화 주소 비트

__sme_pa_nodebug는 부팅 환경의 SME 주소 표현을 고려합니다. 일반 가상 포인터를 그대로 CR3에 쓰는 코드가 아닙니다.

처음 읽을 때

지울 임시 매핑과 계속 실행에 필요한 커널 매핑을 구분해 그려 보십시오.

더 깊이 살펴볼 때

초기 page fault가 새 임시 매핑을 만드는 경로와 next_early_pgt 재설정의 관계를 검토하십시오.

그림으로 보는 변화

x86-64 커널의 32비트 진입과 long mode·가상 주소 전환의 단계별 개념 그림
각 단계에 화살표 의미와 생략 범위를 표시했습니다. 주소·숫자 예제는 실제 장치 값을 뜻하지 않습니다.
1단계 설명

1단계 고정

GIF 원본 열기

1. 임시 매핑 정리

최상위 표의 마지막 항목을 제외한 항목들을 0으로 만듭니다.

화살표는 페이지 표 데이터 수정입니다.

2. 표 할당 상태 초기화

초기 동적 표의 다음 할당 인덱스를 0으로 되돌립니다.

기존 사용자 프로세스를 삭제하는 동작이 아닙니다.

3. CR3 다시 적재

물리 주소 표현으로 바꾼 루트를 CPU에 씁니다.

페이지 표 메모리 변경을 실행 환경에 연결하는 단계입니다.

reset_early_page_tables를 한 줄씩 읽기

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

static void __init reset_early_page_tables(void)
{
	memset(early_top_pgt, 0, sizeof(pgd_t)*(PTRS_PER_PGD-1));
	next_early_pgt = 0;
	write_cr3(__sme_pa_nodebug(early_top_pgt));
}
static void __init reset_early_page_tables(void)

아주 초기의 임시 페이지 표를 정리하는 __init 함수입니다. long mode에 들어오기 전 어셈블리의 기능과 구분합니다.

	memset(early_top_pgt, 0, sizeof(pgd_t)*(PTRS_PER_PGD-1));

최상위 표에서 마지막 PGD 항목을 제외한 나머지를 0으로 지웁니다. 현재 실행에 필요한 커널 기호 매핑을 남겨 두려는 크기 계산입니다.

	next_early_pgt = 0;

동적 초기 페이지 표 풀의 다음 사용 위치를 0으로 되돌립니다. 실제 RAM 전체를 지우는 코드가 아닙니다.

	write_cr3(__sme_pa_nodebug(early_top_pgt));

메모리 암호화 주소 표현을 고려한 초기 루트의 물리 주소를 CR3에 다시 기록합니다. 페이지 표 메모리 수정만으로 끝내지 않고 CPU 변환 상태를 갱신합니다.

함께 생각해 볼 질문

왜 표 전체를 지우지 않습니까?

현재 커널 코드가 실행할 기호 매핑을 남겨야 하기 때문입니다.

이 함수가 long mode를 켭니까?

아닙니다. 그보다 뒤의 초기 C 단계 helper입니다.

next_early_pgt=0은 RAM 전체 초기화입니까?

아닙니다. 초기 동적 페이지 표의 사용 인덱스를 재설정합니다.

출처와 읽은 범위

Linux stable v6.18.37 · arch/x86/kernel/head64.c

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

맨 위로 ↑