1 | /* |
2 | * Copyright (c) 2000-2007 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 | * Copyright (c) 1982, 1986, 1989, 1993 |
30 | * The Regents of the University of California. All rights reserved. |
31 | * |
32 | * This code is derived from software contributed to Berkeley by |
33 | * Mike Karels at Berkeley Software Design, Inc. |
34 | * |
35 | * Quite extensively rewritten by Poul-Henning Kamp of the FreeBSD |
36 | * project, to make these variables more userfriendly. |
37 | * |
38 | * Redistribution and use in source and binary forms, with or without |
39 | * modification, are permitted provided that the following conditions |
40 | * are met: |
41 | * 1. Redistributions of source code must retain the above copyright |
42 | * notice, this list of conditions and the following disclaimer. |
43 | * 2. Redistributions in binary form must reproduce the above copyright |
44 | * notice, this list of conditions and the following disclaimer in the |
45 | * documentation and/or other materials provided with the distribution. |
46 | * 3. All advertising materials mentioning features or use of this software |
47 | * must display the following acknowledgement: |
48 | * This product includes software developed by the University of |
49 | * California, Berkeley and its contributors. |
50 | * 4. Neither the name of the University nor the names of its contributors |
51 | * may be used to endorse or promote products derived from this software |
52 | * without specific prior written permission. |
53 | * |
54 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND |
55 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
56 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
57 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE |
58 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
59 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
60 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
61 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
62 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
63 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
64 | * SUCH DAMAGE. |
65 | * |
66 | * @(#)kern_sysctl.c 8.4 (Berkeley) 4/14/94 |
67 | */ |
68 | |
69 | #include <sys/param.h> |
70 | #include <sys/kernel.h> |
71 | #include <sys/systm.h> |
72 | #include <sys/sysctl.h> |
73 | #include <sys/proc_internal.h> |
74 | #include <sys/unistd.h> |
75 | |
76 | #if defined(SMP) |
77 | #include <machine/smp.h> |
78 | #endif |
79 | |
80 | #include <sys/param.h> /* XXX prune includes */ |
81 | #include <sys/systm.h> |
82 | #include <sys/kernel.h> |
83 | #include <sys/malloc.h> |
84 | #include <sys/proc.h> |
85 | #include <sys/file_internal.h> |
86 | #include <sys/vnode.h> |
87 | #include <sys/unistd.h> |
88 | #include <sys/ioctl.h> |
89 | #include <sys/namei.h> |
90 | #include <sys/tty.h> |
91 | #include <sys/disklabel.h> |
92 | #include <sys/vm.h> |
93 | #include <sys/sysctl.h> |
94 | #include <sys/user.h> |
95 | #include <mach/machine.h> |
96 | #include <mach/mach_types.h> |
97 | #include <mach/vm_param.h> |
98 | #include <kern/task.h> |
99 | #include <vm/vm_kern.h> |
100 | #include <vm/vm_map.h> |
101 | #include <vm/vm_protos.h> |
102 | #include <mach/host_info.h> |
103 | #include <kern/pms.h> |
104 | #include <pexpert/device_tree.h> |
105 | #include <pexpert/pexpert.h> |
106 | #include <kern/sched_prim.h> |
107 | #include <console/serial_protos.h> |
108 | |
109 | extern vm_map_t bsd_pageable_map; |
110 | |
111 | #include <sys/mount_internal.h> |
112 | #include <sys/kdebug.h> |
113 | |
114 | #include <IOKit/IOPlatformExpert.h> |
115 | #include <pexpert/pexpert.h> |
116 | |
117 | #include <machine/config.h> |
118 | #include <machine/machine_routines.h> |
119 | #include <machine/cpu_capabilities.h> |
120 | |
121 | #include <mach/mach_host.h> /* for host_info() */ |
122 | |
123 | #if defined(__i386__) || defined(__x86_64__) |
124 | #include <i386/cpuid.h> /* for cpuid_info() */ |
125 | #endif |
126 | |
127 | #if defined(__arm64__) |
128 | #include <arm/cpuid.h> /* for cpuid_info() & cache_info() */ |
129 | #endif |
130 | |
131 | #if defined(CONFIG_XNUPOST) |
132 | #include <tests/ktest.h> |
133 | #endif |
134 | |
135 | /** |
136 | * Prevents an issue with creating the sysctl node hw.optional.arm on some |
137 | * platforms. If the 'arm' macro is defined, then the word "arm" is preprocessed |
138 | * to 1. As the 'arm' macro is not used in this file, we do not need to redefine |
139 | * after we are done. |
140 | */ |
141 | #if defined(arm) |
142 | #undef arm |
143 | #endif /* defined(arm) */ |
144 | |
145 | #ifndef MAX |
146 | #define MAX(a, b) (a >= b ? a : b) |
147 | #endif |
148 | |
149 | #if defined(__arm64__) && defined(CONFIG_XNUPOST) |
150 | kern_return_t arm_cpu_capabilities_legacy_test(void); |
151 | #endif /* defined(__arm64__) && defined(CONFIG_XNUPOST) */ |
152 | |
153 | /* XXX This should be in a BSD accessible Mach header, but isn't. */ |
154 | extern unsigned int vm_page_wire_count; |
155 | |
156 | static int cputhreadtype, cpu64bit; |
157 | static uint64_t cacheconfig[10]; |
158 | static int packages; |
159 | |
160 | static char * osenvironment = NULL; |
161 | static uint32_t osenvironment_size = 0; |
162 | static int osenvironment_initialized = 0; |
163 | |
164 | static uint32_t ephemeral_storage = 0; |
165 | static uint32_t use_recovery_securityd = 0; |
166 | |
167 | static struct { |
168 | uint32_t ephemeral_storage:1; |
169 | uint32_t use_recovery_securityd:1; |
170 | } property_existence = {0, 0}; |
171 | |
172 | SYSCTL_EXTENSIBLE_NODE(, 0, sysctl, CTLFLAG_RW | CTLFLAG_LOCKED, 0, |
173 | "Sysctl internal magic" ); |
174 | SYSCTL_EXTENSIBLE_NODE(, CTL_KERN, kern, CTLFLAG_RW | CTLFLAG_LOCKED, 0, |
175 | "High kernel, proc, limits &c" ); |
176 | SYSCTL_EXTENSIBLE_NODE(, CTL_VM, vm, CTLFLAG_RW | CTLFLAG_LOCKED, 0, |
177 | "Virtual memory" ); |
178 | SYSCTL_EXTENSIBLE_NODE(, CTL_VFS, vfs, CTLFLAG_RW | CTLFLAG_LOCKED, 0, |
179 | "File system" ); |
180 | SYSCTL_EXTENSIBLE_NODE(, CTL_NET, net, CTLFLAG_RW | CTLFLAG_LOCKED, 0, |
181 | "Network, (see socket.h)" ); |
182 | SYSCTL_EXTENSIBLE_NODE(, CTL_DEBUG, debug, CTLFLAG_RW | CTLFLAG_LOCKED, 0, |
183 | "Debugging" ); |
184 | #if DEBUG || DEVELOPMENT |
185 | SYSCTL_NODE(_debug, OID_AUTO, test, |
186 | CTLFLAG_RW | CTLFLAG_LOCKED | CTLFLAG_MASKED, 0, "tests" ); |
187 | #endif |
188 | SYSCTL_NODE(, CTL_HW, hw, CTLFLAG_RW | CTLFLAG_LOCKED, 0, |
189 | "hardware" ); |
190 | SYSCTL_EXTENSIBLE_NODE(, CTL_MACHDEP, machdep, CTLFLAG_RW | CTLFLAG_LOCKED, 0, |
191 | "machine dependent" ); |
192 | SYSCTL_NODE(, CTL_USER, user, CTLFLAG_RW | CTLFLAG_LOCKED, 0, |
193 | "user-level" ); |
194 | |
195 | SYSCTL_NODE(_kern, OID_AUTO, bridge, CTLFLAG_RW | CTLFLAG_LOCKED, 0, |
196 | "bridge" ); |
197 | |
198 | #define SYSCTL_RETURN(r, x) SYSCTL_OUT(r, &x, sizeof(x)) |
199 | |
200 | /****************************************************************************** |
201 | * hw.* MIB |
202 | */ |
203 | |
204 | #define CTLHW_RETQUAD (1U << 31) |
205 | #define CTLHW_LOCAL (1U << 30) |
206 | #define CTLHW_PERFLEVEL (1U << 29) |
207 | |
208 | #define HW_LOCAL_CPUTHREADTYPE (1 | CTLHW_LOCAL) |
209 | #define HW_LOCAL_PHYSICALCPU (2 | CTLHW_LOCAL) |
210 | #define HW_LOCAL_PHYSICALCPUMAX (3 | CTLHW_LOCAL) |
211 | #define HW_LOCAL_LOGICALCPU (4 | CTLHW_LOCAL) |
212 | #define HW_LOCAL_LOGICALCPUMAX (5 | CTLHW_LOCAL) |
213 | #define HW_LOCAL_CPUTYPE (6 | CTLHW_LOCAL) |
214 | #define HW_LOCAL_CPUSUBTYPE (7 | CTLHW_LOCAL) |
215 | #define HW_LOCAL_CPUFAMILY (8 | CTLHW_LOCAL) |
216 | #define HW_LOCAL_CPUSUBFAMILY (9 | CTLHW_LOCAL) |
217 | #define HW_NPERFLEVELS (10 | CTLHW_LOCAL) |
218 | #define HW_PERFLEVEL_PHYSICALCPU (11 | CTLHW_PERFLEVEL) |
219 | #define HW_PERFLEVEL_PHYSICALCPUMAX (12 | CTLHW_PERFLEVEL) |
220 | #define HW_PERFLEVEL_LOGICALCPU (13 | CTLHW_PERFLEVEL) |
221 | #define HW_PERFLEVEL_LOGICALCPUMAX (14 | CTLHW_PERFLEVEL) |
222 | #define HW_PERFLEVEL_L1ICACHESIZE (15 | CTLHW_PERFLEVEL) |
223 | #define HW_PERFLEVEL_L1DCACHESIZE (16 | CTLHW_PERFLEVEL) |
224 | #define HW_PERFLEVEL_L2CACHESIZE (17 | CTLHW_PERFLEVEL) |
225 | #define HW_PERFLEVEL_CPUSPERL2 (18 | CTLHW_PERFLEVEL) |
226 | #define HW_PERFLEVEL_L3CACHESIZE (19 | CTLHW_PERFLEVEL) |
227 | #define HW_PERFLEVEL_CPUSPERL3 (20 | CTLHW_PERFLEVEL) |
228 | #define HW_PERFLEVEL_NAME (21 | CTLHW_PERFLEVEL) |
229 | |
230 | |
231 | /* |
232 | * For a given perflevel, return the corresponding CPU type. |
233 | */ |
234 | cluster_type_t cpu_type_for_perflevel(int perflevel); |
235 | cluster_type_t |
236 | cpu_type_for_perflevel(int perflevel) |
237 | { |
238 | unsigned int cpu_types = ml_get_cpu_types(); |
239 | unsigned int n_perflevels = __builtin_popcount(cpu_types); |
240 | |
241 | assert((perflevel >= 0) && (perflevel < n_perflevels)); |
242 | |
243 | int current_idx = 0, current_perflevel = -1; |
244 | |
245 | while (cpu_types) { |
246 | current_perflevel += cpu_types & 1; |
247 | if (current_perflevel == (n_perflevels - (perflevel + 1))) { |
248 | return current_idx; |
249 | } |
250 | |
251 | cpu_types >>= 1; |
252 | current_idx++; |
253 | } |
254 | |
255 | return 0; |
256 | } |
257 | |
258 | static ml_cpu_info_t |
259 | sysctl_hw_generic_cpu_info(int perflevel, int arg2 __unused) |
260 | { |
261 | bool ignore_perflevel = false; |
262 | #if APPLE_ARM64_ARCH_FAMILY |
263 | if (arg2 == HW_CACHELINE) { |
264 | /* Apple SoCs have a uniform cacheline size across all clusters */ |
265 | ignore_perflevel = true; |
266 | } |
267 | #endif |
268 | |
269 | ml_cpu_info_t cpu_info; |
270 | if (ignore_perflevel) { |
271 | ml_cpu_get_info(ml_cpu_info: &cpu_info); |
272 | } else { |
273 | ml_cpu_get_info_type(ml_cpu_info: &cpu_info, cluster_type: cpu_type_for_perflevel(perflevel)); |
274 | } |
275 | return cpu_info; |
276 | } |
277 | |
278 | /* |
279 | * Supporting some variables requires us to do "real" work. We |
280 | * gather some of that here. |
281 | */ |
282 | static int |
283 | sysctl_hw_generic(__unused struct sysctl_oid *oidp, void *arg1, |
284 | int arg2, struct sysctl_req *req) |
285 | { |
286 | char dummy[65]; |
287 | int epochTemp; |
288 | int val, doquad; |
289 | long long qval; |
290 | unsigned int cpu_count; |
291 | host_basic_info_data_t hinfo; |
292 | kern_return_t kret; |
293 | mach_msg_type_number_t count = HOST_BASIC_INFO_COUNT; |
294 | |
295 | /* |
296 | * If we are using one of the perflevel sysctls, return early if the perflevel |
297 | * does not exist in this system. |
298 | */ |
299 | int perflevel = (int)arg1; |
300 | int n_perflevels = __builtin_popcount(ml_get_cpu_types()); |
301 | |
302 | if (arg2 & CTLHW_PERFLEVEL) { |
303 | if ((perflevel < 0) || (perflevel >= n_perflevels)) { |
304 | return ENOENT; |
305 | } |
306 | } else { |
307 | perflevel = n_perflevels - 1; |
308 | } |
309 | |
310 | /* |
311 | * Test and mask off the 'return quad' flag. |
312 | * Note that only some things here support it. |
313 | */ |
314 | doquad = arg2 & CTLHW_RETQUAD; |
315 | arg2 &= ~CTLHW_RETQUAD; |
316 | |
317 | #define BSD_HOST 1 |
318 | kret = host_info(host: (host_t)BSD_HOST, HOST_BASIC_INFO, host_info_out: (host_info_t)&hinfo, host_info_outCnt: &count); |
319 | |
320 | /* |
321 | * Handle various OIDs. |
322 | * |
323 | * OIDs that can return int or quad set val and qval and then break. |
324 | * Errors and int-only values return inline. |
325 | */ |
326 | switch (arg2) { |
327 | case HW_NCPU: |
328 | if (kret == KERN_SUCCESS) { |
329 | return SYSCTL_RETURN(req, hinfo.max_cpus); |
330 | } else { |
331 | return EINVAL; |
332 | } |
333 | case HW_AVAILCPU: |
334 | if (kret == KERN_SUCCESS) { |
335 | return SYSCTL_RETURN(req, hinfo.avail_cpus); |
336 | } else { |
337 | return EINVAL; |
338 | } |
339 | case HW_LOCAL_PHYSICALCPU: |
340 | if (kret == KERN_SUCCESS) { |
341 | return SYSCTL_RETURN(req, hinfo.physical_cpu); |
342 | } else { |
343 | return EINVAL; |
344 | } |
345 | case HW_LOCAL_PHYSICALCPUMAX: |
346 | if (kret == KERN_SUCCESS) { |
347 | return SYSCTL_RETURN(req, hinfo.physical_cpu_max); |
348 | } else { |
349 | return EINVAL; |
350 | } |
351 | case HW_LOCAL_LOGICALCPU: |
352 | if (kret == KERN_SUCCESS) { |
353 | return SYSCTL_RETURN(req, hinfo.logical_cpu); |
354 | } else { |
355 | return EINVAL; |
356 | } |
357 | case HW_LOCAL_LOGICALCPUMAX: |
358 | if (kret == KERN_SUCCESS) { |
359 | return SYSCTL_RETURN(req, hinfo.logical_cpu_max); |
360 | } else { |
361 | return EINVAL; |
362 | } |
363 | case HW_NPERFLEVELS: |
364 | return SYSCTL_RETURN(req, n_perflevels); |
365 | case HW_PERFLEVEL_PHYSICALCPU: |
366 | cpu_count = ml_get_cpu_number_type(cluster_type: cpu_type_for_perflevel(perflevel), false, true); |
367 | return SYSCTL_RETURN(req, cpu_count); |
368 | case HW_PERFLEVEL_PHYSICALCPUMAX: |
369 | cpu_count = ml_get_cpu_number_type(cluster_type: cpu_type_for_perflevel(perflevel), false, false); |
370 | return SYSCTL_RETURN(req, cpu_count); |
371 | case HW_PERFLEVEL_LOGICALCPU: |
372 | cpu_count = ml_get_cpu_number_type(cluster_type: cpu_type_for_perflevel(perflevel), true, true); |
373 | return SYSCTL_RETURN(req, cpu_count); |
374 | case HW_PERFLEVEL_LOGICALCPUMAX: |
375 | cpu_count = ml_get_cpu_number_type(cluster_type: cpu_type_for_perflevel(perflevel), true, false); |
376 | return SYSCTL_RETURN(req, cpu_count); |
377 | case HW_PERFLEVEL_L1ICACHESIZE: { |
378 | ml_cpu_info_t cpu_info = sysctl_hw_generic_cpu_info(perflevel, arg2); |
379 | val = (int)cpu_info.l1_icache_size; |
380 | qval = (long long)cpu_info.l1_icache_size; |
381 | break; |
382 | } |
383 | case HW_PERFLEVEL_L1DCACHESIZE: { |
384 | ml_cpu_info_t cpu_info = sysctl_hw_generic_cpu_info(perflevel, arg2); |
385 | val = (int)cpu_info.l1_dcache_size; |
386 | qval = (long long)cpu_info.l1_dcache_size; |
387 | break; |
388 | } |
389 | case HW_PERFLEVEL_L2CACHESIZE: { |
390 | ml_cpu_info_t cpu_info = sysctl_hw_generic_cpu_info(perflevel, arg2); |
391 | val = (int)cpu_info.l2_cache_size; |
392 | qval = (long long)cpu_info.l2_cache_size; |
393 | break; |
394 | } |
395 | case HW_PERFLEVEL_CPUSPERL2: |
396 | cpu_count = ml_cpu_cache_sharing(level: 2, cluster_type: cpu_type_for_perflevel(perflevel), false); |
397 | return SYSCTL_RETURN(req, cpu_count); |
398 | case HW_PERFLEVEL_L3CACHESIZE: { |
399 | ml_cpu_info_t cpu_info = sysctl_hw_generic_cpu_info(perflevel, arg2); |
400 | if (cpu_info.l3_cache_size == UINT32_MAX) { |
401 | return EINVAL; |
402 | } |
403 | val = (int)cpu_info.l3_cache_size; |
404 | qval = (long long)cpu_info.l3_cache_size; |
405 | break; |
406 | } |
407 | case HW_PERFLEVEL_CPUSPERL3: { |
408 | ml_cpu_info_t cpu_info = sysctl_hw_generic_cpu_info(perflevel, arg2); |
409 | if (cpu_info.l3_cache_size == UINT32_MAX) { |
410 | return EINVAL; |
411 | } |
412 | cpu_count = ml_cpu_cache_sharing(level: 3, cluster_type: cpu_type_for_perflevel(perflevel), false); |
413 | return SYSCTL_RETURN(req, cpu_count); |
414 | } |
415 | case HW_PERFLEVEL_NAME: |
416 | bzero(s: dummy, n: sizeof(dummy)); |
417 | ml_get_cluster_type_name(cluster_type: cpu_type_for_perflevel(perflevel), name: dummy, name_size: sizeof(dummy)); |
418 | return SYSCTL_OUT(req, dummy, strlen(dummy) + 1); |
419 | case HW_LOCAL_CPUTYPE: |
420 | if (kret == KERN_SUCCESS) { |
421 | return SYSCTL_RETURN(req, hinfo.cpu_type); |
422 | } else { |
423 | return EINVAL; |
424 | } |
425 | case HW_LOCAL_CPUSUBTYPE: |
426 | if (kret == KERN_SUCCESS) { |
427 | return SYSCTL_RETURN(req, hinfo.cpu_subtype); |
428 | } else { |
429 | return EINVAL; |
430 | } |
431 | case HW_LOCAL_CPUFAMILY: |
432 | { |
433 | int cpufamily = 0; |
434 | #if defined (__i386__) || defined (__x86_64__) |
435 | cpufamily = cpuid_cpufamily(); |
436 | #elif defined(__arm64__) |
437 | { |
438 | cpufamily = cpuid_get_cpufamily(); |
439 | } |
440 | #else |
441 | #error unknown architecture |
442 | #endif |
443 | return SYSCTL_RETURN(req, cpufamily); |
444 | } |
445 | case HW_LOCAL_CPUSUBFAMILY: |
446 | { |
447 | int cpusubfamily = 0; |
448 | #if defined (__i386__) || defined (__x86_64__) |
449 | cpusubfamily = CPUSUBFAMILY_UNKNOWN; |
450 | #elif defined(__arm64__) |
451 | { |
452 | cpusubfamily = cpuid_get_cpusubfamily(); |
453 | } |
454 | #else |
455 | #error unknown architecture |
456 | #endif |
457 | return SYSCTL_RETURN(req, cpusubfamily); |
458 | } |
459 | case HW_PAGESIZE: |
460 | { |
461 | vm_map_t map = get_task_map(current_task()); |
462 | val = vm_map_page_size(map); |
463 | qval = (long long)val; |
464 | break; |
465 | } |
466 | case HW_CACHELINE: { |
467 | ml_cpu_info_t cpu_info = sysctl_hw_generic_cpu_info(perflevel, arg2); |
468 | val = (int)cpu_info.cache_line_size; |
469 | qval = (long long)val; |
470 | break; |
471 | } |
472 | case HW_L1ICACHESIZE: { |
473 | ml_cpu_info_t cpu_info = sysctl_hw_generic_cpu_info(perflevel, arg2); |
474 | val = (int)cpu_info.l1_icache_size; |
475 | qval = (long long)cpu_info.l1_icache_size; |
476 | break; |
477 | } |
478 | case HW_L1DCACHESIZE: { |
479 | ml_cpu_info_t cpu_info = sysctl_hw_generic_cpu_info(perflevel, arg2); |
480 | val = (int)cpu_info.l1_dcache_size; |
481 | qval = (long long)cpu_info.l1_dcache_size; |
482 | break; |
483 | } |
484 | case HW_L2CACHESIZE: { |
485 | ml_cpu_info_t cpu_info = sysctl_hw_generic_cpu_info(perflevel, arg2); |
486 | if (cpu_info.l2_cache_size == UINT32_MAX) { |
487 | return EINVAL; |
488 | } |
489 | val = (int)cpu_info.l2_cache_size; |
490 | qval = (long long)cpu_info.l2_cache_size; |
491 | break; |
492 | } |
493 | case HW_L3CACHESIZE: { |
494 | ml_cpu_info_t cpu_info = sysctl_hw_generic_cpu_info(perflevel, arg2); |
495 | if (cpu_info.l3_cache_size == UINT32_MAX) { |
496 | return EINVAL; |
497 | } |
498 | val = (int)cpu_info.l3_cache_size; |
499 | qval = (long long)cpu_info.l3_cache_size; |
500 | break; |
501 | } |
502 | case HW_TARGET: |
503 | bzero(s: dummy, n: sizeof(dummy)); |
504 | if (!PEGetTargetName(name: dummy, maxLength: 64)) { |
505 | return EINVAL; |
506 | } |
507 | dummy[64] = 0; |
508 | return SYSCTL_OUT(req, dummy, strlen(dummy) + 1); |
509 | case HW_PRODUCT: |
510 | bzero(s: dummy, n: sizeof(dummy)); |
511 | if (!PEGetProductName(name: dummy, maxLength: 64)) { |
512 | return EINVAL; |
513 | } |
514 | dummy[64] = 0; |
515 | return SYSCTL_OUT(req, dummy, strlen(dummy) + 1); |
516 | |
517 | /* |
518 | * Deprecated variables. We still support these for |
519 | * backwards compatibility purposes only. |
520 | */ |
521 | #if XNU_TARGET_OS_OSX && defined(__arm64__) |
522 | /* The following two are kludged for backward |
523 | * compatibility. Use hw.product/hw.target for something |
524 | * consistent instead. */ |
525 | |
526 | case HW_MACHINE: |
527 | bzero(s: dummy, n: sizeof(dummy)); |
528 | if (proc_platform(req->p) == PLATFORM_IOS) { |
529 | /* iOS-on-Mac processes don't expect the macOS kind of |
530 | * hw.machine, e.g. "arm64", but are used to seeing |
531 | * a product string on iOS, which we here hardcode |
532 | * to return as "iPad8,6" for compatibility. |
533 | * |
534 | * Another reason why hw.machine and hw.model are |
535 | * trouble and hw.target+hw.product should be used |
536 | * instead. |
537 | */ |
538 | |
539 | strlcpy(dst: dummy, src: "iPad8,6" , n: sizeof(dummy)); |
540 | } |
541 | else { |
542 | strlcpy(dst: dummy, src: "arm64" , n: sizeof(dummy)); |
543 | } |
544 | dummy[64] = 0; |
545 | return SYSCTL_OUT(req, dummy, strlen(dummy) + 1); |
546 | case HW_MODEL: |
547 | bzero(s: dummy, n: sizeof(dummy)); |
548 | if (!PEGetProductName(name: dummy, maxLength: 64)) { |
549 | return EINVAL; |
550 | } |
551 | dummy[64] = 0; |
552 | return SYSCTL_OUT(req, dummy, strlen(dummy) + 1); |
553 | #else |
554 | case HW_MACHINE: |
555 | bzero(dummy, sizeof(dummy)); |
556 | if (!PEGetMachineName(dummy, 64)) { |
557 | return EINVAL; |
558 | } |
559 | dummy[64] = 0; |
560 | return SYSCTL_OUT(req, dummy, strlen(dummy) + 1); |
561 | case HW_MODEL: |
562 | bzero(dummy, sizeof(dummy)); |
563 | if (!PEGetModelName(dummy, 64)) { |
564 | return EINVAL; |
565 | } |
566 | dummy[64] = 0; |
567 | return SYSCTL_OUT(req, dummy, strlen(dummy) + 1); |
568 | #endif |
569 | case HW_USERMEM: |
570 | { |
571 | int usermem = (int)(mem_size - vm_page_wire_count * page_size); |
572 | |
573 | return SYSCTL_RETURN(req, usermem); |
574 | } |
575 | case HW_EPOCH: |
576 | epochTemp = PEGetPlatformEpoch(); |
577 | if (epochTemp == -1) { |
578 | return EINVAL; |
579 | } |
580 | return SYSCTL_RETURN(req, epochTemp); |
581 | case HW_VECTORUNIT: { |
582 | ml_cpu_info_t cpu_info = sysctl_hw_generic_cpu_info(perflevel, arg2); |
583 | int vector = cpu_info.vector_unit == 0? 0 : 1; |
584 | return SYSCTL_RETURN(req, vector); |
585 | } |
586 | case HW_L2SETTINGS: { |
587 | ml_cpu_info_t cpu_info = sysctl_hw_generic_cpu_info(perflevel, arg2); |
588 | if (cpu_info.l2_cache_size == UINT32_MAX) { |
589 | return EINVAL; |
590 | } |
591 | return SYSCTL_RETURN(req, cpu_info.l2_settings); |
592 | } |
593 | case HW_L3SETTINGS: { |
594 | ml_cpu_info_t cpu_info = sysctl_hw_generic_cpu_info(perflevel, arg2); |
595 | if (cpu_info.l3_cache_size == UINT32_MAX) { |
596 | return EINVAL; |
597 | } |
598 | return SYSCTL_RETURN(req, cpu_info.l3_settings); |
599 | } |
600 | default: |
601 | return ENOTSUP; |
602 | } |
603 | /* |
604 | * Callers may come to us with either int or quad buffers. |
605 | */ |
606 | if (doquad) { |
607 | return SYSCTL_RETURN(req, qval); |
608 | } |
609 | return SYSCTL_RETURN(req, val); |
610 | } |
611 | |
612 | static int |
613 | sysctl_hw_cachesize(struct sysctl_oid *oidp __unused, void *arg1 __unused, |
614 | int arg2 __unused, struct sysctl_req *req) |
615 | { |
616 | uint64_t cachesize[10] = {}; |
617 | |
618 | #if __x86_64__ |
619 | cachesize[0] = ml_cpu_cache_size(0); |
620 | cachesize[1] = ml_cpu_cache_size(1); |
621 | cachesize[2] = ml_cpu_cache_size(2); |
622 | cachesize[3] = ml_cpu_cache_size(3); |
623 | #elif __arm64__ |
624 | cluster_type_t min_perflevel_cluster_type = cpu_type_for_perflevel(perflevel: __builtin_popcount(ml_get_cpu_types()) - 1); |
625 | |
626 | cachesize[0] = ml_get_machine_mem(); |
627 | cachesize[1] = cache_info_type(cluster_type: min_perflevel_cluster_type)->c_dsize; /* Using the DCache */ |
628 | cachesize[2] = cache_info_type(cluster_type: min_perflevel_cluster_type)->c_l2size; |
629 | #else |
630 | #error unknown architecture |
631 | #endif |
632 | |
633 | return SYSCTL_RETURN(req, cachesize); |
634 | } |
635 | |
636 | /* hw.pagesize and hw.tbfrequency are expected as 64 bit values */ |
637 | static int |
638 | sysctl_pagesize |
639 | (__unused struct sysctl_oid *oidp, __unused void *arg1, __unused int arg2, struct sysctl_req *req) |
640 | { |
641 | vm_map_t map = get_task_map(current_task()); |
642 | long long l = vm_map_page_size(map); |
643 | return sysctl_io_number(req, bigValue: l, valueSize: sizeof(l), NULL, NULL); |
644 | } |
645 | |
646 | static int |
647 | sysctl_pagesize32 |
648 | (__unused struct sysctl_oid *oidp, __unused void *arg1, __unused int arg2, struct sysctl_req *req) |
649 | { |
650 | long long l; |
651 | #if __arm64__ |
652 | l = (long long) (1 << page_shift_user32); |
653 | #else /* __arm64__ */ |
654 | l = (long long) PAGE_SIZE; |
655 | #endif /* __arm64__ */ |
656 | return sysctl_io_number(req, bigValue: l, valueSize: sizeof(l), NULL, NULL); |
657 | } |
658 | |
659 | static int |
660 | sysctl_tbfrequency |
661 | (__unused struct sysctl_oid *oidp, __unused void *arg1, __unused int arg2, struct sysctl_req *req) |
662 | { |
663 | long long l = gPEClockFrequencyInfo.timebase_frequency_hz; |
664 | return sysctl_io_number(req, bigValue: l, valueSize: sizeof(l), NULL, NULL); |
665 | } |
666 | |
667 | /* |
668 | * Called by IOKit on Intel, or by sysctl_load_devicetree_entries() |
669 | */ |
670 | void |
671 | sysctl_set_osenvironment(unsigned int size, const void* value) |
672 | { |
673 | if (osenvironment_size == 0 && size > 0) { |
674 | osenvironment = zalloc_permanent(size, ZALIGN_NONE); |
675 | if (osenvironment) { |
676 | memcpy(dst: osenvironment, src: value, n: size); |
677 | osenvironment_size = size; |
678 | } |
679 | } |
680 | } |
681 | |
682 | void |
683 | sysctl_unblock_osenvironment(void) |
684 | { |
685 | os_atomic_inc(&osenvironment_initialized, relaxed); |
686 | thread_wakeup((event_t) &osenvironment_initialized); |
687 | } |
688 | |
689 | /* |
690 | * Create sysctl entries coming from device tree. |
691 | * |
692 | * Entries from device tree are loaded here because SecureDTLookupEntry() only works before |
693 | * PE_init_iokit(). Doing this also avoids the extern-C hackery to access these entries |
694 | * from IORegistry (which requires C++). |
695 | */ |
696 | __startup_func |
697 | static void |
698 | sysctl_load_devicetree_entries(void) |
699 | { |
700 | DTEntry chosen; |
701 | void const *value; |
702 | unsigned int size; |
703 | |
704 | if (kSuccess != SecureDTLookupEntry(searchPoint: 0, pathName: "/chosen" , foundEntry: &chosen)) { |
705 | return; |
706 | } |
707 | |
708 | /* load osenvironment */ |
709 | if (kSuccess == SecureDTGetProperty(entry: chosen, propertyName: "osenvironment" , propertyValue: (void const **) &value, propertySize: &size)) { |
710 | sysctl_set_osenvironment(size, value); |
711 | } |
712 | |
713 | /* load ephemeral_storage */ |
714 | if (kSuccess == SecureDTGetProperty(entry: chosen, propertyName: "ephemeral-storage" , propertyValue: (void const **) &value, propertySize: &size)) { |
715 | if (size == sizeof(uint32_t)) { |
716 | ephemeral_storage = *(uint32_t const *)value; |
717 | property_existence.ephemeral_storage = 1; |
718 | } |
719 | } |
720 | |
721 | /* load use_recovery_securityd */ |
722 | if (kSuccess == SecureDTGetProperty(entry: chosen, propertyName: "use-recovery-securityd" , propertyValue: (void const **) &value, propertySize: &size)) { |
723 | if (size == sizeof(uint32_t)) { |
724 | use_recovery_securityd = *(uint32_t const *)value; |
725 | property_existence.use_recovery_securityd = 1; |
726 | } |
727 | } |
728 | } |
729 | STARTUP(SYSCTL, STARTUP_RANK_MIDDLE, sysctl_load_devicetree_entries); |
730 | |
731 | static int |
732 | sysctl_osenvironment |
733 | (__unused struct sysctl_oid *oidp, __unused void *arg1, __unused int arg2, struct sysctl_req *req) |
734 | { |
735 | #if defined(__x86_64__) |
736 | #if (DEVELOPMENT || DEBUG) |
737 | if (os_atomic_load(&osenvironment_initialized, relaxed) == 0) { |
738 | assert_wait((event_t) &osenvironment_initialized, THREAD_UNINT); |
739 | if (os_atomic_load(&osenvironment_initialized, relaxed) != 0) { |
740 | clear_wait(current_thread(), THREAD_AWAKENED); |
741 | } else { |
742 | (void) thread_block(THREAD_CONTINUE_NULL); |
743 | } |
744 | } |
745 | #endif |
746 | #endif |
747 | if (osenvironment_size > 0) { |
748 | return SYSCTL_OUT(req, osenvironment, osenvironment_size); |
749 | } else { |
750 | return EINVAL; |
751 | } |
752 | } |
753 | |
754 | static int |
755 | sysctl_ephemeral_storage |
756 | (__unused struct sysctl_oid *oidp, __unused void *arg1, __unused int arg2, struct sysctl_req *req) |
757 | { |
758 | if (property_existence.ephemeral_storage) { |
759 | return SYSCTL_OUT(req, &ephemeral_storage, sizeof(ephemeral_storage)); |
760 | } else { |
761 | return EINVAL; |
762 | } |
763 | } |
764 | |
765 | static int |
766 | sysctl_use_recovery_securityd |
767 | (__unused struct sysctl_oid *oidp, __unused void *arg1, __unused int arg2, struct sysctl_req *req) |
768 | { |
769 | if (property_existence.use_recovery_securityd) { |
770 | return SYSCTL_OUT(req, &use_recovery_securityd, sizeof(use_recovery_securityd)); |
771 | } else { |
772 | return EINVAL; |
773 | } |
774 | } |
775 | |
776 | static int |
777 | sysctl_use_kernelmanagerd |
778 | (__unused struct sysctl_oid *oidp, __unused void *arg1, __unused int arg2, struct sysctl_req *req) |
779 | { |
780 | #if XNU_TARGET_OS_OSX |
781 | static int use_kernelmanagerd = 1; |
782 | static bool once = false; |
783 | |
784 | if (!once) { |
785 | kc_format_t kc_format; |
786 | PE_get_primary_kc_format(type: &kc_format); |
787 | if (kc_format == KCFormatFileset) { |
788 | use_kernelmanagerd = 1; |
789 | } else { |
790 | PE_parse_boot_argn(arg_string: "kernelmanagerd" , arg_ptr: &use_kernelmanagerd, max_arg: sizeof(use_kernelmanagerd)); |
791 | } |
792 | once = true; |
793 | } |
794 | #else |
795 | static int use_kernelmanagerd = 0; |
796 | #endif |
797 | return SYSCTL_OUT(req, &use_kernelmanagerd, sizeof(use_kernelmanagerd)); |
798 | } |
799 | |
800 | #define HW_LOCAL_FREQUENCY 1 |
801 | #define HW_LOCAL_FREQUENCY_MIN 2 |
802 | #define HW_LOCAL_FREQUENCY_MAX 3 |
803 | #define HW_LOCAL_FREQUENCY_CLOCK_RATE 4 |
804 | |
805 | static int |
806 | sysctl_bus_frequency |
807 | (__unused struct sysctl_oid *oidp, __unused void *arg1, __unused int arg2, __unused struct sysctl_req *req) |
808 | { |
809 | |
810 | #if DEBUG || DEVELOPMENT || !defined(__arm64__) |
811 | switch (arg2) { |
812 | case HW_LOCAL_FREQUENCY: |
813 | return SYSCTL_RETURN(req, gPEClockFrequencyInfo.bus_frequency_hz); |
814 | case HW_LOCAL_FREQUENCY_MIN: |
815 | return SYSCTL_RETURN(req, gPEClockFrequencyInfo.bus_frequency_min_hz); |
816 | case HW_LOCAL_FREQUENCY_MAX: |
817 | return SYSCTL_RETURN(req, gPEClockFrequencyInfo.bus_frequency_max_hz); |
818 | case HW_LOCAL_FREQUENCY_CLOCK_RATE: |
819 | return SYSCTL_OUT(req, &gPEClockFrequencyInfo.bus_clock_rate_hz, sizeof(int)); |
820 | default: |
821 | return EINVAL; |
822 | } |
823 | #else |
824 | return ENOENT; |
825 | #endif |
826 | } |
827 | |
828 | static int |
829 | sysctl_cpu_frequency |
830 | (__unused struct sysctl_oid *oidp, __unused void *arg1, __unused int arg2, __unused struct sysctl_req *req) |
831 | { |
832 | |
833 | #if DEBUG || DEVELOPMENT || !defined(__arm64__) |
834 | switch (arg2) { |
835 | case HW_LOCAL_FREQUENCY: |
836 | return SYSCTL_RETURN(req, gPEClockFrequencyInfo.cpu_frequency_hz); |
837 | case HW_LOCAL_FREQUENCY_MIN: |
838 | return SYSCTL_RETURN(req, gPEClockFrequencyInfo.cpu_frequency_min_hz); |
839 | case HW_LOCAL_FREQUENCY_MAX: |
840 | return SYSCTL_RETURN(req, gPEClockFrequencyInfo.cpu_frequency_max_hz); |
841 | case HW_LOCAL_FREQUENCY_CLOCK_RATE: |
842 | return SYSCTL_OUT(req, &gPEClockFrequencyInfo.cpu_clock_rate_hz, sizeof(int)); |
843 | default: |
844 | return EINVAL; |
845 | } |
846 | #else |
847 | return ENOENT; |
848 | #endif |
849 | } |
850 | |
851 | /* |
852 | * This sysctl will signal to userspace that a serial console is desired: |
853 | * |
854 | * hw.serialdebugmode = 1 will load the serial console job in the multi-user session; |
855 | * hw.serialdebugmode = 2 will load the serial console job in the base system as well |
856 | */ |
857 | static int |
858 | sysctl_serialdebugmode |
859 | (__unused struct sysctl_oid *oidp, __unused void *arg1, __unused int arg2, struct sysctl_req *req) |
860 | { |
861 | uint32_t serial_boot_arg; |
862 | int serialdebugmode = 0; |
863 | |
864 | if (PE_parse_boot_argn(arg_string: "serial" , arg_ptr: &serial_boot_arg, max_arg: sizeof(serial_boot_arg)) && |
865 | (serial_boot_arg & SERIALMODE_OUTPUT) && (serial_boot_arg & SERIALMODE_INPUT)) { |
866 | serialdebugmode = (serial_boot_arg & SERIALMODE_BASE_TTY) ? 2 : 1; |
867 | } |
868 | |
869 | return sysctl_io_number(req, bigValue: serialdebugmode, valueSize: sizeof(serialdebugmode), NULL, NULL); |
870 | } |
871 | |
872 | /* |
873 | * hw.* MIB variables. |
874 | */ |
875 | SYSCTL_PROC(_hw, HW_NCPU, ncpu, CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED, 0, HW_NCPU, sysctl_hw_generic, "I" , "" ); |
876 | SYSCTL_PROC(_hw, HW_AVAILCPU, activecpu, CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED, 0, HW_AVAILCPU, sysctl_hw_generic, "I" , "" ); |
877 | SYSCTL_PROC(_hw, OID_AUTO, physicalcpu, CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED, 0, HW_LOCAL_PHYSICALCPU, sysctl_hw_generic, "I" , "" ); |
878 | SYSCTL_PROC(_hw, OID_AUTO, physicalcpu_max, CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED, 0, HW_LOCAL_PHYSICALCPUMAX, sysctl_hw_generic, "I" , "" ); |
879 | SYSCTL_PROC(_hw, OID_AUTO, logicalcpu, CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED, 0, HW_LOCAL_LOGICALCPU, sysctl_hw_generic, "I" , "" ); |
880 | SYSCTL_PROC(_hw, OID_AUTO, logicalcpu_max, CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED, 0, HW_LOCAL_LOGICALCPUMAX, sysctl_hw_generic, "I" , "" ); |
881 | SYSCTL_INT(_hw, HW_BYTEORDER, byteorder, CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED, (int *)NULL, BYTE_ORDER, "" ); |
882 | SYSCTL_PROC(_hw, OID_AUTO, cputype, CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED, 0, HW_LOCAL_CPUTYPE, sysctl_hw_generic, "I" , "" ); |
883 | SYSCTL_PROC(_hw, OID_AUTO, cpusubtype, CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED, 0, HW_LOCAL_CPUSUBTYPE, sysctl_hw_generic, "I" , "" ); |
884 | SYSCTL_INT(_hw, OID_AUTO, cpu64bit_capable, CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED, &cpu64bit, 0, "" ); |
885 | SYSCTL_PROC(_hw, OID_AUTO, cpufamily, CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED, 0, HW_LOCAL_CPUFAMILY, sysctl_hw_generic, "I" , "" ); |
886 | SYSCTL_PROC(_hw, OID_AUTO, cpusubfamily, CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED, 0, HW_LOCAL_CPUSUBFAMILY, sysctl_hw_generic, "I" , "" ); |
887 | SYSCTL_OPAQUE(_hw, OID_AUTO, cacheconfig, CTLFLAG_RD | CTLFLAG_LOCKED, &cacheconfig, sizeof(cacheconfig), "Q" , "" ); |
888 | SYSCTL_PROC(_hw, OID_AUTO, cachesize, CTLTYPE_OPAQUE | CTLFLAG_RD | CTLFLAG_LOCKED, 0, 0, sysctl_hw_cachesize, "Q" , "" ); |
889 | SYSCTL_PROC(_hw, OID_AUTO, pagesize, CTLTYPE_QUAD | CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED, 0, 0, sysctl_pagesize, "Q" , "" ); |
890 | SYSCTL_PROC(_hw, OID_AUTO, pagesize32, CTLTYPE_QUAD | CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED, 0, 0, sysctl_pagesize32, "Q" , "" ); |
891 | SYSCTL_PROC(_hw, OID_AUTO, busfrequency, CTLTYPE_QUAD | CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED, 0, HW_LOCAL_FREQUENCY, sysctl_bus_frequency, "Q" , "" ); |
892 | SYSCTL_PROC(_hw, OID_AUTO, busfrequency_min, CTLTYPE_QUAD | CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED, 0, HW_LOCAL_FREQUENCY_MIN, sysctl_bus_frequency, "Q" , "" ); |
893 | SYSCTL_PROC(_hw, OID_AUTO, busfrequency_max, CTLTYPE_QUAD | CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED, 0, HW_LOCAL_FREQUENCY_MAX, sysctl_bus_frequency, "Q" , "" ); |
894 | SYSCTL_PROC(_hw, OID_AUTO, cpufrequency, CTLTYPE_QUAD | CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED, 0, HW_LOCAL_FREQUENCY, sysctl_cpu_frequency, "Q" , "" ); |
895 | SYSCTL_PROC(_hw, OID_AUTO, cpufrequency_min, CTLTYPE_QUAD | CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED, 0, HW_LOCAL_FREQUENCY_MIN, sysctl_cpu_frequency, "Q" , "" ); |
896 | SYSCTL_PROC(_hw, OID_AUTO, cpufrequency_max, CTLTYPE_QUAD | CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED, 0, HW_LOCAL_FREQUENCY_MAX, sysctl_cpu_frequency, "Q" , "" ); |
897 | SYSCTL_PROC(_hw, OID_AUTO, cachelinesize, CTLTYPE_QUAD | CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED, 0, HW_CACHELINE | CTLHW_RETQUAD, sysctl_hw_generic, "Q" , "" ); |
898 | SYSCTL_PROC(_hw, OID_AUTO, l1icachesize, CTLTYPE_QUAD | CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED, 0, HW_L1ICACHESIZE | CTLHW_RETQUAD, sysctl_hw_generic, "Q" , "" ); |
899 | SYSCTL_PROC(_hw, OID_AUTO, l1dcachesize, CTLTYPE_QUAD | CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED, 0, HW_L1DCACHESIZE | CTLHW_RETQUAD, sysctl_hw_generic, "Q" , "" ); |
900 | SYSCTL_PROC(_hw, OID_AUTO, l2cachesize, CTLTYPE_QUAD | CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED, 0, HW_L2CACHESIZE | CTLHW_RETQUAD, sysctl_hw_generic, "Q" , "" ); |
901 | SYSCTL_PROC(_hw, OID_AUTO, l3cachesize, CTLTYPE_QUAD | CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED, 0, HW_L3CACHESIZE | CTLHW_RETQUAD, sysctl_hw_generic, "Q" , "" ); |
902 | #if defined(__arm64__) && (DEBUG || DEVELOPMENT) |
903 | SYSCTL_QUAD(_hw, OID_AUTO, memfrequency, CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED, &gPEClockFrequencyInfo.mem_frequency_hz, "" ); |
904 | SYSCTL_QUAD(_hw, OID_AUTO, memfrequency_min, CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED, &gPEClockFrequencyInfo.mem_frequency_min_hz, "" ); |
905 | SYSCTL_QUAD(_hw, OID_AUTO, memfrequency_max, CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED, &gPEClockFrequencyInfo.mem_frequency_max_hz, "" ); |
906 | SYSCTL_QUAD(_hw, OID_AUTO, prffrequency, CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED, &gPEClockFrequencyInfo.prf_frequency_hz, "" ); |
907 | SYSCTL_QUAD(_hw, OID_AUTO, prffrequency_min, CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED, &gPEClockFrequencyInfo.prf_frequency_min_hz, "" ); |
908 | SYSCTL_QUAD(_hw, OID_AUTO, prffrequency_max, CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED, &gPEClockFrequencyInfo.prf_frequency_max_hz, "" ); |
909 | SYSCTL_QUAD(_hw, OID_AUTO, fixfrequency, CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED, &gPEClockFrequencyInfo.fix_frequency_hz, "" ); |
910 | #endif /* __arm64__ */ |
911 | SYSCTL_PROC(_hw, OID_AUTO, tbfrequency, CTLTYPE_QUAD | CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED, 0, 0, sysctl_tbfrequency, "Q" , "" ); |
912 | /** |
913 | * The naming around the sysctls for max_mem and max_mem_actual are different between macOS and |
914 | * non-macOS platforms because historically macOS's hw.memsize provided the value of the actual |
915 | * physical memory size, whereas on non-macOS it is the memory size minus any carveouts. |
916 | */ |
917 | #if XNU_TARGET_OS_OSX |
918 | SYSCTL_QUAD(_hw, HW_MEMSIZE, memsize, CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED, &max_mem_actual, "" ); |
919 | SYSCTL_QUAD(_hw, OID_AUTO, memsize_usable, CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED, &max_mem, "" ); |
920 | #else |
921 | SYSCTL_QUAD(_hw, HW_MEMSIZE, memsize, CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED, &max_mem, "" ); |
922 | SYSCTL_QUAD(_hw, OID_AUTO, memsize_physical, CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED, &max_mem_actual, "" ); |
923 | #endif /* XNU_TARGET_OS_OSX */ |
924 | SYSCTL_INT(_hw, OID_AUTO, packages, CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED, &packages, 0, "" ); |
925 | SYSCTL_PROC(_hw, OID_AUTO, osenvironment, CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED, 0, 0, sysctl_osenvironment, "A" , "" ); |
926 | SYSCTL_PROC(_hw, OID_AUTO, ephemeral_storage, CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED, 0, 0, sysctl_ephemeral_storage, "I" , "" ); |
927 | SYSCTL_PROC(_hw, OID_AUTO, use_recovery_securityd, CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED, 0, 0, sysctl_use_recovery_securityd, "I" , "" ); |
928 | SYSCTL_PROC(_hw, OID_AUTO, use_kernelmanagerd, CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED, 0, 0, sysctl_use_kernelmanagerd, "I" , "" ); |
929 | SYSCTL_PROC(_hw, OID_AUTO, serialdebugmode, CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_LOCKED, 0, 0, sysctl_serialdebugmode, "I" , "" ); |
930 | |
931 | /* |
932 | * hw.perflevelN.* variables. |
933 | * Users may check these to determine properties that vary across different CPU types, such as number of CPUs, |
934 | * or cache sizes. Perflevel 0 corresponds to the highest performance one. |
935 | */ |
936 | SYSCTL_NODE(_hw, OID_AUTO, perflevel0, CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED, NULL, "Perf level 0 topology and cache geometry paramaters" ); |
937 | SYSCTL_NODE(_hw, OID_AUTO, perflevel1, CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED, NULL, "Perf level 1 topology and cache geometry paramaters" ); |
938 | SYSCTL_PROC(_hw, OID_AUTO, nperflevels, CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED, (void *)0, HW_NPERFLEVELS, sysctl_hw_generic, "I" , "Number of performance levels supported by this system" ); |
939 | |
940 | SYSCTL_PROC(_hw_perflevel0, OID_AUTO, physicalcpu, CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED, (void *)0, HW_PERFLEVEL_PHYSICALCPU, sysctl_hw_generic, "I" , "" ); |
941 | SYSCTL_PROC(_hw_perflevel0, OID_AUTO, physicalcpu_max, CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED, (void *)0, HW_PERFLEVEL_PHYSICALCPUMAX, sysctl_hw_generic, "I" , "" ); |
942 | SYSCTL_PROC(_hw_perflevel0, OID_AUTO, logicalcpu, CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED, (void *)0, HW_PERFLEVEL_LOGICALCPU, sysctl_hw_generic, "I" , "" ); |
943 | SYSCTL_PROC(_hw_perflevel0, OID_AUTO, logicalcpu_max, CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED, (void *)0, HW_PERFLEVEL_LOGICALCPUMAX, sysctl_hw_generic, "I" , "" ); |
944 | SYSCTL_PROC(_hw_perflevel0, OID_AUTO, l1icachesize, CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED, (void *)0, HW_PERFLEVEL_L1ICACHESIZE, sysctl_hw_generic, "I" , "" ); |
945 | SYSCTL_PROC(_hw_perflevel0, OID_AUTO, l1dcachesize, CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED, (void *)0, HW_PERFLEVEL_L1DCACHESIZE, sysctl_hw_generic, "I" , "" ); |
946 | SYSCTL_PROC(_hw_perflevel0, OID_AUTO, l2cachesize, CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED, (void *)0, HW_PERFLEVEL_L2CACHESIZE, sysctl_hw_generic, "I" , "" ); |
947 | SYSCTL_PROC(_hw_perflevel0, OID_AUTO, cpusperl2, CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED, (void *)0, HW_PERFLEVEL_CPUSPERL2, sysctl_hw_generic, "I" , "" ); |
948 | SYSCTL_PROC(_hw_perflevel0, OID_AUTO, l3cachesize, CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED, (void *)0, HW_PERFLEVEL_L3CACHESIZE, sysctl_hw_generic, "I" , "" ); |
949 | SYSCTL_PROC(_hw_perflevel0, OID_AUTO, cpusperl3, CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED, (void *)0, HW_PERFLEVEL_CPUSPERL3, sysctl_hw_generic, "I" , "" ); |
950 | SYSCTL_PROC(_hw_perflevel0, OID_AUTO, name, CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED, (void *)0, HW_PERFLEVEL_NAME, sysctl_hw_generic, "A" , "" ); |
951 | |
952 | SYSCTL_PROC(_hw_perflevel1, OID_AUTO, physicalcpu, CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED, (void *)1, HW_PERFLEVEL_PHYSICALCPU, sysctl_hw_generic, "I" , "" ); |
953 | SYSCTL_PROC(_hw_perflevel1, OID_AUTO, physicalcpu_max, CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED, (void *)1, HW_PERFLEVEL_PHYSICALCPUMAX, sysctl_hw_generic, "I" , "" ); |
954 | SYSCTL_PROC(_hw_perflevel1, OID_AUTO, logicalcpu, CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED, (void *)1, HW_PERFLEVEL_LOGICALCPU, sysctl_hw_generic, "I" , "" ); |
955 | SYSCTL_PROC(_hw_perflevel1, OID_AUTO, logicalcpu_max, CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED, (void *)1, HW_PERFLEVEL_LOGICALCPUMAX, sysctl_hw_generic, "I" , "" ); |
956 | SYSCTL_PROC(_hw_perflevel1, OID_AUTO, l1icachesize, CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED, (void *)1, HW_PERFLEVEL_L1ICACHESIZE, sysctl_hw_generic, "I" , "" ); |
957 | SYSCTL_PROC(_hw_perflevel1, OID_AUTO, l1dcachesize, CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED, (void *)1, HW_PERFLEVEL_L1DCACHESIZE, sysctl_hw_generic, "I" , "" ); |
958 | SYSCTL_PROC(_hw_perflevel1, OID_AUTO, l2cachesize, CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED, (void *)1, HW_PERFLEVEL_L2CACHESIZE, sysctl_hw_generic, "I" , "" ); |
959 | SYSCTL_PROC(_hw_perflevel1, OID_AUTO, cpusperl2, CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED, (void *)1, HW_PERFLEVEL_CPUSPERL2, sysctl_hw_generic, "I" , "" ); |
960 | SYSCTL_PROC(_hw_perflevel1, OID_AUTO, l3cachesize, CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED, (void *)1, HW_PERFLEVEL_L3CACHESIZE, sysctl_hw_generic, "I" , "" ); |
961 | SYSCTL_PROC(_hw_perflevel1, OID_AUTO, cpusperl3, CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED, (void *)1, HW_PERFLEVEL_CPUSPERL3, sysctl_hw_generic, "I" , "" ); |
962 | SYSCTL_PROC(_hw_perflevel1, OID_AUTO, name, CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED, (void *)1, HW_PERFLEVEL_NAME, sysctl_hw_generic, "A" , "" ); |
963 | |
964 | /* |
965 | * Optional CPU features can register nodes below hw.optional. |
966 | * |
967 | * If the feature is not present, the node should either not be registered, |
968 | * or it should return 0. If the feature is present, the node should return |
969 | * 1. |
970 | */ |
971 | SYSCTL_NODE(_hw, OID_AUTO, optional, CTLFLAG_RW | CTLFLAG_LOCKED, NULL, "optional features" ); |
972 | SYSCTL_NODE(_hw_optional, OID_AUTO, arm, CTLFLAG_RW | CTLFLAG_LOCKED, NULL, "optional features for ARM processors" ); |
973 | |
974 | SYSCTL_INT(_hw_optional, OID_AUTO, floatingpoint, CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED, (int *)NULL, 1, "" ); /* always set */ |
975 | |
976 | /* |
977 | * Optional device hardware features can be registered by drivers below hw.features |
978 | */ |
979 | SYSCTL_EXTENSIBLE_NODE(_hw, OID_AUTO, features, CTLFLAG_RD | CTLFLAG_LOCKED, NULL, "hardware features" ); |
980 | |
981 | /* |
982 | * Deprecated variables. These are supported for backwards compatibility |
983 | * purposes only. The MASKED flag requests that the variables not be |
984 | * printed by sysctl(8) and similar utilities. |
985 | * |
986 | * The variables named *_compat here are int-sized versions of variables |
987 | * that are now exported as quads. The int-sized versions are normally |
988 | * looked up only by number, wheras the quad-sized versions should be |
989 | * looked up by name. |
990 | * |
991 | * The *_compat nodes are *NOT* visible within the kernel. |
992 | */ |
993 | |
994 | SYSCTL_PROC(_hw, HW_PAGESIZE, pagesize_compat, CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_MASKED | CTLFLAG_LOCKED, 0, HW_PAGESIZE, sysctl_hw_generic, "I" , "" ); |
995 | SYSCTL_PROC(_hw, HW_BUS_FREQ, busfrequency_compat, CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_MASKED | CTLFLAG_LOCKED, 0, HW_LOCAL_FREQUENCY_CLOCK_RATE, sysctl_bus_frequency, "I" , "" ); |
996 | SYSCTL_PROC(_hw, HW_CPU_FREQ, cpufrequency_compat, CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_MASKED | CTLFLAG_LOCKED, 0, HW_LOCAL_FREQUENCY_CLOCK_RATE, sysctl_cpu_frequency, "I" , "" ); |
997 | SYSCTL_PROC(_hw, HW_CACHELINE, cachelinesize_compat, CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_MASKED | CTLFLAG_LOCKED, 0, HW_CACHELINE, sysctl_hw_generic, "I" , "" ); |
998 | SYSCTL_PROC(_hw, HW_L1ICACHESIZE, l1icachesize_compat, CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_MASKED | CTLFLAG_LOCKED, 0, HW_L1ICACHESIZE, sysctl_hw_generic, "I" , "" ); |
999 | SYSCTL_PROC(_hw, HW_L1DCACHESIZE, l1dcachesize_compat, CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_MASKED | CTLFLAG_LOCKED, 0, HW_L1DCACHESIZE, sysctl_hw_generic, "I" , "" ); |
1000 | SYSCTL_PROC(_hw, HW_L2CACHESIZE, l2cachesize_compat, CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_MASKED | CTLFLAG_LOCKED, 0, HW_L2CACHESIZE, sysctl_hw_generic, "I" , "" ); |
1001 | SYSCTL_PROC(_hw, HW_L3CACHESIZE, l3cachesize_compat, CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_MASKED | CTLFLAG_LOCKED, 0, HW_L3CACHESIZE, sysctl_hw_generic, "I" , "" ); |
1002 | SYSCTL_COMPAT_INT(_hw, HW_TB_FREQ, tbfrequency_compat, CTLFLAG_RD | CTLFLAG_MASKED | CTLFLAG_LOCKED, &gPEClockFrequencyInfo.timebase_frequency_hz, 0, "" ); |
1003 | SYSCTL_PROC(_hw, HW_MACHINE, machine, CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_MASKED | CTLFLAG_LOCKED, 0, HW_MACHINE, sysctl_hw_generic, "A" , "" ); |
1004 | SYSCTL_PROC(_hw, HW_MODEL, model, CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_MASKED | CTLFLAG_LOCKED, 0, HW_MODEL, sysctl_hw_generic, "A" , "" ); |
1005 | SYSCTL_PROC(_hw, HW_TARGET, target, CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_MASKED | CTLFLAG_LOCKED, 0, HW_TARGET, sysctl_hw_generic, "A" , "" ); |
1006 | SYSCTL_PROC(_hw, HW_PRODUCT, product, CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_MASKED | CTLFLAG_LOCKED, 0, HW_PRODUCT, sysctl_hw_generic, "A" , "" ); |
1007 | SYSCTL_COMPAT_UINT(_hw, HW_PHYSMEM, physmem, CTLFLAG_RD | CTLFLAG_MASKED | CTLFLAG_LOCKED, &mem_size, 0, "" ); |
1008 | SYSCTL_PROC(_hw, HW_USERMEM, usermem, CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_MASKED | CTLFLAG_LOCKED, 0, HW_USERMEM, sysctl_hw_generic, "I" , "" ); |
1009 | SYSCTL_PROC(_hw, HW_EPOCH, epoch, CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_MASKED | CTLFLAG_LOCKED, 0, HW_EPOCH, sysctl_hw_generic, "I" , "" ); |
1010 | SYSCTL_PROC(_hw, HW_VECTORUNIT, vectorunit, CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_MASKED | CTLFLAG_LOCKED, 0, HW_VECTORUNIT, sysctl_hw_generic, "I" , "" ); |
1011 | SYSCTL_PROC(_hw, HW_L2SETTINGS, l2settings, CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_MASKED | CTLFLAG_LOCKED, 0, HW_L2SETTINGS, sysctl_hw_generic, "I" , "" ); |
1012 | SYSCTL_PROC(_hw, HW_L3SETTINGS, l3settings, CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_MASKED | CTLFLAG_LOCKED, 0, HW_L3SETTINGS, sysctl_hw_generic, "I" , "" ); |
1013 | SYSCTL_INT(_hw, OID_AUTO, cputhreadtype, CTLFLAG_RD | CTLFLAG_NOAUTO | CTLFLAG_KERN | CTLFLAG_LOCKED, &cputhreadtype, 0, "" ); |
1014 | |
1015 | #if defined(__i386__) || defined(__x86_64__) || CONFIG_X86_64_COMPAT |
1016 | static int |
1017 | sysctl_cpu_capability |
1018 | (__unused struct sysctl_oid *oidp, void *arg1, __unused int arg2, struct sysctl_req *req) |
1019 | { |
1020 | uint64_t caps; |
1021 | caps = _get_cpu_capabilities(); |
1022 | |
1023 | uint64_t mask = (uint64_t) (uintptr_t) arg1; |
1024 | boolean_t is_capable = (caps & mask) != 0; |
1025 | |
1026 | return SYSCTL_OUT(req, &is_capable, sizeof(is_capable)); |
1027 | } |
1028 | #define capability(name) name |
1029 | |
1030 | |
1031 | SYSCTL_PROC(_hw_optional, OID_AUTO, mmx, CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED, (void *) capability(kHasMMX), 0, sysctl_cpu_capability, "I" , "" ); |
1032 | SYSCTL_PROC(_hw_optional, OID_AUTO, sse, CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED, (void *) capability(kHasSSE), 0, sysctl_cpu_capability, "I" , "" ); |
1033 | SYSCTL_PROC(_hw_optional, OID_AUTO, sse2, CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED, (void *) capability(kHasSSE2), 0, sysctl_cpu_capability, "I" , "" ); |
1034 | SYSCTL_PROC(_hw_optional, OID_AUTO, sse3, CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED, (void *) capability(kHasSSE3), 0, sysctl_cpu_capability, "I" , "" ); |
1035 | SYSCTL_PROC(_hw_optional, OID_AUTO, supplementalsse3, CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED, (void *) capability(kHasSupplementalSSE3), 0, sysctl_cpu_capability, "I" , "" ); |
1036 | SYSCTL_PROC(_hw_optional, OID_AUTO, sse4_1, CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED, (void *) capability(kHasSSE4_1), 0, sysctl_cpu_capability, "I" , "" ); |
1037 | SYSCTL_PROC(_hw_optional, OID_AUTO, sse4_2, CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED, (void *) capability(kHasSSE4_2), 0, sysctl_cpu_capability, "I" , "" ); |
1038 | /* "x86_64" is actually a preprocessor symbol on the x86_64 kernel, so we have to hack this */ |
1039 | #undef x86_64 |
1040 | SYSCTL_PROC(_hw_optional, OID_AUTO, x86_64, CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED, (void *) capability(k64Bit), 0, sysctl_cpu_capability, "I" , "" ); |
1041 | SYSCTL_PROC(_hw_optional, OID_AUTO, aes, CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED, (void *) capability(kHasAES), 0, sysctl_cpu_capability, "I" , "" ); |
1042 | SYSCTL_PROC(_hw_optional, OID_AUTO, avx1_0, CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED, (void *) capability(kHasAVX1_0), 0, sysctl_cpu_capability, "I" , "" ); |
1043 | SYSCTL_PROC(_hw_optional, OID_AUTO, rdrand, CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED, (void *) capability(kHasRDRAND), 0, sysctl_cpu_capability, "I" , "" ); |
1044 | SYSCTL_PROC(_hw_optional, OID_AUTO, f16c, CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED, (void *) capability(kHasF16C), 0, sysctl_cpu_capability, "I" , "" ); |
1045 | SYSCTL_PROC(_hw_optional, OID_AUTO, enfstrg, CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED, (void *) capability(kHasENFSTRG), 0, sysctl_cpu_capability, "I" , "" ); |
1046 | SYSCTL_PROC(_hw_optional, OID_AUTO, fma, CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED, (void *) capability(kHasFMA), 0, sysctl_cpu_capability, "I" , "" ); |
1047 | SYSCTL_PROC(_hw_optional, OID_AUTO, avx2_0, CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED, (void *) capability(kHasAVX2_0), 0, sysctl_cpu_capability, "I" , "" ); |
1048 | SYSCTL_PROC(_hw_optional, OID_AUTO, bmi1, CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED, (void *) capability(kHasBMI1), 0, sysctl_cpu_capability, "I" , "" ); |
1049 | SYSCTL_PROC(_hw_optional, OID_AUTO, bmi2, CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED, (void *) capability(kHasBMI2), 0, sysctl_cpu_capability, "I" , "" ); |
1050 | SYSCTL_PROC(_hw_optional, OID_AUTO, rtm, CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED, (void *) capability(kHasRTM), 0, sysctl_cpu_capability, "I" , "" ); |
1051 | SYSCTL_PROC(_hw_optional, OID_AUTO, hle, CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED, (void *) capability(kHasHLE), 0, sysctl_cpu_capability, "I" , "" ); |
1052 | SYSCTL_PROC(_hw_optional, OID_AUTO, adx, CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED, (void *) capability(kHasADX), 0, sysctl_cpu_capability, "I" , "" ); |
1053 | SYSCTL_PROC(_hw_optional, OID_AUTO, mpx, CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED, (void *) capability(kHasMPX), 0, sysctl_cpu_capability, "I" , "" ); |
1054 | SYSCTL_PROC(_hw_optional, OID_AUTO, sgx, CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED, (void *) capability(kHasSGX), 0, sysctl_cpu_capability, "I" , "" ); |
1055 | SYSCTL_PROC(_hw_optional, OID_AUTO, avx512f, CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED, (void *) capability(kHasAVX512F), 0, sysctl_cpu_capability, "I" , "" ); |
1056 | SYSCTL_PROC(_hw_optional, OID_AUTO, avx512cd, CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED, (void *) capability(kHasAVX512CD), 0, sysctl_cpu_capability, "I" , "" ); |
1057 | SYSCTL_PROC(_hw_optional, OID_AUTO, avx512dq, CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED, (void *) capability(kHasAVX512DQ), 0, sysctl_cpu_capability, "I" , "" ); |
1058 | SYSCTL_PROC(_hw_optional, OID_AUTO, avx512bw, CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED, (void *) capability(kHasAVX512BW), 0, sysctl_cpu_capability, "I" , "" ); |
1059 | SYSCTL_PROC(_hw_optional, OID_AUTO, avx512vl, CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED, (void *) capability(kHasAVX512VL), 0, sysctl_cpu_capability, "I" , "" ); |
1060 | SYSCTL_PROC(_hw_optional, OID_AUTO, avx512ifma, CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED, (void *) capability(kHasAVX512IFMA), 0, sysctl_cpu_capability, "I" , "" ); |
1061 | SYSCTL_PROC(_hw_optional, OID_AUTO, avx512vbmi, CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED, (void *) capability(kHasAVX512VBMI), 0, sysctl_cpu_capability, "I" , "" ); |
1062 | #undef capability |
1063 | #endif /* !__i386__ && !__x86_64 && !CONFIG_X86_64_COMPAT */ |
1064 | |
1065 | #if defined (__arm64__) |
1066 | int watchpoint_flag = 0; |
1067 | int breakpoint_flag = 0; |
1068 | SECURITY_READ_ONLY_LATE(int) gARMv8Crc32 = 0; |
1069 | |
1070 | /* Features from: ID_AA64ISAR0_EL1 */ |
1071 | SECURITY_READ_ONLY_LATE(int) gARM_FEAT_FlagM = 0; |
1072 | SECURITY_READ_ONLY_LATE(int) gARM_FEAT_FlagM2 = 0; |
1073 | SECURITY_READ_ONLY_LATE(int) gARM_FEAT_FHM = 0; |
1074 | SECURITY_READ_ONLY_LATE(int) gARM_FEAT_DotProd = 0; |
1075 | SECURITY_READ_ONLY_LATE(int) gARM_FEAT_SHA3 = 0; |
1076 | SECURITY_READ_ONLY_LATE(int) gARM_FEAT_RDM = 0; |
1077 | SECURITY_READ_ONLY_LATE(int) gARM_FEAT_LSE = 0; |
1078 | SECURITY_READ_ONLY_LATE(int) gARM_FEAT_SHA256 = 0; |
1079 | SECURITY_READ_ONLY_LATE(int) gARM_FEAT_SHA512 = 0; |
1080 | SECURITY_READ_ONLY_LATE(int) gARM_FEAT_SHA1 = 0; |
1081 | SECURITY_READ_ONLY_LATE(int) gARM_FEAT_AES = 0; |
1082 | SECURITY_READ_ONLY_LATE(int) gARM_FEAT_PMULL = 0; |
1083 | |
1084 | /* Features from: ID_AA64ISAR1_EL1 */ |
1085 | SECURITY_READ_ONLY_LATE(int) gARM_FEAT_SPECRES = 0; |
1086 | SECURITY_READ_ONLY_LATE(int) gARM_FEAT_SB = 0; |
1087 | SECURITY_READ_ONLY_LATE(int) gARM_FEAT_FRINTTS = 0; |
1088 | SECURITY_READ_ONLY_LATE(int) gARMv8Gpi = 0; |
1089 | SECURITY_READ_ONLY_LATE(int) gARM_FEAT_LRCPC = 0; |
1090 | SECURITY_READ_ONLY_LATE(int) gARM_FEAT_LRCPC2 = 0; |
1091 | SECURITY_READ_ONLY_LATE(int) gARM_FEAT_FCMA = 0; |
1092 | SECURITY_READ_ONLY_LATE(int) gARM_FEAT_JSCVT = 0; |
1093 | SECURITY_READ_ONLY_LATE(int) gARM_FEAT_PAuth = 0; |
1094 | SECURITY_READ_ONLY_LATE(int) gARM_FEAT_PAuth2 = 0; |
1095 | SECURITY_READ_ONLY_LATE(int) gARM_FEAT_FPAC = 0; |
1096 | SECURITY_READ_ONLY_LATE(int) gARM_FEAT_FPACCOMBINE = 0; |
1097 | SECURITY_READ_ONLY_LATE(int) gARM_FEAT_DPB = 0; |
1098 | SECURITY_READ_ONLY_LATE(int) gARM_FEAT_DPB2 = 0; |
1099 | SECURITY_READ_ONLY_LATE(int) gARM_FEAT_BF16 = 0; |
1100 | SECURITY_READ_ONLY_LATE(int) gARM_FEAT_I8MM = 0; |
1101 | |
1102 | /* Features from: ID_AA64ISAR2_EL1 */ |
1103 | SECURITY_READ_ONLY_LATE(int) gARM_FEAT_RPRES = 0; |
1104 | |
1105 | /* Features from: ID_AA64MMFR0_EL1 */ |
1106 | SECURITY_READ_ONLY_LATE(int) gARM_FEAT_ECV = 0; |
1107 | |
1108 | /* Features from: ID_AA64MMFR1_EL1 */ |
1109 | SECURITY_READ_ONLY_LATE(int) gARM_FEAT_AFP = 0; |
1110 | |
1111 | /* Features from: ID_AA64MMFR2_EL1 */ |
1112 | SECURITY_READ_ONLY_LATE(int) gARM_FEAT_LSE2 = 0; |
1113 | |
1114 | /* Features from: ID_AA64PFR0_EL1 */ |
1115 | SECURITY_READ_ONLY_LATE(int) gARM_FEAT_CSV2 = 0; |
1116 | SECURITY_READ_ONLY_LATE(int) gARM_FEAT_CSV3 = 0; |
1117 | SECURITY_READ_ONLY_LATE(int) gARM_FEAT_DIT = 0; |
1118 | SECURITY_READ_ONLY_LATE(int) gARM_AdvSIMD = 0; |
1119 | SECURITY_READ_ONLY_LATE(int) gARM_AdvSIMD_HPFPCvt = 0; |
1120 | SECURITY_READ_ONLY_LATE(int) gARM_FEAT_FP16 = 0; |
1121 | |
1122 | /* Features from: ID_AA64PFR1_EL1 */ |
1123 | SECURITY_READ_ONLY_LATE(int) gARM_FEAT_SSBS = 0; |
1124 | SECURITY_READ_ONLY_LATE(int) gARM_FEAT_BTI = 0; |
1125 | |
1126 | |
1127 | SECURITY_READ_ONLY_LATE(int) gUCNormalMem = 0; |
1128 | |
1129 | #if defined (__arm64__) |
1130 | SECURITY_READ_ONLY_LATE(int) arm64_flag = 1; |
1131 | #else /* end __arm64__*/ |
1132 | SECURITY_READ_ONLY_LATE(int) arm64_flag = 0; |
1133 | #endif |
1134 | |
1135 | /* Legacy Names ARM Optional Feature Sysctls */ |
1136 | SYSCTL_INT(_hw_optional, OID_AUTO, neon, CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED, &gARM_AdvSIMD, 0, "" ); |
1137 | SYSCTL_INT(_hw_optional, OID_AUTO, neon_hpfp, CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED, &gARM_AdvSIMD_HPFPCvt, 0, "" ); |
1138 | SYSCTL_INT(_hw_optional, OID_AUTO, neon_fp16, CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED, &gARM_FEAT_FP16, 0, "" ); |
1139 | SYSCTL_INT(_hw_optional, OID_AUTO, armv8_1_atomics, CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED, &gARM_FEAT_LSE, 0, "" ); |
1140 | SYSCTL_INT(_hw_optional, OID_AUTO, armv8_2_fhm, CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED, &gARM_FEAT_FHM, 0, "" ); |
1141 | SYSCTL_INT(_hw_optional, OID_AUTO, armv8_2_sha512, CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED, &gARM_FEAT_SHA512, 0, "" ); |
1142 | SYSCTL_INT(_hw_optional, OID_AUTO, armv8_2_sha3, CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED, &gARM_FEAT_SHA3, 0, "" ); |
1143 | SYSCTL_INT(_hw_optional, OID_AUTO, armv8_3_compnum, CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED, &gARM_FEAT_FCMA, 0, "" ); |
1144 | |
1145 | /* Misc ARM Optional Feature Sysctls */ |
1146 | SYSCTL_INT(_hw_optional, OID_AUTO, watchpoint, CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED, &watchpoint_flag, 0, "" ); |
1147 | SYSCTL_INT(_hw_optional, OID_AUTO, breakpoint, CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED, &breakpoint_flag, 0, "" ); |
1148 | |
1149 | /** |
1150 | * Enumerated syscalls for every ARM optional feature to be exported to |
1151 | * userspace. These are to be enumerated using the official feature name from |
1152 | * the ARM ARM. They are grouped below based on the MSR that will be used to populate the data. |
1153 | */ |
1154 | |
1155 | /* Features from: ID_AA64ISAR0_EL1 */ |
1156 | SYSCTL_INT(_hw_optional, OID_AUTO, armv8_crc32, CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED, &gARMv8Crc32, 0, "" ); |
1157 | SYSCTL_INT(_hw_optional_arm, OID_AUTO, FEAT_FlagM, CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED, &gARM_FEAT_FlagM, 0, "" ); |
1158 | SYSCTL_INT(_hw_optional_arm, OID_AUTO, FEAT_FlagM2, CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED, &gARM_FEAT_FlagM2, 0, "" ); |
1159 | SYSCTL_INT(_hw_optional_arm, OID_AUTO, FEAT_FHM, CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED, &gARM_FEAT_FHM, 0, "" ); |
1160 | SYSCTL_INT(_hw_optional_arm, OID_AUTO, FEAT_DotProd, CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED, &gARM_FEAT_DotProd, 0, "" ); |
1161 | SYSCTL_INT(_hw_optional_arm, OID_AUTO, FEAT_SHA3, CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED, &gARM_FEAT_SHA3, 0, "" ); |
1162 | SYSCTL_INT(_hw_optional_arm, OID_AUTO, FEAT_RDM, CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED, &gARM_FEAT_RDM, 0, "" ); |
1163 | SYSCTL_INT(_hw_optional_arm, OID_AUTO, FEAT_LSE, CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED, &gARM_FEAT_LSE, 0, "" ); |
1164 | SYSCTL_INT(_hw_optional_arm, OID_AUTO, FEAT_SHA256, CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED, &gARM_FEAT_SHA256, 0, "" ); |
1165 | SYSCTL_INT(_hw_optional_arm, OID_AUTO, FEAT_SHA512, CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED, &gARM_FEAT_SHA512, 0, "" ); |
1166 | SYSCTL_INT(_hw_optional_arm, OID_AUTO, FEAT_SHA1, CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED, &gARM_FEAT_SHA1, 0, "" ); |
1167 | SYSCTL_INT(_hw_optional_arm, OID_AUTO, FEAT_AES, CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED, &gARM_FEAT_AES, 0, "" ); |
1168 | SYSCTL_INT(_hw_optional_arm, OID_AUTO, FEAT_PMULL, CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED, &gARM_FEAT_PMULL, 0, "" ); |
1169 | |
1170 | /* Features from: ID_AA64ISAR1_EL1 */ |
1171 | SYSCTL_INT(_hw_optional, OID_AUTO, armv8_gpi, CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED, &gARMv8Gpi, 0, "" ); |
1172 | SYSCTL_INT(_hw_optional_arm, OID_AUTO, FEAT_SPECRES, CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED, &gARM_FEAT_SPECRES, 0, "" ); |
1173 | SYSCTL_INT(_hw_optional_arm, OID_AUTO, FEAT_SB, CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED, &gARM_FEAT_SB, 0, "" ); |
1174 | SYSCTL_INT(_hw_optional_arm, OID_AUTO, FEAT_FRINTTS, CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED, &gARM_FEAT_FRINTTS, 0, "" ); |
1175 | SYSCTL_INT(_hw_optional_arm, OID_AUTO, FEAT_LRCPC, CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED, &gARM_FEAT_LRCPC, 0, "" ); |
1176 | SYSCTL_INT(_hw_optional_arm, OID_AUTO, FEAT_LRCPC2, CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED, &gARM_FEAT_LRCPC2, 0, "" ); |
1177 | SYSCTL_INT(_hw_optional_arm, OID_AUTO, FEAT_FCMA, CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED, &gARM_FEAT_FCMA, 0, "" ); |
1178 | SYSCTL_INT(_hw_optional_arm, OID_AUTO, FEAT_JSCVT, CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED, &gARM_FEAT_JSCVT, 0, "" ); |
1179 | SYSCTL_INT(_hw_optional_arm, OID_AUTO, FEAT_PAuth, CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED, &gARM_FEAT_PAuth, 0, "" ); |
1180 | SYSCTL_INT(_hw_optional_arm, OID_AUTO, FEAT_PAuth2, CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED, &gARM_FEAT_PAuth2, 0, "" ); |
1181 | SYSCTL_INT(_hw_optional_arm, OID_AUTO, FEAT_FPAC, CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED, &gARM_FEAT_FPAC, 0, "" ); |
1182 | SYSCTL_INT(_hw_optional_arm, OID_AUTO, FEAT_DPB, CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED, &gARM_FEAT_DPB, 0, "" ); |
1183 | SYSCTL_INT(_hw_optional_arm, OID_AUTO, FEAT_DPB2, CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED, &gARM_FEAT_DPB2, 0, "" ); |
1184 | SYSCTL_INT(_hw_optional_arm, OID_AUTO, FEAT_BF16, CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED, &gARM_FEAT_BF16, 0, "" ); |
1185 | SYSCTL_INT(_hw_optional_arm, OID_AUTO, FEAT_I8MM, CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED, &gARM_FEAT_I8MM, 0, "" ); |
1186 | |
1187 | /* Features from: ID_AA64ISAR2_EL1 */ |
1188 | SYSCTL_INT(_hw_optional_arm, OID_AUTO, FEAT_RPRES, CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED, &gARM_FEAT_RPRES, 0, "" ); |
1189 | |
1190 | /* Features from: ID_AA64MMFR0_EL1 */ |
1191 | SYSCTL_INT(_hw_optional_arm, OID_AUTO, FEAT_ECV, CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED, &gARM_FEAT_ECV, 0, "" ); |
1192 | |
1193 | /* Features from: ID_AA64MMFR1_EL1 */ |
1194 | SYSCTL_INT(_hw_optional_arm, OID_AUTO, FEAT_AFP, CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED, &gARM_FEAT_AFP, 0, "" ); |
1195 | |
1196 | /* Features from: ID_AA64MMFR2_EL1 */ |
1197 | SYSCTL_INT(_hw_optional_arm, OID_AUTO, FEAT_LSE2, CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED, &gARM_FEAT_LSE2, 0, "" ); |
1198 | |
1199 | /* Features from: ID_AA64PFR0_EL1 */ |
1200 | SYSCTL_INT(_hw_optional, OID_AUTO, AdvSIMD, CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED, &gARM_AdvSIMD, 0, "" ); |
1201 | SYSCTL_INT(_hw_optional, OID_AUTO, AdvSIMD_HPFPCvt, CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED, &gARM_AdvSIMD_HPFPCvt, 0, "" ); |
1202 | SYSCTL_INT(_hw_optional_arm, OID_AUTO, FEAT_CSV2, CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED, &gARM_FEAT_CSV2, 0, "" ); |
1203 | SYSCTL_INT(_hw_optional_arm, OID_AUTO, FEAT_CSV3, CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED, &gARM_FEAT_CSV3, 0, "" ); |
1204 | SYSCTL_INT(_hw_optional_arm, OID_AUTO, FEAT_DIT, CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED, &gARM_FEAT_DIT, 0, "" ); |
1205 | SYSCTL_INT(_hw_optional_arm, OID_AUTO, FEAT_FP16, CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED, &gARM_FEAT_FP16, 0, "" ); |
1206 | |
1207 | /* Features from: FPCR */ |
1208 | SECURITY_READ_ONLY_LATE(int) gARM_FP_SyncExceptions = 0; |
1209 | |
1210 | /* Features from: ID_AA64PFR1_EL1 */ |
1211 | SYSCTL_INT(_hw_optional_arm, OID_AUTO, FEAT_SSBS, CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED, &gARM_FEAT_SSBS, 0, "" ); |
1212 | SYSCTL_INT(_hw_optional_arm, OID_AUTO, FEAT_BTI, CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED, &gARM_FEAT_BTI, 0, "" ); |
1213 | |
1214 | |
1215 | /* Features from FPCR. */ |
1216 | SYSCTL_INT(_hw_optional_arm, OID_AUTO, FP_SyncExceptions, CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED, &gARM_FP_SyncExceptions, 0, "" ); |
1217 | |
1218 | SYSCTL_INT(_hw_optional, OID_AUTO, ucnormal_mem, CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED, &gUCNormalMem, 0, "" ); |
1219 | |
1220 | #if DEBUG || DEVELOPMENT |
1221 | #if __ARM_KERNEL_PROTECT__ |
1222 | static SECURITY_READ_ONLY_LATE(int) arm_kernel_protect = 1; |
1223 | #else |
1224 | static SECURITY_READ_ONLY_LATE(int) arm_kernel_protect = 0; |
1225 | #endif |
1226 | SYSCTL_INT(_hw_optional, OID_AUTO, arm_kernel_protect, CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED, &arm_kernel_protect, 0, "" ); |
1227 | #endif |
1228 | |
1229 | #if DEBUG || DEVELOPMENT |
1230 | static int ic_inval_filters = 0; |
1231 | SYSCTL_INT(_hw_optional, OID_AUTO, ic_inval_filters, CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED, &ic_inval_filters, 0, "" ); |
1232 | #endif |
1233 | |
1234 | #if DEBUG || DEVELOPMENT |
1235 | static SECURITY_READ_ONLY_LATE(int) wkdm_popcount = 0; |
1236 | SYSCTL_INT(_hw_optional, OID_AUTO, wkdm_popcount, CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED, &wkdm_popcount, 0, "" ); |
1237 | #endif |
1238 | |
1239 | #if DEBUG || DEVELOPMENT |
1240 | #if __has_feature(ptrauth_calls) |
1241 | static SECURITY_READ_ONLY_LATE(int) ptrauth = 1; |
1242 | #else |
1243 | static SECURITY_READ_ONLY_LATE(int) ptrauth = 0; |
1244 | #endif |
1245 | SYSCTL_INT(_hw_optional, OID_AUTO, ptrauth, CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED, &ptrauth, 0, "" ); |
1246 | #endif |
1247 | |
1248 | /* |
1249 | * Without this little ifdef dance, the preprocessor replaces "arm64" with "1", |
1250 | * leaving us with a less-than-helpful sysctl.hwoptional.1. |
1251 | */ |
1252 | #ifdef arm64 |
1253 | #undef arm64 |
1254 | SYSCTL_INT(_hw_optional, OID_AUTO, arm64, CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED, &arm64_flag, 0, "" ); |
1255 | #define arm64 1 |
1256 | #else |
1257 | SYSCTL_INT(_hw_optional, OID_AUTO, arm64, CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED, &arm64_flag, 0, "" ); |
1258 | #endif |
1259 | #endif /* ! __arm64__ */ |
1260 | |
1261 | |
1262 | #if defined(__arm64__) && defined(CONFIG_XNUPOST) |
1263 | /** |
1264 | * Test whether the new values for a few hw.optional sysctls matches the legacy |
1265 | * way of obtaining that information. |
1266 | * |
1267 | * Specifically, hw.optional.neon_fp16 has been used to indicate both FEAT_FP16 |
1268 | * and FEAT_FHM, as we are now grabbing the information directly from the ISA |
1269 | * status registers instead of from the arm_mvfp_info, we need to check that |
1270 | * this new source won't break any existing usecases of the sysctl and assert |
1271 | * that hw.optional.neon_fp16 will return the same value as it used to for all |
1272 | * devices. |
1273 | */ |
1274 | kern_return_t |
1275 | arm_cpu_capabilities_legacy_test(void) |
1276 | { |
1277 | T_SETUPBEGIN; |
1278 | arm_mvfp_info_t *mvfp_info = arm_mvfp_info(); |
1279 | T_ASSERT_NOTNULL(mvfp_info, "arm_mvfp_info returned null pointer." ); |
1280 | T_SETUPEND; |
1281 | |
1282 | |
1283 | T_EXPECT_EQ_INT(mvfp_info->neon, gARM_AdvSIMD, "neon value should match legacy" ); |
1284 | T_EXPECT_EQ_INT(mvfp_info->neon_hpfp, gARM_AdvSIMD_HPFPCvt, "neon hpfp cvt value should match legacy" ); |
1285 | T_EXPECT_EQ_INT(mvfp_info->neon_fp16, gARM_FEAT_FP16, "neon fp16 value should match legacy" ); |
1286 | |
1287 | T_LOG("Completed arm cpu capabalities legacy compliance test." ); |
1288 | return KERN_SUCCESS; |
1289 | } |
1290 | #endif /* defined(__arm64__) && defined(CONFIG_XNUPOST) */ |
1291 | |
1292 | /****************************************************************************** |
1293 | * Generic MIB initialisation. |
1294 | * |
1295 | * This is a hack, and should be replaced with SYSINITs |
1296 | * at some point. |
1297 | */ |
1298 | void |
1299 | sysctl_mib_init(void) |
1300 | { |
1301 | #if defined(__i386__) || defined (__x86_64__) |
1302 | cpu64bit = (_get_cpu_capabilities() & k64Bit) == k64Bit; |
1303 | #elif defined (__arm64__) |
1304 | cpu64bit = (cpu_type() & CPU_ARCH_ABI64) == CPU_ARCH_ABI64; |
1305 | #else |
1306 | #error Unsupported arch |
1307 | #endif |
1308 | #if defined (__i386__) || defined (__x86_64__) |
1309 | /* hw.cacheconfig */ |
1310 | cacheconfig[0] = ml_cpu_cache_sharing(0, CLUSTER_TYPE_SMP, true); |
1311 | cacheconfig[1] = ml_cpu_cache_sharing(1, CLUSTER_TYPE_SMP, true); |
1312 | cacheconfig[2] = ml_cpu_cache_sharing(2, CLUSTER_TYPE_SMP, true); |
1313 | cacheconfig[3] = ml_cpu_cache_sharing(3, CLUSTER_TYPE_SMP, true); |
1314 | cacheconfig[4] = 0; |
1315 | |
1316 | /* hw.packages */ |
1317 | packages = (int)(roundup(ml_cpu_cache_sharing(0, CLUSTER_TYPE_SMP, true), cpuid_info()->thread_count) |
1318 | / cpuid_info()->thread_count); |
1319 | |
1320 | #elif defined(__arm64__) /* end __i386 */ |
1321 | watchpoint_flag = arm_debug_info()->num_watchpoint_pairs; |
1322 | breakpoint_flag = arm_debug_info()->num_breakpoint_pairs; |
1323 | |
1324 | cluster_type_t min_perflevel_cluster_type = cpu_type_for_perflevel(perflevel: __builtin_popcount(ml_get_cpu_types()) - 1); |
1325 | |
1326 | cacheconfig[0] = ml_wait_max_cpus(); |
1327 | cacheconfig[1] = ml_cpu_cache_sharing(level: 1, cluster_type: min_perflevel_cluster_type, true); |
1328 | cacheconfig[2] = ml_cpu_cache_sharing(level: 2, cluster_type: min_perflevel_cluster_type, true); |
1329 | cacheconfig[3] = 0; |
1330 | cacheconfig[4] = 0; |
1331 | cacheconfig[5] = 0; |
1332 | cacheconfig[6] = 0; |
1333 | |
1334 | packages = 1; |
1335 | #else |
1336 | #error unknown architecture |
1337 | #endif /* !__i386__ && !__x86_64 && !__arm64__ */ |
1338 | } |
1339 | |
1340 | __startup_func |
1341 | static void |
1342 | sysctl_mib_startup(void) |
1343 | { |
1344 | cputhreadtype = cpu_threadtype(); |
1345 | |
1346 | /* |
1347 | * Populate the optional portion of the hw.* MIB. |
1348 | * |
1349 | * XXX This could be broken out into parts of the code |
1350 | * that actually directly relate to the functions in |
1351 | * question. |
1352 | */ |
1353 | |
1354 | if (cputhreadtype != CPU_THREADTYPE_NONE) { |
1355 | sysctl_register_oid_early(oidp: &sysctl__hw_cputhreadtype); |
1356 | } |
1357 | |
1358 | } |
1359 | STARTUP(SYSCTL, STARTUP_RANK_MIDDLE, sysctl_mib_startup); |
1360 | |