]> git.saurik.com Git - apple/xnu.git/blame - osfmk/arm/cpuid.c
xnu-4570.1.46.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
45
46 Ctype1:3, /* 2:0 */
47 Ctype2:3, /* 5:3 */
48 Ctype3:3, /* 8:6 */
49 Ctypes:15, /* 6:23 - Don't Care */
50 LoC:3, /* 26-24 - Level of Coherency */
51 LoU:3, /* 29:27 - Level of Unification */
52 RAZ:2; /* 31:30 - Read-As-Zero */
53} arm_cache_clidr_t;
54
55typedef union {
56 arm_cache_clidr_t bits;
57 uint32_t value;
58} arm_cache_clidr_info_t;
59
60
61typedef struct {
62 uint32_t
63
64 LineSize:3, /* 2:0 - Number of words in cache line */
65 Assoc:10, /* 12:3 - Associativity of cache */
66 NumSets:15, /* 27:13 - Number of sets in cache */
67 c_type:4; /* 31:28 - Cache type */
68} arm_cache_ccsidr_t;
69
70
71typedef union {
72 arm_cache_ccsidr_t bits;
73 uint32_t value;
74} arm_cache_ccsidr_info_t;
75
76/* Statics */
77
78static SECURITY_READ_ONLY_LATE(arm_cpu_info_t) cpuid_cpu_info;
79static SECURITY_READ_ONLY_LATE(cache_info_t) cpuid_cache_info;
80
81/* Code */
82
83__private_extern__
84void
85do_cpuid(void)
86{
87 cpuid_cpu_info.value = machine_read_midr();
88#if (__ARM_ARCH__ == 8)
89
90 cpuid_cpu_info.arm_info.arm_arch = CPU_ARCH_ARMv8;
91
92#elif (__ARM_ARCH__ == 7)
93 #ifdef __ARM_SUB_ARCH__
94 cpuid_cpu_info.arm_info.arm_arch = __ARM_SUB_ARCH__;
95 #else
96 cpuid_cpu_info.arm_info.arm_arch = CPU_ARCH_ARMv7;
97 #endif
98#else
99 /* 1176 architecture lives in the extended feature register */
100 if (cpuid_cpu_info.arm_info.arm_arch == CPU_ARCH_EXTENDED) {
101 arm_isa_feat1_reg isa = machine_read_isa_feat1();
102
103 /*
104 * if isa feature register 1 [15:12] == 0x2, this chip
105 * supports sign extention instructions, which indicate ARMv6
106 */
107 if (isa.field.sign_zero_ext_support == 0x2) {
108 cpuid_cpu_info.arm_info.arm_arch = CPU_ARCH_ARMv6;
109 }
110 }
111#endif
112}
113
114arm_cpu_info_t *
115cpuid_info(void)
116{
117 return &cpuid_cpu_info;
118}
119
120int
121cpuid_get_cpufamily(void)
122{
123 int cpufamily = 0;
124
125 switch (cpuid_info()->arm_info.arm_implementor) {
126 case CPU_VID_ARM:
127 switch (cpuid_info()->arm_info.arm_part) {
128 case CPU_PART_CORTEXA9:
129 cpufamily = CPUFAMILY_ARM_14;
130 break;
131 case CPU_PART_CORTEXA8:
132 cpufamily = CPUFAMILY_ARM_13;
133 break;
134 case CPU_PART_CORTEXA7:
135 cpufamily = CPUFAMILY_ARM_15;
136 break;
137 case CPU_PART_1136JFS:
138 case CPU_PART_1176JZFS:
139 cpufamily = CPUFAMILY_ARM_11;
140 break;
141 case CPU_PART_926EJS:
142 case CPU_PART_920T:
143 cpufamily = CPUFAMILY_ARM_9;
144 break;
145 default:
146 cpufamily = CPUFAMILY_UNKNOWN;
147 break;
148 }
149 break;
150
151 case CPU_VID_INTEL:
152 cpufamily = CPUFAMILY_ARM_XSCALE;
153 break;
154
155 case CPU_VID_APPLE:
156 switch (cpuid_info()->arm_info.arm_part) {
157 case CPU_PART_SWIFT:
158 cpufamily = CPUFAMILY_ARM_SWIFT;
159 break;
160 case CPU_PART_CYCLONE:
161 cpufamily = CPUFAMILY_ARM_CYCLONE;
162 break;
163 case CPU_PART_TYPHOON:
164 case CPU_PART_TYPHOON_CAPRI:
165 cpufamily = CPUFAMILY_ARM_TYPHOON;
166 break;
167 case CPU_PART_TWISTER:
168 case CPU_PART_TWISTER_ELBA_MALTA:
169 cpufamily = CPUFAMILY_ARM_TWISTER;
170 break;
171 case CPU_PART_HURRICANE:
172 case CPU_PART_HURRICANE_MYST:
173 cpufamily = CPUFAMILY_ARM_HURRICANE;
174 break;
175 default:
176 cpufamily = CPUFAMILY_UNKNOWN;
177 break;
178 }
179 break;
180
181 default:
182 cpufamily = CPUFAMILY_UNKNOWN;
183 break;
184 }
185
186 return cpufamily;
187}
188
189void
190do_debugid(void)
191{
192 machine_do_debugid();
193}
194
195arm_debug_info_t *
196arm_debug_info(void)
197{
198 return machine_arm_debug_info();
199}
200
201void
202do_mvfpid(void)
203{
204 return machine_do_mvfpid();
205}
206
207arm_mvfp_info_t
208*arm_mvfp_info(void)
209{
210 return machine_arm_mvfp_info();
211}
212
213void
214do_cacheid(void)
215{
216 arm_cache_clidr_info_t arm_cache_clidr_info;
217 arm_cache_ccsidr_info_t arm_cache_ccsidr_info;
218
219 arm_cache_clidr_info.value = machine_read_clidr();
220
221
222 /* Select L1 data/unified cache */
223
224 machine_write_csselr(CSSELR_L1, CSSELR_DATA_UNIFIED);
225 arm_cache_ccsidr_info.value = machine_read_ccsidr();
226
227 cpuid_cache_info.c_unified = (arm_cache_clidr_info.bits.Ctype1 == 0x4) ? 1 : 0;
228
229 switch (arm_cache_ccsidr_info.bits.c_type) {
230 case 0x1:
231 cpuid_cache_info.c_type = CACHE_WRITE_ALLOCATION;
232 break;
233 case 0x2:
234 cpuid_cache_info.c_type = CACHE_READ_ALLOCATION;
235 break;
236 case 0x4:
237 cpuid_cache_info.c_type = CACHE_WRITE_BACK;
238 break;
239 case 0x8:
240 cpuid_cache_info.c_type = CACHE_WRITE_THROUGH;
241 break;
242 default:
243 cpuid_cache_info.c_type = CACHE_UNKNOWN;
244 }
245
246 cpuid_cache_info.c_linesz = 4 * (1<<(arm_cache_ccsidr_info.bits.LineSize + 2));
247 cpuid_cache_info.c_assoc = (arm_cache_ccsidr_info.bits.Assoc + 1);
248
249 /* I cache size */
250 cpuid_cache_info.c_isize = (arm_cache_ccsidr_info.bits.NumSets + 1) * cpuid_cache_info.c_linesz * cpuid_cache_info.c_assoc;
251
252 /* D cache size */
253 cpuid_cache_info.c_dsize = (arm_cache_ccsidr_info.bits.NumSets + 1) * cpuid_cache_info.c_linesz * cpuid_cache_info.c_assoc;
254
255
256 if ((arm_cache_clidr_info.bits.Ctype3 == 0x4) ||
257 (arm_cache_clidr_info.bits.Ctype2 == 0x4) || (arm_cache_clidr_info.bits.Ctype2 == 0x2)) {
258
259 if (arm_cache_clidr_info.bits.Ctype3 == 0x4) {
260 /* Select L3 (LLC) if the SoC is new enough to have that.
261 * This will be the second-level cache for the highest-performing ACC. */
262 machine_write_csselr(CSSELR_L3, CSSELR_DATA_UNIFIED);
263 } else {
264 /* Select L2 data cache */
265 machine_write_csselr(CSSELR_L2, CSSELR_DATA_UNIFIED);
266 }
267 arm_cache_ccsidr_info.value = machine_read_ccsidr();
268
269 cpuid_cache_info.c_linesz = 4 * (1<<(arm_cache_ccsidr_info.bits.LineSize + 2));
270 cpuid_cache_info.c_assoc = (arm_cache_ccsidr_info.bits.Assoc + 1);
271 cpuid_cache_info.c_l2size = (arm_cache_ccsidr_info.bits.NumSets + 1) * cpuid_cache_info.c_linesz * cpuid_cache_info.c_assoc;
272 cpuid_cache_info.c_inner_cache_size = cpuid_cache_info.c_dsize;
273 cpuid_cache_info.c_bulksize_op = cpuid_cache_info.c_l2size;
274
275 /* capri has a 2MB L2 cache unlike every other SoC up to this
276 * point with a 1MB L2 cache, so to get the same performance
277 * gain from coloring, we have to double the number of colors.
278 * Note that in general (and in fact as it's implemented in
279 * i386/cpuid.c), the number of colors is calculated as the
280 * cache line size * the number of sets divided by the page
281 * size. Also note that for H8 devices and up, the page size
282 * will be 16k instead of 4, which will reduce the number of
283 * colors required. Thus, this is really a temporary solution
284 * for capri specifically that we may want to generalize later:
285 *
286 * TODO: Are there any special considerations for our unusual
287 * cache geometries (3MB)?
288 */
289 vm_cache_geometry_colors = ((arm_cache_ccsidr_info.bits.NumSets + 1) * cpuid_cache_info.c_linesz) / PAGE_SIZE;
290 kprintf(" vm_cache_geometry_colors: %d\n", vm_cache_geometry_colors);
291 } else {
292 cpuid_cache_info.c_l2size = 0;
293
294 cpuid_cache_info.c_inner_cache_size = cpuid_cache_info.c_dsize;
295 cpuid_cache_info.c_bulksize_op = cpuid_cache_info.c_dsize;
296 }
297
298 kprintf("%s() - %u bytes %s cache (I:%u D:%u (%s)), %u-way assoc, %u bytes/line\n",
299 __FUNCTION__,
300 cpuid_cache_info.c_dsize + cpuid_cache_info.c_isize,
301 ((cpuid_cache_info.c_type == CACHE_WRITE_BACK) ? "WB" :
302 (cpuid_cache_info.c_type == CACHE_WRITE_THROUGH ? "WT" : "Unknown")),
303 cpuid_cache_info.c_isize,
304 cpuid_cache_info.c_dsize,
305 (cpuid_cache_info.c_unified) ? "unified" : "separate",
306 cpuid_cache_info.c_assoc,
307 cpuid_cache_info.c_linesz);
308}
309
310cache_info_t *
311cache_info(void)
312{
313 return &cpuid_cache_info;
314}