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 <kern/hvg_hypercall.h>
14 #include <vm/pmap.h>
15 #include <kern/zalloc.h>
16 #include <libkern/libkern.h>
17 #include <pexpert/device_tree.h>
18
19 #if HYPERVISOR
20 #include <kern/hv_support.h>
21 #include <kern/bits.h>
22 #endif
23
24 extern uint64_t wake_abstime;
25
26 #if DEVELOPMENT || DEBUG
27 /* Various tuneables to modulate selection of WFE in the idle path */
28 extern int wfe_rec_max;
29 extern int wfe_allowed;
30
31 extern int wfe_rec_none;
32 extern uint32_t idle_proximate_timer_wfe;
33 extern uint32_t idle_proximate_io_wfe_masked;
34 extern uint32_t idle_proximate_io_wfe_unmasked;
35
36 static
37 SYSCTL_INT(_machdep, OID_AUTO, wfe_rec_max,
38 CTLFLAG_RW, &wfe_rec_max, 0,
39 "");
40
41 static
42 SYSCTL_INT(_machdep, OID_AUTO, wfe_allowed,
43 CTLFLAG_RW, &wfe_allowed, 0,
44 "");
45
46 static
47 SYSCTL_INT(_machdep, OID_AUTO, idle_timer_wfe,
48 CTLFLAG_RW, &idle_proximate_timer_wfe, 0,
49 "");
50
51 static
52 SYSCTL_INT(_machdep, OID_AUTO, idle_io_wfe_masked,
53 CTLFLAG_RW, &idle_proximate_io_wfe_masked, 0,
54 "");
55 static
56 SYSCTL_INT(_machdep, OID_AUTO, idle_io_wfe_unmasked,
57 CTLFLAG_RW, &idle_proximate_io_wfe_unmasked, 0,
58 "");
59
60 static
61 SYSCTL_INT(_machdep, OID_AUTO, wfe_rec_none,
62 CTLFLAG_RW, &wfe_rec_none, 0,
63 "");
64
65 extern uint64_t wfe_rec_override_mat;
66 SYSCTL_QUAD(_machdep, OID_AUTO, wfe_rec_override_mat,
67 CTLFLAG_RW, &wfe_rec_override_mat,
68 "");
69
70 extern uint64_t wfe_rec_clamp;
71 SYSCTL_QUAD(_machdep, OID_AUTO, wfe_rec_clamp,
72 CTLFLAG_RW, &wfe_rec_clamp,
73 "");
74
75 #endif
76
77 static
78 SYSCTL_QUAD(_machdep, OID_AUTO, wake_abstime,
79 CTLFLAG_RD, &wake_abstime,
80 "Absolute Time at the last wakeup");
81
82 static int
83 sysctl_time_since_reset SYSCTL_HANDLER_ARGS
84 {
85 #pragma unused(arg1, arg2, oidp)
86 uint64_t return_value = ml_get_time_since_reset();
87 return SYSCTL_OUT(req, &return_value, sizeof(return_value));
88 }
89
90 SYSCTL_PROC(_machdep, OID_AUTO, time_since_reset,
91 CTLFLAG_RD | CTLTYPE_QUAD | CTLFLAG_LOCKED,
92 0, 0, sysctl_time_since_reset, "I",
93 "Continuous time since last SOC boot/wake started");
94
95 static int
96 sysctl_wake_conttime SYSCTL_HANDLER_ARGS
97 {
98 #pragma unused(arg1, arg2, oidp)
99 uint64_t return_value = ml_get_conttime_wake_time();
100 return SYSCTL_OUT(req, &return_value, sizeof(return_value));
101 }
102
103 SYSCTL_PROC(_machdep, OID_AUTO, wake_conttime,
104 CTLFLAG_RD | CTLTYPE_QUAD | CTLFLAG_LOCKED,
105 0, 0, sysctl_wake_conttime, "I",
106 "Continuous Time at the last wakeup");
107
108 #if defined(HAS_IPI)
109 static int
cpu_signal_deferred_timer(__unused struct sysctl_oid * oidp,__unused void * arg1,__unused int arg2,struct sysctl_req * req)110 cpu_signal_deferred_timer(__unused struct sysctl_oid *oidp, __unused void *arg1, __unused int arg2, struct sysctl_req *req)
111 {
112 int new_value = 0;
113 int changed = 0;
114
115 int old_value = (int)ml_cpu_signal_deferred_get_timer();
116
117 int error = sysctl_io_number(req, old_value, sizeof(int), &new_value, &changed);
118
119 if (error == 0 && changed) {
120 ml_cpu_signal_deferred_adjust_timer((uint64_t)new_value);
121 }
122
123 return error;
124 }
125
126 SYSCTL_PROC(_machdep, OID_AUTO, deferred_ipi_timeout,
127 CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_LOCKED,
128 0, 0,
129 cpu_signal_deferred_timer, "I", "Deferred IPI timeout (nanoseconds)");
130
131 #endif /* defined(HAS_IPI) */
132
133 /*
134 * For source compatibility, here's some machdep.cpu mibs that
135 * use host_info() to simulate reasonable answers.
136 */
137
138 SYSCTL_NODE(_machdep, OID_AUTO, cpu, CTLFLAG_RW | CTLFLAG_LOCKED, 0,
139 "CPU info");
140
141 static int
142 arm_host_info SYSCTL_HANDLER_ARGS
143 {
144 __unused struct sysctl_oid *unused_oidp = oidp;
145
146 host_basic_info_data_t hinfo;
147 mach_msg_type_number_t count = HOST_BASIC_INFO_COUNT;
148 #define BSD_HOST 1
149 kern_return_t kret = host_info((host_t)BSD_HOST,
150 HOST_BASIC_INFO, (host_info_t)&hinfo, &count);
151 if (KERN_SUCCESS != kret) {
152 return EINVAL;
153 }
154
155 if (sizeof(uint32_t) != arg2) {
156 panic("size mismatch");
157 }
158
159 uintptr_t woffset = (uintptr_t)arg1 / sizeof(uint32_t);
160 uint32_t datum = *(uint32_t *)(((uint32_t *)&hinfo) + woffset);
161 return SYSCTL_OUT(req, &datum, sizeof(datum));
162 }
163
164 /*
165 * machdep.cpu.cores_per_package
166 *
167 * x86: derived from CPUID data.
168 * ARM: how many physical cores we have in the AP; aka hw.physicalcpu_max
169 */
170 static
171 SYSCTL_PROC(_machdep_cpu, OID_AUTO, cores_per_package,
172 CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_LOCKED,
173 (void *)offsetof(host_basic_info_data_t, physical_cpu_max),
174 sizeof(integer_t),
175 arm_host_info, "I", "CPU cores per package");
176
177 /*
178 * machdep.cpu.core_count
179 *
180 * x86: derived from CPUID data.
181 * ARM: # active physical cores in the AP; aka hw.physicalcpu
182 */
183 static
184 SYSCTL_PROC(_machdep_cpu, OID_AUTO, core_count,
185 CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_LOCKED,
186 (void *)offsetof(host_basic_info_data_t, physical_cpu),
187 sizeof(integer_t),
188 arm_host_info, "I", "Number of enabled cores per package");
189
190 /*
191 * machdep.cpu.logical_per_package
192 *
193 * x86: derived from CPUID data. Returns ENOENT if HTT bit not set, but
194 * most x64 CPUs have that, so assume it's available.
195 * ARM: total # logical cores in the AP; aka hw.logicalcpu_max
196 */
197 static
198 SYSCTL_PROC(_machdep_cpu, OID_AUTO, logical_per_package,
199 CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_LOCKED,
200 (void *)offsetof(host_basic_info_data_t, logical_cpu_max),
201 sizeof(integer_t),
202 arm_host_info, "I", "CPU logical cpus per package");
203
204 /*
205 * machdep.cpu.thread_count
206 *
207 * x86: derived from CPUID data.
208 * ARM: # active logical cores in the AP; aka hw.logicalcpu
209 */
210 static
211 SYSCTL_PROC(_machdep_cpu, OID_AUTO, thread_count,
212 CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_LOCKED,
213 (void *)offsetof(host_basic_info_data_t, logical_cpu),
214 sizeof(integer_t),
215 arm_host_info, "I", "Number of enabled threads per package");
216
217 static SECURITY_READ_ONLY_LATE(char*) brand_string = NULL;
218 static SECURITY_READ_ONLY_LATE(size_t) brand_string_len = 0;
219
220 /*
221 * SecureDTLookupEntry() is only guaranteed to work before PE_init_iokit(),
222 * so we load the brand string (if available) in a startup handler.
223 */
224 __startup_func
225 static void
sysctl_load_brand_string(void)226 sysctl_load_brand_string(void)
227 {
228 DTEntry node;
229 void const *value = NULL;
230 unsigned int size = 0;
231
232 if (kSuccess != SecureDTLookupEntry(0, "/product", &node)) {
233 return;
234 }
235
236 if (kSuccess != SecureDTGetProperty(node, "product-soc-name", (void const **) &value, &size)) {
237 return;
238 }
239
240 if (size == 0) {
241 return;
242 }
243
244 brand_string = zalloc_permanent(size, ZALIGN_NONE);
245 if (brand_string == NULL) {
246 return;
247 }
248
249 memcpy(brand_string, value, size);
250 brand_string_len = size;
251 }
252 STARTUP(SYSCTL, STARTUP_RANK_MIDDLE, sysctl_load_brand_string);
253
254 /*
255 * machdep.cpu.brand_string
256 *
257 * x86: derived from CPUID data.
258 * ARM: Grab the product string from the device tree, if it exists.
259 * Otherwise, cons something up from the CPUID register.
260 * the value is already exported via the commpage. So keep it simple.
261 */
262 static int
263 make_brand_string SYSCTL_HANDLER_ARGS
264 {
265 __unused struct sysctl_oid *unused_oidp = oidp;
266 __unused void *unused_arg1 = arg1;
267 __unused int unused_arg2 = arg2;
268
269 if (brand_string != NULL) {
270 return SYSCTL_OUT(req, brand_string, brand_string_len);
271 }
272
273 const char *impl;
274
275 switch (cpuid_info()->arm_info.arm_implementor) {
276 case CPU_VID_APPLE:
277 impl = "Apple";
278 break;
279 case CPU_VID_ARM:
280 impl = "ARM";
281 break;
282 default:
283 impl = "ARM architecture";
284 break;
285 }
286
287 char buf[80];
288 snprintf(buf, sizeof(buf), "%s processor", impl);
289 return SYSCTL_OUT(req, buf, strlen(buf) + 1);
290 }
291
292 SYSCTL_PROC(_machdep_cpu, OID_AUTO, brand_string,
293 CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_LOCKED,
294 0, 0, make_brand_string, "A", "CPU brand string");
295
296
297 static int
298 virtual_address_size SYSCTL_HANDLER_ARGS
299 {
300 #pragma unused(arg1, arg2, oidp)
301 int return_value = 64 - T0SZ_BOOT;
302 return SYSCTL_OUT(req, &return_value, sizeof(return_value));
303 }
304
305 static
306 SYSCTL_PROC(_machdep, OID_AUTO, virtual_address_size,
307 CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_LOCKED,
308 0, 0, virtual_address_size, "I",
309 "Number of addressable bits in userspace virtual addresses");
310
311
312 #if DEVELOPMENT || DEBUG
313 extern uint64_t TLockTimeOut;
314 SYSCTL_QUAD(_machdep, OID_AUTO, tlto,
315 CTLFLAG_RW | CTLFLAG_LOCKED, &TLockTimeOut,
316 "Ticket spinlock timeout (MATUs): use with care");
317
318 extern uint32_t timebase_validation;
319 SYSCTL_UINT(_machdep, OID_AUTO, timebase_validation,
320 CTLFLAG_RW | CTLFLAG_LOCKED, &timebase_validation, 0,
321 "Monotonicity validation of kernel mach_absolute_time()");
322
323 #if __WKDM_ISA_2P_WORKAROUND__
324 extern uint64_t wkdmdretries, wkdmdretriespb;
325 extern uint32_t simulate_wkdm2p_error, wkdm_isa_2p_war_required;
326 SYSCTL_QUAD(_machdep, OID_AUTO, wkdmdretries,
327 CTLFLAG_RW | CTLFLAG_LOCKED, &wkdmdretries,
328 "Number of WKDM errata retries");
329 SYSCTL_QUAD(_machdep, OID_AUTO, wkdmdretriespb,
330 CTLFLAG_RW | CTLFLAG_LOCKED, &wkdmdretriespb,
331 "Number of retries where payload was on page boundary");
332 SYSCTL_UINT(_machdep, OID_AUTO, simulate_wkdm2p_error,
333 CTLFLAG_RW | CTLFLAG_LOCKED,
334 &simulate_wkdm2p_error, 0, "");
335 SYSCTL_UINT(_machdep, OID_AUTO, wkdm_isa_2p_war_required,
336 CTLFLAG_RW | CTLFLAG_LOCKED,
337 &wkdm_isa_2p_war_required, 0, "");
338 #endif /* __WKDM_ISA_2P_WORKAROUND__ */
339
340
341 /*
342 * macro to generate a sysctl machdep.cpu.sysreg_* for a given system register
343 * using __builtin_arm_rsr64.
344 */
345 #define SYSCTL_PROC_MACHDEP_CPU_SYSREG(name) \
346 static int \
347 sysctl_sysreg_##name SYSCTL_HANDLER_ARGS \
348 { \
349 _Pragma("unused(arg1, arg2, oidp)") \
350 uint64_t return_value = __builtin_arm_rsr64(#name); \
351 return SYSCTL_OUT(req, &return_value, sizeof(return_value)); \
352 } \
353 SYSCTL_PROC(_machdep_cpu, OID_AUTO, sysreg_##name, \
354 CTLFLAG_RD | CTLTYPE_QUAD | CTLFLAG_LOCKED, \
355 0, 0, sysctl_sysreg_##name, "Q", \
356 #name " register on the current CPU");
357
358
359 // CPU system registers
360 // ARM64: AArch64 Vector Base Address Register
361 SYSCTL_PROC_MACHDEP_CPU_SYSREG(VBAR_EL1);
362 // ARM64: AArch64 Memory Attribute Indirection Register
363 SYSCTL_PROC_MACHDEP_CPU_SYSREG(MAIR_EL1);
364 // ARM64: AArch64 Translation table base register 1
365 SYSCTL_PROC_MACHDEP_CPU_SYSREG(TTBR1_EL1);
366 // ARM64: AArch64 System Control Register
367 SYSCTL_PROC_MACHDEP_CPU_SYSREG(SCTLR_EL1);
368 // ARM64: AArch64 Translation Control Register
369 SYSCTL_PROC_MACHDEP_CPU_SYSREG(TCR_EL1);
370 // ARM64: AArch64 Memory Model Feature Register 0
371 SYSCTL_PROC_MACHDEP_CPU_SYSREG(ID_AA64MMFR0_EL1);
372 // ARM64: AArch64 Instruction Set Attribute Register 1
373 SYSCTL_PROC_MACHDEP_CPU_SYSREG(ID_AA64ISAR1_EL1);
374 #if APPLE_ARM64_ARCH_FAMILY
375 // Apple ID Register
376 SYSCTL_PROC_MACHDEP_CPU_SYSREG(AIDR_EL1);
377 #endif /* APPLE_ARM64_ARCH_FAMILY */
378
379 #endif /* DEVELOPMENT || DEBUG */
380
381
382 #ifdef ML_IO_TIMEOUTS_ENABLED
383 /*
384 * Timeouts for ml_{io|phys}_{read|write}...
385 * RO on DEVELOPMENT/DEBUG kernels.
386 */
387
388 #if DEVELOPMENT || DEBUG
389 #define MMIO_TIMEOUT_FLAGS (CTLFLAG_KERN | CTLFLAG_RW | CTLFLAG_LOCKED)
390 #else
391 #define MMIO_TIMEOUT_FLAGS (CTLFLAG_KERN | CTLFLAG_RD | CTLFLAG_LOCKED)
392 #endif
393
394 SYSCTL_QUAD(_machdep, OID_AUTO, report_phy_read_delay, MMIO_TIMEOUT_FLAGS,
395 &report_phy_read_delay_to, "Maximum time before io/phys read gets reported or panics");
396 SYSCTL_QUAD(_machdep, OID_AUTO, report_phy_write_delay, MMIO_TIMEOUT_FLAGS,
397 &report_phy_write_delay_to, "Maximum time before io/phys write gets reported or panics");
398 SYSCTL_QUAD(_machdep, OID_AUTO, trace_phy_read_delay, MMIO_TIMEOUT_FLAGS,
399 &trace_phy_read_delay_to, "Maximum time before io/phys read gets ktraced");
400 SYSCTL_QUAD(_machdep, OID_AUTO, trace_phy_write_delay, MMIO_TIMEOUT_FLAGS,
401 &trace_phy_write_delay_to, "Maximum time before io/phys write gets ktraced");
402
403 SYSCTL_INT(_machdep, OID_AUTO, phy_read_delay_panic, CTLFLAG_KERN | CTLFLAG_RW | CTLFLAG_LOCKED,
404 &phy_read_panic, 0, "if set, report-phy-read-delay timeout panics");
405 SYSCTL_INT(_machdep, OID_AUTO, phy_write_delay_panic, CTLFLAG_KERN | CTLFLAG_RW | CTLFLAG_LOCKED,
406 &phy_write_panic, 0, "if set, report-phy-write-delay timeout panics");
407
408 #if ML_IO_SIMULATE_STRETCHED_ENABLED
409 SYSCTL_QUAD(_machdep, OID_AUTO, sim_stretched_io_ns, CTLFLAG_KERN | CTLFLAG_RW | CTLFLAG_LOCKED,
410 &simulate_stretched_io, "simulate stretched io in ml_read_io, ml_write_io");
411 #endif /* ML_IO_SIMULATE_STRETCHED_ENABLED */
412
413 #endif /* ML_IO_TIMEOUTS_ENABLED */
414