• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #include <stddef.h>
2 #include <stdint.h>
3 #include <stdlib.h>
4 #include <string.h>
5 
6 #include <arm/linux/api.h>
7 #include <cpuinfo.h>
8 #if defined(__ANDROID__)
9 #include <arm/android/api.h>
10 #endif
11 #include <arm/api.h>
12 #include <arm/midr.h>
13 #include <cpuinfo/internal-api.h>
14 #include <cpuinfo/log.h>
15 #include <linux/api.h>
16 
bitmask_all(uint32_t bitfield,uint32_t mask)17 static inline bool bitmask_all(uint32_t bitfield, uint32_t mask) {
18 	return (bitfield & mask) == mask;
19 }
20 
21 /*
22  * Assigns logical processors to clusters of cores using heuristic based on the
23  * typical configuration of clusters for 5, 6, 8, and 10 cores:
24  * - 5 cores (ARM32 Android only): 2 clusters of 4+1 cores
25  * - 6 cores: 2 clusters of 4+2 cores
26  * - 8 cores: 2 clusters of 4+4 cores
27  * - 10 cores: 3 clusters of 4+4+2 cores
28  *
29  * The function must be called after parsing OS-provided information on core
30  * clusters. Its purpose is to detect clusters of cores when OS-provided
31  * information is lacking or incomplete, i.e.
32  * - Linux kernel is not configured to report information in sysfs topology
33  * leaf.
34  * - Linux kernel reports topology information only for online cores, and only
35  * cores on one cluster are online, e.g.:
36  *   - Exynos 8890 has 8 cores in 4+4 clusters, but only the first cluster of 4
37  * cores is reported, and cluster configuration of logical processors 4-7 is not
38  * reported (all remaining processors 4-7 form cluster 1)
39  *   - MT6797 has 10 cores in 4+4+2, but only the first cluster of 4 cores is
40  * reported, and cluster configuration of logical processors 4-9 is not reported
41  * (processors 4-7 form cluster 1, and processors 8-9 form cluster 2).
42  *
43  * Heuristic assignment of processors to the above pre-defined clusters fails if
44  * such assignment would contradict information provided by the operating
45  * system:
46  * - Any of the OS-reported processor clusters is different than the
47  * corresponding heuristic cluster.
48  * - Processors in a heuristic cluster have no OS-provided cluster siblings
49  * information, but have known and different minimum/maximum frequency.
50  * - Processors in a heuristic cluster have no OS-provided cluster siblings
51  * information, but have known and different MIDR components.
52  *
53  * If the heuristic assignment of processors to clusters of cores fails, all
54  * processors' clusters are unchanged.
55  *
56  * @param usable_processors - number of processors in the @p processors array
57  * with CPUINFO_LINUX_FLAG_VALID flags.
58  * @param max_processors - number of elements in the @p processors array.
59  * @param[in,out] processors - processor descriptors with pre-parsed POSSIBLE
60  * and PRESENT flags, minimum/maximum frequency, MIDR information, and core
61  * cluster (package siblings list) information.
62  *
63  * @retval true if the heuristic successfully assigned all processors into
64  * clusters of cores.
65  * @retval false if known details about processors contradict the heuristic
66  * configuration of core clusters.
67  */
cpuinfo_arm_linux_detect_core_clusters_by_heuristic(uint32_t usable_processors,uint32_t max_processors,struct cpuinfo_arm_linux_processor processors[restrict static max_processors])68 bool cpuinfo_arm_linux_detect_core_clusters_by_heuristic(
69 	uint32_t usable_processors,
70 	uint32_t max_processors,
71 	struct cpuinfo_arm_linux_processor processors[restrict static max_processors]) {
72 	uint32_t cluster_processors[3];
73 	switch (usable_processors) {
74 		case 10:
75 			cluster_processors[0] = 4;
76 			cluster_processors[1] = 4;
77 			cluster_processors[2] = 2;
78 			break;
79 		case 8:
80 			cluster_processors[0] = 4;
81 			cluster_processors[1] = 4;
82 			break;
83 		case 6:
84 			cluster_processors[0] = 4;
85 			cluster_processors[1] = 2;
86 			break;
87 #if defined(__ANDROID__) && CPUINFO_ARCH_ARM
88 		case 5:
89 			/*
90 			 * The only processor with 5 cores is Leadcore L1860C
91 			 * (ARMv7, mobile), but this configuration is not too
92 			 * unreasonable for a virtualized ARM server.
93 			 */
94 			cluster_processors[0] = 4;
95 			cluster_processors[1] = 1;
96 			break;
97 #endif
98 		default:
99 			return false;
100 	}
101 
102 	/*
103 	 * Assignment of processors to core clusters is done in two passes:
104 	 * 1. Verify that the clusters proposed by heuristic are compatible with
105 	 * known details about processors.
106 	 * 2. If verification passed, update core clusters for the processors.
107 	 */
108 
109 	uint32_t cluster = 0;
110 	uint32_t expected_cluster_processors = 0;
111 	uint32_t cluster_start, cluster_flags, cluster_midr, cluster_max_frequency, cluster_min_frequency;
112 	bool expected_cluster_exists;
113 	for (uint32_t i = 0; i < max_processors; i++) {
114 		if (bitmask_all(processors[i].flags, CPUINFO_LINUX_FLAG_VALID)) {
115 			if (expected_cluster_processors == 0) {
116 				/* Expect this processor to start a new cluster
117 				 */
118 
119 				expected_cluster_exists = !!(processors[i].flags & CPUINFO_LINUX_FLAG_PACKAGE_CLUSTER);
120 				if (expected_cluster_exists) {
121 					if (processors[i].package_leader_id != i) {
122 						cpuinfo_log_debug(
123 							"heuristic detection of core clusters failed: "
124 							"processor %" PRIu32
125 							" is expected to start a new cluster #%" PRIu32 " with %" PRIu32
126 							" cores, "
127 							"but system siblings lists reported it as a sibling of processor %" PRIu32,
128 							i,
129 							cluster,
130 							cluster_processors[cluster],
131 							processors[i].package_leader_id);
132 						return false;
133 					}
134 				} else {
135 					cluster_flags = 0;
136 				}
137 
138 				cluster_start = i;
139 				expected_cluster_processors = cluster_processors[cluster++];
140 			} else {
141 				/* Expect this processor to belong to the same
142 				 * cluster as processor */
143 
144 				if (expected_cluster_exists) {
145 					/*
146 					 * The cluster suggested by the
147 					 * heuristic was already parsed from
148 					 * system siblings lists. For all
149 					 * processors we expect in the cluster,
150 					 * check that:
151 					 * - They have pre-assigned cluster from
152 					 * siblings lists
153 					 * (CPUINFO_LINUX_FLAG_PACKAGE_CLUSTER
154 					 * flag).
155 					 * - They were assigned to the same
156 					 * cluster based on siblings lists
157 					 *   (package_leader_id points to the
158 					 * first processor in the cluster).
159 					 */
160 
161 					if ((processors[i].flags & CPUINFO_LINUX_FLAG_PACKAGE_CLUSTER) == 0) {
162 						cpuinfo_log_debug(
163 							"heuristic detection of core clusters failed: "
164 							"processor %" PRIu32
165 							" is expected to belong to the cluster of processor %" PRIu32
166 							", "
167 							"but system siblings lists did not report it as a sibling of processor %" PRIu32,
168 							i,
169 							cluster_start,
170 							cluster_start);
171 						return false;
172 					}
173 					if (processors[i].package_leader_id != cluster_start) {
174 						cpuinfo_log_debug(
175 							"heuristic detection of core clusters failed: "
176 							"processor %" PRIu32
177 							" is expected to belong to the cluster of processor %" PRIu32
178 							", "
179 							"but system siblings lists reported it to belong to the cluster of processor %" PRIu32,
180 							i,
181 							cluster_start,
182 							cluster_start);
183 						return false;
184 					}
185 				} else {
186 					/*
187 					 * The cluster suggest by the heuristic
188 					 * was not parsed from system siblings
189 					 * lists. For all processors we expect
190 					 * in the cluster, check that:
191 					 * - They have no pre-assigned cluster
192 					 * from siblings lists.
193 					 * - If their min/max CPU frequency is
194 					 * known, it is the same.
195 					 * - If any part of their MIDR
196 					 * (Implementer, Variant, Part,
197 					 * Revision) is known, it is the same.
198 					 */
199 
200 					if (processors[i].flags & CPUINFO_LINUX_FLAG_PACKAGE_CLUSTER) {
201 						cpuinfo_log_debug(
202 							"heuristic detection of core clusters failed: "
203 							"processor %" PRIu32
204 							" is expected to be unassigned to any cluster, "
205 							"but system siblings lists reported it to belong to the cluster of processor %" PRIu32,
206 							i,
207 							processors[i].package_leader_id);
208 						return false;
209 					}
210 
211 					if (processors[i].flags & CPUINFO_LINUX_FLAG_MIN_FREQUENCY) {
212 						if (cluster_flags & CPUINFO_LINUX_FLAG_MIN_FREQUENCY) {
213 							if (cluster_min_frequency != processors[i].min_frequency) {
214 								cpuinfo_log_debug(
215 									"heuristic detection of core clusters failed: "
216 									"minimum frequency of processor %" PRIu32
217 									" (%" PRIu32
218 									" KHz) is different than of its expected cluster (%" PRIu32
219 									" KHz)",
220 									i,
221 									processors[i].min_frequency,
222 									cluster_min_frequency);
223 								return false;
224 							}
225 						} else {
226 							cluster_min_frequency = processors[i].min_frequency;
227 							cluster_flags |= CPUINFO_LINUX_FLAG_MIN_FREQUENCY;
228 						}
229 					}
230 
231 					if (processors[i].flags & CPUINFO_LINUX_FLAG_MAX_FREQUENCY) {
232 						if (cluster_flags & CPUINFO_LINUX_FLAG_MAX_FREQUENCY) {
233 							if (cluster_max_frequency != processors[i].max_frequency) {
234 								cpuinfo_log_debug(
235 									"heuristic detection of core clusters failed: "
236 									"maximum frequency of processor %" PRIu32
237 									" (%" PRIu32
238 									" KHz) is different than of its expected cluster (%" PRIu32
239 									" KHz)",
240 									i,
241 									processors[i].max_frequency,
242 									cluster_max_frequency);
243 								return false;
244 							}
245 						} else {
246 							cluster_max_frequency = processors[i].max_frequency;
247 							cluster_flags |= CPUINFO_LINUX_FLAG_MAX_FREQUENCY;
248 						}
249 					}
250 
251 					if (processors[i].flags & CPUINFO_ARM_LINUX_VALID_IMPLEMENTER) {
252 						if (cluster_flags & CPUINFO_ARM_LINUX_VALID_IMPLEMENTER) {
253 							if ((cluster_midr & CPUINFO_ARM_MIDR_IMPLEMENTER_MASK) !=
254 							    (processors[i].midr & CPUINFO_ARM_MIDR_IMPLEMENTER_MASK)) {
255 								cpuinfo_log_debug(
256 									"heuristic detection of core clusters failed: "
257 									"CPU Implementer of processor %" PRIu32
258 									" (0x%02" PRIx32
259 									") is different than of its expected cluster (0x%02" PRIx32
260 									")",
261 									i,
262 									midr_get_implementer(processors[i].midr),
263 									midr_get_implementer(cluster_midr));
264 								return false;
265 							}
266 						} else {
267 							cluster_midr =
268 								midr_copy_implementer(cluster_midr, processors[i].midr);
269 							cluster_flags |= CPUINFO_ARM_LINUX_VALID_IMPLEMENTER;
270 						}
271 					}
272 
273 					if (processors[i].flags & CPUINFO_ARM_LINUX_VALID_VARIANT) {
274 						if (cluster_flags & CPUINFO_ARM_LINUX_VALID_VARIANT) {
275 							if ((cluster_midr & CPUINFO_ARM_MIDR_VARIANT_MASK) !=
276 							    (processors[i].midr & CPUINFO_ARM_MIDR_VARIANT_MASK)) {
277 								cpuinfo_log_debug(
278 									"heuristic detection of core clusters failed: "
279 									"CPU Variant of processor %" PRIu32
280 									" (0x%" PRIx32
281 									") is different than of its expected cluster (0x%" PRIx32
282 									")",
283 									i,
284 									midr_get_variant(processors[i].midr),
285 									midr_get_variant(cluster_midr));
286 								return false;
287 							}
288 						} else {
289 							cluster_midr =
290 								midr_copy_variant(cluster_midr, processors[i].midr);
291 							cluster_flags |= CPUINFO_ARM_LINUX_VALID_VARIANT;
292 						}
293 					}
294 
295 					if (processors[i].flags & CPUINFO_ARM_LINUX_VALID_PART) {
296 						if (cluster_flags & CPUINFO_ARM_LINUX_VALID_PART) {
297 							if ((cluster_midr & CPUINFO_ARM_MIDR_PART_MASK) !=
298 							    (processors[i].midr & CPUINFO_ARM_MIDR_PART_MASK)) {
299 								cpuinfo_log_debug(
300 									"heuristic detection of core clusters failed: "
301 									"CPU Part of processor %" PRIu32
302 									" (0x%03" PRIx32
303 									") is different than of its expected cluster (0x%03" PRIx32
304 									")",
305 									i,
306 									midr_get_part(processors[i].midr),
307 									midr_get_part(cluster_midr));
308 								return false;
309 							}
310 						} else {
311 							cluster_midr = midr_copy_part(cluster_midr, processors[i].midr);
312 							cluster_flags |= CPUINFO_ARM_LINUX_VALID_PART;
313 						}
314 					}
315 
316 					if (processors[i].flags & CPUINFO_ARM_LINUX_VALID_REVISION) {
317 						if (cluster_flags & CPUINFO_ARM_LINUX_VALID_REVISION) {
318 							if ((cluster_midr & CPUINFO_ARM_MIDR_REVISION_MASK) !=
319 							    (processors[i].midr & CPUINFO_ARM_MIDR_REVISION_MASK)) {
320 								cpuinfo_log_debug(
321 									"heuristic detection of core clusters failed: "
322 									"CPU Revision of processor %" PRIu32
323 									" (0x%" PRIx32
324 									") is different than of its expected cluster (0x%" PRIx32
325 									")",
326 									i,
327 									midr_get_revision(cluster_midr),
328 									midr_get_revision(processors[i].midr));
329 								return false;
330 							}
331 						} else {
332 							cluster_midr =
333 								midr_copy_revision(cluster_midr, processors[i].midr);
334 							cluster_flags |= CPUINFO_ARM_LINUX_VALID_REVISION;
335 						}
336 					}
337 				}
338 			}
339 			expected_cluster_processors--;
340 		}
341 	}
342 
343 	/* Verification passed, assign all processors to new clusters */
344 	cluster = 0;
345 	expected_cluster_processors = 0;
346 	for (uint32_t i = 0; i < max_processors; i++) {
347 		if (bitmask_all(processors[i].flags, CPUINFO_LINUX_FLAG_VALID)) {
348 			if (expected_cluster_processors == 0) {
349 				/* Expect this processor to start a new cluster
350 				 */
351 
352 				cluster_start = i;
353 				expected_cluster_processors = cluster_processors[cluster++];
354 			} else {
355 				/* Expect this processor to belong to the same
356 				 * cluster as processor */
357 
358 				if (!(processors[i].flags & CPUINFO_LINUX_FLAG_PACKAGE_CLUSTER)) {
359 					cpuinfo_log_debug(
360 						"assigned processor %" PRIu32 " to cluster of processor %" PRIu32
361 						" based on heuristic",
362 						i,
363 						cluster_start);
364 				}
365 
366 				processors[i].package_leader_id = cluster_start;
367 				processors[i].flags |= CPUINFO_LINUX_FLAG_PACKAGE_CLUSTER;
368 			}
369 			expected_cluster_processors--;
370 		}
371 	}
372 	return true;
373 }
374 
375 /*
376  * Assigns logical processors to clusters of cores in sequential manner:
377  * - Clusters detected from OS-provided information are unchanged:
378  *   - Processors assigned to these clusters stay assigned to the same clusters
379  *   - No new processors are added to these clusters
380  * - Processors without pre-assigned cluster are clustered in one sequential
381  * scan:
382  *   - If known details (min/max frequency, MIDR components) of a processor are
383  * compatible with a preceding processor, without pre-assigned cluster, the
384  * processor is assigned to the cluster of the preceding processor.
385  *   - If known details (min/max frequency, MIDR components) of a processor are
386  * not compatible with a preceding processor, the processor is assigned to a
387  * newly created cluster.
388  *
389  * The function must be called after parsing OS-provided information on core
390  * clusters, and usually is called only if heuristic assignment of processors to
391  * clusters (cpuinfo_arm_linux_cluster_processors_by_heuristic) failed.
392  *
393  * Its purpose is to detect clusters of cores when OS-provided information is
394  * lacking or incomplete, i.e.
395  * - Linux kernel is not configured to report information in sysfs topology
396  * leaf.
397  * - Linux kernel reports topology information only for online cores, and all
398  * cores on some of the clusters are offline.
399  *
400  * Sequential assignment of processors to clusters always succeeds, and upon
401  * exit, all usable processors in the
402  * @p processors array have cluster information.
403  *
404  * @param max_processors - number of elements in the @p processors array.
405  * @param[in,out] processors - processor descriptors with pre-parsed POSSIBLE
406  * and PRESENT flags, minimum/maximum frequency, MIDR information, and core
407  * cluster (package siblings list) information.
408  *
409  * @retval true if the heuristic successfully assigned all processors into
410  * clusters of cores.
411  * @retval false if known details about processors contradict the heuristic
412  * configuration of core clusters.
413  */
cpuinfo_arm_linux_detect_core_clusters_by_sequential_scan(uint32_t max_processors,struct cpuinfo_arm_linux_processor processors[restrict static max_processors])414 void cpuinfo_arm_linux_detect_core_clusters_by_sequential_scan(
415 	uint32_t max_processors,
416 	struct cpuinfo_arm_linux_processor processors[restrict static max_processors]) {
417 	uint32_t cluster_flags = 0;
418 	uint32_t cluster_processors = 0;
419 	uint32_t cluster_start, cluster_midr, cluster_max_frequency, cluster_min_frequency;
420 	for (uint32_t i = 0; i < max_processors; i++) {
421 		if ((processors[i].flags & (CPUINFO_LINUX_FLAG_VALID | CPUINFO_LINUX_FLAG_PACKAGE_CLUSTER)) ==
422 		    CPUINFO_LINUX_FLAG_VALID) {
423 			if (cluster_processors == 0) {
424 				goto new_cluster;
425 			}
426 
427 			if (processors[i].flags & CPUINFO_LINUX_FLAG_MIN_FREQUENCY) {
428 				if (cluster_flags & CPUINFO_LINUX_FLAG_MIN_FREQUENCY) {
429 					if (cluster_min_frequency != processors[i].min_frequency) {
430 						cpuinfo_log_info(
431 							"minimum frequency of processor %" PRIu32 " (%" PRIu32
432 							" KHz) is different than of preceding cluster (%" PRIu32
433 							" KHz); "
434 							"processor %" PRIu32 " starts to a new cluster",
435 							i,
436 							processors[i].min_frequency,
437 							cluster_min_frequency,
438 							i);
439 						goto new_cluster;
440 					}
441 				} else {
442 					cluster_min_frequency = processors[i].min_frequency;
443 					cluster_flags |= CPUINFO_LINUX_FLAG_MIN_FREQUENCY;
444 				}
445 			}
446 
447 			if (processors[i].flags & CPUINFO_LINUX_FLAG_MAX_FREQUENCY) {
448 				if (cluster_flags & CPUINFO_LINUX_FLAG_MAX_FREQUENCY) {
449 					if (cluster_max_frequency != processors[i].max_frequency) {
450 						cpuinfo_log_debug(
451 							"maximum frequency of processor %" PRIu32 " (%" PRIu32
452 							" KHz) is different than of preceding cluster (%" PRIu32
453 							" KHz); "
454 							"processor %" PRIu32 " starts a new cluster",
455 							i,
456 							processors[i].max_frequency,
457 							cluster_max_frequency,
458 							i);
459 						goto new_cluster;
460 					}
461 				} else {
462 					cluster_max_frequency = processors[i].max_frequency;
463 					cluster_flags |= CPUINFO_LINUX_FLAG_MAX_FREQUENCY;
464 				}
465 			}
466 
467 			if (processors[i].flags & CPUINFO_ARM_LINUX_VALID_IMPLEMENTER) {
468 				if (cluster_flags & CPUINFO_ARM_LINUX_VALID_IMPLEMENTER) {
469 					if ((cluster_midr & CPUINFO_ARM_MIDR_IMPLEMENTER_MASK) !=
470 					    (processors[i].midr & CPUINFO_ARM_MIDR_IMPLEMENTER_MASK)) {
471 						cpuinfo_log_debug(
472 							"CPU Implementer of processor %" PRIu32 " (0x%02" PRIx32
473 							") is different than of preceding cluster (0x%02" PRIx32
474 							"); "
475 							"processor %" PRIu32 " starts to a new cluster",
476 							i,
477 							midr_get_implementer(processors[i].midr),
478 							midr_get_implementer(cluster_midr),
479 							i);
480 						goto new_cluster;
481 					}
482 				} else {
483 					cluster_midr = midr_copy_implementer(cluster_midr, processors[i].midr);
484 					cluster_flags |= CPUINFO_ARM_LINUX_VALID_IMPLEMENTER;
485 				}
486 			}
487 
488 			if (processors[i].flags & CPUINFO_ARM_LINUX_VALID_VARIANT) {
489 				if (cluster_flags & CPUINFO_ARM_LINUX_VALID_VARIANT) {
490 					if ((cluster_midr & CPUINFO_ARM_MIDR_VARIANT_MASK) !=
491 					    (processors[i].midr & CPUINFO_ARM_MIDR_VARIANT_MASK)) {
492 						cpuinfo_log_debug(
493 							"CPU Variant of processor %" PRIu32 " (0x%" PRIx32
494 							") is different than of its expected cluster (0x%" PRIx32
495 							")"
496 							"processor %" PRIu32 " starts to a new cluster",
497 							i,
498 							midr_get_variant(processors[i].midr),
499 							midr_get_variant(cluster_midr),
500 							i);
501 						goto new_cluster;
502 					}
503 				} else {
504 					cluster_midr = midr_copy_variant(cluster_midr, processors[i].midr);
505 					cluster_flags |= CPUINFO_ARM_LINUX_VALID_VARIANT;
506 				}
507 			}
508 
509 			if (processors[i].flags & CPUINFO_ARM_LINUX_VALID_PART) {
510 				if (cluster_flags & CPUINFO_ARM_LINUX_VALID_PART) {
511 					if ((cluster_midr & CPUINFO_ARM_MIDR_PART_MASK) !=
512 					    (processors[i].midr & CPUINFO_ARM_MIDR_PART_MASK)) {
513 						cpuinfo_log_debug(
514 							"CPU Part of processor %" PRIu32 " (0x%03" PRIx32
515 							") is different than of its expected cluster (0x%03" PRIx32
516 							")"
517 							"processor %" PRIu32 " starts to a new cluster",
518 							i,
519 							midr_get_part(processors[i].midr),
520 							midr_get_part(cluster_midr),
521 							i);
522 						goto new_cluster;
523 					}
524 				} else {
525 					cluster_midr = midr_copy_part(cluster_midr, processors[i].midr);
526 					cluster_flags |= CPUINFO_ARM_LINUX_VALID_PART;
527 				}
528 			}
529 
530 			if (processors[i].flags & CPUINFO_ARM_LINUX_VALID_REVISION) {
531 				if (cluster_flags & CPUINFO_ARM_LINUX_VALID_REVISION) {
532 					if ((cluster_midr & CPUINFO_ARM_MIDR_REVISION_MASK) !=
533 					    (processors[i].midr & CPUINFO_ARM_MIDR_REVISION_MASK)) {
534 						cpuinfo_log_debug(
535 							"CPU Revision of processor %" PRIu32 " (0x%" PRIx32
536 							") is different than of its expected cluster (0x%" PRIx32
537 							")"
538 							"processor %" PRIu32 " starts to a new cluster",
539 							i,
540 							midr_get_revision(cluster_midr),
541 							midr_get_revision(processors[i].midr),
542 							i);
543 						goto new_cluster;
544 					}
545 				} else {
546 					cluster_midr = midr_copy_revision(cluster_midr, processors[i].midr);
547 					cluster_flags |= CPUINFO_ARM_LINUX_VALID_REVISION;
548 				}
549 			}
550 
551 			/* All checks passed, attach processor to the preceding
552 			 * cluster */
553 			cluster_processors++;
554 			processors[i].package_leader_id = cluster_start;
555 			processors[i].flags |= CPUINFO_LINUX_FLAG_PACKAGE_CLUSTER;
556 			cpuinfo_log_debug(
557 				"assigned processor %" PRIu32 " to preceding cluster of processor %" PRIu32,
558 				i,
559 				cluster_start);
560 			continue;
561 
562 		new_cluster:
563 			/* Create a new cluster starting with processor i */
564 			cluster_start = i;
565 			processors[i].package_leader_id = i;
566 			processors[i].flags |= CPUINFO_LINUX_FLAG_PACKAGE_CLUSTER;
567 			cluster_processors = 1;
568 
569 			/* Copy known information from processor to cluster, and
570 			 * set the flags accordingly */
571 			cluster_flags = 0;
572 			if (processors[i].flags & CPUINFO_LINUX_FLAG_MIN_FREQUENCY) {
573 				cluster_min_frequency = processors[i].min_frequency;
574 				cluster_flags |= CPUINFO_LINUX_FLAG_MIN_FREQUENCY;
575 			}
576 			if (processors[i].flags & CPUINFO_LINUX_FLAG_MAX_FREQUENCY) {
577 				cluster_max_frequency = processors[i].max_frequency;
578 				cluster_flags |= CPUINFO_LINUX_FLAG_MAX_FREQUENCY;
579 			}
580 			if (processors[i].flags & CPUINFO_ARM_LINUX_VALID_IMPLEMENTER) {
581 				cluster_midr = midr_copy_implementer(cluster_midr, processors[i].midr);
582 				cluster_flags |= CPUINFO_ARM_LINUX_VALID_IMPLEMENTER;
583 			}
584 			if (processors[i].flags & CPUINFO_ARM_LINUX_VALID_VARIANT) {
585 				cluster_midr = midr_copy_variant(cluster_midr, processors[i].midr);
586 				cluster_flags |= CPUINFO_ARM_LINUX_VALID_VARIANT;
587 			}
588 			if (processors[i].flags & CPUINFO_ARM_LINUX_VALID_PART) {
589 				cluster_midr = midr_copy_part(cluster_midr, processors[i].midr);
590 				cluster_flags |= CPUINFO_ARM_LINUX_VALID_PART;
591 			}
592 			if (processors[i].flags & CPUINFO_ARM_LINUX_VALID_REVISION) {
593 				cluster_midr = midr_copy_revision(cluster_midr, processors[i].midr);
594 				cluster_flags |= CPUINFO_ARM_LINUX_VALID_REVISION;
595 			}
596 		}
597 	}
598 }
599 
600 /*
601  * Counts the number of logical processors in each core cluster.
602  * This function should be called after all processors are assigned to core
603  * clusters.
604  *
605  * @param max_processors - number of elements in the @p processors array.
606  * @param[in,out] processors - processor descriptors with pre-parsed POSSIBLE
607  * and PRESENT flags, and decoded core cluster (package_leader_id) information.
608  *                             The function expects the value of
609  * processors[i].package_processor_count to be zero. Upon return,
610  * processors[i].package_processor_count will contain the number of logical
611  *                             processors in the respective core cluster.
612  */
cpuinfo_arm_linux_count_cluster_processors(uint32_t max_processors,struct cpuinfo_arm_linux_processor processors[restrict static max_processors])613 void cpuinfo_arm_linux_count_cluster_processors(
614 	uint32_t max_processors,
615 	struct cpuinfo_arm_linux_processor processors[restrict static max_processors]) {
616 	/* First pass: accumulate the number of processors at the group leader's
617 	 * package_processor_count */
618 	for (uint32_t i = 0; i < max_processors; i++) {
619 		if (bitmask_all(processors[i].flags, CPUINFO_LINUX_FLAG_VALID)) {
620 			const uint32_t package_leader_id = processors[i].package_leader_id;
621 			processors[package_leader_id].package_processor_count += 1;
622 		}
623 	}
624 	/* Second pass: copy the package_processor_count from the group leader
625 	 * processor */
626 	for (uint32_t i = 0; i < max_processors; i++) {
627 		if (bitmask_all(processors[i].flags, CPUINFO_LINUX_FLAG_VALID)) {
628 			const uint32_t package_leader_id = processors[i].package_leader_id;
629 			processors[i].package_processor_count = processors[package_leader_id].package_processor_count;
630 		}
631 	}
632 }
633