← Documents Documentation/devicetree/bindings/cpu/cpu-capacity.txt GitHub 원문 ↗

Linux 6.18.37 · Devicetree Bindings

CPU capacity bindings

Heterogeneous CPU의 normalized DMIPS/MHz capacity와 cluster 예제입니다.

Source pathDocumentation/devicetree/bindings/cpu/cpu-capacity.txt
Source versionLinux v6.18.37
TranslationDUJINLABS 전문 번역 + 해설

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

1. 요약·해설

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

요약과 해설

cpu-capacity.txt:1-238

Benchmark 측정, all-or-nothing 속성과 frequency 기반 normalization을 설명합니다.

2. 영어 원문 전체

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

원문 전체 펼치기
1 ==========================================
2 CPU capacity bindings
3 ==========================================
4
5 ==========================================
6 1 - Introduction
7 ==========================================
8
9 Some systems may be configured to have cpus with different power/performance
10 characteristics within the same chip. In this case, additional information has
11 to be made available to the kernel for it to be aware of such differences and
12 take decisions accordingly.
13
14 ==========================================
15 2 - CPU capacity definition
16 ==========================================
17
18 CPU capacity is a number that provides the scheduler information about CPUs
19 heterogeneity. Such heterogeneity can come from micro-architectural differences
20 (e.g., ARM big.LITTLE systems) or maximum frequency at which CPUs can run
21 (e.g., SMP systems with multiple frequency domains). Heterogeneity in this
22 context is about differing performance characteristics; this binding tries to
23 capture a first-order approximation of the relative performance of CPUs.
24
25 CPU capacities are obtained by running a suitable benchmark. This binding makes
26 no guarantees on the validity or suitability of any particular benchmark, the
27 final capacity should, however, be:
28
29 * A "single-threaded" or CPU affine benchmark
30 * Divided by the running frequency of the CPU executing the benchmark
31 * Not subject to dynamic frequency scaling of the CPU
32
33 For the time being we however advise usage of the Dhrystone benchmark. What
34 above thus becomes:
35
36 CPU capacities are obtained by running the Dhrystone benchmark on each CPU at
37 max frequency (with caches enabled). The obtained DMIPS score is then divided
38 by the frequency (in MHz) at which the benchmark has been run, so that
39 DMIPS/MHz are obtained. Such values are then normalized w.r.t. the highest
40 score obtained in the system.
41
42 ==========================================
43 3 - capacity-dmips-mhz
44 ==========================================
45
46 capacity-dmips-mhz is an optional cpu node [1] property: u32 value
47 representing CPU capacity expressed in normalized DMIPS/MHz. At boot time, the
48 maximum frequency available to the cpu is then used to calculate the capacity
49 value internally used by the kernel.
50
51 capacity-dmips-mhz property is all-or-nothing: if it is specified for a cpu
52 node, it has to be specified for every other cpu nodes, or the system will
53 fall back to the default capacity value for every CPU. If cpufreq is not
54 available, final capacities are calculated by directly using capacity-dmips-
55 mhz values (normalized w.r.t. the highest value found while parsing the DT).
56
57 ===========================================
58 4 - Examples
59 ===========================================
60
61 Example 1 (ARM 64-bit, 6-cpu system, two clusters):
62 The capacities-dmips-mhz or DMIPS/MHz values (scaled to 1024)
63 are 1024 and 578 for cluster0 and cluster1. Further normalization
64 is done by the operating system based on cluster0@max-freq=1100 and
65 cluster1@max-freq=850, final capacities are 1024 for cluster0 and
66 446 for cluster1 (578*850/1100).
67
68 cpus {
69 #address-cells = <2>;
70 #size-cells = <0>;
71
72 cpu-map {
73 cluster0 {
74 core0 {
75 cpu = <&A57_0>;
76 };
77 core1 {
78 cpu = <&A57_1>;
79 };
80 };
81
82 cluster1 {
83 core0 {
84 cpu = <&A53_0>;
85 };
86 core1 {
87 cpu = <&A53_1>;
88 };
89 core2 {
90 cpu = <&A53_2>;
91 };
92 core3 {
93 cpu = <&A53_3>;
94 };
95 };
96 };
97
98 idle-states {
99 entry-method = "psci";
100
101 CPU_SLEEP_0: cpu-sleep-0 {
102 compatible = "arm,idle-state";
103 arm,psci-suspend-param = <0x0010000>;
104 local-timer-stop;
105 entry-latency-us = <100>;
106 exit-latency-us = <250>;
107 min-residency-us = <150>;
108 };
109
110 CLUSTER_SLEEP_0: cluster-sleep-0 {
111 compatible = "arm,idle-state";
112 arm,psci-suspend-param = <0x1010000>;
113 local-timer-stop;
114 entry-latency-us = <800>;
115 exit-latency-us = <700>;
116 min-residency-us = <2500>;
117 };
118 };
119
120 A57_0: cpu@0 {
121 compatible = "arm,cortex-a57";
122 reg = <0x0 0x0>;
123 device_type = "cpu";
124 enable-method = "psci";
125 next-level-cache = <&A57_L2>;
126 clocks = <&scpi_dvfs 0>;
127 cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
128 capacity-dmips-mhz = <1024>;
129 };
130
131 A57_1: cpu@1 {
132 compatible = "arm,cortex-a57";
133 reg = <0x0 0x1>;
134 device_type = "cpu";
135 enable-method = "psci";
136 next-level-cache = <&A57_L2>;
137 clocks = <&scpi_dvfs 0>;
138 cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
139 capacity-dmips-mhz = <1024>;
140 };
141
142 A53_0: cpu@100 {
143 compatible = "arm,cortex-a53";
144 reg = <0x0 0x100>;
145 device_type = "cpu";
146 enable-method = "psci";
147 next-level-cache = <&A53_L2>;
148 clocks = <&scpi_dvfs 1>;
149 cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
150 capacity-dmips-mhz = <578>;
151 };
152
153 A53_1: cpu@101 {
154 compatible = "arm,cortex-a53";
155 reg = <0x0 0x101>;
156 device_type = "cpu";
157 enable-method = "psci";
158 next-level-cache = <&A53_L2>;
159 clocks = <&scpi_dvfs 1>;
160 cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
161 capacity-dmips-mhz = <578>;
162 };
163
164 A53_2: cpu@102 {
165 compatible = "arm,cortex-a53";
166 reg = <0x0 0x102>;
167 device_type = "cpu";
168 enable-method = "psci";
169 next-level-cache = <&A53_L2>;
170 clocks = <&scpi_dvfs 1>;
171 cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
172 capacity-dmips-mhz = <578>;
173 };
174
175 A53_3: cpu@103 {
176 compatible = "arm,cortex-a53";
177 reg = <0x0 0x103>;
178 device_type = "cpu";
179 enable-method = "psci";
180 next-level-cache = <&A53_L2>;
181 clocks = <&scpi_dvfs 1>;
182 cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
183 capacity-dmips-mhz = <578>;
184 };
185
186 A57_L2: l2-cache0 {
187 compatible = "cache";
188 };
189
190 A53_L2: l2-cache1 {
191 compatible = "cache";
192 };
193 };
194
195 Example 2 (ARM 32-bit, 4-cpu system, two clusters,
196 cpus 0,1@1GHz, cpus 2,3@500MHz):
197 capacities-dmips-mhz are scaled w.r.t. 2 (cpu@0 and cpu@1), this means that first
198 cpu@0 and cpu@1 are twice fast than cpu@2 and cpu@3 (at the same frequency)
199
200 cpus {
201 #address-cells = <1>;
202 #size-cells = <0>;
203
204 cpu0: cpu@0 {
205 device_type = "cpu";
206 compatible = "arm,cortex-a15";
207 reg = <0>;
208 capacity-dmips-mhz = <2>;
209 };
210
211 cpu1: cpu@1 {
212 device_type = "cpu";
213 compatible = "arm,cortex-a15";
214 reg = <1>;
215 capacity-dmips-mhz = <2>;
216 };
217
218 cpu2: cpu@2 {
219 device_type = "cpu";
220 compatible = "arm,cortex-a15";
221 reg = <0x100>;
222 capacity-dmips-mhz = <1>;
223 };
224
225 cpu3: cpu@3 {
226 device_type = "cpu";
227 compatible = "arm,cortex-a15";
228 reg = <0x101>;
229 capacity-dmips-mhz = <1>;
230 };
231 };
232
233 ===========================================
234 5 - References
235 ===========================================
236
237 [1] ARM Linux Kernel documentation - CPUs bindings
238 Documentation/devicetree/bindings/arm/cpus.yaml
239

