]>
Commit | Line | Data |
---|---|---|
5ba3f43e A |
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 | ||
d9a64523 A |
10 | #include <mach/host_info.h> |
11 | #include <mach/mach_host.h> | |
12 | #include <arm/cpuid.h> | |
13 | #include <libkern/libkern.h> | |
14 | ||
f427ee49 A |
15 | #if HYPERVISOR |
16 | #include <kern/hv_support.h> | |
17 | #endif | |
18 | ||
0a7de745 A |
19 | extern uint64_t wake_abstime; |
20 | extern int lck_mtx_adaptive_spin_mode; | |
5ba3f43e A |
21 | |
22 | static | |
23 | SYSCTL_QUAD(_machdep, OID_AUTO, wake_abstime, | |
0a7de745 A |
24 | CTLFLAG_RD, &wake_abstime, |
25 | "Absolute Time at the last wakeup"); | |
5ba3f43e A |
26 | |
27 | static int | |
28 | sysctl_time_since_reset SYSCTL_HANDLER_ARGS | |
29 | { | |
30 | #pragma unused(arg1, arg2, oidp) | |
cb323159 A |
31 | uint64_t return_value = ml_get_time_since_reset(); |
32 | return SYSCTL_OUT(req, &return_value, sizeof(return_value)); | |
5ba3f43e A |
33 | } |
34 | ||
35 | SYSCTL_PROC(_machdep, OID_AUTO, time_since_reset, | |
0a7de745 A |
36 | CTLFLAG_RD | CTLTYPE_QUAD | CTLFLAG_LOCKED, |
37 | 0, 0, sysctl_time_since_reset, "I", | |
38 | "Continuous time since last SOC boot/wake started"); | |
5ba3f43e A |
39 | |
40 | static int | |
41 | sysctl_wake_conttime SYSCTL_HANDLER_ARGS | |
42 | { | |
43 | #pragma unused(arg1, arg2, oidp) | |
cb323159 A |
44 | uint64_t return_value = ml_get_conttime_wake_time(); |
45 | return SYSCTL_OUT(req, &return_value, sizeof(return_value)); | |
5ba3f43e A |
46 | } |
47 | ||
48 | SYSCTL_PROC(_machdep, OID_AUTO, wake_conttime, | |
0a7de745 A |
49 | CTLFLAG_RD | CTLTYPE_QUAD | CTLFLAG_LOCKED, |
50 | 0, 0, sysctl_wake_conttime, "I", | |
51 | "Continuous Time at the last wakeup"); | |
5ba3f43e | 52 | |
c6bf4f31 A |
53 | #if defined(HAS_IPI) |
54 | static int | |
55 | cpu_signal_deferred_timer(__unused struct sysctl_oid *oidp, __unused void *arg1, __unused int arg2, struct sysctl_req *req) | |
56 | { | |
57 | int new_value = 0; | |
58 | int changed = 0; | |
59 | ||
60 | int old_value = (int)ml_cpu_signal_deferred_get_timer(); | |
61 | ||
62 | int error = sysctl_io_number(req, old_value, sizeof(int), &new_value, &changed); | |
63 | ||
64 | if (error == 0 && changed) { | |
65 | ml_cpu_signal_deferred_adjust_timer((uint64_t)new_value); | |
66 | } | |
67 | ||
68 | return error; | |
69 | } | |
70 | ||
71 | SYSCTL_PROC(_machdep, OID_AUTO, deferred_ipi_timeout, | |
72 | CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_LOCKED, | |
73 | 0, 0, | |
74 | cpu_signal_deferred_timer, "I", "Deferred IPI timeout (nanoseconds)"); | |
75 | ||
76 | #endif /* defined(HAS_IPI) */ | |
5ba3f43e | 77 | |
d9a64523 A |
78 | /* |
79 | * For source compatibility, here's some machdep.cpu mibs that | |
80 | * use host_info() to simulate reasonable answers. | |
81 | */ | |
82 | ||
0a7de745 A |
83 | SYSCTL_NODE(_machdep, OID_AUTO, cpu, CTLFLAG_RW | CTLFLAG_LOCKED, 0, |
84 | "CPU info"); | |
d9a64523 A |
85 | |
86 | static int | |
87 | arm_host_info SYSCTL_HANDLER_ARGS | |
88 | { | |
89 | __unused struct sysctl_oid *unused_oidp = oidp; | |
90 | ||
91 | host_basic_info_data_t hinfo; | |
92 | mach_msg_type_number_t count = HOST_BASIC_INFO_COUNT; | |
0a7de745 | 93 | #define BSD_HOST 1 |
d9a64523 | 94 | kern_return_t kret = host_info((host_t)BSD_HOST, |
0a7de745 A |
95 | HOST_BASIC_INFO, (host_info_t)&hinfo, &count); |
96 | if (KERN_SUCCESS != kret) { | |
97 | return EINVAL; | |
98 | } | |
d9a64523 | 99 | |
0a7de745 | 100 | if (sizeof(uint32_t) != arg2) { |
d9a64523 | 101 | panic("size mismatch"); |
0a7de745 | 102 | } |
d9a64523 | 103 | |
0a7de745 | 104 | uintptr_t woffset = (uintptr_t)arg1 / sizeof(uint32_t); |
d9a64523 | 105 | uint32_t datum = *(uint32_t *)(((uint32_t *)&hinfo) + woffset); |
0a7de745 | 106 | return SYSCTL_OUT(req, &datum, sizeof(datum)); |
d9a64523 A |
107 | } |
108 | ||
109 | /* | |
110 | * machdep.cpu.cores_per_package | |
111 | * | |
112 | * x86: derived from CPUID data. | |
113 | * ARM: how many physical cores we have in the AP; aka hw.physicalcpu_max | |
114 | */ | |
115 | static | |
116 | SYSCTL_PROC(_machdep_cpu, OID_AUTO, cores_per_package, | |
0a7de745 A |
117 | CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_LOCKED, |
118 | (void *)offsetof(host_basic_info_data_t, physical_cpu_max), | |
119 | sizeof(integer_t), | |
120 | arm_host_info, "I", "CPU cores per package"); | |
d9a64523 A |
121 | |
122 | /* | |
123 | * machdep.cpu.core_count | |
124 | * | |
125 | * x86: derived from CPUID data. | |
126 | * ARM: # active physical cores in the AP; aka hw.physicalcpu | |
127 | */ | |
128 | static | |
129 | SYSCTL_PROC(_machdep_cpu, OID_AUTO, core_count, | |
0a7de745 A |
130 | CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_LOCKED, |
131 | (void *)offsetof(host_basic_info_data_t, physical_cpu), | |
132 | sizeof(integer_t), | |
133 | arm_host_info, "I", "Number of enabled cores per package"); | |
d9a64523 A |
134 | |
135 | /* | |
136 | * machdep.cpu.logical_per_package | |
137 | * | |
138 | * x86: derived from CPUID data. Returns ENOENT if HTT bit not set, but | |
139 | * most x64 CPUs have that, so assume it's available. | |
140 | * ARM: total # logical cores in the AP; aka hw.logicalcpu_max | |
141 | */ | |
142 | static | |
143 | SYSCTL_PROC(_machdep_cpu, OID_AUTO, logical_per_package, | |
0a7de745 A |
144 | CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_LOCKED, |
145 | (void *)offsetof(host_basic_info_data_t, logical_cpu_max), | |
146 | sizeof(integer_t), | |
147 | arm_host_info, "I", "CPU logical cpus per package"); | |
d9a64523 A |
148 | |
149 | /* | |
150 | * machdep.cpu.thread_count | |
151 | * | |
152 | * x86: derived from CPUID data. | |
153 | * ARM: # active logical cores in the AP; aka hw.logicalcpu | |
154 | */ | |
155 | static | |
156 | SYSCTL_PROC(_machdep_cpu, OID_AUTO, thread_count, | |
0a7de745 A |
157 | CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_LOCKED, |
158 | (void *)offsetof(host_basic_info_data_t, logical_cpu), | |
159 | sizeof(integer_t), | |
160 | arm_host_info, "I", "Number of enabled threads per package"); | |
d9a64523 A |
161 | |
162 | /* | |
163 | * machdep.cpu.brand_string | |
164 | * | |
165 | * x86: derived from CPUID data. | |
166 | * ARM: cons something up from the CPUID register. Could include cpufamily | |
167 | * here and map it to a "marketing" name, but there's no obvious need; | |
168 | * the value is already exported via the commpage. So keep it simple. | |
169 | */ | |
170 | static int | |
171 | make_brand_string SYSCTL_HANDLER_ARGS | |
172 | { | |
173 | __unused struct sysctl_oid *unused_oidp = oidp; | |
174 | __unused void *unused_arg1 = arg1; | |
175 | __unused int unused_arg2 = arg2; | |
176 | ||
177 | const char *impl; | |
178 | ||
179 | switch (cpuid_info()->arm_info.arm_implementor) { | |
180 | case CPU_VID_APPLE: | |
181 | impl = "Apple"; | |
182 | break; | |
183 | case CPU_VID_ARM: | |
184 | impl = "ARM"; | |
185 | break; | |
186 | default: | |
187 | impl = "ARM architecture"; | |
188 | break; | |
189 | } | |
f427ee49 A |
190 | |
191 | ||
d9a64523 | 192 | char buf[80]; |
0a7de745 A |
193 | snprintf(buf, sizeof(buf), "%s processor", impl); |
194 | return SYSCTL_OUT(req, buf, strlen(buf) + 1); | |
d9a64523 A |
195 | } |
196 | ||
197 | SYSCTL_PROC(_machdep_cpu, OID_AUTO, brand_string, | |
0a7de745 A |
198 | CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_LOCKED, |
199 | 0, 0, make_brand_string, "A", "CPU brand string"); | |
200 | ||
f427ee49 | 201 | |
0a7de745 A |
202 | static |
203 | SYSCTL_INT(_machdep, OID_AUTO, lck_mtx_adaptive_spin_mode, | |
204 | CTLFLAG_RW, &lck_mtx_adaptive_spin_mode, 0, | |
205 | "Enable adaptive spin behavior for kernel mutexes"); | |
206 | ||
f427ee49 A |
207 | static int |
208 | virtual_address_size SYSCTL_HANDLER_ARGS | |
209 | { | |
210 | #pragma unused(arg1, arg2, oidp) | |
211 | int return_value = 64 - T0SZ_BOOT; | |
212 | return SYSCTL_OUT(req, &return_value, sizeof(return_value)); | |
213 | } | |
214 | ||
215 | static | |
216 | SYSCTL_PROC(_machdep, OID_AUTO, virtual_address_size, | |
217 | CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_LOCKED, | |
218 | 0, 0, virtual_address_size, "I", | |
219 | "Number of addressable bits in userspace virtual addresses"); | |
220 | ||
cb323159 | 221 | |
0a7de745 A |
222 | #if DEVELOPMENT || DEBUG |
223 | extern uint64_t TLockTimeOut; | |
224 | SYSCTL_QUAD(_machdep, OID_AUTO, tlto, | |
225 | CTLFLAG_RW | CTLFLAG_LOCKED, &TLockTimeOut, | |
226 | "Ticket spinlock timeout (MATUs): use with care"); | |
cb323159 | 227 | |
cb323159 | 228 | /* |
f427ee49 A |
229 | * macro to generate a sysctl machdep.cpu.sysreg_* for a given system register |
230 | * using __builtin_arm_rsr64. | |
cb323159 | 231 | */ |
f427ee49 A |
232 | #define SYSCTL_PROC_MACHDEP_CPU_SYSREG(name) \ |
233 | static int \ | |
234 | sysctl_sysreg_##name SYSCTL_HANDLER_ARGS \ | |
235 | { \ | |
236 | _Pragma("unused(arg1, arg2, oidp)") \ | |
237 | uint64_t return_value = __builtin_arm_rsr64(#name); \ | |
238 | return SYSCTL_OUT(req, &return_value, sizeof(return_value)); \ | |
239 | } \ | |
240 | SYSCTL_PROC(_machdep_cpu, OID_AUTO, sysreg_##name, \ | |
241 | CTLFLAG_RD | CTLTYPE_QUAD | CTLFLAG_LOCKED, \ | |
242 | 0, 0, sysctl_sysreg_##name, "Q", \ | |
243 | #name " register on the current CPU"); | |
244 | ||
245 | ||
246 | // CPU system registers | |
247 | // ARM64: AArch64 Vector Base Address Register | |
248 | SYSCTL_PROC_MACHDEP_CPU_SYSREG(VBAR_EL1); | |
249 | // ARM64: AArch64 Memory Attribute Indirection Register | |
250 | SYSCTL_PROC_MACHDEP_CPU_SYSREG(MAIR_EL1); | |
251 | // ARM64: AArch64 Translation table base register 1 | |
252 | SYSCTL_PROC_MACHDEP_CPU_SYSREG(TTBR1_EL1); | |
253 | // ARM64: AArch64 System Control Register | |
254 | SYSCTL_PROC_MACHDEP_CPU_SYSREG(SCTLR_EL1); | |
255 | // ARM64: AArch64 Translation Control Register | |
256 | SYSCTL_PROC_MACHDEP_CPU_SYSREG(TCR_EL1); | |
257 | // ARM64: AArch64 Memory Model Feature Register 0 | |
258 | SYSCTL_PROC_MACHDEP_CPU_SYSREG(ID_AA64MMFR0_EL1); | |
259 | // ARM64: AArch64 Instruction Set Attribute Register 1 | |
260 | SYSCTL_PROC_MACHDEP_CPU_SYSREG(ID_AA64ISAR1_EL1); | |
cb323159 | 261 | /* |
f427ee49 | 262 | * ARM64: AArch64 Guarded Execution Mode GENTER Vector |
cb323159 | 263 | * |
f427ee49 A |
264 | * Workaround for pre-H13, since register cannot be read unless in guarded |
265 | * mode, thus expose software convention that GXF_ENTRY_EL1 is always set | |
266 | * to the address of the gxf_ppl_entry_handler. | |
cb323159 | 267 | */ |
f427ee49 | 268 | #endif /* DEVELOPMENT || DEBUG */ |
cb323159 | 269 | |
f427ee49 A |
270 | #if HYPERVISOR |
271 | SYSCTL_NODE(_kern, OID_AUTO, hv, CTLFLAG_RW | CTLFLAG_LOCKED, 0, "Hypervisor info"); | |
cb323159 | 272 | |
f427ee49 A |
273 | SYSCTL_INT(_kern_hv, OID_AUTO, supported, |
274 | CTLFLAG_KERN | CTLFLAG_RD | CTLFLAG_LOCKED, | |
275 | &hv_support_available, 0, ""); | |
cb323159 | 276 | |
f427ee49 | 277 | extern unsigned int arm64_num_vmids; |
cb323159 | 278 | |
f427ee49 A |
279 | SYSCTL_UINT(_kern_hv, OID_AUTO, max_address_spaces, |
280 | CTLFLAG_KERN | CTLFLAG_RD | CTLFLAG_LOCKED, | |
281 | &arm64_num_vmids, 0, ""); | |
282 | ||
283 | extern uint64_t pmap_ipa_size(uint64_t granule); | |
cb323159 A |
284 | |
285 | static int | |
f427ee49 | 286 | sysctl_ipa_size_16k SYSCTL_HANDLER_ARGS |
cb323159 A |
287 | { |
288 | #pragma unused(arg1, arg2, oidp) | |
f427ee49 | 289 | uint64_t return_value = pmap_ipa_size(16384); |
cb323159 A |
290 | return SYSCTL_OUT(req, &return_value, sizeof(return_value)); |
291 | } | |
292 | ||
f427ee49 | 293 | SYSCTL_PROC(_kern_hv, OID_AUTO, ipa_size_16k, |
cb323159 | 294 | CTLFLAG_RD | CTLTYPE_QUAD | CTLFLAG_LOCKED, |
f427ee49 A |
295 | 0, 0, sysctl_ipa_size_16k, "P", |
296 | "Maximum size allowed for 16K-page guest IPA spaces"); | |
cb323159 A |
297 | |
298 | static int | |
f427ee49 | 299 | sysctl_ipa_size_4k SYSCTL_HANDLER_ARGS |
cb323159 A |
300 | { |
301 | #pragma unused(arg1, arg2, oidp) | |
f427ee49 | 302 | uint64_t return_value = pmap_ipa_size(4096); |
cb323159 A |
303 | return SYSCTL_OUT(req, &return_value, sizeof(return_value)); |
304 | } | |
305 | ||
f427ee49 | 306 | SYSCTL_PROC(_kern_hv, OID_AUTO, ipa_size_4k, |
cb323159 | 307 | CTLFLAG_RD | CTLTYPE_QUAD | CTLFLAG_LOCKED, |
f427ee49 A |
308 | 0, 0, sysctl_ipa_size_4k, "P", |
309 | "Maximum size allowed for 4K-page guest IPA spaces"); | |
cb323159 | 310 | |
f427ee49 | 311 | #endif // HYPERVISOR |