]> git.saurik.com Git - apple/xnu.git/blame - osfmk/arm/cpuid.c
xnu-7195.101.1.tar.gz
[apple/xnu.git] / osfmk / arm / cpuid.c
CommitLineData
5ba3f43e
A
1/*
2 * Copyright (c) 2007-2016 Apple Inc. All rights reserved.
3 *
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
14 *
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
17 *
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
25 *
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27 */
28/*
29 * @OSF_COPYRIGHT@
30 */
31
32#include <pexpert/pexpert.h>
33#include <arm/cpuid.h>
34#include <arm/cpuid_internal.h>
35#include <vm/vm_page.h>
36#include "proc_reg.h"
37
38#include <libkern/section_keywords.h>
39
40/* Temporary types to aid decoding,
41 * Everything in Little Endian */
42
43typedef struct {
44 uint32_t
cb323159
A
45 Ctype1:3, /* 2:0 */
46 Ctype2:3, /* 5:3 */
47 Ctype3:3, /* 8:6 */
48 Ctypes:15, /* 6:23 - Don't Care */
49 LoC:3, /* 26-24 - Level of Coherency */
50 LoU:3, /* 29:27 - Level of Unification */
51 RAZ:2; /* 31:30 - Read-As-Zero */
52} arm_cache_clidr_t;
5ba3f43e
A
53
54typedef union {
55 arm_cache_clidr_t bits;
cb323159
A
56 uint32_t value;
57} arm_cache_clidr_info_t;
5ba3f43e
A
58
59
60typedef struct {
61 uint32_t
0a7de745 62 LineSize:3, /* 2:0 - Number of words in cache line */
cb323159 63 Assoc:10, /* 12:3 - Associativity of cache */
0a7de745 64 NumSets:15, /* 27:13 - Number of sets in cache */
cb323159
A
65 c_type:4; /* 31:28 - Cache type */
66} arm_cache_ccsidr_t;
5ba3f43e
A
67
68
69typedef union {
70 arm_cache_ccsidr_t bits;
cb323159
A
71 uint32_t value;
72} arm_cache_ccsidr_info_t;
5ba3f43e
A
73
74/* Statics */
75
76static SECURITY_READ_ONLY_LATE(arm_cpu_info_t) cpuid_cpu_info;
77static SECURITY_READ_ONLY_LATE(cache_info_t) cpuid_cache_info;
78
79/* Code */
80
81__private_extern__
82void
83do_cpuid(void)
84{
85 cpuid_cpu_info.value = machine_read_midr();
cb323159 86#if (__ARM_ARCH__ == 8)
5ba3f43e 87
cb323159
A
88#if defined(HAS_APPLE_PAC)
89 cpuid_cpu_info.arm_info.arm_arch = CPU_ARCH_ARMv8E;
90#else /* defined(HAS_APPLE_PAC) */
5ba3f43e 91 cpuid_cpu_info.arm_info.arm_arch = CPU_ARCH_ARMv8;
cb323159 92#endif /* defined(HAS_APPLE_PAC) */
5ba3f43e 93
cb323159
A
94#elif (__ARM_ARCH__ == 7)
95#ifdef __ARM_SUB_ARCH__
5ba3f43e 96 cpuid_cpu_info.arm_info.arm_arch = __ARM_SUB_ARCH__;
cb323159 97#else /* __ARM_SUB_ARCH__ */
5ba3f43e 98 cpuid_cpu_info.arm_info.arm_arch = CPU_ARCH_ARMv7;
cb323159
A
99#endif /* __ARM_SUB_ARCH__ */
100#else /* (__ARM_ARCH__ != 7) && (__ARM_ARCH__ != 8) */
5ba3f43e
A
101 /* 1176 architecture lives in the extended feature register */
102 if (cpuid_cpu_info.arm_info.arm_arch == CPU_ARCH_EXTENDED) {
103 arm_isa_feat1_reg isa = machine_read_isa_feat1();
104
105 /*
106 * if isa feature register 1 [15:12] == 0x2, this chip
107 * supports sign extention instructions, which indicate ARMv6
108 */
109 if (isa.field.sign_zero_ext_support == 0x2) {
110 cpuid_cpu_info.arm_info.arm_arch = CPU_ARCH_ARMv6;
111 }
112 }
cb323159 113#endif /* (__ARM_ARCH__ != 7) && (__ARM_ARCH__ != 8) */
5ba3f43e
A
114}
115
116arm_cpu_info_t *
117cpuid_info(void)
118{
119 return &cpuid_cpu_info;
120}
121
122int
123cpuid_get_cpufamily(void)
124{
125 int cpufamily = 0;
126
127 switch (cpuid_info()->arm_info.arm_implementor) {
128 case CPU_VID_ARM:
129 switch (cpuid_info()->arm_info.arm_part) {
130 case CPU_PART_CORTEXA9:
131 cpufamily = CPUFAMILY_ARM_14;
132 break;
133 case CPU_PART_CORTEXA8:
134 cpufamily = CPUFAMILY_ARM_13;
135 break;
136 case CPU_PART_CORTEXA7:
137 cpufamily = CPUFAMILY_ARM_15;
138 break;
139 case CPU_PART_1136JFS:
140 case CPU_PART_1176JZFS:
141 cpufamily = CPUFAMILY_ARM_11;
142 break;
143 case CPU_PART_926EJS:
144 case CPU_PART_920T:
145 cpufamily = CPUFAMILY_ARM_9;
146 break;
147 default:
148 cpufamily = CPUFAMILY_UNKNOWN;
149 break;
150 }
151 break;
152
153 case CPU_VID_INTEL:
154 cpufamily = CPUFAMILY_ARM_XSCALE;
155 break;
156
157 case CPU_VID_APPLE:
158 switch (cpuid_info()->arm_info.arm_part) {
5ba3f43e
A
159 case CPU_PART_TYPHOON:
160 case CPU_PART_TYPHOON_CAPRI:
161 cpufamily = CPUFAMILY_ARM_TYPHOON;
162 break;
163 case CPU_PART_TWISTER:
164 case CPU_PART_TWISTER_ELBA_MALTA:
165 cpufamily = CPUFAMILY_ARM_TWISTER;
166 break;
167 case CPU_PART_HURRICANE:
168 case CPU_PART_HURRICANE_MYST:
169 cpufamily = CPUFAMILY_ARM_HURRICANE;
170 break;
d9a64523
A
171 case CPU_PART_MONSOON:
172 case CPU_PART_MISTRAL:
173 cpufamily = CPUFAMILY_ARM_MONSOON_MISTRAL;
174 break;
cb323159
A
175 case CPU_PART_VORTEX:
176 case CPU_PART_TEMPEST:
177 case CPU_PART_TEMPEST_M9:
178 case CPU_PART_VORTEX_ARUBA:
179 case CPU_PART_TEMPEST_ARUBA:
180 cpufamily = CPUFAMILY_ARM_VORTEX_TEMPEST;
181 break;
c6bf4f31
A
182 case CPU_PART_LIGHTNING:
183 case CPU_PART_THUNDER:
2a1bd2d3
A
184#ifndef RC_HIDE_XNU_FIRESTORM
185 case CPU_PART_THUNDER_M10:
186#endif
c6bf4f31
A
187 cpufamily = CPUFAMILY_ARM_LIGHTNING_THUNDER;
188 break;
2a1bd2d3
A
189#ifndef RC_HIDE_XNU_FIRESTORM
190 case CPU_PART_FIRESTORM:
191 case CPU_PART_ICESTORM:
192 case CPU_PART_FIRESTORM_TONGA:
193 case CPU_PART_ICESTORM_TONGA:
194 cpufamily = CPUFAMILY_ARM_FIRESTORM_ICESTORM;
195 break;
196#endif
5ba3f43e
A
197 default:
198 cpufamily = CPUFAMILY_UNKNOWN;
199 break;
200 }
201 break;
202
203 default:
204 cpufamily = CPUFAMILY_UNKNOWN;
205 break;
206 }
207
208 return cpufamily;
209}
210
f427ee49
A
211int
212cpuid_get_cpusubfamily(void)
213{
214 int cpusubfamily = CPUSUBFAMILY_UNKNOWN;
215
216 if (cpuid_info()->arm_info.arm_implementor != CPU_VID_APPLE) {
217 return cpusubfamily;
218 }
219
220 switch (cpuid_info()->arm_info.arm_part) {
221 case CPU_PART_TYPHOON:
222 case CPU_PART_TWISTER:
223 case CPU_PART_HURRICANE:
224 case CPU_PART_MONSOON:
225 case CPU_PART_MISTRAL:
226 case CPU_PART_VORTEX:
227 case CPU_PART_TEMPEST:
228 case CPU_PART_LIGHTNING:
229 case CPU_PART_THUNDER:
2a1bd2d3
A
230#ifndef RC_HIDE_XNU_FIRESTORM
231 case CPU_PART_FIRESTORM:
232 case CPU_PART_ICESTORM:
233#endif
f427ee49
A
234 cpusubfamily = CPUSUBFAMILY_ARM_HP;
235 break;
236 case CPU_PART_TYPHOON_CAPRI:
237 case CPU_PART_TWISTER_ELBA_MALTA:
238 case CPU_PART_HURRICANE_MYST:
239 case CPU_PART_VORTEX_ARUBA:
240 case CPU_PART_TEMPEST_ARUBA:
2a1bd2d3
A
241#ifndef RC_HIDE_XNU_FIRESTORM
242 case CPU_PART_FIRESTORM_TONGA:
243 case CPU_PART_ICESTORM_TONGA:
244#endif
f427ee49
A
245 cpusubfamily = CPUSUBFAMILY_ARM_HG;
246 break;
247 case CPU_PART_TEMPEST_M9:
2a1bd2d3
A
248#ifndef RC_HIDE_XNU_FIRESTORM
249 case CPU_PART_THUNDER_M10:
250#endif
f427ee49
A
251 cpusubfamily = CPUSUBFAMILY_ARM_M;
252 break;
253 default:
254 cpusubfamily = CPUFAMILY_UNKNOWN;
255 break;
256 }
257
258 return cpusubfamily;
259}
260
5ba3f43e
A
261void
262do_debugid(void)
263{
264 machine_do_debugid();
265}
266
267arm_debug_info_t *
268arm_debug_info(void)
269{
270 return machine_arm_debug_info();
271}
272
273void
274do_mvfpid(void)
275{
276 return machine_do_mvfpid();
277}
278
279arm_mvfp_info_t
0a7de745
A
280*
281arm_mvfp_info(void)
5ba3f43e
A
282{
283 return machine_arm_mvfp_info();
284}
285
286void
287do_cacheid(void)
288{
289 arm_cache_clidr_info_t arm_cache_clidr_info;
290 arm_cache_ccsidr_info_t arm_cache_ccsidr_info;
291
292 arm_cache_clidr_info.value = machine_read_clidr();
293
294
295 /* Select L1 data/unified cache */
296
297 machine_write_csselr(CSSELR_L1, CSSELR_DATA_UNIFIED);
298 arm_cache_ccsidr_info.value = machine_read_ccsidr();
299
300 cpuid_cache_info.c_unified = (arm_cache_clidr_info.bits.Ctype1 == 0x4) ? 1 : 0;
301
302 switch (arm_cache_ccsidr_info.bits.c_type) {
303 case 0x1:
304 cpuid_cache_info.c_type = CACHE_WRITE_ALLOCATION;
305 break;
306 case 0x2:
307 cpuid_cache_info.c_type = CACHE_READ_ALLOCATION;
308 break;
309 case 0x4:
310 cpuid_cache_info.c_type = CACHE_WRITE_BACK;
311 break;
312 case 0x8:
313 cpuid_cache_info.c_type = CACHE_WRITE_THROUGH;
314 break;
315 default:
316 cpuid_cache_info.c_type = CACHE_UNKNOWN;
317 }
318
0a7de745 319 cpuid_cache_info.c_linesz = 4 * (1 << (arm_cache_ccsidr_info.bits.LineSize + 2));
5ba3f43e
A
320 cpuid_cache_info.c_assoc = (arm_cache_ccsidr_info.bits.Assoc + 1);
321
322 /* I cache size */
323 cpuid_cache_info.c_isize = (arm_cache_ccsidr_info.bits.NumSets + 1) * cpuid_cache_info.c_linesz * cpuid_cache_info.c_assoc;
324
325 /* D cache size */
326 cpuid_cache_info.c_dsize = (arm_cache_ccsidr_info.bits.NumSets + 1) * cpuid_cache_info.c_linesz * cpuid_cache_info.c_assoc;
327
328
329 if ((arm_cache_clidr_info.bits.Ctype3 == 0x4) ||
330 (arm_cache_clidr_info.bits.Ctype2 == 0x4) || (arm_cache_clidr_info.bits.Ctype2 == 0x2)) {
5ba3f43e
A
331 if (arm_cache_clidr_info.bits.Ctype3 == 0x4) {
332 /* Select L3 (LLC) if the SoC is new enough to have that.
333 * This will be the second-level cache for the highest-performing ACC. */
334 machine_write_csselr(CSSELR_L3, CSSELR_DATA_UNIFIED);
335 } else {
336 /* Select L2 data cache */
337 machine_write_csselr(CSSELR_L2, CSSELR_DATA_UNIFIED);
338 }
339 arm_cache_ccsidr_info.value = machine_read_ccsidr();
340
0a7de745 341 cpuid_cache_info.c_linesz = 4 * (1 << (arm_cache_ccsidr_info.bits.LineSize + 2));
5ba3f43e
A
342 cpuid_cache_info.c_assoc = (arm_cache_ccsidr_info.bits.Assoc + 1);
343 cpuid_cache_info.c_l2size = (arm_cache_ccsidr_info.bits.NumSets + 1) * cpuid_cache_info.c_linesz * cpuid_cache_info.c_assoc;
344 cpuid_cache_info.c_inner_cache_size = cpuid_cache_info.c_dsize;
345 cpuid_cache_info.c_bulksize_op = cpuid_cache_info.c_l2size;
346
347 /* capri has a 2MB L2 cache unlike every other SoC up to this
348 * point with a 1MB L2 cache, so to get the same performance
349 * gain from coloring, we have to double the number of colors.
350 * Note that in general (and in fact as it's implemented in
351 * i386/cpuid.c), the number of colors is calculated as the
352 * cache line size * the number of sets divided by the page
353 * size. Also note that for H8 devices and up, the page size
354 * will be 16k instead of 4, which will reduce the number of
355 * colors required. Thus, this is really a temporary solution
356 * for capri specifically that we may want to generalize later:
357 *
358 * TODO: Are there any special considerations for our unusual
359 * cache geometries (3MB)?
360 */
361 vm_cache_geometry_colors = ((arm_cache_ccsidr_info.bits.NumSets + 1) * cpuid_cache_info.c_linesz) / PAGE_SIZE;
362 kprintf(" vm_cache_geometry_colors: %d\n", vm_cache_geometry_colors);
363 } else {
364 cpuid_cache_info.c_l2size = 0;
365
366 cpuid_cache_info.c_inner_cache_size = cpuid_cache_info.c_dsize;
367 cpuid_cache_info.c_bulksize_op = cpuid_cache_info.c_dsize;
368 }
369
f427ee49
A
370 if (cpuid_cache_info.c_unified == 0) {
371 machine_write_csselr(CSSELR_L1, CSSELR_INSTR);
372 arm_cache_ccsidr_info.value = machine_read_ccsidr();
373 uint32_t c_linesz = 4 * (1 << (arm_cache_ccsidr_info.bits.LineSize + 2));
374 uint32_t c_assoc = (arm_cache_ccsidr_info.bits.Assoc + 1);
375 /* I cache size */
376 cpuid_cache_info.c_isize = (arm_cache_ccsidr_info.bits.NumSets + 1) * c_linesz * c_assoc;
377 }
378
5ba3f43e 379 kprintf("%s() - %u bytes %s cache (I:%u D:%u (%s)), %u-way assoc, %u bytes/line\n",
0a7de745
A
380 __FUNCTION__,
381 cpuid_cache_info.c_dsize + cpuid_cache_info.c_isize,
382 ((cpuid_cache_info.c_type == CACHE_WRITE_BACK) ? "WB" :
383 (cpuid_cache_info.c_type == CACHE_WRITE_THROUGH ? "WT" : "Unknown")),
384 cpuid_cache_info.c_isize,
385 cpuid_cache_info.c_dsize,
386 (cpuid_cache_info.c_unified) ? "unified" : "separate",
387 cpuid_cache_info.c_assoc,
388 cpuid_cache_info.c_linesz);
5ba3f43e
A
389}
390
391cache_info_t *
392cache_info(void)
393{
394 return &cpuid_cache_info;
395}