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 <mach/host_info.h> 101#include <kern/pms.h> 102 103extern vm_map_t bsd_pageable_map; 104 105#include <sys/mount_internal.h> 106#include <sys/kdebug.h> 107 108#include <IOKit/IOPlatformExpert.h> 109#include <pexpert/pexpert.h> 110 111#include <machine/machine_routines.h> 112#include <machine/cpu_capabilities.h> 113 114#include <mach/mach_host.h> /* for host_info() */ 115 116#if defined(__i386__) || defined(__x86_64__) 117#include <i386/cpuid.h> /* for cpuid_info() */ 118#endif 119 120#if defined(__arm__) 121#include <arm/cpuid.h> 122#endif 123 124#ifndef MAX 125#define MAX(a,b) (a >= b ? a : b) 126#endif 127 128/* XXX This should be in a BSD accessible Mach header, but isn't. */ 129extern unsigned int vm_page_wire_count; 130 131static int cputype, cpusubtype, cputhreadtype, cpufamily, cpu64bit; 132static uint64_t cacheconfig[10], cachesize[10]; 133static int packages; 134 135SYSCTL_NODE(, 0, sysctl, CTLFLAG_RW|CTLFLAG_LOCKED, 0, 136 "Sysctl internal magic"); 137SYSCTL_NODE(, CTL_KERN, kern, CTLFLAG_RW|CTLFLAG_LOCKED, 0, 138 "High kernel, proc, limits &c"); 139SYSCTL_NODE(, CTL_VM, vm, CTLFLAG_RW|CTLFLAG_LOCKED, 0, 140 "Virtual memory"); 141SYSCTL_NODE(, CTL_VFS, vfs, CTLFLAG_RW|CTLFLAG_LOCKED, 0, 142 "File system"); 143SYSCTL_NODE(, CTL_NET, net, CTLFLAG_RW|CTLFLAG_LOCKED, 0, 144 "Network, (see socket.h)"); 145SYSCTL_NODE(, CTL_DEBUG, debug, CTLFLAG_RW|CTLFLAG_LOCKED, 0, 146 "Debugging"); 147SYSCTL_NODE(, CTL_HW, hw, CTLFLAG_RW|CTLFLAG_LOCKED, 0, 148 "hardware"); 149SYSCTL_NODE(, CTL_MACHDEP, machdep, CTLFLAG_RW|CTLFLAG_LOCKED, 0, 150 "machine dependent"); 151SYSCTL_NODE(, CTL_USER, user, CTLFLAG_RW|CTLFLAG_LOCKED, 0, 152 "user-level"); 153 154#define SYSCTL_RETURN(r, x) SYSCTL_OUT(r, &x, sizeof(x)) 155 156/****************************************************************************** 157 * hw.* MIB 158 */ 159 160#define CTLHW_RETQUAD (1 << 31) 161#define CTLHW_LOCAL (1 << 30) 162 163#define HW_LOCAL_CPUTHREADTYPE (1 | CTLHW_LOCAL) 164#define HW_LOCAL_PHYSICALCPU (2 | CTLHW_LOCAL) 165#define HW_LOCAL_PHYSICALCPUMAX (3 | CTLHW_LOCAL) 166#define HW_LOCAL_LOGICALCPU (4 | CTLHW_LOCAL) 167#define HW_LOCAL_LOGICALCPUMAX (5 | CTLHW_LOCAL) 168 169 170/* 171 * Supporting some variables requires us to do "real" work. We 172 * gather some of that here. 173 */ 174static int 175sysctl_hw_generic(__unused struct sysctl_oid *oidp, __unused void *arg1, 176 int arg2, struct sysctl_req *req) 177{ 178 char dummy[65]; 179 int epochTemp; 180 ml_cpu_info_t cpu_info; 181 int val, doquad; 182 long long qval; 183 host_basic_info_data_t hinfo; 184 kern_return_t kret; 185 mach_msg_type_number_t count = HOST_BASIC_INFO_COUNT; 186 187 /* 188 * Test and mask off the 'return quad' flag. 189 * Note that only some things here support it. 190 */ 191 doquad = arg2 & CTLHW_RETQUAD; 192 arg2 &= ~CTLHW_RETQUAD; 193 194 ml_cpu_get_info(&cpu_info); 195 196#define BSD_HOST 1 197 kret = host_info((host_t)BSD_HOST, HOST_BASIC_INFO, (host_info_t)&hinfo, &count); 198 199 /* 200 * Handle various OIDs. 201 * 202 * OIDs that can return int or quad set val and qval and then break. 203 * Errors and int-only values return inline. 204 */ 205 switch (arg2) { 206 case HW_NCPU: 207 if (kret == KERN_SUCCESS) { 208 return(SYSCTL_RETURN(req, hinfo.max_cpus)); 209 } else { 210 return(EINVAL); 211 } 212 case HW_AVAILCPU: 213 if (kret == KERN_SUCCESS) { 214 return(SYSCTL_RETURN(req, hinfo.avail_cpus)); 215 } else { 216 return(EINVAL); 217 } 218 case HW_LOCAL_PHYSICALCPU: 219 if (kret == KERN_SUCCESS) { 220 return(SYSCTL_RETURN(req, hinfo.physical_cpu)); 221 } else { 222 return(EINVAL); 223 } 224 case HW_LOCAL_PHYSICALCPUMAX: 225 if (kret == KERN_SUCCESS) { 226 return(SYSCTL_RETURN(req, hinfo.physical_cpu_max)); 227 } else { 228 return(EINVAL); 229 } 230 case HW_LOCAL_LOGICALCPU: 231 if (kret == KERN_SUCCESS) { 232 return(SYSCTL_RETURN(req, hinfo.logical_cpu)); 233 } else { 234 return(EINVAL); 235 } 236 case HW_LOCAL_LOGICALCPUMAX: 237 if (kret == KERN_SUCCESS) { 238 return(SYSCTL_RETURN(req, hinfo.logical_cpu_max)); 239 } else { 240 return(EINVAL); 241 } 242 case HW_CACHELINE: 243 val = cpu_info.cache_line_size; 244 qval = (long long)val; 245 break; 246 case HW_L1ICACHESIZE: 247 val = cpu_info.l1_icache_size; 248 qval = (long long)val; 249 break; 250 case HW_L1DCACHESIZE: 251 val = cpu_info.l1_dcache_size; 252 qval = (long long)val; 253 break; 254 case HW_L2CACHESIZE: 255 if (cpu_info.l2_cache_size == 0xFFFFFFFF) 256 return(EINVAL); 257 val = cpu_info.l2_cache_size; 258 qval = (long long)val; 259 break; 260 case HW_L3CACHESIZE: 261 if (cpu_info.l3_cache_size == 0xFFFFFFFF) 262 return(EINVAL); 263 val = cpu_info.l3_cache_size; 264 qval = (long long)val; 265 break; 266 267 /* 268 * Deprecated variables. We still support these for 269 * backwards compatibility purposes only. 270 */ 271 case HW_MACHINE: 272 bzero(dummy, sizeof(dummy)); 273 if(!PEGetMachineName(dummy,64)) 274 return(EINVAL); 275 dummy[64] = 0; 276 return(SYSCTL_OUT(req, dummy, strlen(dummy) + 1)); 277 case HW_MODEL: 278 bzero(dummy, sizeof(dummy)); 279 if(!PEGetModelName(dummy,64)) 280 return(EINVAL); 281 dummy[64] = 0; 282 return(SYSCTL_OUT(req, dummy, strlen(dummy) + 1)); 283 case HW_USERMEM: 284 { 285 int usermem = mem_size - vm_page_wire_count * page_size; 286 287 return(SYSCTL_RETURN(req, usermem)); 288 } 289 case HW_EPOCH: 290 epochTemp = PEGetPlatformEpoch(); 291 if (epochTemp == -1) 292 return(EINVAL); 293 return(SYSCTL_RETURN(req, epochTemp)); 294 case HW_VECTORUNIT: { 295 int vector = cpu_info.vector_unit == 0? 0 : 1; 296 return(SYSCTL_RETURN(req, vector)); 297 } 298 case HW_L2SETTINGS: 299 if (cpu_info.l2_cache_size == 0xFFFFFFFF) 300 return(EINVAL); 301 return(SYSCTL_RETURN(req, cpu_info.l2_settings)); 302 case HW_L3SETTINGS: 303 if (cpu_info.l3_cache_size == 0xFFFFFFFF) 304 return(EINVAL); 305 return(SYSCTL_RETURN(req, cpu_info.l3_settings)); 306 default: 307 return(ENOTSUP); 308 } 309 /* 310 * Callers may come to us with either int or quad buffers. 311 */ 312 if (doquad) { 313 return(SYSCTL_RETURN(req, qval)); 314 } 315 return(SYSCTL_RETURN(req, val)); 316} 317 318/* hw.pagesize and hw.tbfrequency are expected as 64 bit values */ 319static int 320sysctl_pagesize 321(__unused struct sysctl_oid *oidp, __unused void *arg1, __unused int arg2, struct sysctl_req *req) 322{ 323 long long l = page_size; 324 return sysctl_io_number(req, l, sizeof(l), NULL, NULL); 325} 326 327static int 328sysctl_tbfrequency 329(__unused struct sysctl_oid *oidp, __unused void *arg1, __unused int arg2, struct sysctl_req *req) 330{ 331 long long l = gPEClockFrequencyInfo.timebase_frequency_hz; 332 return sysctl_io_number(req, l, sizeof(l), NULL, NULL); 333} 334 335/* 336 * hw.* MIB variables. 337 */ 338SYSCTL_PROC (_hw, HW_NCPU, ncpu, CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED, 0, HW_NCPU, sysctl_hw_generic, "I", ""); 339SYSCTL_PROC (_hw, HW_AVAILCPU, activecpu, CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED, 0, HW_AVAILCPU, sysctl_hw_generic, "I", ""); 340SYSCTL_PROC (_hw, OID_AUTO, physicalcpu, CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED, 0, HW_LOCAL_PHYSICALCPU, sysctl_hw_generic, "I", ""); 341SYSCTL_PROC (_hw, OID_AUTO, physicalcpu_max, CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED, 0, HW_LOCAL_PHYSICALCPUMAX, sysctl_hw_generic, "I", ""); 342SYSCTL_PROC (_hw, OID_AUTO, logicalcpu, CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED, 0, HW_LOCAL_LOGICALCPU, sysctl_hw_generic, "I", ""); 343SYSCTL_PROC (_hw, OID_AUTO, logicalcpu_max, CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED, 0, HW_LOCAL_LOGICALCPUMAX, sysctl_hw_generic, "I", ""); 344SYSCTL_INT (_hw, HW_BYTEORDER, byteorder, CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED, (int *)NULL, BYTE_ORDER, ""); 345SYSCTL_INT (_hw, OID_AUTO, cputype, CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED, &cputype, 0, ""); 346SYSCTL_INT (_hw, OID_AUTO, cpusubtype, CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED, &cpusubtype, 0, ""); 347SYSCTL_INT (_hw, OID_AUTO, cpu64bit_capable, CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED, &cpu64bit, 0, ""); 348SYSCTL_INT (_hw, OID_AUTO, cpufamily, CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED, &cpufamily, 0, ""); 349SYSCTL_OPAQUE (_hw, OID_AUTO, cacheconfig, CTLFLAG_RD | CTLFLAG_LOCKED, &cacheconfig, sizeof(cacheconfig), "Q", ""); 350SYSCTL_OPAQUE (_hw, OID_AUTO, cachesize, CTLFLAG_RD | CTLFLAG_LOCKED, &cachesize, sizeof(cachesize), "Q", ""); 351SYSCTL_PROC (_hw, OID_AUTO, pagesize, CTLTYPE_QUAD | CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED, 0, 0, sysctl_pagesize, "Q", ""); 352SYSCTL_QUAD (_hw, OID_AUTO, busfrequency, CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED, &gPEClockFrequencyInfo.bus_frequency_hz, ""); 353SYSCTL_QUAD (_hw, OID_AUTO, busfrequency_min, CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED, &gPEClockFrequencyInfo.bus_frequency_min_hz, ""); 354SYSCTL_QUAD (_hw, OID_AUTO, busfrequency_max, CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED, &gPEClockFrequencyInfo.bus_frequency_max_hz, ""); 355SYSCTL_QUAD (_hw, OID_AUTO, cpufrequency, CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED, &gPEClockFrequencyInfo.cpu_frequency_hz, ""); 356SYSCTL_QUAD (_hw, OID_AUTO, cpufrequency_min, CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED, &gPEClockFrequencyInfo.cpu_frequency_min_hz, ""); 357SYSCTL_QUAD (_hw, OID_AUTO, cpufrequency_max, CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED, &gPEClockFrequencyInfo.cpu_frequency_max_hz, ""); 358SYSCTL_PROC (_hw, OID_AUTO, cachelinesize, CTLTYPE_QUAD | CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED, 0, HW_CACHELINE | CTLHW_RETQUAD, sysctl_hw_generic, "Q", ""); 359SYSCTL_PROC (_hw, OID_AUTO, l1icachesize, CTLTYPE_QUAD | CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED, 0, HW_L1ICACHESIZE | CTLHW_RETQUAD, sysctl_hw_generic, "Q", ""); 360SYSCTL_PROC (_hw, OID_AUTO, l1dcachesize, CTLTYPE_QUAD | CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED, 0, HW_L1DCACHESIZE | CTLHW_RETQUAD, sysctl_hw_generic, "Q", ""); 361SYSCTL_PROC (_hw, OID_AUTO, l2cachesize, CTLTYPE_QUAD | CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED, 0, HW_L2CACHESIZE | CTLHW_RETQUAD, sysctl_hw_generic, "Q", ""); 362SYSCTL_PROC (_hw, OID_AUTO, l3cachesize, CTLTYPE_QUAD | CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED, 0, HW_L3CACHESIZE | CTLHW_RETQUAD, sysctl_hw_generic, "Q", ""); 363SYSCTL_PROC(_hw, OID_AUTO, tbfrequency, CTLTYPE_QUAD | CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED, 0, 0, sysctl_tbfrequency, "Q", ""); 364SYSCTL_QUAD (_hw, HW_MEMSIZE, memsize, CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED, &max_mem, ""); 365SYSCTL_INT (_hw, OID_AUTO, packages, CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED, &packages, 0, ""); 366 367/* 368 * Optional features can register nodes below hw.optional. 369 * 370 * If the feature is not present, the node should either not be registered, 371 * or it should return -1. If the feature is present, the node should return 372 * 0. If the feature is present and its use is advised, the node should 373 * return 1. 374 */ 375SYSCTL_NODE(_hw, OID_AUTO, optional, CTLFLAG_RW|CTLFLAG_LOCKED, NULL, "optional features"); 376 377SYSCTL_INT(_hw_optional, OID_AUTO, floatingpoint, CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED, (int *)NULL, 1, ""); /* always set */ 378 379/* 380 * Deprecated variables. These are supported for backwards compatibility 381 * purposes only. The MASKED flag requests that the variables not be 382 * printed by sysctl(8) and similar utilities. 383 * 384 * The variables named *_compat here are int-sized versions of variables 385 * that are now exported as quads. The int-sized versions are normally 386 * looked up only by number, wheras the quad-sized versions should be 387 * looked up by name. 388 * 389 * The *_compat nodes are *NOT* visible within the kernel. 390 */ 391SYSCTL_COMPAT_INT (_hw, HW_PAGESIZE, pagesize_compat, CTLFLAG_RD | CTLFLAG_MASKED | CTLFLAG_LOCKED, &page_size, 0, ""); 392SYSCTL_COMPAT_INT (_hw, HW_BUS_FREQ, busfrequency_compat, CTLFLAG_RD | CTLFLAG_MASKED | CTLFLAG_LOCKED, &gPEClockFrequencyInfo.bus_clock_rate_hz, 0, ""); 393SYSCTL_COMPAT_INT (_hw, HW_CPU_FREQ, cpufrequency_compat, CTLFLAG_RD | CTLFLAG_MASKED | CTLFLAG_LOCKED, &gPEClockFrequencyInfo.cpu_clock_rate_hz, 0, ""); 394SYSCTL_PROC(_hw, HW_CACHELINE, cachelinesize_compat, CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_MASKED | CTLFLAG_LOCKED, 0, HW_CACHELINE, sysctl_hw_generic, "I", ""); 395SYSCTL_PROC(_hw, HW_L1ICACHESIZE, l1icachesize_compat, CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_MASKED | CTLFLAG_LOCKED, 0, HW_L1ICACHESIZE, sysctl_hw_generic, "I", ""); 396SYSCTL_PROC(_hw, HW_L1DCACHESIZE, l1dcachesize_compat, CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_MASKED | CTLFLAG_LOCKED, 0, HW_L1DCACHESIZE, sysctl_hw_generic, "I", ""); 397SYSCTL_PROC(_hw, HW_L2CACHESIZE, l2cachesize_compat, CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_MASKED | CTLFLAG_LOCKED, 0, HW_L2CACHESIZE, sysctl_hw_generic, "I", ""); 398SYSCTL_PROC(_hw, HW_L3CACHESIZE, l3cachesize_compat, CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_MASKED | CTLFLAG_LOCKED, 0, HW_L3CACHESIZE, sysctl_hw_generic, "I", ""); 399SYSCTL_COMPAT_INT (_hw, HW_TB_FREQ, tbfrequency_compat, CTLFLAG_RD | CTLFLAG_MASKED | CTLFLAG_LOCKED, &gPEClockFrequencyInfo.timebase_frequency_hz, 0, ""); 400SYSCTL_PROC(_hw, HW_MACHINE, machine, CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_MASKED | CTLFLAG_LOCKED, 0, HW_MACHINE, sysctl_hw_generic, "A", ""); 401SYSCTL_PROC(_hw, HW_MODEL, model, CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_MASKED | CTLFLAG_LOCKED, 0, HW_MODEL, sysctl_hw_generic, "A", ""); 402SYSCTL_COMPAT_UINT(_hw, HW_PHYSMEM, physmem, CTLFLAG_RD | CTLFLAG_MASKED | CTLFLAG_LOCKED, &mem_size, 0, ""); 403SYSCTL_PROC(_hw, HW_USERMEM, usermem, CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_MASKED | CTLFLAG_LOCKED, 0, HW_USERMEM, sysctl_hw_generic, "I", ""); 404SYSCTL_PROC(_hw, HW_EPOCH, epoch, CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_MASKED | CTLFLAG_LOCKED, 0, HW_EPOCH, sysctl_hw_generic, "I", ""); 405SYSCTL_PROC(_hw, HW_VECTORUNIT, vectorunit, CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_MASKED | CTLFLAG_LOCKED, 0, HW_VECTORUNIT, sysctl_hw_generic, "I", ""); 406SYSCTL_PROC(_hw, HW_L2SETTINGS, l2settings, CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_MASKED | CTLFLAG_LOCKED, 0, HW_L2SETTINGS, sysctl_hw_generic, "I", ""); 407SYSCTL_PROC(_hw, HW_L3SETTINGS, l3settings, CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_MASKED | CTLFLAG_LOCKED, 0, HW_L3SETTINGS, sysctl_hw_generic, "I", ""); 408SYSCTL_INT (_hw, OID_AUTO, cputhreadtype, CTLFLAG_RD | CTLFLAG_NOAUTO | CTLFLAG_KERN | CTLFLAG_LOCKED, &cputhreadtype, 0, ""); 409 410#if defined(__i386__) || defined(__x86_64__) 411int mmx_flag = -1; 412int sse_flag = -1; 413int sse2_flag = -1; 414int sse3_flag = -1; 415int sse4_1_flag = -1; 416int sse4_2_flag = -1; 417int x86_64_flag = -1; 418int supplementalsse3_flag = -1; 419int aes_flag = -1; 420int avx1_0_flag = -1; 421int rdrand_flag = -1; 422int f16c_flag = -1; 423int enfstrg_flag = -1; 424 425SYSCTL_INT(_hw_optional, OID_AUTO, mmx, CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED, &mmx_flag, 0, ""); 426SYSCTL_INT(_hw_optional, OID_AUTO, sse, CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED, &sse_flag, 0, ""); 427SYSCTL_INT(_hw_optional, OID_AUTO, sse2, CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED, &sse2_flag, 0, ""); 428SYSCTL_INT(_hw_optional, OID_AUTO, sse3, CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED, &sse3_flag, 0, ""); 429SYSCTL_INT(_hw_optional, OID_AUTO, supplementalsse3, CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED, &supplementalsse3_flag, 0, ""); 430SYSCTL_INT(_hw_optional, OID_AUTO, sse4_1, CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED, &sse4_1_flag, 0, ""); 431SYSCTL_INT(_hw_optional, OID_AUTO, sse4_2, CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED, &sse4_2_flag, 0, ""); 432/* "x86_64" is actually a preprocessor symbol on the x86_64 kernel, so we have to hack this */ 433#undef x86_64 434SYSCTL_INT(_hw_optional, OID_AUTO, x86_64, CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED, &x86_64_flag, 0, ""); 435SYSCTL_INT(_hw_optional, OID_AUTO, aes, CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED, &aes_flag, 0, ""); 436SYSCTL_INT(_hw_optional, OID_AUTO, avx1_0, CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED, &avx1_0_flag, 0, ""); 437SYSCTL_INT(_hw_optional, OID_AUTO, rdrand, CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED, &rdrand_flag, 0, ""); 438SYSCTL_INT(_hw_optional, OID_AUTO, f16c, CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED, &f16c_flag, 0, ""); 439SYSCTL_INT(_hw_optional, OID_AUTO, enfstrg, CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED, &enfstrg_flag, 0, ""); 440#elif defined (__arm__) 441int arm_isa_flag = -1; 442int arm_thumb_flag = -1; 443int arm_thumb2_flag = -1; 444int arm_jazelle_flag = -1; 445int arm_thumbee_flag = -1; 446int arm_armv4_flag = -1; 447int arm_security_flag = -1; 448int arm_armvm_flag = -1; 449 450SYSCTL_INT(_hw_optional, OID_AUTO, arm_isa, CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED, &arm_isa_flag, 0, ""); 451SYSCTL_INT(_hw_optional, OID_AUTO, thumb, CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED, &arm_thumb_flag, 0, ""); 452SYSCTL_INT(_hw_optional, OID_AUTO, thumb2, CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED, &arm_thumb2_flag, 0, ""); 453SYSCTL_INT(_hw_optional, OID_AUTO, jazelle, CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED, &arm_jazelle_flag, 0, ""); 454SYSCTL_INT(_hw_optional, OID_AUTO, thumbee, CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED, &arm_thumbee_flag, 0, ""); 455SYSCTL_INT(_hw_optional, OID_AUTO, armv4, CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED, &arm_armv4_flag, 0, ""); 456SYSCTL_INT(_hw_optional, OID_AUTO, security, CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED, &arm_security_flag, 0, ""); 457SYSCTL_INT(_hw_optional, OID_AUTO, microcontroller, CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED, &arm_armvm_flag, 0, ""); 458#else 459#error Unsupported arch 460#endif /* !__i386__ && !__x86_64 && !__arm__ */ 461 462/* 463 * Debugging interface to the CPU power management code. 464 * 465 * Note: Does not need locks because it disables interrupts over 466 * the call. 467 */ 468static int 469pmsSysctl(__unused struct sysctl_oid *oidp, __unused void *arg1, 470 __unused int arg2, struct sysctl_req *req) 471{ 472 pmsctl_t ctl; 473 int error; 474 boolean_t intr; 475 476 if ((error = SYSCTL_IN(req, &ctl, sizeof(ctl)))) 477 return(error); 478 479 intr = ml_set_interrupts_enabled(FALSE); /* No interruptions in here */ 480 error = pmsControl(ctl.request, (user_addr_t)(uintptr_t)ctl.reqaddr, ctl.reqsize); 481 (void)ml_set_interrupts_enabled(intr); /* Restore interruptions */ 482 483 return(error); 484} 485 486SYSCTL_PROC(_hw, OID_AUTO, pms, CTLTYPE_STRUCT | CTLFLAG_WR | CTLFLAG_LOCKED, 0, 0, pmsSysctl, "S", "Processor Power Management"); 487 488 489 490/****************************************************************************** 491 * Generic MIB initialisation. 492 * 493 * This is a hack, and should be replaced with SYSINITs 494 * at some point. 495 */ 496void 497sysctl_mib_init(void) 498{ 499 cputype = cpu_type(); 500 cpusubtype = cpu_subtype(); 501 cputhreadtype = cpu_threadtype(); 502#if defined(__i386__) || defined (__x86_64__) 503 cpu64bit = (_get_cpu_capabilities() & k64Bit) == k64Bit; 504#elif defined(__arm__) 505 506#else 507#error Unsupported arch 508#endif 509 510 /* 511 * Populate the optional portion of the hw.* MIB. 512 * 513 * XXX This could be broken out into parts of the code 514 * that actually directly relate to the functions in 515 * question. 516 */ 517 518 if (cputhreadtype != CPU_THREADTYPE_NONE) { 519 sysctl_register_oid(&sysctl__hw_cputhreadtype); 520 } 521 522#if defined (__i386__) || defined (__x86_64__) 523#define is_capability_set(k) (((_get_cpu_capabilities() & (k)) == (k)) ? 1 : 0) 524 mmx_flag = is_capability_set(kHasMMX); 525 sse_flag = is_capability_set(kHasSSE); 526 sse2_flag = is_capability_set(kHasSSE2); 527 sse3_flag = is_capability_set(kHasSSE3); 528 supplementalsse3_flag = is_capability_set(kHasSupplementalSSE3); 529 sse4_1_flag = is_capability_set(kHasSSE4_1); 530 sse4_2_flag = is_capability_set(kHasSSE4_2); 531 x86_64_flag = is_capability_set(k64Bit); 532 aes_flag = is_capability_set(kHasAES); 533 avx1_0_flag = is_capability_set(kHasAVX1_0); 534 rdrand_flag = is_capability_set(kHasRDRAND); 535 f16c_flag = is_capability_set(kHasF16C); 536 enfstrg_flag = is_capability_set(kHasENFSTRG); 537 538 /* hw.cpufamily */ 539 cpufamily = cpuid_cpufamily(); 540 541 /* hw.cacheconfig */ 542 cacheconfig[0] = ml_cpu_cache_sharing(0); 543 cacheconfig[1] = ml_cpu_cache_sharing(1); 544 cacheconfig[2] = ml_cpu_cache_sharing(2); 545 cacheconfig[3] = ml_cpu_cache_sharing(3); 546 cacheconfig[4] = 0; 547 548 /* hw.cachesize */ 549 cachesize[0] = ml_cpu_cache_size(0); 550 cachesize[1] = ml_cpu_cache_size(1); 551 cachesize[2] = ml_cpu_cache_size(2); 552 cachesize[3] = ml_cpu_cache_size(3); 553 cachesize[4] = 0; 554 555 /* hw.packages */ 556 packages = roundup(ml_cpu_cache_sharing(0), cpuid_info()->thread_count) 557 / cpuid_info()->thread_count; 558#elif defined(__arm__) 559 560#define OrBits(var, feat) \ 561 var = (arm_processor_id.processor_features & feat) ? 1 : 0; 562 563 OrBits(arm_isa_flag, kProcessorFeatureARM_ISA); 564 OrBits(arm_thumb_flag, kProcessorFeatureThumb); 565 OrBits(arm_thumbee_flag, kProcessorFeatureThumbEE); 566 OrBits(arm_thumb2_flag, kProcessorFeatureThumb2); 567 OrBits(arm_jazelle_flag, kProcessorFeatureJazelle); 568 OrBits(arm_armv4_flag, kProcessorFeatureARMv4); 569 OrBits(arm_security_flag, kProcessorFeatureSecurity); 570 OrBits(arm_armvm_flag, kProcessorFeatureMicrocontroller); 571#undef OrBits 572 573 /* hw.cpufamily */ 574 cpufamily = CPUFAMILY_ARM_13; 575 576 /* hw.cacheconfig */ 577 cacheconfig[0] = ml_cpu_cache_sharing(0); 578 cacheconfig[1] = ml_cpu_cache_sharing(1); 579 cacheconfig[2] = ml_cpu_cache_sharing(2); 580 cacheconfig[3] = ml_cpu_cache_sharing(3); 581 cacheconfig[4] = 0; 582 583 /* hw.cachesize */ 584 cachesize[0] = ml_cpu_cache_size(0); 585 cachesize[1] = ml_cpu_cache_size(1); 586 cachesize[2] = ml_cpu_cache_size(2); 587 cachesize[3] = ml_cpu_cache_size(3); 588 cachesize[4] = 0; 589 590 /* hw.packages */ 591 packages = 1; 592 593#else 594#error unknown architecture 595#endif /* !__i386__ && !__x86_64 && !__arm__ */ 596 597} 598