1 /* 2 * Copyright (c) 2003-2007 Apple Inc. All rights reserved. 3 */ 4 #include <sys/param.h> 5 #include <sys/kernel.h> 6 #include <sys/sysctl.h> 7 8 #include <machine/machine_routines.h> 9 10 #include <mach/host_info.h> 11 #include <mach/mach_host.h> 12 #include <arm/cpuid.h> 13 #include <libkern/libkern.h> 14 15 extern int trap_on_alignment_fault; 16 extern uint64_t wake_abstime; 17 extern int lck_mtx_adaptive_spin_mode; 18 19 static 20 SYSCTL_INT(_machdep, OID_AUTO, alignmenttrap, 21 CTLFLAG_RW, &trap_on_alignment_fault, 0, 22 "trap on alignment faults (number of alignment faults per trap)"); 23 24 static 25 SYSCTL_QUAD(_machdep, OID_AUTO, wake_abstime, 26 CTLFLAG_RD | CTLFLAG_KERN, &wake_abstime, 27 "Absolute Time at the last wakeup"); 28 29 static int 30 sysctl_time_since_reset SYSCTL_HANDLER_ARGS 31 { 32 #pragma unused(arg1, arg2, oidp) 33 int error = 0; 34 uint64_t return_value = 0; 35 36 return_value = ml_get_time_since_reset(); 37 38 SYSCTL_OUT(req, &return_value, sizeof(return_value)); 39 40 return error; 41 } 42 43 SYSCTL_PROC(_machdep, OID_AUTO, time_since_reset, 44 CTLFLAG_RD | CTLTYPE_QUAD | CTLFLAG_LOCKED, 45 0, 0, sysctl_time_since_reset, "I", 46 "Continuous time since last SOC boot/wake started"); 47 48 static int 49 sysctl_wake_conttime SYSCTL_HANDLER_ARGS 50 { 51 #pragma unused(arg1, arg2, oidp) 52 int error = 0; 53 uint64_t return_value = 0; 54 55 return_value = ml_get_conttime_wake_time(); 56 57 SYSCTL_OUT(req, &return_value, sizeof(return_value)); 58 59 return error; 60 } 61 62 SYSCTL_PROC(_machdep, OID_AUTO, wake_conttime, 63 CTLFLAG_RD | CTLTYPE_QUAD | CTLFLAG_LOCKED, 64 0, 0, sysctl_wake_conttime, "I", 65 "Continuous Time at the last wakeup"); 66 67 /* 68 * For source compatibility, here's some machdep.cpu mibs that 69 * use host_info() to simulate reasonable answers. 70 */ 71 72 SYSCTL_NODE(_machdep, OID_AUTO, cpu, CTLFLAG_RW | CTLFLAG_LOCKED, 0, 73 "CPU info"); 74 75 static int 76 arm_host_info SYSCTL_HANDLER_ARGS 77 { 78 __unused struct sysctl_oid *unused_oidp = oidp; 79 80 host_basic_info_data_t hinfo; 81 mach_msg_type_number_t count = HOST_BASIC_INFO_COUNT; 82 #define BSD_HOST 1 83 kern_return_t kret = host_info((host_t)BSD_HOST, 84 HOST_BASIC_INFO, (host_info_t)&hinfo, &count); 85 if (KERN_SUCCESS != kret) { 86 return EINVAL; 87 } 88 89 if (sizeof(uint32_t) != arg2) { 90 panic("size mismatch"); 91 } 92 93 uintptr_t woffset = (uintptr_t)arg1 / sizeof(uint32_t); 94 uint32_t datum = *(uint32_t *)(((uint32_t *)&hinfo) + woffset); 95 return SYSCTL_OUT(req, &datum, sizeof(datum)); 96 } 97 98 /* 99 * machdep.cpu.cores_per_package 100 * 101 * x86: derived from CPUID data. 102 * ARM: how many physical cores we have in the AP; aka hw.physicalcpu_max 103 */ 104 static 105 SYSCTL_PROC(_machdep_cpu, OID_AUTO, cores_per_package, 106 CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_LOCKED, 107 (void *)offsetof(host_basic_info_data_t, physical_cpu_max), 108 sizeof(integer_t), 109 arm_host_info, "I", "CPU cores per package"); 110 111 /* 112 * machdep.cpu.core_count 113 * 114 * x86: derived from CPUID data. 115 * ARM: # active physical cores in the AP; aka hw.physicalcpu 116 */ 117 static 118 SYSCTL_PROC(_machdep_cpu, OID_AUTO, core_count, 119 CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_LOCKED, 120 (void *)offsetof(host_basic_info_data_t, physical_cpu), 121 sizeof(integer_t), 122 arm_host_info, "I", "Number of enabled cores per package"); 123 124 /* 125 * machdep.cpu.logical_per_package 126 * 127 * x86: derived from CPUID data. Returns ENOENT if HTT bit not set, but 128 * most x64 CPUs have that, so assume it's available. 129 * ARM: total # logical cores in the AP; aka hw.logicalcpu_max 130 */ 131 static 132 SYSCTL_PROC(_machdep_cpu, OID_AUTO, logical_per_package, 133 CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_LOCKED, 134 (void *)offsetof(host_basic_info_data_t, logical_cpu_max), 135 sizeof(integer_t), 136 arm_host_info, "I", "CPU logical cpus per package"); 137 138 /* 139 * machdep.cpu.thread_count 140 * 141 * x86: derived from CPUID data. 142 * ARM: # active logical cores in the AP; aka hw.logicalcpu 143 */ 144 static 145 SYSCTL_PROC(_machdep_cpu, OID_AUTO, thread_count, 146 CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_LOCKED, 147 (void *)offsetof(host_basic_info_data_t, logical_cpu), 148 sizeof(integer_t), 149 arm_host_info, "I", "Number of enabled threads per package"); 150 151 /* 152 * machdep.cpu.brand_string 153 * 154 * x86: derived from CPUID data. 155 * ARM: cons something up from the CPUID register. Could include cpufamily 156 * here and map it to a "marketing" name, but there's no obvious need; 157 * the value is already exported via the commpage. So keep it simple. 158 */ 159 static int 160 make_brand_string SYSCTL_HANDLER_ARGS 161 { 162 __unused struct sysctl_oid *unused_oidp = oidp; 163 __unused void *unused_arg1 = arg1; 164 __unused int unused_arg2 = arg2; 165 166 const char *impl; 167 168 switch (cpuid_info()->arm_info.arm_implementor) { 169 case CPU_VID_APPLE: 170 impl = "Apple"; 171 break; 172 case CPU_VID_ARM: 173 impl = "ARM"; 174 break; 175 default: 176 impl = "ARM architecture"; 177 break; 178 } 179 char buf[80]; 180 snprintf(buf, sizeof(buf), "%s processor", impl); 181 return SYSCTL_OUT(req, buf, strlen(buf) + 1); 182 } 183 184 SYSCTL_PROC(_machdep_cpu, OID_AUTO, brand_string, 185 CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_LOCKED, 186 0, 0, make_brand_string, "A", "CPU brand string"); 187 188 static 189 SYSCTL_INT(_machdep, OID_AUTO, lck_mtx_adaptive_spin_mode, 190 CTLFLAG_RW, &lck_mtx_adaptive_spin_mode, 0, 191 "Enable adaptive spin behavior for kernel mutexes"); 192 193 static int 194 virtual_address_size SYSCTL_HANDLER_ARGS 195 { 196 #pragma unused(arg1, arg2, oidp) 197 int return_value = 32 - (TTBCR_N_SETUP & TTBCR_N_MASK); 198 return SYSCTL_OUT(req, &return_value, sizeof(return_value)); 199 } 200 201 static 202 SYSCTL_PROC(_machdep, OID_AUTO, virtual_address_size, 203 CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_LOCKED, 204 0, 0, virtual_address_size, "I", 205 "Number of addressable bits in userspace virtual addresses"); 206