부트로더에서 이 함수까지 이어 보기
U-Boot가 최종 DTB 주소를 x0로 넘기면 head.S가 이를 보존하고, 초기 커널이 물리 DTB를 읽을 가상 주소를 준비합니다. bootargs·initramfs·RAM·예약 영역의 정보는 이 DTB 안에서 읽습니다. 주소 전달, 매핑, 예약과 내용 해석을 별개의 동작으로 따라가면 이 함수가 부트로더에 기대하는 조건을 확인할 수 있습니다.
이 코드는 어떤 문제를 푸나요?
커널이 처음 실행될 때에는 장치와 사용 가능한 RAM을 아직 모릅니다. 펌웨어와 부트로더가 준 정보를 실제로 읽을 수 있는 주소에 연결해야 합니다. arm64는 DTB 또는 ACPI를, x86은 boot_params·메모리 지도·ACPI 등을, RISC-V는 DTB 및 SBI 환경 등을 이용합니다. 여기서는 arm64 DTB 초기 처리 함수를 대표로 읽습니다.
읽을 범위: v6.18.37 · arch/arm64/kernel/setup.c · setup_machine_fdt 170–208행입니다. 아래에 이 범위의 원문과 각 줄의 설명을 실었습니다. 주제 전체의 흐름과 다른 경로는 기존 분석에서 함께 읽으실 수 있습니다.
먼저 알아둘 개념
물리 주소와 가상 주소
부트로더가 준 DTB의 물리 주소를 C 코드에서 바로 역참조할 수 있는 것은 아닙니다. fixmap으로 접근 가능한 가상 주소를 준비합니다.
memblock 예약
초기 메모리 할당기가 DTB 저장 영역을 다른 용도로 덮지 않도록 표시하는 작업입니다.
__init
부팅 후 회수할 수 있는 초기화 코드 영역에 함수를 두는 표시입니다. 특별한 CPU 명령은 아닙니다.
처음 읽을 때
DTB를 받은 주소, 매핑한 주소, 예약한 범위를 다른 색으로 구분해 보십시오.
더 깊이 살펴볼 때
fixmap 주소에 일반 __pa 변환을 적용할 수 없는 이유와 초기 실패 경로의 제약을 살펴보십시오.
그림으로 보는 변화