3. 한국어 전문 번역

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

CPU heterogeneity 정보

1-13

한 chip 안에서 power/performance 특성이 다른 CPU를 함께 구성할 수 있습니다. Kernel이 차이를 인식하고 scheduling 결정을 내리려면 devicetree가 추가 정보를 제공해야 합니다.

CPU capacity 정의와 측정

14-41

CPU capacity는 scheduler에 CPU heterogeneity를 알려 주는 수치입니다. 차이는 ARM big.LITTLE 같은 microarchitecture 차이 또는 여러 frequency domain을 가진 SMP의 최대 frequency 차이에서 올 수 있습니다. 이 값은 CPU 상대 성능의 first-order approximation입니다.

적절한 benchmark로 capacity를 얻어야 합니다. 특정 benchmark의 유효성이나 적합성을 보장하지는 않지만 single-threaded 또는 CPU-affine이어야 하고, 실행 CPU frequency로 결과를 나누며, 실행 중 dynamic frequency scaling의 영향을 받지 않아야 합니다.

현재 권장 방식은 cache를 enable한 상태에서 각 CPU를 maximum frequency로 두고 Dhrystone을 실행하는 것입니다. DMIPS score를 실행 frequency(MHz)로 나눠 DMIPS/MHz를 구한 뒤 system에서 가장 높은 score를 기준으로 normalize합니다.

