← Documents Documentation/arch/arm64/memory.rst GitHub 원문 ↗

Linux 6.18.37 · Architecture

Memory Layout on AArch64 Linux

AArch64의 39/42/48/52비트 가상 주소 배치, TTBR 분리, KVM EL2 mapping, 52비트 사용자 공간 opt-in을 설명합니다.

Source pathDocumentation/arch/arm64/memory.rst
Source versionLinux v6.18.37
TranslationDUJINLABS 전문 번역 + 해설

요약·해설과 원문, 전문 번역을 서로 분리했습니다. API 이름, symbol, source path는 원문 표기를 사용합니다.

1. 요약·해설

원문의 핵심 논리와 kernel programming 관점의 보충 설명입니다. 아래의 전문 번역과는 별도로 작성했습니다.

요약과 해설

memory.rst:1-100

AArch64 Linux는 page size와 변환 단계 수에 따라 39비트부터 52비트까지 VA 공간을 구성합니다. 핵심은 user/kernel mapping을 `TTBR0`/`TTBR1`으로 분리하면서 하나의 kernel binary가 48비트와 52비트 hardware를 모두 지원하도록 높은 주소 영역을 안정적으로 유지하는 것입니다.

가상 주소 폭 선택
4KB page3-level39-bit / 512GB
4KB page4-level48-bit / 256TB
64KB page2-level42-bit / 4TB
64KB + ARMv8.2-LVA확장 first level52-bit

Page size와 hardware LVA 지원이 kernel이 사용할 수 있는 주소 폭을 결정합니다.

주소 공간 책임
요소내용불변 조건
`TTBR0`User non-global mapping`swapper_pg_dir` 기록 금지
`TTBR1`Kernel global mapping`swapper_pg_dir` 저장
`PAGE_OFFSET`Linear mapping 기준`0xFFF0000000000000`
`vabits_actual`실제 VA 폭Early boot에서 확정

TTBR과 VA 관련 값이 담당하는 역할을 구분합니다.

2. 영어 원문 전체

번역 기준이 된 Linux v6.18.37 원문입니다. 줄 번호는 이 버전의 파일 좌표입니다.