1. DTB 접근 준비
물리 주소를 fixmap에 매핑하고 크기를 얻습니다.
화살표는 같은 DTB 바이트에 접근할 주소를 준비하는 과정입니다.
2. 덮어쓰기 방지와 검사
memblock에 영역을 예약하고 DTB 구조를 읽습니다.
예약은 데이터 보존, 스캔은 내용 해석이라는 서로 다른 작업입니다.
3. 읽기 전용 전환
초기 수정을 마친 DTB를 읽기 전용으로 다시 매핑합니다.
초기 입력을 이후 커널에서 보존하는 권한 변화입니다.
setup_machine_fdt를 한 줄씩 읽기
줄 번호는 v6.18.37 원문 기준입니다. 주석·빈 줄을 포함한 함수 전체를 먼저 보고, 그 아래에서 각 줄을 설명합니다.
static void __init setup_machine_fdt(phys_addr_t dt_phys)
{
int size = 0;
void *dt_virt = fixmap_remap_fdt(dt_phys, &size, PAGE_KERNEL);
const char *name;
if (dt_virt)
memblock_reserve(dt_phys, size);
/*
* dt_virt is a fixmap address, hence __pa(dt_virt) can't be used.
* Pass dt_phys directly.
*/
if (!early_init_dt_scan(dt_virt, dt_phys)) {
pr_crit("\n"
"Error: invalid device tree blob: PA=%pa, VA=%px, size=%d bytes\n"
"The dtb must be 8-byte aligned and must not exceed 2 MB in size.\n"
"\nPlease check your bootloader.\n",
&dt_phys, dt_virt, size);
/*
* Note that in this _really_ early stage we cannot even BUG()
* or oops, so the least terrible thing to do is cpu_relax(),
* or else we could end-up printing non-initialized data, etc.
*/
while (true)
cpu_relax();
}
/* Early fixups are done, map the FDT as read-only now */
fixmap_remap_fdt(dt_phys, &size, PAGE_KERNEL_RO);
name = of_flat_dt_get_machine_name();
if (!name)
return;
pr_info("Machine model: %s\n", name);
dump_stack_set_arch_desc("%s (DT)", name);
}static void __init setup_machine_fdt(phys_addr_t dt_phys)부트로더가 전달한 DTB 물리 주소를 받아 초기 매핑과 구조 해석을 준비합니다. __init 코드는 부팅 후 회수 가능한 영역에 놓입니다.
int size = 0;DTB 크기의 출력값을 받을 변수를 0으로 준비합니다. 처음부터 크기를 알고 있다고 가정하지 않습니다.
void *dt_virt = fixmap_remap_fdt(dt_phys, &size, PAGE_KERNEL);물리 DTB를 fixmap에 연결해 C에서 읽을 가상 주소를 얻습니다. &size로 실제 크기도 받으며 초기 접근 속성은 PAGE_KERNEL입니다.
const char *name;뒤에서 DTB의 machine model 문자열을 받을 포인터를 선언합니다.
if (dt_virt)매핑이 성공해 유효한 가상 주소를 얻었는지 확인합니다.
memblock_reserve(dt_phys, size);초기 할당기가 DTB 물리 영역을 다른 용도로 덮어쓰지 않도록 예약합니다. 매핑과 메모리 예약은 다른 작업입니다.
if (!early_init_dt_scan(dt_virt, dt_phys)) {DTB를 검사하고 초기 정보를 읽습니다. fixmap 주소를 __pa로 역변환하지 않고 원래 dt_phys를 별도로 전달합니다.
pr_crit("\n"DTB 검사가 실패했음을 심각한 오류 메시지로 출력하기 시작합니다.
"Error: invalid device tree blob: PA=%pa, VA=%px, size=%d bytes\n"오류를 재현할 수 있도록 DTB의 물리 주소·가상 주소·크기를 메시지에 포함합니다. %pa에는 물리 주소 변수의 주소를 넘깁니다.
"The dtb must be 8-byte aligned and must not exceed 2 MB in size.\n"부팅 프로토콜이 요구하는 DTB의 8바이트 정렬 및 2MiB 크기 제한을 안내하는 문자열입니다.
"\nPlease check your bootloader.\n",입력 DTB를 준비한 부트로더를 확인하도록 안내하고 앞선 문자열을 끝냅니다. 여러 C 문자열은 컴파일 때 이어집니다.
&dt_phys, dt_virt, size);앞 메시지의 서식 항목에 물리 주소 변수의 주소, 매핑 주소, 크기를 전달합니다.
while (true)매우 초기라 정상적인 오류 처리도 기대하기 어려우므로 무한 반복으로 더 진행하지 않습니다.
cpu_relax();반복 대기용 cpu_relax를 실행합니다. 잘못된 DTB 상태로 일반 초기화를 계속하지 않으려는 경로입니다.
fixmap_remap_fdt(dt_phys, &size, PAGE_KERNEL_RO);초기 DTB 수정이 끝난 뒤 같은 영역을 읽기 전용으로 다시 매핑해 이후 의도치 않은 변경을 제한합니다.
name = of_flat_dt_get_machine_name();펼치기 전의 DTB에서 기계 모델 이름을 얻습니다.
if (!name)선택적인 모델 문자열이 없을 경우를 검사합니다.
return;이름이 없어도 앞선 초기화는 끝났으므로 함수에서 돌아갑니다.
pr_info("Machine model: %s\n", name);부팅 로그에 모델 이름을 남겨 사용 중인 플랫폼을 확인하게 합니다.
dump_stack_set_arch_desc("%s (DT)", name);이후 스택 덤프에도 표시할 아키텍처 설명을 등록합니다.
함께 생각해 볼 질문
DTB를 매핑하면 그 메모리가 예약됩니까?
매핑과 예약은 다릅니다. 이 함수가 fixmap_remap_fdt 다음에 memblock_reserve를 따로 호출하는 이유입니다.
DTB가 깨져 있으면 일반적인 오류 화면이 나옵니까?
아주 초기 단계에는 정상적인 오류 처리 환경도 부족합니다. 이 함수는 메시지를 남긴 뒤 반복 대기합니다.
세 아키텍처가 같은 부팅 자료를 받습니까?
아닙니다. 각 부팅 프로토콜의 레지스터·구조체·펌웨어 인터페이스를 따로 확인해야 합니다.
출처와 읽은 범위
Linux stable v6.18.37 · arch/arm64/kernel/setup.c
해당 버전 원본 파일 · 기존 코드 분석 · 설명 원고
