• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1diff --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
1476