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