2 * Copyright (c) 2003-2007 Apple Inc. All rights reserved.
5 #include <sys/kernel.h>
6 #include <sys/sysctl.h>
8 #include <machine/machine_routines.h>
10 #include <mach/host_info.h>
11 #include <mach/mach_host.h>
12 #include <arm/cpuid.h>
13 #include <libkern/libkern.h>
16 #include <kern/hv_support.h>
19 extern uint64_t wake_abstime
;
20 extern int lck_mtx_adaptive_spin_mode
;
23 SYSCTL_QUAD(_machdep
, OID_AUTO
, wake_abstime
,
24 CTLFLAG_RD
, &wake_abstime
,
25 "Absolute Time at the last wakeup");
28 sysctl_time_since_reset SYSCTL_HANDLER_ARGS
30 #pragma unused(arg1, arg2, oidp)
31 uint64_t return_value
= ml_get_time_since_reset();
32 return SYSCTL_OUT(req
, &return_value
, sizeof(return_value
));
35 SYSCTL_PROC(_machdep
, OID_AUTO
, time_since_reset
,
36 CTLFLAG_RD
| CTLTYPE_QUAD
| CTLFLAG_LOCKED
,
37 0, 0, sysctl_time_since_reset
, "I",
38 "Continuous time since last SOC boot/wake started");
41 sysctl_wake_conttime SYSCTL_HANDLER_ARGS
43 #pragma unused(arg1, arg2, oidp)
44 uint64_t return_value
= ml_get_conttime_wake_time();
45 return SYSCTL_OUT(req
, &return_value
, sizeof(return_value
));
48 SYSCTL_PROC(_machdep
, OID_AUTO
, wake_conttime
,
49 CTLFLAG_RD
| CTLTYPE_QUAD
| CTLFLAG_LOCKED
,
50 0, 0, sysctl_wake_conttime
, "I",
51 "Continuous Time at the last wakeup");
55 cpu_signal_deferred_timer(__unused
struct sysctl_oid
*oidp
, __unused
void *arg1
, __unused
int arg2
, struct sysctl_req
*req
)
60 int old_value
= (int)ml_cpu_signal_deferred_get_timer();
62 int error
= sysctl_io_number(req
, old_value
, sizeof(int), &new_value
, &changed
);
64 if (error
== 0 && changed
) {
65 ml_cpu_signal_deferred_adjust_timer((uint64_t)new_value
);
71 SYSCTL_PROC(_machdep
, OID_AUTO
, deferred_ipi_timeout
,
72 CTLTYPE_INT
| CTLFLAG_RW
| CTLFLAG_LOCKED
,
74 cpu_signal_deferred_timer
, "I", "Deferred IPI timeout (nanoseconds)");
76 #endif /* defined(HAS_IPI) */
79 * For source compatibility, here's some machdep.cpu mibs that
80 * use host_info() to simulate reasonable answers.
83 SYSCTL_NODE(_machdep
, OID_AUTO
, cpu
, CTLFLAG_RW
| CTLFLAG_LOCKED
, 0,
87 arm_host_info SYSCTL_HANDLER_ARGS
89 __unused
struct sysctl_oid
*unused_oidp
= oidp
;
91 host_basic_info_data_t hinfo
;
92 mach_msg_type_number_t count
= HOST_BASIC_INFO_COUNT
;
94 kern_return_t kret
= host_info((host_t
)BSD_HOST
,
95 HOST_BASIC_INFO
, (host_info_t
)&hinfo
, &count
);
96 if (KERN_SUCCESS
!= kret
) {
100 if (sizeof(uint32_t) != arg2
) {
101 panic("size mismatch");
104 uintptr_t woffset
= (uintptr_t)arg1
/ sizeof(uint32_t);
105 uint32_t datum
= *(uint32_t *)(((uint32_t *)&hinfo
) + woffset
);
106 return SYSCTL_OUT(req
, &datum
, sizeof(datum
));
110 * machdep.cpu.cores_per_package
112 * x86: derived from CPUID data.
113 * ARM: how many physical cores we have in the AP; aka hw.physicalcpu_max
116 SYSCTL_PROC(_machdep_cpu
, OID_AUTO
, cores_per_package
,
117 CTLTYPE_INT
| CTLFLAG_RD
| CTLFLAG_LOCKED
,
118 (void *)offsetof(host_basic_info_data_t
, physical_cpu_max
),
120 arm_host_info
, "I", "CPU cores per package");
123 * machdep.cpu.core_count
125 * x86: derived from CPUID data.
126 * ARM: # active physical cores in the AP; aka hw.physicalcpu
129 SYSCTL_PROC(_machdep_cpu
, OID_AUTO
, core_count
,
130 CTLTYPE_INT
| CTLFLAG_RD
| CTLFLAG_LOCKED
,
131 (void *)offsetof(host_basic_info_data_t
, physical_cpu
),
133 arm_host_info
, "I", "Number of enabled cores per package");
136 * machdep.cpu.logical_per_package
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
143 SYSCTL_PROC(_machdep_cpu
, OID_AUTO
, logical_per_package
,
144 CTLTYPE_INT
| CTLFLAG_RD
| CTLFLAG_LOCKED
,
145 (void *)offsetof(host_basic_info_data_t
, logical_cpu_max
),
147 arm_host_info
, "I", "CPU logical cpus per package");
150 * machdep.cpu.thread_count
152 * x86: derived from CPUID data.
153 * ARM: # active logical cores in the AP; aka hw.logicalcpu
156 SYSCTL_PROC(_machdep_cpu
, OID_AUTO
, thread_count
,
157 CTLTYPE_INT
| CTLFLAG_RD
| CTLFLAG_LOCKED
,
158 (void *)offsetof(host_basic_info_data_t
, logical_cpu
),
160 arm_host_info
, "I", "Number of enabled threads per package");
163 * machdep.cpu.brand_string
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.
171 make_brand_string SYSCTL_HANDLER_ARGS
173 __unused
struct sysctl_oid
*unused_oidp
= oidp
;
174 __unused
void *unused_arg1
= arg1
;
175 __unused
int unused_arg2
= arg2
;
179 switch (cpuid_info()->arm_info
.arm_implementor
) {
187 impl
= "ARM architecture";
193 snprintf(buf
, sizeof(buf
), "%s processor", impl
);
194 return SYSCTL_OUT(req
, buf
, strlen(buf
) + 1);
197 SYSCTL_PROC(_machdep_cpu
, OID_AUTO
, brand_string
,
198 CTLTYPE_STRING
| CTLFLAG_RD
| CTLFLAG_LOCKED
,
199 0, 0, make_brand_string
, "A", "CPU brand string");
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");
208 virtual_address_size SYSCTL_HANDLER_ARGS
210 #pragma unused(arg1, arg2, oidp)
211 int return_value
= 64 - T0SZ_BOOT
;
212 return SYSCTL_OUT(req
, &return_value
, sizeof(return_value
));
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");
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");
229 * macro to generate a sysctl machdep.cpu.sysreg_* for a given system register
230 * using __builtin_arm_rsr64.
232 #define SYSCTL_PROC_MACHDEP_CPU_SYSREG(name) \
234 sysctl_sysreg_##name SYSCTL_HANDLER_ARGS \
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)); \
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");
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
);
262 * ARM64: AArch64 Guarded Execution Mode GENTER Vector
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.
268 #endif /* DEVELOPMENT || DEBUG */
271 SYSCTL_NODE(_kern
, OID_AUTO
, hv
, CTLFLAG_RW
| CTLFLAG_LOCKED
, 0, "Hypervisor info");
273 SYSCTL_INT(_kern_hv
, OID_AUTO
, supported
,
274 CTLFLAG_KERN
| CTLFLAG_RD
| CTLFLAG_LOCKED
,
275 &hv_support_available
, 0, "");
277 extern unsigned int arm64_num_vmids
;
279 SYSCTL_UINT(_kern_hv
, OID_AUTO
, max_address_spaces
,
280 CTLFLAG_KERN
| CTLFLAG_RD
| CTLFLAG_LOCKED
,
281 &arm64_num_vmids
, 0, "");
283 extern uint64_t pmap_ipa_size(uint64_t granule
);
286 sysctl_ipa_size_16k SYSCTL_HANDLER_ARGS
288 #pragma unused(arg1, arg2, oidp)
289 uint64_t return_value
= pmap_ipa_size(16384);
290 return SYSCTL_OUT(req
, &return_value
, sizeof(return_value
));
293 SYSCTL_PROC(_kern_hv
, OID_AUTO
, ipa_size_16k
,
294 CTLFLAG_RD
| CTLTYPE_QUAD
| CTLFLAG_LOCKED
,
295 0, 0, sysctl_ipa_size_16k
, "P",
296 "Maximum size allowed for 16K-page guest IPA spaces");
299 sysctl_ipa_size_4k SYSCTL_HANDLER_ARGS
301 #pragma unused(arg1, arg2, oidp)
302 uint64_t return_value
= pmap_ipa_size(4096);
303 return SYSCTL_OUT(req
, &return_value
, sizeof(return_value
));
306 SYSCTL_PROC(_kern_hv
, OID_AUTO
, ipa_size_4k
,
307 CTLFLAG_RD
| CTLTYPE_QUAD
| CTLFLAG_LOCKED
,
308 0, 0, sysctl_ipa_size_4k
, "P",
309 "Maximum size allowed for 4K-page guest IPA spaces");