CPU capacity benchmark pipeline
CPU at maximum fixed frequencyCache enabled, scaling disabled
Single-threaded DhrystoneDMIPS score
DMIPS / frequency in MHzDMIPS/MHz
Normalize to highest scoreRelative capacity

Raw benchmark 결과를 frequency-independent relative capacity로 변환합니다.

capacity-dmips-mhz 속성

42-56

`capacity-dmips-mhz`는 CPU node의 선택적 u32 속성이며 normalized DMIPS/MHz로 CPU capacity를 나타냅니다. Boot 시 kernel은 해당 CPU의 maximum available frequency를 사용해 내부 capacity 값을 계산합니다.

이 속성은 all-or-nothing입니다. 한 CPU node에 지정했다면 모든 CPU node에 지정해야 하며, 하나라도 빠지면 모든 CPU가 default capacity로 fallback합니다.

cpufreq를 사용할 수 없으면 DT parsing 중 발견한 최고 `capacity-dmips-mhz` 값을 기준으로 이 값 자체를 normalize하여 final capacity를 계산합니다.

capacity-dmips-mhz 적용 규칙
ConditionKernel behavior
모든 CPU에 property + cpufreq availableDMIPS/MHz와 maximum frequency로 final capacity 계산
일부 CPU에만 property모든 CPU가 default capacity로 fallback
모든 CPU에 property + cpufreq unavailableDT 값 중 최고값 기준 직접 normalize

Property 완전성 및 cpufreq availability에 따른 계산 경로입니다.

ARM64 6-CPU, 2-cluster 예제

57-194

첫 예제는 ARM64 6-CPU system의 A57 cluster0 두 core와 A53 cluster1 네 core를 기술합니다. Scaled DMIPS/MHz 값은 cluster0이 1024, cluster1이 578입니다.

OS가 maximum frequency를 추가 반영합니다. Cluster0은 1100 MHz, cluster1은 850 MHz이므로 cluster0 final capacity는 1024, cluster1은 `578*850/1100 = 446`입니다.

CPU map, PSCI idle state, SCPI DVFS clock, shared L2 cache와 모든 CPU node의 `capacity-dmips-mhz`를 포함한 원문 예제를 그대로 보존합니다.