원문 전체 펼치기
1 ==============================
2 Memory Layout on AArch64 Linux
3 ==============================
4
5 Author: Catalin Marinas <catalin.marinas@arm.com>
6
7 This document describes the virtual memory layout used by the AArch64
8 Linux kernel. The architecture allows up to 4 levels of translation
9 tables with a 4KB page size and up to 3 levels with a 64KB page size.
10
11 AArch64 Linux uses either 3 levels or 4 levels of translation tables
12 with the 4KB page configuration, allowing 39-bit (512GB) or 48-bit
13 (256TB) virtual addresses, respectively, for both user and kernel. With
14 64KB pages, only 2 levels of translation tables, allowing 42-bit (4TB)
15 virtual address, are used but the memory layout is the same.
16
17 ARMv8.2 adds optional support for Large Virtual Address space. This is
18 only available when running with a 64KB page size and expands the
19 number of descriptors in the first level of translation.
20
21 TTBRx selection is given by bit 55 of the virtual address. The
22 swapper_pg_dir contains only kernel (global) mappings while the user pgd
23 contains only user (non-global) mappings. The swapper_pg_dir address is
24 written to TTBR1 and never written to TTBR0.
25
26 When using KVM without the Virtualization Host Extensions, the
27 hypervisor maps kernel pages in EL2 at a fixed (and potentially
28 random) offset from the linear mapping. See the kern_hyp_va macro and
29 kvm_update_va_mask function for more details. MMIO devices such as
30 GICv2 gets mapped next to the HYP idmap page, as do vectors when
31 ARM64_SPECTRE_V3A is enabled for particular CPUs.
32
33 When using KVM with the Virtualization Host Extensions, no additional
34 mappings are created, since the host kernel runs directly in EL2.
35
36 52-bit VA support in the kernel
37 -------------------------------
38 If the ARMv8.2-LVA optional feature is present, and we are running
39 with a 64KB page size; then it is possible to use 52-bits of address
40 space for both userspace and kernel addresses. However, any kernel
41 binary that supports 52-bit must also be able to fall back to 48-bit
42 at early boot time if the hardware feature is not present.
43
44 This fallback mechanism necessitates the kernel .text to be in the
45 higher addresses such that they are invariant to 48/52-bit VAs. Due
46 to the kasan shadow being a fraction of the entire kernel VA space,
47 the end of the kasan shadow must also be in the higher half of the
48 kernel VA space for both 48/52-bit. (Switching from 48-bit to 52-bit,
49 the end of the kasan shadow is invariant and dependent on ~0UL,
50 whilst the start address will "grow" towards the lower addresses).
51
52 In order to optimise phys_to_virt and virt_to_phys, the PAGE_OFFSET
53 is kept constant at 0xFFF0000000000000 (corresponding to 52-bit),
54 this obviates the need for an extra variable read. The physvirt
55 offset and vmemmap offsets are computed at early boot to enable
56 this logic.
57
58 As a single binary will need to support both 48-bit and 52-bit VA
59 spaces, the VMEMMAP must be sized large enough for 52-bit VAs and
60 also must be sized large enough to accommodate a fixed PAGE_OFFSET.
61
62 Most code in the kernel should not need to consider the VA_BITS, for
63 code that does need to know the VA size the variables are
64 defined as follows:
65
66 VA_BITS constant the *maximum* VA space size
67
68 VA_BITS_MIN constant the *minimum* VA space size
69
70 vabits_actual variable the *actual* VA space size
71
72
73 Maximum and minimum sizes can be useful to ensure that buffers are
74 sized large enough or that addresses are positioned close enough for
75 the "worst" case.
76
77 52-bit userspace VAs
78 --------------------
79 To maintain compatibility with software that relies on the ARMv8.0
80 VA space maximum size of 48-bits, the kernel will, by default,
81 return virtual addresses to userspace from a 48-bit range.
82
83 Software can "opt-in" to receiving VAs from a 52-bit space by
84 specifying an mmap hint parameter that is larger than 48-bit.
85
86 For example:
87
88 .. code-block:: c
89
90 maybe_high_address = mmap(~0UL, size, prot, flags,...);
91
92 It is also possible to build a debug kernel that returns addresses
93 from a 52-bit space by enabling the following kernel config options:
94
95 .. code-block:: sh
96
97 CONFIG_EXPERT=y && CONFIG_ARM64_FORCE_52BIT=y
98
99 Note that this option is only intended for debugging applications
100 and should not be used in production.
101

3. 한국어 전문 번역

영어 원문의 문단 순서와 의미를 유지한 전체 번역입니다. 코드, 함수명, symbol과 URL은 원문 표기를 유지합니다.

AArch64 가상 메모리 배치

1-35

저자: Catalin Marinas <catalin.marinas@arm.com>. 이 문서는 AArch64 Linux 커널이 사용하는 가상 메모리 배치를 설명합니다. 아키텍처는 4KB 페이지에서 최대 4단계, 64KB 페이지에서 최대 3단계의 변환 테이블을 허용합니다.

Linux는 4KB 페이지 구성에서 3단계 또는 4단계 변환 테이블을 사용합니다. 이에 따라 사용자 공간과 커널 공간 모두 각각 `39-bit`(512GB) 또는 `48-bit`(256TB) 가상 주소를 사용할 수 있습니다. 64KB 페이지에서는 2단계 변환 테이블만 사용해 42비트(4TB) 가상 주소를 제공하지만 메모리 배치 자체는 같습니다.

ARMv8.2의 선택 기능인 LVA(Large Virtual Address)는 64KB 페이지에서만 사용할 수 있으며 첫 번째 변환 단계의 descriptor 수를 늘립니다.

