blob: 0077bd1e12f79f10a9211a961cb43a6adcd259c4 [file] [log] [blame]
Marat Dukhan3045d4f2017-03-04 01:51:42 -05001#include <stdint.h>
2#include <stddef.h>
3#include <stdlib.h>
4#include <string.h>
5#include <errno.h>
6
7#include <sched.h>
8
9#include <cpuinfo.h>
10#include <x86/api.h>
Marat Dukhanfbc4cfc2017-09-22 16:45:45 -070011#include <gpu/api.h>
Marat Dukhan3045d4f2017-03-04 01:51:42 -050012#include <linux/api.h>
13#include <api.h>
14#include <log.h>
15
16
17static inline uint32_t max(uint32_t a, uint32_t b) {
18 return a > b ? a : b;
19}
20
Marat Dukhan77eb9412017-03-04 21:01:16 -050021static inline uint32_t bit_mask(uint32_t bits) {
22 return (UINT32_C(1) << bits) - UINT32_C(1);
23}
24
Marat Dukhan3045d4f2017-03-04 01:51:42 -050025static int cmp_x86_processor_by_apic_id(const void* processor_a, const void* processor_b) {
26 const uint32_t id_a = ((const struct cpuinfo_x86_processor*) processor_a)->topology.apic_id;
27 const uint32_t id_b = ((const struct cpuinfo_x86_processor*) processor_b)->topology.apic_id;
28
29 if (id_a < id_b) {
30 return -1;
31 } else {
32 return id_a > id_b;
33 }
34}
35
Marat Dukhan43a51cd2017-09-22 16:35:05 -070036static void cpuinfo_x86_count_objects(
Marat Dukhan3045d4f2017-03-04 01:51:42 -050037 const struct cpuinfo_x86_processor* processors,
38 uint32_t processors_count,
Marat Dukhan43a51cd2017-09-22 16:35:05 -070039 uint32_t cores_count_ptr[restrict static 1],
40 uint32_t packages_count_ptr[restrict static 1],
Marat Dukhan3045d4f2017-03-04 01:51:42 -050041 uint32_t l1i_count_ptr[restrict static 1],
42 uint32_t l1d_count_ptr[restrict static 1],
43 uint32_t l2_count_ptr[restrict static 1],
44 uint32_t l3_count_ptr[restrict static 1],
45 uint32_t l4_count_ptr[restrict static 1])
46{
Marat Dukhan43a51cd2017-09-22 16:35:05 -070047 uint32_t cores_count = 0, packages_count = 0;
Marat Dukhan3045d4f2017-03-04 01:51:42 -050048 uint32_t l1i_count = 0, l1d_count = 0, l2_count = 0, l3_count = 0, l4_count = 0;
Marat Dukhan43a51cd2017-09-22 16:35:05 -070049 uint32_t last_core_id = UINT32_MAX, last_package_id = UINT32_MAX;
Marat Dukhan3045d4f2017-03-04 01:51:42 -050050 uint32_t last_l1i_id = UINT32_MAX, last_l1d_id = UINT32_MAX;
51 uint32_t last_l2_id = UINT32_MAX, last_l3_id = UINT32_MAX, last_l4_id = UINT32_MAX;
52 for (uint32_t i = 0; i < processors_count; i++) {
53 const uint32_t apic_id = processors[i].topology.apic_id;
Marat Dukhan43a51cd2017-09-22 16:35:05 -070054 const uint32_t core_id =
55 (apic_id >> processors[i].topology.core_bits_offset) & ~bit_mask(processors[i].topology.core_bits_length);
56 if (core_id != last_core_id) {
57 last_core_id = core_id;
58 cores_count++;
59 }
60 const uint32_t package_id = apic_id >>
61 max(processors[i].topology.core_bits_offset + processors[i].topology.core_bits_length,
62 processors[i].topology.thread_bits_offset + processors[i].topology.thread_bits_length);
63 if (package_id != last_package_id) {
64 last_package_id = package_id;
65 packages_count++;
66 }
Marat Dukhan3045d4f2017-03-04 01:51:42 -050067 if (processors[i].cache.l1i.size != 0) {
68 const uint32_t l1i_id = apic_id & ~bit_mask(processors[i].cache.l1i.apic_bits);
69 if (l1i_id != last_l1i_id) {
70 last_l1i_id = l1i_id;
71 l1i_count++;
72 }
73 }
74 if (processors[i].cache.l1d.size != 0) {
75 const uint32_t l1d_id = apic_id & ~bit_mask(processors[i].cache.l1d.apic_bits);
76 if (l1d_id != last_l1d_id) {
77 last_l1d_id = l1d_id;
78 l1d_count++;
79 }
80 }
81 if (processors[i].cache.l2.size != 0) {
82 const uint32_t l2_id = apic_id & ~bit_mask(processors[i].cache.l2.apic_bits);
83 if (l2_id != last_l2_id) {
84 last_l2_id = l2_id;
85 l2_count++;
86 }
87 }
88 if (processors[i].cache.l3.size != 0) {
89 const uint32_t l3_id = apic_id & ~bit_mask(processors[i].cache.l3.apic_bits);
90 if (l3_id != last_l3_id) {
91 last_l3_id = l3_id;
92 l3_count++;
93 }
94 }
95 if (processors[i].cache.l4.size != 0) {
96 const uint32_t l4_id = apic_id & ~bit_mask(processors[i].cache.l4.apic_bits);
97 if (l4_id != last_l4_id) {
98 last_l4_id = l4_id;
99 l4_count++;
100 }
101 }
102 }
Marat Dukhan43a51cd2017-09-22 16:35:05 -0700103 *cores_count_ptr = cores_count;
104 *packages_count_ptr = packages_count;
Marat Dukhan3045d4f2017-03-04 01:51:42 -0500105 *l1i_count_ptr = l1i_count;
106 *l1d_count_ptr = l1d_count;
107 *l2_count_ptr = l2_count;
108 *l3_count_ptr = l3_count;
109 *l4_count_ptr = l4_count;
110}
111
Marat Dukhana8fb3dd2017-08-09 13:49:39 -0700112static bool cpuinfo_x86_linux_cpulist_callback(uint32_t cpulist_start, uint32_t cpulist_end, void* context) {
113 cpu_set_t* cpuset = (cpu_set_t*) context;
114 for (uint32_t cpu = cpulist_start; cpu < cpulist_end; cpu++) {
115 CPU_SET((int) cpu, cpuset);
116 }
117 return true;
118}
119
Marat Dukhan3045d4f2017-03-04 01:51:42 -0500120void cpuinfo_x86_linux_init(void) {
121 struct cpuinfo_x86_processor* x86_processors = NULL;
122 struct cpuinfo_processor* processors = NULL;
Marat Dukhan43a51cd2017-09-22 16:35:05 -0700123 struct cpuinfo_package* packages = NULL;
124 struct cpuinfo_core* cores = NULL;
Marat Dukhan3045d4f2017-03-04 01:51:42 -0500125 struct cpuinfo_cache* l1i = NULL;
126 struct cpuinfo_cache* l1d = NULL;
127 struct cpuinfo_cache* l2 = NULL;
128 struct cpuinfo_cache* l3 = NULL;
129 struct cpuinfo_cache* l4 = NULL;
130
131 cpu_set_t old_affinity;
132 if (sched_getaffinity(0, sizeof(cpu_set_t), &old_affinity) != 0) {
133 cpuinfo_log_error("sched_getaffinity failed: %s", strerror(errno));
134 return;
135 }
136
137 cpu_set_t present_set;
Marat Dukhana8fb3dd2017-08-09 13:49:39 -0700138 CPU_ZERO(&present_set);
139 cpuinfo_linux_parse_cpulist("/sys/devices/system/cpu/present", cpuinfo_x86_linux_cpulist_callback, &present_set);
Marat Dukhan3045d4f2017-03-04 01:51:42 -0500140
141 cpu_set_t possible_set;
Marat Dukhana8fb3dd2017-08-09 13:49:39 -0700142 CPU_ZERO(&possible_set);
143 cpuinfo_linux_parse_cpulist("/sys/devices/system/cpu/possible", cpuinfo_x86_linux_cpulist_callback, &possible_set);
Marat Dukhan3045d4f2017-03-04 01:51:42 -0500144
145 cpu_set_t processors_set;
146 CPU_AND(&processors_set, &present_set, &possible_set);
147 const uint32_t processors_count = (uint32_t) CPU_COUNT(&processors_set);
148 cpuinfo_log_debug("detected %"PRIu32" logical processors", processors_count);
149
150 x86_processors = calloc(processors_count, sizeof(struct cpuinfo_x86_processor));
151 if (x86_processors == NULL) {
152 cpuinfo_log_error("failed to allocate %zu bytes for descriptions of %d x86 logical processors",
153 processors_count * sizeof(struct cpuinfo_x86_processor), processors_count);
154 goto cleanup;
155 }
156
157 int processor_bit = 0;
158 for (int i = 0; i < processors_count; i++, processor_bit++) {
159 while (!CPU_ISSET(processor_bit, &processors_set)) {
160 processor_bit++;
161 }
162 cpu_set_t processor_set;
163 CPU_ZERO(&processor_set);
164 CPU_SET(processor_bit, &processor_set);
165 if (sched_setaffinity(0, sizeof(cpu_set_t), &processor_set) != 0) {
166 cpuinfo_log_error("sched_setaffinity for processor %d (bit %d) failed: %s",
167 i, processor_bit, strerror(errno));
168 goto cleanup;
169 }
170
171 cpuinfo_x86_init_processor(&x86_processors[i]);
Marat Dukhan15e1df92017-09-13 11:10:10 -0700172 x86_processors[i].linux_id = processor_bit;
Marat Dukhan3045d4f2017-03-04 01:51:42 -0500173 }
174
175 qsort(x86_processors, (size_t) processors_count, sizeof(struct cpuinfo_x86_processor),
176 cmp_x86_processor_by_apic_id);
177
178 processors = calloc((size_t) processors_count, sizeof(struct cpuinfo_processor));
179 if (processors == NULL) {
180 cpuinfo_log_error("failed to allocate %zu bytes for descriptions of %d logical processors",
181 (size_t) processors_count * sizeof(struct cpuinfo_processor), processors_count);
182 goto cleanup;
183 }
184
185 for (uint32_t i = 0; i < (uint32_t) processors_count; i++) {
Marat Dukhan15e1df92017-09-13 11:10:10 -0700186 processors[i].vendor = x86_processors[i].vendor;
187 processors[i].uarch = x86_processors[i].uarch;
188 processors[i].linux_id = x86_processors[i].linux_id;
Marat Dukhan3045d4f2017-03-04 01:51:42 -0500189
190 /* Initialize topology information */
191 const uint32_t apic_id = x86_processors[i].topology.apic_id;
192 const uint32_t thread_mask = bit_mask(x86_processors[i].topology.thread_bits_length);
193 const uint32_t core_mask = bit_mask(x86_processors[i].topology.core_bits_length);
194 const uint32_t package_offset = max(
195 x86_processors[i].topology.thread_bits_offset,
196 x86_processors[i].topology.core_bits_offset);
197 processors[i].topology = (struct cpuinfo_topology) {
198 .thread_id = (apic_id >> x86_processors[i].topology.thread_bits_offset) & thread_mask,
199 .core_id = (apic_id >> x86_processors[i].topology.core_bits_offset) & core_mask,
200 .package_id = apic_id >> package_offset,
Marat Dukhan3045d4f2017-03-04 01:51:42 -0500201 .apic_id = x86_processors[i].topology.apic_id,
202 };
203 }
204
Marat Dukhan43a51cd2017-09-22 16:35:05 -0700205 uint32_t packages_count = 0, cores_count = 0;
Marat Dukhan3045d4f2017-03-04 01:51:42 -0500206 uint32_t l1i_count = 0, l1d_count = 0, l2_count = 0, l3_count = 0, l4_count = 0;
Marat Dukhan43a51cd2017-09-22 16:35:05 -0700207 cpuinfo_x86_count_objects(x86_processors, processors_count,
208 &packages_count, &cores_count, &l1i_count, &l1d_count, &l2_count, &l3_count, &l4_count);
Marat Dukhan3045d4f2017-03-04 01:51:42 -0500209
Marat Dukhan43a51cd2017-09-22 16:35:05 -0700210 cpuinfo_log_debug("detected %"PRIu32" cores caches", cores_count);
211 cpuinfo_log_debug("detected %"PRIu32" packages caches", packages_count);
212 cpuinfo_log_debug("detected %"PRIu32" L1I caches", l1i_count);
213 cpuinfo_log_debug("detected %"PRIu32" L1D caches", l1d_count);
214 cpuinfo_log_debug("detected %"PRIu32" L2 caches", l2_count);
215 cpuinfo_log_debug("detected %"PRIu32" L3 caches", l3_count);
216 cpuinfo_log_debug("detected %"PRIu32" L4 caches", l4_count);
Marat Dukhan3045d4f2017-03-04 01:51:42 -0500217
Marat Dukhan43a51cd2017-09-22 16:35:05 -0700218 cores = calloc(cores_count, sizeof(struct cpuinfo_core));
219 if (cores == NULL) {
220 cpuinfo_log_error("failed to allocate %zu bytes for descriptions of %"PRIu32" cores",
221 cores_count * sizeof(struct cpuinfo_core), cores_count);
222 goto cleanup;
223 }
224 packages = calloc(packages_count, sizeof(struct cpuinfo_package));
225 if (packages == NULL) {
226 cpuinfo_log_error("failed to allocate %zu bytes for descriptions of %"PRIu32" cores",
227 packages_count * sizeof(struct cpuinfo_package), packages_count);
228 goto cleanup;
229 }
Marat Dukhan3045d4f2017-03-04 01:51:42 -0500230 if (l1i_count != 0) {
231 l1i = calloc(l1i_count, sizeof(struct cpuinfo_cache));
232 if (l1i == NULL) {
233 cpuinfo_log_error("failed to allocate %zu bytes for descriptions of %"PRIu32" L1I caches",
234 l1i_count * sizeof(struct cpuinfo_cache), l1i_count);
235 goto cleanup;
236 }
237 }
238 if (l1d_count != 0) {
239 l1d = calloc(l1d_count, sizeof(struct cpuinfo_cache));
240 if (l1d == NULL) {
241 cpuinfo_log_error("failed to allocate %zu bytes for descriptions of %"PRIu32" L1D caches",
242 l1d_count * sizeof(struct cpuinfo_cache), l1d_count);
243 goto cleanup;
244 }
245 }
246 if (l2_count != 0) {
247 l2 = calloc(l2_count, sizeof(struct cpuinfo_cache));
248 if (l2 == NULL) {
249 cpuinfo_log_error("failed to allocate %zu bytes for descriptions of %"PRIu32" L2 caches",
250 l2_count * sizeof(struct cpuinfo_cache), l2_count);
251 goto cleanup;
252 }
253 }
254 if (l3_count != 0) {
255 l3 = calloc(l3_count, sizeof(struct cpuinfo_cache));
256 if (l3 == NULL) {
257 cpuinfo_log_error("failed to allocate %zu bytes for descriptions of %"PRIu32" L3 caches",
258 l3_count * sizeof(struct cpuinfo_cache), l3_count);
259 goto cleanup;
260 }
261 }
262 if (l4_count != 0) {
263 l4 = calloc(l4_count, sizeof(struct cpuinfo_cache));
264 if (l4 == NULL) {
265 cpuinfo_log_error("failed to allocate %zu bytes for descriptions of %"PRIu32" L4 caches",
266 l4_count * sizeof(struct cpuinfo_cache), l4_count);
267 goto cleanup;
268 }
269 }
270
Marat Dukhanfbc4cfc2017-09-22 16:45:45 -0700271 uint32_t core_index = UINT32_MAX, package_index = UINT32_MAX;
272 uint32_t l1i_index = UINT32_MAX, l1d_index = UINT32_MAX, l2_index = UINT32_MAX, l3_index = UINT32_MAX, l4_index = UINT32_MAX;
Marat Dukhan43a51cd2017-09-22 16:35:05 -0700273 uint32_t last_core_id = UINT32_MAX, last_package_id = UINT32_MAX;
Marat Dukhan3045d4f2017-03-04 01:51:42 -0500274 uint32_t last_l1i_id = UINT32_MAX, last_l1d_id = UINT32_MAX;
275 uint32_t last_l2_id = UINT32_MAX, last_l3_id = UINT32_MAX, last_l4_id = UINT32_MAX;
276 for (uint32_t i = 0; i < processors_count; i++) {
Marat Dukhan43a51cd2017-09-22 16:35:05 -0700277 const uint32_t apic_id = x86_processors[i].topology.apic_id;
278 const uint32_t core_id =
279 (apic_id >> x86_processors[i].topology.core_bits_offset) & ~bit_mask(x86_processors[i].topology.core_bits_length);
280 uint32_t new_core = 0;
281 if (core_id != last_core_id) {
282 /* new core */
283 new_core = 1;
Marat Dukhanfbc4cfc2017-09-22 16:45:45 -0700284 cores[++core_index] = (struct cpuinfo_core) {
Marat Dukhan43a51cd2017-09-22 16:35:05 -0700285 .processor_start = i,
286 .processor_count = 1,
287 };
288 last_core_id = core_id;
289 } else {
290 /* another logical processor on the same core */
Marat Dukhanfbc4cfc2017-09-22 16:45:45 -0700291 cores[core_index].processor_count++;
Marat Dukhan43a51cd2017-09-22 16:35:05 -0700292 }
293
294 const uint32_t package_id = apic_id >>
295 max(x86_processors[i].topology.core_bits_offset + x86_processors[i].topology.core_bits_length,
296 x86_processors[i].topology.thread_bits_offset + x86_processors[i].topology.thread_bits_length);
297 if (package_id != last_package_id) {
298 /* new package */
Marat Dukhanfbc4cfc2017-09-22 16:45:45 -0700299 packages[++package_index] = (struct cpuinfo_package) {
Marat Dukhan43a51cd2017-09-22 16:35:05 -0700300 .processor_start = i,
301 .processor_count = 1,
Marat Dukhanfbc4cfc2017-09-22 16:45:45 -0700302 .core_start = core_index,
Marat Dukhan43a51cd2017-09-22 16:35:05 -0700303 .core_count = 1,
304 };
305 const uint32_t brand_string_length = cpuinfo_x86_normalize_brand_string(x86_processors[i].brand_string);
Marat Dukhanfbc4cfc2017-09-22 16:45:45 -0700306 memcpy(packages[package_index].name, x86_processors[i].brand_string, brand_string_length);
Marat Dukhan43a51cd2017-09-22 16:35:05 -0700307 if (brand_string_length < CPUINFO_PACKAGE_NAME_MAX) {
Marat Dukhanfbc4cfc2017-09-22 16:45:45 -0700308 packages[package_index].name[brand_string_length] = '\0';
Marat Dukhan43a51cd2017-09-22 16:35:05 -0700309 }
310 last_package_id = package_id;
311 } else {
312 /* another logical processor on the same package */
Marat Dukhanfbc4cfc2017-09-22 16:45:45 -0700313 packages[package_index].processor_count++;
314 packages[package_index].core_count += new_core;
Marat Dukhan43a51cd2017-09-22 16:35:05 -0700315 }
316
317 if (x86_processors[i].cache.l1i.size != 0) {
318 const uint32_t l1i_id = apic_id & ~bit_mask(x86_processors[i].cache.l1i.apic_bits);
319 processors[i].cache.l1i = &l1i[l1i_index];
320 if (l1i_id != last_l1i_id) {
321 /* new cache */
322 last_l1i_id = l1i_id;
Marat Dukhanfbc4cfc2017-09-22 16:45:45 -0700323 l1i[++l1i_index] = (struct cpuinfo_cache) {
Marat Dukhan43a51cd2017-09-22 16:35:05 -0700324 .size = x86_processors[i].cache.l1i.size,
325 .associativity = x86_processors[i].cache.l1i.associativity,
326 .sets = x86_processors[i].cache.l1i.sets,
327 .partitions = x86_processors[i].cache.l1i.partitions,
328 .line_size = x86_processors[i].cache.l1i.line_size,
329 .flags = x86_processors[i].cache.l1i.flags,
330 .processor_start = i,
331 .processor_count = 1,
332 };
333 } else {
334 /* another processor sharing the same cache */
Marat Dukhanfbc4cfc2017-09-22 16:45:45 -0700335 l1i[l1i_index].processor_count += 1;
Marat Dukhan43a51cd2017-09-22 16:35:05 -0700336 }
337 } else {
338 /* reset cache id */
339 last_l1i_id = UINT32_MAX;
340 }
Marat Dukhan3045d4f2017-03-04 01:51:42 -0500341 if (x86_processors[i].cache.l1i.size != 0) {
342 const uint32_t l1i_id = apic_id & ~bit_mask(x86_processors[i].cache.l1i.apic_bits);
343 processors[i].cache.l1i = &l1i[l1i_index];
344 if (l1i_id != last_l1i_id) {
345 /* new cache */
346 last_l1i_id = l1i_id;
Marat Dukhanfbc4cfc2017-09-22 16:45:45 -0700347 l1i[++l1i_index] = (struct cpuinfo_cache) {
Marat Dukhanab3a1272017-08-25 23:20:07 -0700348 .size = x86_processors[i].cache.l1i.size,
349 .associativity = x86_processors[i].cache.l1i.associativity,
350 .sets = x86_processors[i].cache.l1i.sets,
351 .partitions = x86_processors[i].cache.l1i.partitions,
352 .line_size = x86_processors[i].cache.l1i.line_size,
353 .flags = x86_processors[i].cache.l1i.flags,
354 .processor_start = i,
355 .processor_count = 1,
Marat Dukhan3045d4f2017-03-04 01:51:42 -0500356 };
357 } else {
358 /* another processor sharing the same cache */
Marat Dukhanfbc4cfc2017-09-22 16:45:45 -0700359 l1i[l1i_index].processor_count += 1;
Marat Dukhan3045d4f2017-03-04 01:51:42 -0500360 }
361 } else {
362 /* reset cache id */
363 last_l1i_id = UINT32_MAX;
364 }
365 if (x86_processors[i].cache.l1d.size != 0) {
366 const uint32_t l1d_id = apic_id & ~bit_mask(x86_processors[i].cache.l1d.apic_bits);
367 processors[i].cache.l1d = &l1d[l1d_index];
368 if (l1d_id != last_l1d_id) {
369 /* new cache */
370 last_l1d_id = l1d_id;
Marat Dukhanfbc4cfc2017-09-22 16:45:45 -0700371 l1d[++l1d_index] = (struct cpuinfo_cache) {
Marat Dukhanab3a1272017-08-25 23:20:07 -0700372 .size = x86_processors[i].cache.l1d.size,
373 .associativity = x86_processors[i].cache.l1d.associativity,
374 .sets = x86_processors[i].cache.l1d.sets,
375 .partitions = x86_processors[i].cache.l1d.partitions,
376 .line_size = x86_processors[i].cache.l1d.line_size,
377 .flags = x86_processors[i].cache.l1d.flags,
378 .processor_start = i,
379 .processor_count = 1,
Marat Dukhan3045d4f2017-03-04 01:51:42 -0500380 };
381 } else {
382 /* another processor sharing the same cache */
Marat Dukhanfbc4cfc2017-09-22 16:45:45 -0700383 l1d[l1d_index].processor_count += 1;
Marat Dukhan3045d4f2017-03-04 01:51:42 -0500384 }
385 } else {
386 /* reset cache id */
387 last_l1d_id = UINT32_MAX;
388 }
389 if (x86_processors[i].cache.l2.size != 0) {
390 const uint32_t l2_id = apic_id & ~bit_mask(x86_processors[i].cache.l2.apic_bits);
391 processors[i].cache.l2 = &l2[l2_index];
392 if (l2_id != last_l2_id) {
393 /* new cache */
394 last_l2_id = l2_id;
Marat Dukhanfbc4cfc2017-09-22 16:45:45 -0700395 l2[++l2_index] = (struct cpuinfo_cache) {
Marat Dukhanab3a1272017-08-25 23:20:07 -0700396 .size = x86_processors[i].cache.l2.size,
397 .associativity = x86_processors[i].cache.l2.associativity,
398 .sets = x86_processors[i].cache.l2.sets,
399 .partitions = x86_processors[i].cache.l2.partitions,
400 .line_size = x86_processors[i].cache.l2.line_size,
401 .flags = x86_processors[i].cache.l2.flags,
402 .processor_start = i,
403 .processor_count = 1,
Marat Dukhan3045d4f2017-03-04 01:51:42 -0500404 };
405 } else {
406 /* another processor sharing the same cache */
Marat Dukhanfbc4cfc2017-09-22 16:45:45 -0700407 l2[l2_index].processor_count += 1;
Marat Dukhan3045d4f2017-03-04 01:51:42 -0500408 }
409 } else {
410 /* reset cache id */
411 last_l2_id = UINT32_MAX;
412 }
413 if (x86_processors[i].cache.l3.size != 0) {
414 const uint32_t l3_id = apic_id & ~bit_mask(x86_processors[i].cache.l3.apic_bits);
415 processors[i].cache.l3 = &l3[l3_index];
416 if (l3_id != last_l3_id) {
417 /* new cache */
418 last_l3_id = l3_id;
Marat Dukhanfbc4cfc2017-09-22 16:45:45 -0700419 l3[++l3_index] = (struct cpuinfo_cache) {
Marat Dukhanab3a1272017-08-25 23:20:07 -0700420 .size = x86_processors[i].cache.l3.size,
421 .associativity = x86_processors[i].cache.l3.associativity,
422 .sets = x86_processors[i].cache.l3.sets,
423 .partitions = x86_processors[i].cache.l3.partitions,
424 .line_size = x86_processors[i].cache.l3.line_size,
425 .flags = x86_processors[i].cache.l3.flags,
426 .processor_start = i,
427 .processor_count = 1,
Marat Dukhan3045d4f2017-03-04 01:51:42 -0500428 };
429 } else {
430 /* another processor sharing the same cache */
Marat Dukhanfbc4cfc2017-09-22 16:45:45 -0700431 l3[l3_index].processor_count += 1;
Marat Dukhan3045d4f2017-03-04 01:51:42 -0500432 }
433 } else {
434 /* reset cache id */
435 last_l3_id = UINT32_MAX;
436 }
437 if (x86_processors[i].cache.l4.size != 0) {
438 const uint32_t l4_id = apic_id & ~bit_mask(x86_processors[i].cache.l4.apic_bits);
439 processors[i].cache.l4 = &l4[l4_index];
440 if (l4_id != last_l4_id) {
441 /* new cache */
442 last_l4_id = l4_id;
Marat Dukhanfbc4cfc2017-09-22 16:45:45 -0700443 l4[++l4_index] = (struct cpuinfo_cache) {
Marat Dukhanab3a1272017-08-25 23:20:07 -0700444 .size = x86_processors[i].cache.l4.size,
445 .associativity = x86_processors[i].cache.l4.associativity,
446 .sets = x86_processors[i].cache.l4.sets,
447 .partitions = x86_processors[i].cache.l4.partitions,
448 .line_size = x86_processors[i].cache.l4.line_size,
449 .flags = x86_processors[i].cache.l4.flags,
450 .processor_start = i,
451 .processor_count = 1,
Marat Dukhan3045d4f2017-03-04 01:51:42 -0500452 };
453 } else {
454 /* another processor sharing the same cache */
Marat Dukhanfbc4cfc2017-09-22 16:45:45 -0700455 l4[l4_index].processor_count += 1;
Marat Dukhan3045d4f2017-03-04 01:51:42 -0500456 }
457 } else {
458 /* reset cache id */
459 last_l4_id = UINT32_MAX;
460 }
461 }
462
Marat Dukhanfbc4cfc2017-09-22 16:45:45 -0700463 #ifdef __ANDROID__
464 cpuinfo_gpu_query_gles2(packages[0].gpu_name);
465 #endif
466
Marat Dukhan3045d4f2017-03-04 01:51:42 -0500467 /* Commit changes */
468 cpuinfo_processors = processors;
Marat Dukhan43a51cd2017-09-22 16:35:05 -0700469 cpuinfo_cores = cores;
470 cpuinfo_packages = packages;
Marat Dukhan3045d4f2017-03-04 01:51:42 -0500471 cpuinfo_cache[cpuinfo_cache_level_1i] = l1i;
472 cpuinfo_cache[cpuinfo_cache_level_1d] = l1d;
473 cpuinfo_cache[cpuinfo_cache_level_2] = l2;
474 cpuinfo_cache[cpuinfo_cache_level_3] = l3;
475 cpuinfo_cache[cpuinfo_cache_level_4] = l4;
476
Marat Dukhan8ecad1a2017-05-08 07:21:57 +0000477 cpuinfo_processors_count = processors_count;
Marat Dukhan43a51cd2017-09-22 16:35:05 -0700478 cpuinfo_cores_count = cores_count;
479 cpuinfo_packages_count = packages_count;
Marat Dukhan3045d4f2017-03-04 01:51:42 -0500480 cpuinfo_cache_count[cpuinfo_cache_level_1i] = l1i_count;
481 cpuinfo_cache_count[cpuinfo_cache_level_1d] = l1d_count;
482 cpuinfo_cache_count[cpuinfo_cache_level_2] = l2_count;
483 cpuinfo_cache_count[cpuinfo_cache_level_3] = l3_count;
484 cpuinfo_cache_count[cpuinfo_cache_level_4] = l4_count;
485
Marat Dukhan3045d4f2017-03-04 01:51:42 -0500486 processors = NULL;
Marat Dukhan43a51cd2017-09-22 16:35:05 -0700487 cores = NULL;
488 packages = NULL;
Marat Dukhan3045d4f2017-03-04 01:51:42 -0500489 l1i = l1d = l2 = l3 = l4 = NULL;
490
491cleanup:
492 if (sched_setaffinity(0, sizeof(cpu_set_t), &old_affinity) != 0) {
493 cpuinfo_log_warning("could not restore initial process affinity: "
494 "sched_getaffinity failed: %s", strerror(errno));
495 }
496
497 free(x86_processors);
498 free(processors);
Marat Dukhan43a51cd2017-09-22 16:35:05 -0700499 free(cores);
500 free(packages);
Marat Dukhan3045d4f2017-03-04 01:51:42 -0500501 free(l1i);
502 free(l1d);
503 free(l2);
504 free(l3);
505 free(l4);
506}