cpus {
        #address-cells = <2>;
        #size-cells = <0>;

        cpu-map {
                cluster0 {
                        core0 {
                                cpu = <&A57_0>;
                        };
                        core1 {
                                cpu = <&A57_1>;
                        };
                };

                cluster1 {
                        core0 {
                                cpu = <&A53_0>;
                        };
                        core1 {
                                cpu = <&A53_1>;
                        };
                        core2 {
                                cpu = <&A53_2>;
                        };
                        core3 {
                                cpu = <&A53_3>;
                        };
                };
        };

        idle-states {
                entry-method = "psci";

                CPU_SLEEP_0: cpu-sleep-0 {
                        compatible = "arm,idle-state";
                        arm,psci-suspend-param = <0x0010000>;
                        local-timer-stop;
                        entry-latency-us = <100>;
                        exit-latency-us = <250>;
                        min-residency-us = <150>;
                };

                CLUSTER_SLEEP_0: cluster-sleep-0 {
                        compatible = "arm,idle-state";
                        arm,psci-suspend-param = <0x1010000>;
                        local-timer-stop;
                        entry-latency-us = <800>;
                        exit-latency-us = <700>;
                        min-residency-us = <2500>;
                };
        };

        A57_0: cpu@0 {
                compatible = "arm,cortex-a57";
                reg = <0x0 0x0>;
                device_type = "cpu";
                enable-method = "psci";
                next-level-cache = <&A57_L2>;
                clocks = <&scpi_dvfs 0>;
                cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
                capacity-dmips-mhz = <1024>;
        };

        A57_1: cpu@1 {
                compatible = "arm,cortex-a57";
                reg = <0x0 0x1>;
                device_type = "cpu";
                enable-method = "psci";
                next-level-cache = <&A57_L2>;
                clocks = <&scpi_dvfs 0>;
                cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
                capacity-dmips-mhz = <1024>;
        };

        A53_0: cpu@100 {
                compatible = "arm,cortex-a53";
                reg = <0x0 0x100>;
                device_type = "cpu";
                enable-method = "psci";
                next-level-cache = <&A53_L2>;
                clocks = <&scpi_dvfs 1>;
                cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
                capacity-dmips-mhz = <578>;
        };

        A53_1: cpu@101 {
                compatible = "arm,cortex-a53";
                reg = <0x0 0x101>;
                device_type = "cpu";
                enable-method = "psci";
                next-level-cache = <&A53_L2>;
                clocks = <&scpi_dvfs 1>;
                cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
                capacity-dmips-mhz = <578>;
        };

        A53_2: cpu@102 {
                compatible = "arm,cortex-a53";
                reg = <0x0 0x102>;
                device_type = "cpu";
                enable-method = "psci";
                next-level-cache = <&A53_L2>;
                clocks = <&scpi_dvfs 1>;
                cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
                capacity-dmips-mhz = <578>;
        };

        A53_3: cpu@103 {
                compatible = "arm,cortex-a53";
                reg = <0x0 0x103>;
                device_type = "cpu";
                enable-method = "psci";
                next-level-cache = <&A53_L2>;
                clocks = <&scpi_dvfs 1>;
                cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
                capacity-dmips-mhz = <578>;
        };

        A57_L2: l2-cache0 {
                compatible = "cache";
        };

        A53_L2: l2-cache1 {
                compatible = "cache";
        };
};
ARM64 cluster normalization
A57 cluster01024 at 1100 MHz
System maximum referenceFinal capacity 1024
A53 cluster1578 at 850 MHz
578 x 850 / 1100Final capacity 446

DMIPS/MHz와 maximum frequency가 scheduler의 final capacity로 결합됩니다.

ARM32 4-CPU, 2-cluster 예제

195-232

두 번째 예제는 ARM32 4-CPU system입니다. CPU0과 CPU1은 1 GHz, CPU2와 CPU3은 500 MHz에서 동작하며 `capacity-dmips-mhz`는 앞 두 CPU가 2, 뒤 두 CPU가 1입니다.

같은 frequency에서 CPU0/1이 CPU2/3보다 두 배 빠르다는 뜻입니다. 실제 final capacity는 이 microarchitectural ratio와 각 maximum frequency를 함께 반영합니다.

cpus {
        #address-cells = <1>;
        #size-cells = <0>;

        cpu0: cpu@0 {
                device_type = "cpu";
                compatible = "arm,cortex-a15";
                reg = <0>;
                capacity-dmips-mhz = <2>;
        };

        cpu1: cpu@1 {
                device_type = "cpu";
                compatible = "arm,cortex-a15";
                reg = <1>;
                capacity-dmips-mhz = <2>;
        };

        cpu2: cpu@2 {
                device_type = "cpu";
                compatible = "arm,cortex-a15";
                reg = <0x100>;
                capacity-dmips-mhz = <1>;
        };

        cpu3: cpu@3 {
                device_type = "cpu";
                compatible = "arm,cortex-a15";
                reg = <0x101>;
                capacity-dmips-mhz = <1>;
        };
};

CPU binding 참조

233-238

CPU node 자체의 공통 속성은 ARM Linux Kernel CPU binding `Documentation/devicetree/bindings/arm/cpus.yaml`을 참조합니다.