← Documents Documentation/arch/arm/kernel_mode_neon.rst GitHub 원문 ↗

Linux 6.18.37 · Architecture

Kernel mode NEON

kernel NEON/VFP state 관리, non-preemptible 제약과 compilation unit·compiler flag 분리 규칙을 설명합니다.

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

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

1. 요약·해설

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

요약과 해설

kernel_mode_neon.rst:1-124

kernel은 NEON/VFP state를 매 전환마다 보존하지 않으므로 사용 구간을 begin/end로 명시하고 sleep·interrupt context를 피해야 합니다. compiler가 경계를 이해하지 못하므로 NEON code와 호출 code를 서로 다른 compilation unit으로 분리하는 것이 안전성의 핵심입니다.

2. 영어 원문 전체

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

원문 전체 펼치기
1 ================
2 Kernel mode NEON
3 ================
4
5 TL;DR summary
6 -------------
7 * Use only NEON instructions, or VFP instructions that don't rely on support
8 code
9 * Isolate your NEON code in a separate compilation unit, and compile it with
10 '-march=armv7-a -mfpu=neon -mfloat-abi=softfp'
11 * Put kernel_neon_begin() and kernel_neon_end() calls around the calls into your
12 NEON code
13 * Don't sleep in your NEON code, and be aware that it will be executed with
14 preemption disabled
15
16
17 Introduction
18 ------------
19 It is possible to use NEON instructions (and in some cases, VFP instructions) in
20 code that runs in kernel mode. However, for performance reasons, the NEON/VFP
21 register file is not preserved and restored at every context switch or taken
22 exception like the normal register file is, so some manual intervention is
23 required. Furthermore, special care is required for code that may sleep [i.e.,
24 may call schedule()], as NEON or VFP instructions will be executed in a
25 non-preemptible section for reasons outlined below.
26
27
28 Lazy preserve and restore
29 -------------------------
30 The NEON/VFP register file is managed using lazy preserve (on UP systems) and
31 lazy restore (on both SMP and UP systems). This means that the register file is
32 kept 'live', and is only preserved and restored when multiple tasks are
33 contending for the NEON/VFP unit (or, in the SMP case, when a task migrates to
34 another core). Lazy restore is implemented by disabling the NEON/VFP unit after
35 every context switch, resulting in a trap when subsequently a NEON/VFP
36 instruction is issued, allowing the kernel to step in and perform the restore if
37 necessary.
38
39 Any use of the NEON/VFP unit in kernel mode should not interfere with this, so
40 it is required to do an 'eager' preserve of the NEON/VFP register file, and
41 enable the NEON/VFP unit explicitly so no exceptions are generated on first
42 subsequent use. This is handled by the function kernel_neon_begin(), which
43 should be called before any kernel mode NEON or VFP instructions are issued.
44 Likewise, the NEON/VFP unit should be disabled again after use to make sure user
45 mode will hit the lazy restore trap upon next use. This is handled by the
46 function kernel_neon_end().
47
48
49 Interruptions in kernel mode
50 ----------------------------
51 For reasons of performance and simplicity, it was decided that there shall be no
52 preserve/restore mechanism for the kernel mode NEON/VFP register contents. This
53 implies that interruptions of a kernel mode NEON section can only be allowed if
54 they are guaranteed not to touch the NEON/VFP registers. For this reason, the
55 following rules and restrictions apply in the kernel:
56 * NEON/VFP code is not allowed in interrupt context;
57 * NEON/VFP code is not allowed to sleep;
58 * NEON/VFP code is executed with preemption disabled.
59
60 If latency is a concern, it is possible to put back to back calls to
61 kernel_neon_end() and kernel_neon_begin() in places in your code where none of
62 the NEON registers are live. (Additional calls to kernel_neon_begin() should be
63 reasonably cheap if no context switch occurred in the meantime)
64
65
66 VFP and support code
67 --------------------
68 Earlier versions of VFP (prior to version 3) rely on software support for things
69 like IEEE-754 compliant underflow handling etc. When the VFP unit needs such
70 software assistance, it signals the kernel by raising an undefined instruction
71 exception. The kernel responds by inspecting the VFP control registers and the
72 current instruction and arguments, and emulates the instruction in software.
73
74 Such software assistance is currently not implemented for VFP instructions
75 executed in kernel mode. If such a condition is encountered, the kernel will
76 fail and generate an OOPS.
77
78
79 Separating NEON code from ordinary code
80 ---------------------------------------
81 The compiler is not aware of the special significance of kernel_neon_begin() and
82 kernel_neon_end(), i.e., that it is only allowed to issue NEON/VFP instructions
83 between calls to these respective functions. Furthermore, GCC may generate NEON
84 instructions of its own at -O3 level if -mfpu=neon is selected, and even if the
85 kernel is currently compiled at -O2, future changes may result in NEON/VFP
86 instructions appearing in unexpected places if no special care is taken.
87
88 Therefore, the recommended and only supported way of using NEON/VFP in the
89 kernel is by adhering to the following rules:
90
91 * isolate the NEON code in a separate compilation unit and compile it with
92 '-march=armv7-a -mfpu=neon -mfloat-abi=softfp';
93 * issue the calls to kernel_neon_begin(), kernel_neon_end() as well as the calls
94 into the unit containing the NEON code from a compilation unit which is *not*
95 built with the GCC flag '-mfpu=neon' set.
96
97 As the kernel is compiled with '-msoft-float', the above will guarantee that
98 both NEON and VFP instructions will only ever appear in designated compilation
99 units at any optimization level.
100
101
102 NEON assembler
103 --------------
104 NEON assembler is supported with no additional caveats as long as the rules
105 above are followed.
106
107
108 NEON code generated by GCC
109 --------------------------
110 The GCC option -ftree-vectorize (implied by -O3) tries to exploit implicit
111 parallelism, and generates NEON code from ordinary C source code. This is fully
112 supported as long as the rules above are followed.
113
114
115 NEON intrinsics
116 ---------------
117 NEON intrinsics are also supported. However, as code using NEON intrinsics
118 relies on the GCC header <arm_neon.h>, (which #includes <stdint.h>), you should
119 observe the following in addition to the rules above:
120
121 * Compile the unit containing the NEON intrinsics with '-ffreestanding' so GCC
122 uses its builtin version of <stdint.h> (this is a C99 header which the kernel
123 does not supply);
124 * Include <arm_neon.h> last, or at least after <linux/types.h>
125

3. 한국어 전문 번역

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

Kernel mode NEON

1-4

ARM kernel mode에서 NEON과 일부 VFP instruction을 안전하게 사용하는 규칙을 설명합니다.

TL;DR summary

5-16
  • NEON instruction 또는 support code에 의존하지 않는 VFP instruction만 사용합니다.
  • NEON code를 별도 compilation unit으로 격리하고 `-march=armv7-a -mfpu=neon -mfloat-abi=softfp`로 컴파일합니다.
  • NEON unit을 호출하는 code를 `kernel_neon_begin()`과 `kernel_neon_end()`로 감쌉니다.
  • NEON code 안에서 sleep하지 않으며 preemption disabled 상태로 실행됨을 고려합니다.

Introduction

17-27

kernel mode code에서 NEON instruction과 일부 VFP instruction을 사용할 수 있습니다. 그러나 성능 때문에 일반 register file과 달리 NEON/VFP register file은 context switch나 exception마다 preserve·restore하지 않으므로 수동 개입이 필요합니다.

`schedule()`을 호출할 수 있는 code처럼 sleep 가능성이 있는 code는 특히 주의해야 합니다. 아래 이유로 NEON/VFP instruction은 non-preemptible section에서 실행됩니다.

Lazy preserve and restore

28-48

NEON/VFP register file은 UP system에서 lazy preserve를, SMP와 UP 모두에서 lazy restore를 사용합니다. register file을 live 상태로 유지하고 여러 task가 NEON/VFP unit을 두고 경쟁하거나 SMP에서 task가 다른 core로 migrate할 때만 preserve·restore합니다.

lazy restore는 context switch마다 NEON/VFP unit을 disable해 구현합니다. 이후 NEON/VFP instruction이 나오면 trap이 발생하고 kernel이 필요할 때 state를 restore합니다.

kernel mode 사용은 이 scheme을 방해하면 안 됩니다. 따라서 NEON/VFP instruction 전에 register file을 eager preserve하고 unit을 명시적으로 enable해 첫 사용 exception을 막아야 합니다. `kernel_neon_begin()`이 이 작업을 수행합니다.

사용 후에는 `kernel_neon_end()`로 unit을 다시 disable해야 다음 user-mode 사용이 lazy restore trap을 통과합니다.

Interruptions in kernel mode

49-65

성능과 단순성을 위해 kernel-mode NEON/VFP register content에는 preserve/restore mechanism을 두지 않았습니다. 따라서 kernel-mode NEON section을 interrupt할 수 있는 경우는 interrupting code가 NEON/VFP register를 건드리지 않는다고 보장될 때뿐입니다.

  • interrupt context에서는 NEON/VFP code를 사용할 수 없습니다.
  • NEON/VFP code는 sleep할 수 없습니다.
  • NEON/VFP code는 preemption disabled 상태로 실행됩니다.

latency가 문제라면 NEON register가 하나도 live하지 않은 지점에서 `kernel_neon_end()` 직후 `kernel_neon_begin()`을 호출해 preemption window를 만들 수 있습니다. 그 사이 context switch가 없었다면 추가 begin 호출 비용은 비교적 작습니다.

VFP and support code

66-78

VFP version 3 이전 구현은 IEEE-754 compliant underflow 처리 등에 software support가 필요합니다. VFP unit은 지원이 필요하면 undefined instruction exception을 발생시키고, kernel은 VFP control register와 현재 instruction·argument를 검사해 software로 emulation합니다.

kernel mode에서 실행한 VFP instruction에는 이 software assistance가 구현되어 있지 않습니다. 해당 조건이 발생하면 kernel이 실패하고 OOPS를 생성합니다.

Separating NEON code from ordinary code

79-101

compiler는 `kernel_neon_begin()`과 `kernel_neon_end()` 사이에서만 NEON/VFP instruction을 내야 한다는 특별한 의미를 알지 못합니다. GCC는 `-mfpu=neon`을 선택하면 `-O3`에서 자체적으로 NEON instruction을 생성할 수 있습니다. 현재 kernel이 `-O2`여도 미래 변경으로 예상 밖 위치에 instruction이 생길 수 있습니다.

지원되는 유일한 사용 방식은 다음 규칙을 따르는 것입니다.

  • NEON code를 별도 compilation unit으로 격리하고 `-march=armv7-a -mfpu=neon -mfloat-abi=softfp`로 컴파일합니다.
  • `kernel_neon_begin()`, `kernel_neon_end()`와 NEON unit 호출은 `-mfpu=neon` 없이 빌드한 compilation unit에서 수행합니다.

kernel 전체가 `-msoft-float`로 컴파일되므로 이 분리는 optimization level과 관계없이 NEON·VFP instruction이 지정한 compilation unit에만 나타나도록 보장합니다.

NEON assembler

102-107

앞의 규칙을 지키는 한 NEON assembler는 추가 주의사항 없이 지원됩니다.

NEON code generated by GCC

108-114

`-O3`에 포함되는 GCC option `-ftree-vectorize`는 implicit parallelism을 활용해 일반 C source에서 NEON code를 생성합니다. 앞 규칙을 지키면 완전히 지원됩니다.

NEON intrinsics

115-124

NEON intrinsic도 지원됩니다. 다만 `<arm_neon.h>`가 kernel이 제공하지 않는 C99 header `<stdint.h>`를 include하므로 추가 규칙이 있습니다.

  • intrinsic을 포함한 unit을 `-ffreestanding`으로 컴파일해 GCC builtin `<stdint.h>`를 사용합니다.
  • `<arm_neon.h>`는 마지막에 include하거나 적어도 `<linux/types.h>` 뒤에 include합니다.