Linux cpu topology
程序员文章站
2024-03-19 09:42:46
...
CPU topology
代码结构
arch/arm/kernel/topology.c
init/main.c
start_kernel
rest_init
kernel_init
kernel_init_freeable
smp_prepare_cpus
arch/arm/kernel/smp.c
smp_prepare_cpus
init_cpu_topology
arch/arm/kernel/topology.c
init_cpu_topology
451 void __init init_cpu_topology(void)
452 {
453 reset_cpu_topology(); //topology初始化
454
455 smp_wmb();
456
457 /*
458 * Discard anything that was parsed if we hit an error so we
459 * don't use partial information.
460 */
461 if (of_have_populated_dt() && parse_dt_topology()) // parse_dt_topology解析dt
462 reset_cpu_topology();
463 else
464 set_sched_topology(arm_topology); //设置调度策略
465 }
16 cpus {
17 #address-cells = <2>;
18 #size-cells = <0>;
19
20 cpu-map {
21 cluster0 {
22 core0 {
23 cpu = <&CPU0>;
24 };
25 core1 {
26 cpu = <&CPU1>;
27 };
28 core2 {
29 cpu = <&CPU2>;
30 };
31 };
32 cluster1 {
33 core0 {
34 cpu = <&CPU3>;
35 };
36 };
37 };
237 static int __init parse_dt_topology(void)
238 {
239 struct device_node *cn, *map;
240 int ret = 0;
241 int cpu;
242
243 cn = of_find_node_by_path("/cpus"); //获取cpus节点信息
244 if (!cn) {
245 pr_err("No CPU information found in DT\n");
246 return 0;
247 }
248
249 /*
250 * When topology is provided cpu-map is essentially a root
251 * cluster with restricted subnodes.
252 */
253 map = of_get_child_by_name(cn, "cpu-map"); //获取cpu-map节点信息
254 if (!map)
255 goto out;
256
257 ret = parse_cluster(map, 0); //重要函数,通过map信息获取cluster
258 if (ret != 0)
259 goto out_map;
260
261 topology_normalize_cpu_scale();
262
263 /*
264 * Check that all cores are in the topology; the SMP code will
265 * only mark cores described in the DT as possible.
266 */
267 for_each_possible_cpu(cpu)
268 if (cpu_topology[cpu].socket_id == -1)
269 ret = -EINVAL;
270
271 out_map:
272 of_node_put(map);
273 out:
274 of_node_put(cn);
275 return ret;
276 }
parse_cluster
parse_core
get_cpu_for_node
topology_parse_cpu_capacity
161 static int __init parse_cluster(struct device_node *cluster, int depth)
162 {
163 char name[10];
164 bool leaf = true;
165 bool has_cores = false;
166 struct device_node *c;
167 static int socket_id __initdata;
168 int core_id = 0;
169 int i, ret;
170
171 /*
172 * First check for child clusters; we currently ignore any
173 * information about the nesting of clusters and present the
174 * scheduler with a flat list of them.
175 */
176 i = 0;
177 do {
178 snprintf(name, sizeof(name), "cluster%d", i);
179 c = of_get_child_by_name(cluster, name);
180 if (c) {
181 leaf = false;
182 ret = parse_cluster(c, depth + 1);
183 of_node_put(c);
184 if (ret != 0)
185 return ret;
186 }
187 i++;
188 } while (c);
189
190 /* Now check for cores */
191 i = 0;
192 do {
193 snprintf(name, sizeof(name), "core%d", i);
194 c = of_get_child_by_name(cluster, name);
195 if (c) {
196 has_cores = true;
197
198 if (depth == 0) {
199 pr_err("%pOF: cpu-map children should be clusters\n",
200 c);
201 of_node_put(c);
202 return -EINVAL;
203 }
204
205 if (leaf) {
206 ret = parse_core(c, socket_id, core_id++);
207 } else {
208 pr_err("%pOF: Non-leaf cluster with core %s\n",
209 cluster, name);
210 ret = -EINVAL;
211 }
212
213 of_node_put(c);
214 if (ret != 0)
215 return ret;
216 }
217 i++;
218 } while (c);
219
220 if (leaf && !has_cores)
221 pr_warn("%pOF: empty cluster\n", cluster);
222
223 if (leaf)
224 socket_id++;
225
226 return 0;
227 }
113 static int __init parse_core(struct device_node *core, int socket_id,
114 int core_id)
115 {
116 char name[10];
117 bool leaf = true;
118 int i = 0;
119 int cpu;
120 struct device_node *t;
121
122 do {
123 snprintf(name, sizeof(name), "thread%d", i);
124 t = of_get_child_by_name(core, name);
125 if (t) {
126 leaf = false;
127 cpu = get_cpu_for_node(t);
128 if (cpu >= 0) {
129 cpu_topology[cpu].socket_id = socket_id;
130 cpu_topology[cpu].core_id = core_id;
131 cpu_topology[cpu].thread_id = i;
132 } else {
133 pr_err("%pOF: Can't get CPU for thread\n",
134 t);
135 of_node_put(t);
136 return -EINVAL;
137 }
138 of_node_put(t);
139 }
140 i++;
141 } while (t);
142
143 cpu = get_cpu_for_node(core);
144 if (cpu >= 0) {
145 if (!leaf) {
146 pr_err("%pOF: Core has both threads and CPU\n",
147 core);
148 return -EINVAL;
149 }
150
151 cpu_topology[cpu].socket_id = socket_id;
152 cpu_topology[cpu].core_id = core_id;
153 } else if (leaf) {
154 pr_err("%pOF: Can't get CPU for leaf core\n", core);
155 return -EINVAL;
156 }
157
158 return 0;
159 }