blob: ca3caa9c3b1501290073a21cf788cd8bd8a87e8b [file] [log] [blame]
Marat Dukhan1f5d9bc2020-01-02 09:11:16 -08001diff --git CMakeLists.txt CMakeLists.txt
2index e594def..cab4d05 100644
3--- CMakeLists.txt
4+++ CMakeLists.txt
5@@ -119,7 +119,8 @@ ENDIF()
6 # ---[ cpuinfo library
7 SET(CPUINFO_SRCS
8 src/init.c
9- src/api.c)
10+ src/api.c
11+ src/cache.c)
12
13 IF(CPUINFO_SUPPORTED_PLATFORM)
14 IF(CMAKE_SYSTEM_PROCESSOR MATCHES "^(i[3-6]86|AMD64|x86(_64)?)$" OR IOS_ARCH MATCHES "^(i386|x86_64)$")
15diff --git LICENSE LICENSE
16index 4910bfe..3f9a4f0 100644
17--- LICENSE
18+++ LICENSE
19@@ -1,3 +1,4 @@
20+Copyright (c) 2019 Google LLC
21 Copyright (c) 2017-2018 Facebook Inc.
22 Copyright (C) 2012-2017 Georgia Institute of Technology
23 Copyright (C) 2010-2012 Marat Dukhan
24diff --git include/cpuinfo.h include/cpuinfo.h
25index 7d5833f..9938d2b 100644
26--- include/cpuinfo.h
27+++ include/cpuinfo.h
28@@ -38,10 +38,18 @@
29 #define CPUINFO_ARCH_PNACL 1
30 #endif
31
32-#if defined(EMSCRIPTEN)
33+#if defined(__asmjs__)
34 #define CPUINFO_ARCH_ASMJS 1
35 #endif
36
37+#if defined(__wasm__)
38+ #if defined(__wasm_simd128__)
39+ #define CPUINFO_ARCH_WASMSIMD 1
40+ #else
41+ #define CPUINFO_ARCH_WASM 1
42+ #endif
43+#endif
44+
45 #if CPUINFO_ARCH_X86 && defined(_MSC_VER)
46 #define CPUINFO_ABI __cdecl
47 #elif CPUINFO_ARCH_X86 && defined(__GNUC__)
48@@ -80,6 +88,14 @@
49 #define CPUINFO_ARCH_ASMJS 0
50 #endif
51
52+#ifndef CPUINFO_ARCH_WASM
53+ #define CPUINFO_ARCH_WASM 0
54+#endif
55+
56+#ifndef CPUINFO_ARCH_WASMSIMD
57+ #define CPUINFO_ARCH_WASMSIMD 0
58+#endif
59+
60 #define CPUINFO_CACHE_UNIFIED 0x00000001
61 #define CPUINFO_CACHE_INCLUSIVE 0x00000002
62 #define CPUINFO_CACHE_COMPLEX_INDEXING 0x00000004
63@@ -278,10 +294,14 @@ enum cpuinfo_uarch {
64 cpuinfo_uarch_haswell = 0x00100208,
65 /** Intel Broadwell microarchitecture. */
66 cpuinfo_uarch_broadwell = 0x00100209,
67- /** Intel Sky Lake microarchitecture. */
68+ /** Intel Sky Lake microarchitecture (14 nm, including Kaby/Coffee/Whiskey/Amber/Comet/Cascade/Cooper Lake). */
69 cpuinfo_uarch_sky_lake = 0x0010020A,
70- /** Intel Kaby Lake microarchitecture. */
71- cpuinfo_uarch_kaby_lake = 0x0010020B,
72+ /** DEPRECATED (Intel Kaby Lake microarchitecture). */
73+ cpuinfo_uarch_kaby_lake = 0x0010020A,
74+ /** Intel Palm Cove microarchitecture (10 nm, Cannon Lake). */
75+ cpuinfo_uarch_palm_cove = 0x0010020B,
76+ /** Intel Sunny Cove microarchitecture (10 nm, Ice Lake). */
77+ cpuinfo_uarch_sunny_cove = 0x0010020C,
78
79 /** Pentium 4 with Willamette, Northwood, or Foster cores. */
80 cpuinfo_uarch_willamette = 0x00100300,
81@@ -289,13 +309,17 @@ enum cpuinfo_uarch {
82 cpuinfo_uarch_prescott = 0x00100301,
83
84 /** Intel Atom on 45 nm process. */
85- cpuinfo_uarch_bonnell = 0x00100400,
86+ cpuinfo_uarch_bonnell = 0x00100400,
87 /** Intel Atom on 32 nm process. */
88- cpuinfo_uarch_saltwell = 0x00100401,
89+ cpuinfo_uarch_saltwell = 0x00100401,
90 /** Intel Silvermont microarchitecture (22 nm out-of-order Atom). */
91- cpuinfo_uarch_silvermont = 0x00100402,
92+ cpuinfo_uarch_silvermont = 0x00100402,
93 /** Intel Airmont microarchitecture (14 nm out-of-order Atom). */
94- cpuinfo_uarch_airmont = 0x00100403,
95+ cpuinfo_uarch_airmont = 0x00100403,
96+ /** Intel Goldmont microarchitecture (Denverton, Apollo Lake). */
97+ cpuinfo_uarch_goldmont = 0x00100404,
98+ /** Intel Goldmont Plus microarchitecture (Gemini Lake). */
99+ cpuinfo_uarch_goldmont_plus = 0x00100405,
100
101 /** Intel Knights Ferry HPC boards. */
102 cpuinfo_uarch_knights_ferry = 0x00100500,
103@@ -335,8 +359,10 @@ enum cpuinfo_uarch {
104 cpuinfo_uarch_steamroller = 0x00200107,
105 /** AMD Excavator microarchitecture (Carizzo APUs). */
106 cpuinfo_uarch_excavator = 0x00200108,
107- /** AMD Zen microarchitecture (Ryzen CPUs). */
108+ /** AMD Zen microarchitecture (12/14 nm Ryzen and EPYC CPUs). */
109 cpuinfo_uarch_zen = 0x00200109,
110+ /** AMD Zen 2 microarchitecture (7 nm Ryzen and EPYC CPUs). */
111+ cpuinfo_uarch_zen2 = 0x0020010A,
112
113 /** NSC Geode and AMD Geode GX and LX. */
114 cpuinfo_uarch_geode = 0x00200200,
115@@ -370,23 +396,34 @@ enum cpuinfo_uarch {
116 cpuinfo_uarch_cortex_a17 = 0x00300217,
117
118 /** ARM Cortex-A32. */
119- cpuinfo_uarch_cortex_a32 = 0x00300332,
120+ cpuinfo_uarch_cortex_a32 = 0x00300332,
121 /** ARM Cortex-A35. */
122- cpuinfo_uarch_cortex_a35 = 0x00300335,
123+ cpuinfo_uarch_cortex_a35 = 0x00300335,
124 /** ARM Cortex-A53. */
125- cpuinfo_uarch_cortex_a53 = 0x00300353,
126+ cpuinfo_uarch_cortex_a53 = 0x00300353,
127 /** ARM Cortex-A55. */
128- cpuinfo_uarch_cortex_a55 = 0x00300355,
129+ cpuinfo_uarch_cortex_a55 = 0x00300355,
130 /** ARM Cortex-A57. */
131- cpuinfo_uarch_cortex_a57 = 0x00300357,
132+ cpuinfo_uarch_cortex_a57 = 0x00300357,
133+ /** ARM Cortex-A65. */
134+ cpuinfo_uarch_cortex_a65 = 0x00300365,
135 /** ARM Cortex-A72. */
136- cpuinfo_uarch_cortex_a72 = 0x00300372,
137+ cpuinfo_uarch_cortex_a72 = 0x00300372,
138 /** ARM Cortex-A73. */
139- cpuinfo_uarch_cortex_a73 = 0x00300373,
140+ cpuinfo_uarch_cortex_a73 = 0x00300373,
141 /** ARM Cortex-A75. */
142- cpuinfo_uarch_cortex_a75 = 0x00300375,
143+ cpuinfo_uarch_cortex_a75 = 0x00300375,
144 /** ARM Cortex-A76. */
145- cpuinfo_uarch_cortex_a76 = 0x00300376,
146+ cpuinfo_uarch_cortex_a76 = 0x00300376,
147+ /** ARM Cortex-A76AE. */
148+ cpuinfo_uarch_cortex_a76ae = 0x00300378,
149+ /** ARM Cortex-A77. */
150+ cpuinfo_uarch_cortex_a77 = 0x00300377,
151+
152+ /** ARM Neoverse N1. */
153+ cpuinfo_uarch_neoverse_n1 = 0x00300400,
154+ /** ARM Neoverse E1. */
155+ cpuinfo_uarch_neoverse_e1 = 0x00300401,
156
157 /** Qualcomm Scorpion. */
158 cpuinfo_uarch_scorpion = 0x00400100,
159@@ -406,12 +443,22 @@ enum cpuinfo_uarch {
160 /** Nvidia Carmel. */
161 cpuinfo_uarch_carmel = 0x00500102,
162
163- /** Samsung Mongoose M1 (Exynos 8890 big cores). */
164+ /** Samsung Exynos M1 (Exynos 8890 big cores). */
165+ cpuinfo_uarch_exynos_m1 = 0x00600100,
166+ /** Samsung Exynos M2 (Exynos 8895 big cores). */
167+ cpuinfo_uarch_exynos_m2 = 0x00600101,
168+ /** Samsung Exynos M3 (Exynos 9810 big cores). */
169+ cpuinfo_uarch_exynos_m3 = 0x00600102,
170+ /** Samsung Exynos M4 (Exynos 9820 big cores). */
171+ cpuinfo_uarch_exynos_m4 = 0x00600103,
172+ /** Samsung Exynos M5 (Exynos 9830 big cores). */
173+ cpuinfo_uarch_exynos_m5 = 0x00600104,
174+
175+ /* Old names for Exynos. */
176 cpuinfo_uarch_mongoose_m1 = 0x00600100,
177- /** Samsung Mongoose M2 (Exynos 8895 big cores). */
178 cpuinfo_uarch_mongoose_m2 = 0x00600101,
179- /** Samsung Meerkat M3 (Exynos 9810 big cores). */
180 cpuinfo_uarch_meerkat_m3 = 0x00600102,
181+ cpuinfo_uarch_meerkat_m4 = 0x00600103,
182
183 /** Apple A6 and A6X processors. */
184 cpuinfo_uarch_swift = 0x00700100,
185@@ -640,6 +687,8 @@ void CPUINFO_ABI cpuinfo_deinitialize(void);
186 bool avx512bitalg;
187 bool avx512vpopcntdq;
188 bool avx512vnni;
189+ bool avx512bf16;
190+ bool avx512vp2intersect;
191 bool avx512_4vnniw;
192 bool avx512_4fmaps;
193 bool hle;
194@@ -1110,6 +1159,22 @@ static inline bool cpuinfo_has_x86_avx512vnni(void) {
195 #endif
196 }
197
198+static inline bool cpuinfo_has_x86_avx512bf16(void) {
199+ #if CPUINFO_ARCH_X86 || CPUINFO_ARCH_X86_64
200+ return cpuinfo_isa.avx512bf16;
201+ #else
202+ return false;
203+ #endif
204+}
205+
206+static inline bool cpuinfo_has_x86_avx512vp2intersect(void) {
207+ #if CPUINFO_ARCH_X86 || CPUINFO_ARCH_X86_64
208+ return cpuinfo_isa.avx512vp2intersect;
209+ #else
210+ return false;
211+ #endif
212+}
213+
214 static inline bool cpuinfo_has_x86_avx512_4vnniw(void) {
215 #if CPUINFO_ARCH_X86 || CPUINFO_ARCH_X86_64
216 return cpuinfo_isa.avx512_4vnniw;
217@@ -1682,6 +1747,11 @@ uint32_t CPUINFO_ABI cpuinfo_get_l2_caches_count(void);
218 uint32_t CPUINFO_ABI cpuinfo_get_l3_caches_count(void);
219 uint32_t CPUINFO_ABI cpuinfo_get_l4_caches_count(void);
220
221+/**
222+ * Returns upper bound on cache size.
223+ */
224+uint32_t CPUINFO_ABI cpuinfo_get_max_cache_size(void);
225+
226 const struct cpuinfo_processor* CPUINFO_ABI cpuinfo_get_current_processor(void);
227 const struct cpuinfo_core* CPUINFO_ABI cpuinfo_get_current_core(void);
228
229diff --git src/api.c src/api.c
230index 98b5805..83744f5 100644
231--- src/api.c
232+++ src/api.c
233@@ -18,6 +18,7 @@ uint32_t cpuinfo_cores_count = 0;
234 uint32_t cpuinfo_clusters_count = 0;
235 uint32_t cpuinfo_packages_count = 0;
236 uint32_t cpuinfo_cache_count[cpuinfo_cache_level_max] = { 0 };
237+uint32_t cpuinfo_max_cache_size = 0;
238
239
240 const struct cpuinfo_processor* cpuinfo_get_processors(void) {
241diff --git src/arm/api.h src/arm/api.h
242index 11e588b..69274bc 100644
243--- src/arm/api.h
244+++ src/arm/api.h
245@@ -104,6 +104,9 @@ CPUINFO_INTERNAL void cpuinfo_arm_decode_cache(
246 struct cpuinfo_cache l1d[restrict static 1],
247 struct cpuinfo_cache l2[restrict static 1],
248 struct cpuinfo_cache l3[restrict static 1]);
249+
250+CPUINFO_INTERNAL uint32_t cpuinfo_arm_compute_max_cache_size(
251+ const struct cpuinfo_processor processor[restrict static 1]);
252 #else /* defined(__cplusplus) */
253 CPUINFO_INTERNAL void cpuinfo_arm_decode_cache(
254 enum cpuinfo_uarch uarch,
255diff --git src/arm/cache.c src/arm/cache.c
256index 5ada7d9..ccadeb4 100644
257--- src/arm/cache.c
258+++ src/arm/cache.c
259@@ -1,10 +1,12 @@
260 #include <stdint.h>
261
262 #include <cpuinfo.h>
263+#include <cpuinfo/internal-api.h>
264 #include <cpuinfo/log.h>
265 #include <arm/api.h>
266 #include <arm/midr.h>
267
268+
269 void cpuinfo_arm_decode_cache(
270 enum cpuinfo_uarch uarch,
271 uint32_t cluster_cores,
272@@ -109,7 +111,7 @@ void cpuinfo_arm_decode_cache(
273 * memory accesses and has been optimized for use with the Cortex-A5 processor.
274 * 8.1.7. Exclusive L2 cache
275 * The Cortex-A5 processor can be connected to an L2 cache that supports an exclusive cache mode.
276- * This mode must be activated both in the Cortex-A5 processor and in the L2 cache controller.
277+ * This mode must be activated both in the Cortex-A5 processor and in the L2 cache controller.
278 *
279 * +--------------------+-----------+-----------+----------+-----------+
280 * | Processor model | L1D cache | L1I cache | L2 cache | Reference |
281@@ -698,7 +700,7 @@ void cpuinfo_arm_decode_cache(
282 * [3] https://en.wikichip.org/wiki/hisilicon/kirin/980
283 */
284 if (midr_is_qualcomm_cortex_a55_silver(midr)) {
285- /* Qualcomm-modified Cortex-A55 in Snapdragon 710 / 845 */
286+ /* Qualcomm-modified Cortex-A55 in Snapdragon 670 / 710 / 845 */
287 uint32_t l3_size = 1024 * 1024;
288 switch (chipset->series) {
289 case cpuinfo_arm_chipset_series_qualcomm_snapdragon:
290@@ -827,6 +829,62 @@ void cpuinfo_arm_decode_cache(
291 .flags = CPUINFO_CACHE_INCLUSIVE
292 };
293 break;
294+ case cpuinfo_uarch_cortex_a65:
295+ {
296+ /*
297+ * ARM Cortex‑A65 Core Technical Reference Manual
298+ * A6.1. About the L1 memory system
299+ * The L1 memory system enhances the performance and power efficiency in the Cortex‑A65 core.
300+ * It consists of separate instruction and data caches. You can configure instruction and data caches
301+ * independently during implementation to sizes of 32KB or 64KB.
302+ *
303+ * L1 instruction-side memory system
304+ * The L1 instruction-side memory system provides an instruction stream to the DPU. Its key features are:
305+ * - 64-byte instruction side cache line length.
306+ * - 4-way set associative L1 instruction cache.
307+ *
308+ * L1 data-side memory system
309+ * - 64-byte data side cache line length.
310+ * - 4-way set associative L1 data cache.
311+ *
312+ * A7.1 About the L2 memory system
313+ * The Cortex‑A65 L2 memory system is required to interface the Cortex‑A65 cores to the L3 memory system.
314+ * The L2 memory subsystem consists of:
315+ * - An optional 4-way, set-associative L2 cache with a configurable size of 64KB, 128KB, or 256KB.
316+ * Cache lines have a fixed length of 64 bytes.
317+ *
318+ * The main features of the L2 memory system are:
319+ * - Strictly exclusive with L1 data cache.
320+ * - Pseudo-inclusive with L1 instruction cache.
321+ * - Private per-core unified L2 cache.
322+ */
323+ const uint32_t l1_size = 32 * 1024;
324+ const uint32_t l2_size = 128 * 1024;
325+ const uint32_t l3_size = 512 * 1024;
326+ *l1i = (struct cpuinfo_cache) {
327+ .size = l1_size,
328+ .associativity = 4,
329+ .line_size = 64,
330+ };
331+ *l1d = (struct cpuinfo_cache) {
332+ .size = l1_size,
333+ .associativity = 4,
334+ .line_size = 64,
335+ };
336+ *l2 = (struct cpuinfo_cache) {
337+ .size = l2_size,
338+ .associativity = 4,
339+ .line_size = 64,
340+ .flags = CPUINFO_CACHE_INCLUSIVE
341+ };
342+ *l3 = (struct cpuinfo_cache) {
343+ .size = l3_size,
344+ /* DynamIQ */
345+ .associativity = 16,
346+ .line_size = 64,
347+ };
348+ break;
349+ }
350 case cpuinfo_uarch_cortex_a72:
351 {
352 /*
353@@ -1047,6 +1105,7 @@ void cpuinfo_arm_decode_cache(
354 break;
355 }
356 case cpuinfo_uarch_cortex_a76:
357+ case cpuinfo_uarch_cortex_a76ae:
358 {
359 /*
360 * ARM Cortex-A76 Core Technical Reference Manual
361@@ -1119,6 +1178,57 @@ void cpuinfo_arm_decode_cache(
362 };
363 break;
364 }
365+ case cpuinfo_uarch_cortex_a77:
366+ {
367+ /*
368+ * ARM Cortex-A77 Core Technical Reference Manual
369+ * A6.1. About the L1 memory system
370+ * The L1 memory system consists of separate instruction and data caches. Both have a fixed size of 64KB.
371+ *
372+ * A6.1.1 L1 instruction-side memory system
373+ * The L1 instruction memory system has the following key features:
374+ * - Virtually Indexed, Physically Tagged (VIPT), which behaves as a Physically Indexed,
375+ * Physically Tagged (PIPT) 4-way set-associative L1 data cache.
376+ * - Fixed cache line length of 64 bytes.
377+ *
378+ * A6.1.2 L1 data-side memory system
379+ * The L1 data memory system has the following features:
380+ * - Virtually Indexed, Physically Tagged (VIPT), which behaves as a Physically Indexed,
381+ * Physically Tagged (PIPT) 4-way set-associative L1 data cache.
382+ * - Fixed cache line length of 64 bytes.
383+ * - Pseudo-LRU cache replacement policy.
384+ *
385+ * A7.1 About the L2 memory system
386+ * The L2 memory subsystem consist of:
387+ * - An 8-way set associative L2 cache with a configurable size of 128KB, 256KB or 512KB. Cache lines
388+ * have a fixed length of 64 bytes.
389+ * - Strictly inclusive with L1 data cache. Weakly inclusive with L1 instruction cache.
390+ */
391+ const uint32_t l2_size = 256 * 1024;
392+ const uint32_t l3_size = 1024 * 1024;
393+ *l1i = (struct cpuinfo_cache) {
394+ .size = 64 * 1024,
395+ .associativity = 4,
396+ .line_size = 64,
397+ };
398+ *l1d = (struct cpuinfo_cache) {
399+ .size = 64 * 1024,
400+ .associativity = 4,
401+ .line_size = 64,
402+ };
403+ *l2 = (struct cpuinfo_cache) {
404+ .size = l2_size,
405+ .associativity = 8,
406+ .line_size = 64,
407+ .flags = CPUINFO_CACHE_INCLUSIVE,
408+ };
409+ *l3 = (struct cpuinfo_cache) {
410+ .size = l3_size,
411+ .associativity = 16,
412+ .line_size = 64,
413+ };
414+ break;
415+ }
416 #if CPUINFO_ARCH_ARM && !defined(__ARM_ARCH_8A__)
417 case cpuinfo_uarch_scorpion:
418 /*
419@@ -1248,8 +1358,8 @@ void cpuinfo_arm_decode_cache(
420 .line_size = 64
421 };
422 break;
423- case cpuinfo_uarch_mongoose_m1:
424- case cpuinfo_uarch_mongoose_m2:
425+ case cpuinfo_uarch_exynos_m1:
426+ case cpuinfo_uarch_exynos_m2:
427 /*
428 * - "Moving past branch prediction we can see some elements of how the cache is set up for the L1 I$,
429 * namely 64 KB split into four sets with 128-byte line sizes for 128 cache lines per set" [1]
430@@ -1283,7 +1393,7 @@ void cpuinfo_arm_decode_cache(
431 .line_size = 64
432 };
433 break;
434- case cpuinfo_uarch_meerkat_m3:
435+ case cpuinfo_uarch_exynos_m3:
436 /*
437 * +--------------------+-------+-----------+-----------+-----------+----------+------------+
438 * | Processor model | Cores | L1D cache | L1I cache | L2 cache | L3 cache | Reference |
439@@ -1294,19 +1404,19 @@ void cpuinfo_arm_decode_cache(
440 * [1] https://www.anandtech.com/show/12478/exynos-9810-handson-awkward-first-results
441 */
442 *l1i = (struct cpuinfo_cache) {
443- .size = 64 * 1024 /* assume same as in Mongoose cores */,
444- .associativity = 4 /* assume same as in Mongoose cores */,
445- .line_size = 128 /* assume same as in Mongoose cores */
446+ .size = 64 * 1024 /* assume same as in Exynos M1/M2 cores */,
447+ .associativity = 4 /* assume same as in Exynos M1/M2 cores */,
448+ .line_size = 128 /* assume same as in Exynos M1/M2 cores */
449 };
450 *l1d = (struct cpuinfo_cache) {
451 .size = 64 * 1024,
452- .associativity = 8 /* assume same as in Mongoose cores */,
453- .line_size = 64 /* assume same as in Mongoose cores */,
454+ .associativity = 8 /* assume same as in Exynos M1/M2 cores */,
455+ .line_size = 64 /* assume same as in Exynos M1/M2 cores */,
456 };
457 *l2 = (struct cpuinfo_cache) {
458 .size = 512 * 1024,
459- .associativity = 16 /* assume same as in Mongoose cores */,
460- .line_size = 64 /* assume same as in Mongoose cores */,
461+ .associativity = 16 /* assume same as in Exynos M1/M2 cores */,
462+ .line_size = 64 /* assume same as in Exynos M1/M2 cores */,
463 };
464 *l3 = (struct cpuinfo_cache) {
465 .size = 4 * 1024 * 1024,
466@@ -1393,3 +1503,124 @@ void cpuinfo_arm_decode_cache(
467 }
468 }
469 }
470+
471+uint32_t cpuinfo_arm_compute_max_cache_size(const struct cpuinfo_processor* processor) {
472+ /*
473+ * There is no precise way to detect cache size on ARM/ARM64, and cache size reported by cpuinfo
474+ * may underestimate the actual cache size. Thus, we use microarchitecture-specific maximum.
475+ */
476+ switch (processor->core->uarch) {
477+ case cpuinfo_uarch_xscale:
478+ case cpuinfo_uarch_arm11:
479+ case cpuinfo_uarch_scorpion:
480+ case cpuinfo_uarch_krait:
481+ case cpuinfo_uarch_kryo:
482+ case cpuinfo_uarch_exynos_m1:
483+ case cpuinfo_uarch_exynos_m2:
484+ case cpuinfo_uarch_exynos_m3:
485+ /* cpuinfo-detected cache size always correct */
486+ return cpuinfo_compute_max_cache_size(processor);
487+ case cpuinfo_uarch_cortex_a5:
488+ /* Max observed (NXP Vybrid SoC) */
489+ return 512 * 1024;
490+ case cpuinfo_uarch_cortex_a7:
491+ /*
492+ * Cortex-A7 MPCore Technical Reference Manual:
493+ * 7.1. About the L2 Memory system
494+ * The L2 memory system consists of an:
495+ * - Optional tightly-coupled L2 cache that includes:
496+ * - Configurable L2 cache size of 128KB, 256KB, 512KB, and 1MB.
497+ */
498+ return 1024 * 1024;
499+ case cpuinfo_uarch_cortex_a8:
500+ /*
501+ * Cortex-A8 Technical Reference Manual:
502+ * 8.1. About the L2 memory system
503+ * The key features of the L2 memory system include:
504+ * - configurable cache size of 0KB, 128KB, 256KB, 512KB, and 1MB
505+ */
506+ return 1024 * 1024;
507+ case cpuinfo_uarch_cortex_a9:
508+ /* Max observed (e.g. Exynos 4212) */
509+ return 1024 * 1024;
510+ case cpuinfo_uarch_cortex_a12:
511+ case cpuinfo_uarch_cortex_a17:
512+ /*
513+ * ARM Cortex-A17 MPCore Processor Technical Reference Manual:
514+ * 7.1. About the L2 Memory system
515+ * The key features of the L2 memory system include:
516+ * - An integrated L2 cache:
517+ * - The cache size is implemented as either 256KB, 512KB, 1MB, 2MB, 4MB or 8MB.
518+ */
519+ return 8 * 1024 * 1024;
520+ case cpuinfo_uarch_cortex_a15:
521+ /*
522+ * ARM Cortex-A15 MPCore Processor Technical Reference Manual:
523+ * 7.1. About the L2 memory system
524+ * The features of the L2 memory system include:
525+ * - Configurable L2 cache size of 512KB, 1MB, 2MB and 4MB.
526+ */
527+ return 4 * 1024 * 1024;
528+ case cpuinfo_uarch_cortex_a35:
529+ /*
530+ * ARM Cortex‑A35 Processor Technical Reference Manual:
531+ * 7.1 About the L2 memory system
532+ * L2 cache
533+ * - Further features of the L2 cache are:
534+ * - Configurable size of 128KB, 256KB, 512KB, and 1MB.
535+ */
536+ return 1024 * 1024;
537+ case cpuinfo_uarch_cortex_a53:
538+ /*
539+ * ARM Cortex-A53 MPCore Processor Technical Reference Manual:
540+ * 7.1. About the L2 memory system
541+ * The L2 memory system consists of an:
542+ * - Optional tightly-coupled L2 cache that includes:
543+ * - Configurable L2 cache size of 128KB, 256KB, 512KB, 1MB and 2MB.
544+ */
545+ return 2 * 1024 * 1024;
546+ case cpuinfo_uarch_cortex_a57:
547+ /*
548+ * ARM Cortex-A57 MPCore Processor Technical Reference Manual:
549+ * 7.1 About the L2 memory system
550+ * The features of the L2 memory system include:
551+ * - Configurable L2 cache size of 512KB, 1MB, and 2MB.
552+ */
553+ return 2 * 1024 * 1024;
554+ case cpuinfo_uarch_cortex_a72:
555+ /*
556+ * ARM Cortex-A72 MPCore Processor Technical Reference Manual:
557+ * 7.1 About the L2 memory system
558+ * The features of the L2 memory system include:
559+ * - Configurable L2 cache size of 512KB, 1MB, 2MB and 4MB.
560+ */
561+ return 4 * 1024 * 1024;
562+ case cpuinfo_uarch_cortex_a73:
563+ /*
564+ * ARM Cortex‑A73 MPCore Processor Technical Reference Manual
565+ * 7.1 About the L2 memory system
566+ * The L2 memory system consists of:
567+ * - A tightly-integrated L2 cache with:
568+ * - A configurable size of 256KB, 512KB, 1MB, 2MB, 4MB, or 8MB.
569+ */
570+ return 8 * 1024 * 1024;
571+ case cpuinfo_uarch_cortex_a55:
572+ case cpuinfo_uarch_cortex_a75:
573+ case cpuinfo_uarch_cortex_a76:
574+ case cpuinfo_uarch_exynos_m4:
575+ default:
576+ /*
577+ * ARM DynamIQ Shared Unit Technical Reference Manual
578+ * 1.3 Implementation options
579+ * L3_CACHE_SIZE
580+ * - 256KB
581+ * - 512KB
582+ * - 1024KB
583+ * - 1536KB
584+ * - 2048KB
585+ * - 3072KB
586+ * - 4096KB
587+ */
588+ return 4 * 1024 * 1024;
589+ }
590+}
591diff --git src/arm/linux/init.c src/arm/linux/init.c
592index a297f63..f0c432c 100644
593--- src/arm/linux/init.c
594+++ src/arm/linux/init.c
595@@ -678,6 +678,8 @@ void cpuinfo_arm_linux_init(void) {
596 cpuinfo_cache_count[cpuinfo_cache_level_2] = l2_count;
597 cpuinfo_cache_count[cpuinfo_cache_level_3] = l3_count;
598
599+ cpuinfo_max_cache_size = cpuinfo_arm_compute_max_cache_size(&processors[0]);
600+
601 __sync_synchronize();
602
603 cpuinfo_is_initialized = true;
604diff --git src/arm/linux/midr.c src/arm/linux/midr.c
605index 668fc72..2c3116b 100644
606--- src/arm/linux/midr.c
607+++ src/arm/linux/midr.c
608@@ -220,7 +220,7 @@ static const struct cluster_config cluster_configs[] = {
609 .model = UINT16_C(7420),
610 .clusters = 2,
611 .cluster_cores = {
612- [0] = 4,
613+ [0] = 4,
614 [1] = 4,
615 },
616 .cluster_midr = {
617@@ -229,7 +229,7 @@ static const struct cluster_config cluster_configs[] = {
618 },
619 },
620 {
621- /* Exynos 8890: 4x Mongoose + 4x Cortex-A53 */
622+ /* Exynos 8890: 4x Exynos M1 + 4x Cortex-A53 */
623 .cores = 8,
624 .series = cpuinfo_arm_chipset_series_samsung_exynos,
625 .model = UINT16_C(8890),
626@@ -695,7 +695,7 @@ static void cpuinfo_arm_linux_detect_cluster_midr_by_sequential_scan(
627 if (bitmask_all(processors[i].flags, CPUINFO_LINUX_FLAG_VALID)) {
628 if (processors[i].package_leader_id == i) {
629 if (bitmask_all(processors[i].flags, CPUINFO_ARM_LINUX_VALID_MIDR)) {
630- midr = processors[i].midr;
631+ midr = processors[i].midr;
632 } else {
633 cpuinfo_log_info("assume processor %"PRIu32" to have MIDR %08"PRIx32, i, midr);
634 /* To be consistent, we copy the MIDR entirely, rather than by parts */
635@@ -836,7 +836,7 @@ uint32_t cpuinfo_arm_linux_detect_cluster_midr(
636 * - Clusters preceeding the first reported MIDR value are assumed to have the last reported MIDR value.
637 * - Clusters following any reported MIDR value to have that MIDR value.
638 */
639-
640+
641 if (cpuinfo_arm_linux_detect_cluster_midr_by_chipset(
642 chipset, clusters_count, cluster_leaders, usable_processors, processors, true))
643 {
644diff --git src/arm/mach/init.c src/arm/mach/init.c
645index 5b14b49..e64cc18 100644
646--- src/arm/mach/init.c
647+++ src/arm/mach/init.c
648@@ -562,6 +562,8 @@ void cpuinfo_arm_mach_init(void) {
649 cpuinfo_clusters_count = num_clusters;
650 cpuinfo_packages_count = mach_topology.packages;
651
652+ cpuinfo_max_cache_size = cpuinfo_compute_max_cache_size(&processors[0]);
653+
654 __sync_synchronize();
655
656 cpuinfo_is_initialized = true;
657diff --git src/arm/midr.h src/arm/midr.h
658index 6363ed7..d5a28e3 100644
659--- src/arm/midr.h
660+++ src/arm/midr.h
661@@ -33,31 +33,31 @@
662 #define CPUINFO_ARM_MIDR_KRYO_SILVER_821 UINT32_C(0x510F2010)
663 #define CPUINFO_ARM_MIDR_KRYO_GOLD UINT32_C(0x510F2050)
664 #define CPUINFO_ARM_MIDR_KRYO_SILVER_820 UINT32_C(0x510F2110)
665-#define CPUINFO_ARM_MIDR_MONGOOSE UINT32_C(0x530F0010)
666+#define CPUINFO_ARM_MIDR_EXYNOS_M1_M2 UINT32_C(0x530F0010)
667 #define CPUINFO_ARM_MIDR_DENVER2 UINT32_C(0x4E0F0030)
668
669 inline static uint32_t midr_set_implementer(uint32_t midr, uint32_t implementer) {
670- return (midr & ~CPUINFO_ARM_MIDR_IMPLEMENTER_MASK) |
671+ return (midr & ~CPUINFO_ARM_MIDR_IMPLEMENTER_MASK) |
672 ((implementer << CPUINFO_ARM_MIDR_IMPLEMENTER_OFFSET) & CPUINFO_ARM_MIDR_IMPLEMENTER_MASK);
673 }
674
675 inline static uint32_t midr_set_variant(uint32_t midr, uint32_t variant) {
676- return (midr & ~CPUINFO_ARM_MIDR_VARIANT_MASK) |
677+ return (midr & ~CPUINFO_ARM_MIDR_VARIANT_MASK) |
678 ((variant << CPUINFO_ARM_MIDR_VARIANT_OFFSET) & CPUINFO_ARM_MIDR_VARIANT_MASK);
679 }
680
681 inline static uint32_t midr_set_architecture(uint32_t midr, uint32_t architecture) {
682- return (midr & ~CPUINFO_ARM_MIDR_ARCHITECTURE_MASK) |
683+ return (midr & ~CPUINFO_ARM_MIDR_ARCHITECTURE_MASK) |
684 ((architecture << CPUINFO_ARM_MIDR_ARCHITECTURE_OFFSET) & CPUINFO_ARM_MIDR_ARCHITECTURE_MASK);
685 }
686
687 inline static uint32_t midr_set_part(uint32_t midr, uint32_t part) {
688- return (midr & ~CPUINFO_ARM_MIDR_PART_MASK) |
689+ return (midr & ~CPUINFO_ARM_MIDR_PART_MASK) |
690 ((part << CPUINFO_ARM_MIDR_PART_OFFSET) & CPUINFO_ARM_MIDR_PART_MASK);
691 }
692
693 inline static uint32_t midr_set_revision(uint32_t midr, uint32_t revision) {
694- return (midr & ~CPUINFO_ARM_MIDR_REVISION_MASK) |
695+ return (midr & ~CPUINFO_ARM_MIDR_REVISION_MASK) |
696 ((revision << CPUINFO_ARM_MIDR_REVISION_OFFSET) & CPUINFO_ARM_MIDR_REVISION_MASK);
697 }
698
699@@ -171,13 +171,20 @@ inline static bool midr_is_kryo_gold(uint32_t midr) {
700 inline static uint32_t midr_score_core(uint32_t midr) {
701 const uint32_t core_mask = CPUINFO_ARM_MIDR_IMPLEMENTER_MASK | CPUINFO_ARM_MIDR_PART_MASK;
702 switch (midr & core_mask) {
703+ case UINT32_C(0x53000040): /* Exynos M5 */
704+ case UINT32_C(0x53000030): /* Exynos M4 */
705+ /* These cores are in big role w.r.t Cortex-A75 or Cortex-A76 */
706+ return 6;
707 case UINT32_C(0x4E000030): /* Denver 2 */
708- case UINT32_C(0x53000010): /* Mongoose */
709- case UINT32_C(0x53000020): /* Meerkat */
710+ case UINT32_C(0x53000010): /* Exynos M1 and Exynos M2 */
711+ case UINT32_C(0x53000020): /* Exynos M3 */
712+ case UINT32_C(0x51008040): /* Kryo 485 Gold / Gold Prime */
713 case UINT32_C(0x51008020): /* Kryo 385 Gold */
714 case UINT32_C(0x51008000): /* Kryo 260 / 280 Gold */
715 case UINT32_C(0x51002050): /* Kryo Gold */
716 case UINT32_C(0x4800D400): /* Cortex-A76 (HiSilicon) */
717+ case UINT32_C(0x4100D0D0): /* Cortex-A77 */
718+ case UINT32_C(0x4100D0E0): /* Cortex-A76AE */
719 case UINT32_C(0x4100D0B0): /* Cortex-A76 */
720 case UINT32_C(0x4100D0A0): /* Cortex-A75 */
721 case UINT32_C(0x4100D090): /* Cortex-A73 */
722@@ -191,12 +198,14 @@ inline static uint32_t midr_score_core(uint32_t midr) {
723 case UINT32_C(0x4100D070): /* Cortex-A57 */
724 /* Cortex-A57 can be in LITTLE role w.r.t. Denver 2, or in big role w.r.t. Cortex-A53 */
725 return 4;
726+ case UINT32_C(0x4100D060): /* Cortex-A65 */
727 case UINT32_C(0x4100D050): /* Cortex-A55 */
728 case UINT32_C(0x4100D030): /* Cortex-A53 */
729 /* Cortex-A53 is usually in LITTLE role, but can be in big role w.r.t. Cortex-A35 */
730 return 2;
731 case UINT32_C(0x4100D040): /* Cortex-A35 */
732 case UINT32_C(0x4100C070): /* Cortex-A7 */
733+ case UINT32_C(0x51008050): /* Kryo 485 Silver */
734 case UINT32_C(0x51008030): /* Kryo 385 Silver */
735 case UINT32_C(0x51008010): /* Kryo 260 / 280 Silver */
736 case UINT32_C(0x51002110): /* Kryo Silver (Snapdragon 820) */
737@@ -215,7 +224,7 @@ inline static uint32_t midr_score_core(uint32_t midr) {
738 }
739
740 inline static uint32_t midr_little_core_for_big(uint32_t midr) {
741- const uint32_t core_mask =
742+ const uint32_t core_mask =
743 CPUINFO_ARM_MIDR_IMPLEMENTER_MASK | CPUINFO_ARM_MIDR_ARCHITECTURE_MASK | CPUINFO_ARM_MIDR_PART_MASK;
744 switch (midr & core_mask) {
745 case CPUINFO_ARM_MIDR_CORTEX_A75:
746@@ -223,7 +232,7 @@ inline static uint32_t midr_little_core_for_big(uint32_t midr) {
747 case CPUINFO_ARM_MIDR_CORTEX_A73:
748 case CPUINFO_ARM_MIDR_CORTEX_A72:
749 case CPUINFO_ARM_MIDR_CORTEX_A57:
750- case CPUINFO_ARM_MIDR_MONGOOSE:
751+ case CPUINFO_ARM_MIDR_EXYNOS_M1_M2:
752 return CPUINFO_ARM_MIDR_CORTEX_A53;
753 case CPUINFO_ARM_MIDR_CORTEX_A17:
754 case CPUINFO_ARM_MIDR_CORTEX_A15:
755diff --git src/arm/uarch.c src/arm/uarch.c
756index d7d2c63..a38250a 100644
757--- src/arm/uarch.c
758+++ src/arm/uarch.c
759@@ -60,6 +60,9 @@ void cpuinfo_arm_decode_vendor_uarch(
760 case 0xD05:
761 *uarch = cpuinfo_uarch_cortex_a55;
762 break;
763+ case 0xD06:
764+ *uarch = cpuinfo_uarch_cortex_a65;
765+ break;
766 case 0xD07:
767 *uarch = cpuinfo_uarch_cortex_a57;
768 break;
769@@ -75,6 +78,22 @@ void cpuinfo_arm_decode_vendor_uarch(
770 case 0xD0B:
771 *uarch = cpuinfo_uarch_cortex_a76;
772 break;
773+#if CPUINFO_ARCH_ARM64 && !defined(__ANDROID__)
774+ case 0xD0C:
775+ *uarch = cpuinfo_uarch_neoverse_n1;
776+ break;
777+#endif /* CPUINFO_ARCH_ARM64 && !defined(__ANDROID__) */
778+ case 0xD0D:
779+ *uarch = cpuinfo_uarch_cortex_a77;
780+ break;
781+ case 0xD0E:
782+ *uarch = cpuinfo_uarch_cortex_a76ae;
783+ break;
784+#if CPUINFO_ARCH_ARM64 && !defined(__ANDROID__)
785+ case 0xD4A:
786+ *uarch = cpuinfo_uarch_neoverse_e1;
787+ break;
788+#endif /* CPUINFO_ARCH_ARM64 && !defined(__ANDROID__) */
789 default:
790 switch (midr_get_part(midr) >> 8) {
791 #if CPUINFO_ARCH_ARM
792@@ -242,10 +261,14 @@ void cpuinfo_arm_decode_vendor_uarch(
793 *vendor = cpuinfo_vendor_arm;
794 *uarch = cpuinfo_uarch_cortex_a55;
795 break;
796- case 0x804:
797+ case 0x804: /* High-performance Kryo 485 "Gold" / "Gold Prime" -> Cortex-A76 */
798 *vendor = cpuinfo_vendor_arm;
799 *uarch = cpuinfo_uarch_cortex_a76;
800 break;
801+ case 0x805: /* Low-performance Kryo 485 "Silver" -> Cortex-A55 */
802+ *vendor = cpuinfo_vendor_arm;
803+ *uarch = cpuinfo_uarch_cortex_a55;
804+ break;
805 #if CPUINFO_ARCH_ARM64 && !defined(__ANDROID__)
806 case 0xC00:
807 *uarch = cpuinfo_uarch_falkor;
808@@ -263,27 +286,43 @@ void cpuinfo_arm_decode_vendor_uarch(
809 switch (midr & (CPUINFO_ARM_MIDR_VARIANT_MASK | CPUINFO_ARM_MIDR_PART_MASK)) {
810 case 0x00100010:
811 /*
812- * Exynos 8890 MIDR = 0x531F0011, assume Mongoose M1 has:
813+ * Exynos 8890 MIDR = 0x531F0011, assume Exynos M1 has:
814 * - CPU variant 0x1
815 * - CPU part 0x001
816 */
817- *uarch = cpuinfo_uarch_mongoose_m1;
818+ *uarch = cpuinfo_uarch_exynos_m1;
819 break;
820 case 0x00400010:
821 /*
822- * Exynos 8895 MIDR = 0x534F0010, assume Mongoose M2 has:
823+ * Exynos 8895 MIDR = 0x534F0010, assume Exynos M2 has:
824 * - CPU variant 0x4
825 * - CPU part 0x001
826 */
827- *uarch = cpuinfo_uarch_mongoose_m2;
828+ *uarch = cpuinfo_uarch_exynos_m2;
829 break;
830 case 0x00100020:
831 /*
832- * Exynos 9810 MIDR = 0x531F0020, assume Meerkat M3 has:
833+ * Exynos 9810 MIDR = 0x531F0020, assume Exynos M3 has:
834 * - CPU variant 0x1
835 * - CPU part 0x002
836 */
837- *uarch = cpuinfo_uarch_meerkat_m3;
838+ *uarch = cpuinfo_uarch_exynos_m3;
839+ break;
840+ case 0x00100030:
841+ /*
842+ * Exynos 9820 MIDR = 0x531F0030, assume Exynos M4 has:
843+ * - CPU variant 0x1
844+ * - CPU part 0x003
845+ */
846+ *uarch = cpuinfo_uarch_exynos_m4;
847+ break;
848+ case 0x00100040:
849+ /*
850+ * Exynos 9820 MIDR = 0x531F0040, assume Exynos M5 has:
851+ * - CPU variant 0x1
852+ * - CPU part 0x004
853+ */
854+ *uarch = cpuinfo_uarch_exynos_m5;
855 break;
856 default:
857 cpuinfo_log_warning("unknown Samsung CPU variant 0x%01"PRIx32" part 0x%03"PRIx32" ignored",
858diff --git src/cache.c src/cache.c
859new file mode 100644
860index 0000000..b976b87
861--- /dev/null
862+++ src/cache.c
863@@ -0,0 +1,18 @@
864+#include <stddef.h>
865+
866+#include <cpuinfo.h>
867+#include <cpuinfo/internal-api.h>
868+
869+
870+uint32_t cpuinfo_compute_max_cache_size(const struct cpuinfo_processor* processor) {
871+ if (processor->cache.l4 != NULL) {
872+ return processor->cache.l4->size;
873+ } else if (processor->cache.l3 != NULL) {
874+ return processor->cache.l3->size;
875+ } else if (processor->cache.l2 != NULL) {
876+ return processor->cache.l2->size;
877+ } else if (processor->cache.l1d != NULL) {
878+ return processor->cache.l1d->size;
879+ }
880+ return 0;
881+}
882diff --git src/cpuinfo/internal-api.h src/cpuinfo/internal-api.h
883index 6045750..717b810 100644
884--- src/cpuinfo/internal-api.h
885+++ src/cpuinfo/internal-api.h
886@@ -31,6 +31,7 @@ extern CPUINFO_INTERNAL uint32_t cpuinfo_cores_count;
887 extern CPUINFO_INTERNAL uint32_t cpuinfo_clusters_count;
888 extern CPUINFO_INTERNAL uint32_t cpuinfo_packages_count;
889 extern CPUINFO_INTERNAL uint32_t cpuinfo_cache_count[cpuinfo_cache_level_max];
890+extern CPUINFO_INTERNAL uint32_t cpuinfo_max_cache_size;
891
892 CPUINFO_PRIVATE void cpuinfo_x86_mach_init(void);
893 CPUINFO_PRIVATE void cpuinfo_x86_linux_init(void);
894@@ -40,4 +41,6 @@ CPUINFO_PRIVATE void cpuinfo_x86_linux_init(void);
895 CPUINFO_PRIVATE void cpuinfo_arm_mach_init(void);
896 CPUINFO_PRIVATE void cpuinfo_arm_linux_init(void);
897
898+CPUINFO_PRIVATE uint32_t cpuinfo_compute_max_cache_size(const struct cpuinfo_processor* processor);
899+
900 typedef void (*cpuinfo_processor_callback)(uint32_t);
901diff --git src/x86/isa.c src/x86/isa.c
902index bca1ecd..d27dbca 100644
903--- src/x86/isa.c
904+++ src/x86/isa.c
905@@ -42,8 +42,10 @@ struct cpuinfo_x86_isa cpuinfo_x86_detect_isa(
906 {
907 struct cpuinfo_x86_isa isa = { 0 };
908
909- const struct cpuid_regs structured_feature_info =
910+ const struct cpuid_regs structured_feature_info0 =
911 (max_base_index >= 7) ? cpuidex(7, 0) : (struct cpuid_regs) { 0, 0, 0, 0};
912+ const struct cpuid_regs structured_feature_info1 =
913+ (max_base_index >= 7) ? cpuidex(7, 1) : (struct cpuid_regs) { 0, 0, 0, 0};
914
915 const uint32_t processor_capacity_info_index = UINT32_C(0x80000008);
916 const struct cpuid_regs processor_capacity_info =
917@@ -144,9 +146,9 @@ struct cpuinfo_x86_isa cpuinfo_x86_detect_isa(
918
919 /*
920 * CLFLUSHOPT instruction:
921- * - Intel: ebx[bit 23] in structured feature info.
922+ * - Intel: ebx[bit 23] in structured feature info (ecx = 0).
923 */
924- isa.clflushopt = !!(structured_feature_info.ebx & UINT32_C(0x00800000));
925+ isa.clflushopt = !!(structured_feature_info0.ebx & UINT32_C(0x00800000));
926
927 /*
928 * MWAIT/MONITOR instructions:
929@@ -273,9 +275,9 @@ struct cpuinfo_x86_isa cpuinfo_x86_detect_isa(
930
931 /*
932 * PREFETCHWT1 instruction:
933- * - Intel: ecx[bit 0] of structured feature info. Reserved bit on AMD.
934+ * - Intel: ecx[bit 0] of structured feature info (ecx = 0). Reserved bit on AMD.
935 */
936- isa.prefetchwt1 = !!(structured_feature_info.ecx & UINT32_C(0x00000001));
937+ isa.prefetchwt1 = !!(structured_feature_info0.ecx & UINT32_C(0x00000001));
938
939 #if CPUINFO_ARCH_X86
940 /*
941@@ -386,111 +388,123 @@ struct cpuinfo_x86_isa cpuinfo_x86_detect_isa(
942
943 /*
944 * AVX2 instructions:
945- * - Intel: ebx[bit 5] in structured feature info.
946+ * - Intel: ebx[bit 5] in structured feature info (ecx = 0).
947 */
948- isa.avx2 = avx_regs && !!(structured_feature_info.ebx & UINT32_C(0x00000020));
949+ isa.avx2 = avx_regs && !!(structured_feature_info0.ebx & UINT32_C(0x00000020));
950
951 /*
952 * AVX512F instructions:
953- * - Intel: ebx[bit 16] in structured feature info.
954+ * - Intel: ebx[bit 16] in structured feature info (ecx = 0).
955 */
956- isa.avx512f = avx512_regs && !!(structured_feature_info.ebx & UINT32_C(0x00010000));
957+ isa.avx512f = avx512_regs && !!(structured_feature_info0.ebx & UINT32_C(0x00010000));
958
959 /*
960 * AVX512PF instructions:
961- * - Intel: ebx[bit 26] in structured feature info.
962+ * - Intel: ebx[bit 26] in structured feature info (ecx = 0).
963 */
964- isa.avx512pf = avx512_regs && !!(structured_feature_info.ebx & UINT32_C(0x04000000));
965+ isa.avx512pf = avx512_regs && !!(structured_feature_info0.ebx & UINT32_C(0x04000000));
966
967 /*
968 * AVX512ER instructions:
969- * - Intel: ebx[bit 27] in structured feature info.
970+ * - Intel: ebx[bit 27] in structured feature info (ecx = 0).
971 */
972- isa.avx512er = avx512_regs && !!(structured_feature_info.ebx & UINT32_C(0x08000000));
973+ isa.avx512er = avx512_regs && !!(structured_feature_info0.ebx & UINT32_C(0x08000000));
974
975 /*
976 * AVX512CD instructions:
977- * - Intel: ebx[bit 28] in structured feature info.
978+ * - Intel: ebx[bit 28] in structured feature info (ecx = 0).
979 */
980- isa.avx512cd = avx512_regs && !!(structured_feature_info.ebx & UINT32_C(0x10000000));
981+ isa.avx512cd = avx512_regs && !!(structured_feature_info0.ebx & UINT32_C(0x10000000));
982
983 /*
984 * AVX512DQ instructions:
985- * - Intel: ebx[bit 17] in structured feature info.
986+ * - Intel: ebx[bit 17] in structured feature info (ecx = 0).
987 */
988- isa.avx512dq = avx512_regs && !!(structured_feature_info.ebx & UINT32_C(0x00020000));
989+ isa.avx512dq = avx512_regs && !!(structured_feature_info0.ebx & UINT32_C(0x00020000));
990
991 /*
992 * AVX512BW instructions:
993- * - Intel: ebx[bit 30] in structured feature info.
994+ * - Intel: ebx[bit 30] in structured feature info (ecx = 0).
995 */
996- isa.avx512bw = avx512_regs && !!(structured_feature_info.ebx & UINT32_C(0x40000000));
997+ isa.avx512bw = avx512_regs && !!(structured_feature_info0.ebx & UINT32_C(0x40000000));
998
999 /*
1000 * AVX512VL instructions:
1001- * - Intel: ebx[bit 31] in structured feature info.
1002+ * - Intel: ebx[bit 31] in structured feature info (ecx = 0).
1003 */
1004- isa.avx512vl = avx512_regs && !!(structured_feature_info.ebx & UINT32_C(0x80000000));
1005+ isa.avx512vl = avx512_regs && !!(structured_feature_info0.ebx & UINT32_C(0x80000000));
1006
1007 /*
1008 * AVX512IFMA instructions:
1009- * - Intel: ebx[bit 21] in structured feature info.
1010+ * - Intel: ebx[bit 21] in structured feature info (ecx = 0).
1011 */
1012- isa.avx512ifma = avx512_regs && !!(structured_feature_info.ebx & UINT32_C(0x00200000));
1013+ isa.avx512ifma = avx512_regs && !!(structured_feature_info0.ebx & UINT32_C(0x00200000));
1014
1015 /*
1016 * AVX512VBMI instructions:
1017- * - Intel: ecx[bit 1] in structured feature info.
1018+ * - Intel: ecx[bit 1] in structured feature info (ecx = 0).
1019 */
1020- isa.avx512vbmi = avx512_regs && !!(structured_feature_info.ecx & UINT32_C(0x00000002));
1021+ isa.avx512vbmi = avx512_regs && !!(structured_feature_info0.ecx & UINT32_C(0x00000002));
1022
1023 /*
1024 * AVX512VBMI2 instructions:
1025- * - Intel: ecx[bit 6] in structured feature info.
1026+ * - Intel: ecx[bit 6] in structured feature info (ecx = 0).
1027 */
1028- isa.avx512vbmi2 = avx512_regs && !!(structured_feature_info.ecx & UINT32_C(0x00000040));
1029+ isa.avx512vbmi2 = avx512_regs && !!(structured_feature_info0.ecx & UINT32_C(0x00000040));
1030
1031 /*
1032 * AVX512BITALG instructions:
1033- * - Intel: ecx[bit 12] in structured feature info.
1034+ * - Intel: ecx[bit 12] in structured feature info (ecx = 0).
1035 */
1036- isa.avx512bitalg = avx512_regs && !!(structured_feature_info.ecx & UINT32_C(0x00001000));
1037+ isa.avx512bitalg = avx512_regs && !!(structured_feature_info0.ecx & UINT32_C(0x00001000));
1038
1039 /*
1040 * AVX512VPOPCNTDQ instructions:
1041- * - Intel: ecx[bit 14] in structured feature info.
1042+ * - Intel: ecx[bit 14] in structured feature info (ecx = 0).
1043 */
1044- isa.avx512vpopcntdq = avx512_regs && !!(structured_feature_info.ecx & UINT32_C(0x00004000));
1045+ isa.avx512vpopcntdq = avx512_regs && !!(structured_feature_info0.ecx & UINT32_C(0x00004000));
1046
1047 /*
1048 * AVX512VNNI instructions:
1049- * - Intel: ecx[bit 11] in structured feature info.
1050+ * - Intel: ecx[bit 11] in structured feature info (ecx = 0).
1051 */
1052- isa.avx512vnni = avx512_regs && !!(structured_feature_info.ecx & UINT32_C(0x00000800));
1053+ isa.avx512vnni = avx512_regs && !!(structured_feature_info0.ecx & UINT32_C(0x00000800));
1054
1055 /*
1056 * AVX512_4VNNIW instructions:
1057- * - Intel: edx[bit 2] in structured feature info.
1058+ * - Intel: edx[bit 2] in structured feature info (ecx = 0).
1059 */
1060- isa.avx512_4vnniw = avx512_regs && !!(structured_feature_info.edx & UINT32_C(0x00000004));
1061+ isa.avx512_4vnniw = avx512_regs && !!(structured_feature_info0.edx & UINT32_C(0x00000004));
1062
1063 /*
1064 * AVX512_4FMAPS instructions:
1065- * - Intel: edx[bit 3] in structured feature info.
1066+ * - Intel: edx[bit 3] in structured feature info (ecx = 0).
1067 */
1068- isa.avx512_4fmaps = avx512_regs && !!(structured_feature_info.edx & UINT32_C(0x00000008));
1069+ isa.avx512_4fmaps = avx512_regs && !!(structured_feature_info0.edx & UINT32_C(0x00000008));
1070+
1071+ /*
1072+ * AVX512_VP2INTERSECT instructions:
1073+ * - Intel: edx[bit 8] in structured feature info (ecx = 0).
1074+ */
1075+ isa.avx512vp2intersect = avx512_regs && !!(structured_feature_info0.edx & UINT32_C(0x00000100));
1076+
1077+ /*
1078+ * AVX512_BF16 instructions:
1079+ * - Intel: eax[bit 5] in structured feature info (ecx = 1).
1080+ */
1081+ isa.avx512bf16 = avx512_regs && !!(structured_feature_info1.eax & UINT32_C(0x00000020));
1082
1083 /*
1084 * HLE instructions:
1085- * - Intel: ebx[bit 4] in structured feature info.
1086+ * - Intel: ebx[bit 4] in structured feature info (ecx = 0).
1087 */
1088- isa.hle = !!(structured_feature_info.ebx & UINT32_C(0x00000010));
1089+ isa.hle = !!(structured_feature_info0.ebx & UINT32_C(0x00000010));
1090
1091 /*
1092 * RTM instructions:
1093- * - Intel: ebx[bit 11] in structured feature info.
1094+ * - Intel: ebx[bit 11] in structured feature info (ecx = 0).
1095 */
1096- isa.rtm = !!(structured_feature_info.ebx & UINT32_C(0x00000800));
1097+ isa.rtm = !!(structured_feature_info0.ebx & UINT32_C(0x00000800));
1098
1099 /*
1100 * XTEST instruction:
1101@@ -500,9 +514,9 @@ struct cpuinfo_x86_isa cpuinfo_x86_detect_isa(
1102
1103 /*
1104 * MPX registers and instructions:
1105- * - Intel: ebx[bit 14] in structured feature info.
1106+ * - Intel: ebx[bit 14] in structured feature info (ecx = 0).
1107 */
1108- isa.mpx = mpx_regs && !!(structured_feature_info.ebx & UINT32_C(0x00004000));
1109+ isa.mpx = mpx_regs && !!(structured_feature_info0.ebx & UINT32_C(0x00004000));
1110
1111 #if CPUINFO_ARCH_X86
1112 /*
1113@@ -528,9 +542,9 @@ struct cpuinfo_x86_isa cpuinfo_x86_detect_isa(
1114
1115 /*
1116 * CLWB instruction:
1117- * - Intel: ebx[bit 24] in structured feature info.
1118+ * - Intel: ebx[bit 24] in structured feature info (ecx = 0).
1119 */
1120- isa.clwb = !!(structured_feature_info.ebx & UINT32_C(0x01000000));
1121+ isa.clwb = !!(structured_feature_info0.ebx & UINT32_C(0x01000000));
1122
1123 /*
1124 * MOVBE instruction:
1125@@ -549,9 +563,9 @@ struct cpuinfo_x86_isa cpuinfo_x86_detect_isa(
1126
1127 /*
1128 * RDFSBASE/RDGSBASE/WRFSBASE/WRGSBASE instructions.
1129- * - Intel: ebx[bit 0] in structured feature info.
1130+ * - Intel: ebx[bit 0] in structured feature info (ecx = 0).
1131 */
1132- isa.fs_gs_base = !!(structured_feature_info.ebx & UINT32_C(0x00000001));
1133+ isa.fs_gs_base = !!(structured_feature_info0.ebx & UINT32_C(0x00000001));
1134
1135 /*
1136 * LZCNT instruction:
1137@@ -573,21 +587,21 @@ struct cpuinfo_x86_isa cpuinfo_x86_detect_isa(
1138
1139 /*
1140 * BMI instructions:
1141- * - Intel, AMD: ebx[bit 3] in structured feature info.
1142+ * - Intel, AMD: ebx[bit 3] in structured feature info (ecx = 0).
1143 */
1144- isa.bmi = !!(structured_feature_info.ebx & UINT32_C(0x00000008));
1145+ isa.bmi = !!(structured_feature_info0.ebx & UINT32_C(0x00000008));
1146
1147 /*
1148 * BMI2 instructions:
1149- * - Intel: ebx[bit 8] in structured feature info.
1150+ * - Intel: ebx[bit 8] in structured feature info (ecx = 0).
1151 */
1152- isa.bmi2 = !!(structured_feature_info.ebx & UINT32_C(0x00000100));
1153+ isa.bmi2 = !!(structured_feature_info0.ebx & UINT32_C(0x00000100));
1154
1155 /*
1156 * ADCX/ADOX instructions:
1157- * - Intel: ebx[bit 19] in structured feature info.
1158+ * - Intel: ebx[bit 19] in structured feature info (ecx = 0).
1159 */
1160- isa.adx = !!(structured_feature_info.ebx & UINT32_C(0x00080000));
1161+ isa.adx = !!(structured_feature_info0.ebx & UINT32_C(0x00080000));
1162
1163 /*
1164 * AES instructions:
1165@@ -597,9 +611,9 @@ struct cpuinfo_x86_isa cpuinfo_x86_detect_isa(
1166
1167 /*
1168 * VAES instructions:
1169- * - Intel: ecx[bit 9] in structured feature info.
1170+ * - Intel: ecx[bit 9] in structured feature info (ecx = 0).
1171 */
1172- isa.vaes = !!(structured_feature_info.ecx & UINT32_C(0x00000200));
1173+ isa.vaes = !!(structured_feature_info0.ecx & UINT32_C(0x00000200));
1174
1175 /*
1176 * PCLMULQDQ instruction:
1177@@ -609,15 +623,15 @@ struct cpuinfo_x86_isa cpuinfo_x86_detect_isa(
1178
1179 /*
1180 * VPCLMULQDQ instruction:
1181- * - Intel: ecx[bit 10] in structured feature info.
1182+ * - Intel: ecx[bit 10] in structured feature info (ecx = 0).
1183 */
1184- isa.vpclmulqdq = !!(structured_feature_info.ecx & UINT32_C(0x00000400));
1185+ isa.vpclmulqdq = !!(structured_feature_info0.ecx & UINT32_C(0x00000400));
1186
1187 /*
1188 * GFNI instructions:
1189- * - Intel: ecx[bit 8] in structured feature info.
1190+ * - Intel: ecx[bit 8] in structured feature info (ecx = 0).
1191 */
1192- isa.gfni = !!(structured_feature_info.ecx & UINT32_C(0x00000100));
1193+ isa.gfni = !!(structured_feature_info0.ecx & UINT32_C(0x00000100));
1194
1195 /*
1196 * RDRAND instruction:
1197@@ -627,15 +641,15 @@ struct cpuinfo_x86_isa cpuinfo_x86_detect_isa(
1198
1199 /*
1200 * RDSEED instruction:
1201- * - Intel: ebx[bit 18] in structured feature info.
1202+ * - Intel: ebx[bit 18] in structured feature info (ecx = 0).
1203 */
1204- isa.rdseed = !!(structured_feature_info.ebx & UINT32_C(0x00040000));
1205+ isa.rdseed = !!(structured_feature_info0.ebx & UINT32_C(0x00040000));
1206
1207 /*
1208 * SHA instructions:
1209- * - Intel: ebx[bit 29] in structured feature info.
1210+ * - Intel: ebx[bit 29] in structured feature info (ecx = 0).
1211 */
1212- isa.sha = !!(structured_feature_info.ebx & UINT32_C(0x20000000));
1213+ isa.sha = !!(structured_feature_info0.ebx & UINT32_C(0x20000000));
1214
1215 if (vendor == cpuinfo_vendor_via) {
1216 const struct cpuid_regs padlock_meta_info = cpuid(UINT32_C(0xC0000000));
1217@@ -700,9 +714,9 @@ struct cpuinfo_x86_isa cpuinfo_x86_detect_isa(
1218
1219 /*
1220 * RDPID instruction:
1221- * - Intel: ecx[bit 22] in structured feature info.
1222+ * - Intel: ecx[bit 22] in structured feature info (ecx = 0).
1223 */
1224- isa.rdpid = !!(structured_feature_info.ecx & UINT32_C(0x00400000));
1225+ isa.rdpid = !!(structured_feature_info0.ecx & UINT32_C(0x00400000));
1226
1227 return isa;
1228 }
1229diff --git src/x86/linux/init.c src/x86/linux/init.c
1230index b5f74d0..c096336 100644
1231--- src/x86/linux/init.c
1232+++ src/x86/linux/init.c
1233@@ -592,6 +592,8 @@ void cpuinfo_x86_linux_init(void) {
1234 cpuinfo_cache_count[cpuinfo_cache_level_3] = l3_count;
1235 cpuinfo_cache_count[cpuinfo_cache_level_4] = l4_count;
1236
1237+ cpuinfo_max_cache_size = cpuinfo_compute_max_cache_size(&processors[0]);
1238+
1239 __sync_synchronize();
1240
1241 cpuinfo_is_initialized = true;
1242diff --git src/x86/mach/init.c src/x86/mach/init.c
1243index 7b41ad0..ae2be33 100644
1244--- src/x86/mach/init.c
1245+++ src/x86/mach/init.c
1246@@ -327,6 +327,8 @@ void cpuinfo_x86_mach_init(void) {
1247 cpuinfo_clusters_count = mach_topology.packages;
1248 cpuinfo_packages_count = mach_topology.packages;
1249
1250+ cpuinfo_max_cache_size = cpuinfo_compute_max_cache_size(&processors[0]);
1251+
1252 __sync_synchronize();
1253
1254 cpuinfo_is_initialized = true;
1255diff --git src/x86/uarch.c src/x86/uarch.c
1256index 71c899e..ba72d8a 100644
1257--- src/x86/uarch.c
1258+++ src/x86/uarch.c
1259@@ -74,13 +74,19 @@ enum cpuinfo_uarch cpuinfo_x86_decode_uarch(
1260 case 0x4F: // Broadwell-E
1261 case 0x56: // Broadwell-DE
1262 return cpuinfo_uarch_broadwell;
1263- case 0x4E: // Skylake-U/Y
1264- case 0x55: // Skylake Server (SKX)
1265- case 0x5E: // Skylake-H/S
1266+ case 0x4E: // Sky Lake Client Y/U
1267+ case 0x55: // Sky/Cascade/Cooper Lake Server
1268+ case 0x5E: // Sky Lake Client DT/H/S
1269+ case 0x8E: // Kaby/Whiskey/Amber/Comet Lake Y/U
1270+ case 0x9E: // Kaby/Coffee Lake DT/H/S
1271 return cpuinfo_uarch_sky_lake;
1272- case 0x8E: // Kaby Lake U/Y
1273- case 0x9E: // Kaby Lake H/S
1274- return cpuinfo_uarch_kaby_lake;
1275+ case 0x66: // Cannon Lake (Core i3-8121U)
1276+ return cpuinfo_uarch_palm_cove;
1277+ case 0x6A: // Ice Lake-DE
1278+ case 0x6C: // Ice Lake-SP
1279+ case 0x7D: // Ice Lake-Y
1280+ case 0x7E: // Ice Lake-U
1281+ return cpuinfo_uarch_sunny_cove;
1282
1283 /* Low-power cores */
1284 case 0x1C: // Diamondville, Silverthorne, Pineview
1285@@ -90,18 +96,20 @@ enum cpuinfo_uarch cpuinfo_x86_decode_uarch(
1286 case 0x35: // Cloverview
1287 case 0x36: // Cedarview, Centerton
1288 return cpuinfo_uarch_saltwell;
1289- case 0x37:
1290- case 0x4A:
1291- case 0x4D:
1292+ case 0x37: // Bay Trail
1293+ case 0x4A: // Merrifield
1294+ case 0x4D: // Avoton, Rangeley
1295 case 0x5A: // Moorefield
1296 case 0x5D: // SoFIA
1297 return cpuinfo_uarch_silvermont;
1298- case 0x4C: // Braswell
1299- case 0x5F: // Denverton
1300+ case 0x4C: // Braswell, Cherry Trail
1301 case 0x75: // Spreadtrum SC9853I-IA
1302- case 0x7A: // Goldmont+
1303 return cpuinfo_uarch_airmont;
1304-
1305+ case 0x5C: // Apollo Lake
1306+ case 0x5F: // Denverton
1307+ return cpuinfo_uarch_goldmont;
1308+ case 0x7A: // Gemini Lake
1309+ return cpuinfo_uarch_goldmont_plus;
1310 /* Knights-series cores */
1311 case 0x57:
1312 return cpuinfo_uarch_knights_landing;
1313@@ -190,7 +198,15 @@ enum cpuinfo_uarch cpuinfo_x86_decode_uarch(
1314 return cpuinfo_uarch_jaguar;
1315 }
1316 case 0x17:
1317- return cpuinfo_uarch_zen;
1318+ switch (model_info->model) {
1319+ case 0x01: // 14 nm Naples, Whitehaven, Summit Ridge, Snowy Owl
1320+ case 0x08: // 12 nm Pinnacle Ridge
1321+ case 0x11: // 14 nm Raven Ridge
1322+ case 0x18: // 12 nm Picasso
1323+ return cpuinfo_uarch_zen;
1324+ case 0x71: // Matisse
1325+ return cpuinfo_uarch_zen2;
1326+ }
1327 }
1328 break;
1329 default:
1330diff --git src/x86/windows/init.c src/x86/windows/init.c
1331index eb3498a..7a2090e 100644
1332--- src/x86/windows/init.c
1333+++ src/x86/windows/init.c
1334@@ -571,6 +571,8 @@ BOOL CALLBACK cpuinfo_x86_windows_init(PINIT_ONCE init_once, PVOID parameter, PV
1335 cpuinfo_clusters_count = packages_count;
1336 cpuinfo_packages_count = packages_count;
1337
1338+ cpuinfo_max_cache_size = cpuinfo_compute_max_cache_size(&processors[0]);
1339+
1340 MemoryBarrier();
1341
1342 cpuinfo_is_initialized = true;
1343diff --git tools/cache-info.c tools/cache-info.c
1344index ba0706f..05f69ee 100644
1345--- tools/cache-info.c
1346+++ tools/cache-info.c
1347@@ -60,6 +60,8 @@ int main(int argc, char** argv) {
1348 fprintf(stderr, "failed to initialize CPU information\n");
1349 exit(EXIT_FAILURE);
1350 }
1351+ printf("Max cache size (upper bound): %"PRIu32" bytes\n", cpuinfo_get_max_cache_size());
1352+
1353 if (cpuinfo_get_l1i_caches_count() != 0 && (cpuinfo_get_l1i_cache(0)->flags & CPUINFO_CACHE_UNIFIED) == 0) {
1354 report_cache(cpuinfo_get_l1i_caches_count(), cpuinfo_get_l1i_cache(0), 1, "instruction");
1355 }
1356diff --git tools/cpu-info.c tools/cpu-info.c
1357index caef424..7fa5187 100644
1358--- tools/cpu-info.c
1359+++ tools/cpu-info.c
1360@@ -73,8 +73,10 @@ static const char* uarch_to_string(enum cpuinfo_uarch uarch) {
1361 return "Broadwell";
1362 case cpuinfo_uarch_sky_lake:
1363 return "Sky Lake";
1364- case cpuinfo_uarch_kaby_lake:
1365- return "Kaby Lake";
1366+ case cpuinfo_uarch_palm_cove:
1367+ return "Palm Cove";
1368+ case cpuinfo_uarch_sunny_cove:
1369+ return "Sunny Cove";
1370 case cpuinfo_uarch_willamette:
1371 return "Willamette";
1372 case cpuinfo_uarch_prescott:
1373@@ -87,6 +89,10 @@ static const char* uarch_to_string(enum cpuinfo_uarch uarch) {
1374 return "Silvermont";
1375 case cpuinfo_uarch_airmont:
1376 return "Airmont";
1377+ case cpuinfo_uarch_goldmont:
1378+ return "Goldmont";
1379+ case cpuinfo_uarch_goldmont_plus:
1380+ return "Goldmont Plus";
1381 case cpuinfo_uarch_knights_ferry:
1382 return "Knights Ferry";
1383 case cpuinfo_uarch_knights_corner:
1384@@ -117,6 +123,8 @@ static const char* uarch_to_string(enum cpuinfo_uarch uarch) {
1385 return "Excavator";
1386 case cpuinfo_uarch_zen:
1387 return "Zen";
1388+ case cpuinfo_uarch_zen2:
1389+ return "Zen 2";
1390 case cpuinfo_uarch_geode:
1391 return "Geode";
1392 case cpuinfo_uarch_bobcat:
1393@@ -157,6 +165,8 @@ static const char* uarch_to_string(enum cpuinfo_uarch uarch) {
1394 return "Cortex-A55";
1395 case cpuinfo_uarch_cortex_a57:
1396 return "Cortex-A57";
1397+ case cpuinfo_uarch_cortex_a65:
1398+ return "Cortex-A65";
1399 case cpuinfo_uarch_cortex_a72:
1400 return "Cortex-A72";
1401 case cpuinfo_uarch_cortex_a73:
1402@@ -165,6 +175,10 @@ static const char* uarch_to_string(enum cpuinfo_uarch uarch) {
1403 return "Cortex-A75";
1404 case cpuinfo_uarch_cortex_a76:
1405 return "Cortex-A76";
1406+ case cpuinfo_uarch_cortex_a76ae:
1407+ return "Cortex-A76AE";
1408+ case cpuinfo_uarch_cortex_a77:
1409+ return "Cortex-A77";
1410 case cpuinfo_uarch_scorpion:
1411 return "Scorpion";
1412 case cpuinfo_uarch_krait:
1413@@ -181,12 +195,16 @@ static const char* uarch_to_string(enum cpuinfo_uarch uarch) {
1414 return "Denver 2";
1415 case cpuinfo_uarch_carmel:
1416 return "Carmel";
1417- case cpuinfo_uarch_mongoose_m1:
1418- return "Mongoose M1";
1419- case cpuinfo_uarch_mongoose_m2:
1420- return "Mongoose M2";
1421- case cpuinfo_uarch_meerkat_m3:
1422- return "Meerkat M3";
1423+ case cpuinfo_uarch_exynos_m1:
1424+ return "Exynos M1";
1425+ case cpuinfo_uarch_exynos_m2:
1426+ return "Exynos M2";
1427+ case cpuinfo_uarch_exynos_m3:
1428+ return "Exynos M3";
1429+ case cpuinfo_uarch_exynos_m4:
1430+ return "Exynos M4";
1431+ case cpuinfo_uarch_exynos_m5:
1432+ return "Exynos M5";
1433 case cpuinfo_uarch_swift:
1434 return "Swift";
1435 case cpuinfo_uarch_cyclone:
1436@@ -258,13 +276,23 @@ int main(int argc, char** argv) {
1437 printf(", %s %s\n", vendor_string, uarch_string);
1438 }
1439 }
1440- printf("Logical processors:\n");
1441+ printf("Logical processors");
1442+ #if defined(__linux__)
1443+ printf(" (System ID)");
1444+ #endif
1445+ printf(":\n");
1446 for (uint32_t i = 0; i < cpuinfo_get_processors_count(); i++) {
1447 const struct cpuinfo_processor* processor = cpuinfo_get_processor(i);
1448+ printf("\t%"PRIu32"", i);
1449+
1450+ #if defined(__linux__)
1451+ printf(" (%"PRId32")", processor->linux_id);
1452+ #endif
1453+
1454 #if CPUINFO_ARCH_X86 || CPUINFO_ARCH_X86_64
1455- printf("\t%"PRIu32": APIC ID 0x%08"PRIx32"\n", i, processor->apic_id);
1456+ printf(": APIC ID 0x%08"PRIx32"\n", processor->apic_id);
1457 #else
1458- printf("\t%"PRIu32"\n", i);
1459+ printf("\n");
1460 #endif
1461 }
1462 }
1463diff --git tools/isa-info.c tools/isa-info.c
1464index 594c46a..98ef919 100644
1465--- tools/isa-info.c
1466+++ tools/isa-info.c
1467@@ -67,6 +67,8 @@ int main(int argc, char** argv) {
1468 printf("\tAVX512BITALG: %s\n", cpuinfo_has_x86_avx512bitalg() ? "yes" : "no");
1469 printf("\tAVX512VPOPCNTDQ: %s\n", cpuinfo_has_x86_avx512vpopcntdq() ? "yes" : "no");
1470 printf("\tAVX512VNNI: %s\n", cpuinfo_has_x86_avx512vnni() ? "yes" : "no");
1471+ printf("\tAVX512BF16: %s\n", cpuinfo_has_x86_avx512bf16() ? "yes" : "no");
1472+ printf("\tAVX512VP2INTERSECT: %s\n", cpuinfo_has_x86_avx512vp2intersect() ? "yes" : "no");
1473 printf("\tAVX512_4VNNIW: %s\n", cpuinfo_has_x86_avx512_4vnniw() ? "yes" : "no");
1474 printf("\tAVX512_4FMAPS: %s\n", cpuinfo_has_x86_avx512_4fmaps() ? "yes" : "no");
1475