가상 주소의 55번 비트가 `TTBRx` 선택을 결정합니다. `swapper_pg_dir`에는 커널의 global mapping만, 사용자 `pgd`에는 사용자의 non-global mapping만 들어갑니다. `swapper_pg_dir` 주소는 `TTBR1`에 기록되며 `TTBR0`에는 절대 기록되지 않습니다.

VHE 없이 KVM을 사용할 때 hypervisor는 linear mapping에서 고정된, 경우에 따라 무작위인 offset을 두고 EL2에 커널 페이지를 매핑합니다. 자세한 내용은 `kern_hyp_va` macro와 `kvm_update_va_mask()`를 참조하십시오. GICv2 같은 MMIO 장치는 HYP identity-map page 옆에 매핑되고, 특정 CPU에서 `ARM64_SPECTRE_V3A`가 켜졌다면 vector도 같은 방식으로 배치됩니다. VHE를 사용하면 host kernel이 EL2에서 직접 실행되므로 추가 mapping을 만들지 않습니다.

커널의 52비트 VA 지원

36-76

ARMv8.2-LVA 선택 기능이 있고 64KB 페이지로 실행 중이면 사용자 공간과 커널 주소에 `52-bit` 주소 공간을 사용할 수 있습니다. 다만 52비트를 지원하는 커널 binary는 하드웨어 기능이 없을 때 초기 boot 단계에서 48비트로 되돌아갈 수 있어야 합니다.

이 fallback 때문에 커널 `.text`는 48비트와 52비트 VA에서 변하지 않는 높은 주소에 놓입니다. KASAN shadow는 전체 커널 VA 공간의 일정 비율이므로 shadow의 끝도 두 구성 모두에서 커널 VA 공간의 높은 절반에 있어야 합니다. 48비트에서 52비트로 전환하면 `~0UL`에 의존하는 끝 주소는 그대로이고 시작 주소가 더 낮은 주소 쪽으로 확장됩니다.

`phys_to_virt()`와 `virt_to_phys()`를 최적화하기 위해 `PAGE_OFFSET`은 52비트에 해당하는 `0xFFF0000000000000`으로 고정합니다. 추가 변수 읽기가 필요하지 않으며, 이 동작에 필요한 physvirt offset과 vmemmap offset은 초기 boot에서 계산합니다.

단일 binary가 48비트와 52비트 VA 공간을 모두 지원해야 하므로 `VMEMMAP`은 52비트 VA와 고정 `PAGE_OFFSET`을 모두 수용할 만큼 크게 잡아야 합니다. 대부분의 커널 코드는 `VA_BITS`를 의식할 필요가 없습니다. VA 크기가 필요한 코드는 다음 값을 사용합니다.

이름형태의미
`VA_BITS`constant지원하는 최대 VA 공간 크기
`VA_BITS_MIN`constant지원하는 최소 VA 공간 크기
`vabits_actual`variable실제로 선택된 VA 공간 크기

최대값과 최소값은 최악의 경우에도 buffer가 충분히 크거나 주소가 필요한 거리 안에 놓이는지 확인할 때 유용합니다.

사용자 공간의 52비트 VA

77-100

ARMv8.0의 최대 48비트 VA 공간에 의존하는 software와 호환되도록 커널은 기본적으로 48비트 범위에서 사용자 공간 가상 주소를 반환합니다.

Software는 48비트보다 큰 `mmap()` hint를 지정해 52비트 공간의 VA를 받도록 명시적으로 선택할 수 있습니다.

maybe_high_address = mmap(~0UL, size, prot, flags,...);

다음 kernel config option을 켜면 52비트 공간의 주소를 반환하는 debug kernel도 만들 수 있습니다.

CONFIG_EXPERT=y && CONFIG_ARM64_FORCE_52BIT=y

`CONFIG_ARM64_FORCE_52BIT`는 application debugging 전용이며 production 환경에서 사용하면 안 됩니다.