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