X-Git-Url: https://git.saurik.com/apple/xnu.git/blobdiff_plain/d9a64523371fa019c4575bb400cbbc3a50ac9903..refs/heads/master:/bsd/dev/arm64/sysctl.c diff --git a/bsd/dev/arm64/sysctl.c b/bsd/dev/arm64/sysctl.c index deb952d44..70c3bf468 100644 --- a/bsd/dev/arm64/sysctl.c +++ b/bsd/dev/arm64/sysctl.c @@ -10,61 +10,80 @@ #include #include #include +#include #include +#include -extern uint64_t wake_abstime; +#if HYPERVISOR +#include +#endif + +extern uint64_t wake_abstime; +extern int lck_mtx_adaptive_spin_mode; static SYSCTL_QUAD(_machdep, OID_AUTO, wake_abstime, - CTLFLAG_RD, &wake_abstime, - "Absolute Time at the last wakeup"); + CTLFLAG_RD, &wake_abstime, + "Absolute Time at the last wakeup"); static int sysctl_time_since_reset SYSCTL_HANDLER_ARGS { #pragma unused(arg1, arg2, oidp) - int error = 0; - uint64_t return_value = 0; - - return_value = ml_get_time_since_reset(); - - SYSCTL_OUT(req, &return_value, sizeof(return_value)); - - return error; + uint64_t return_value = ml_get_time_since_reset(); + return SYSCTL_OUT(req, &return_value, sizeof(return_value)); } SYSCTL_PROC(_machdep, OID_AUTO, time_since_reset, - CTLFLAG_RD | CTLTYPE_QUAD | CTLFLAG_LOCKED, - 0, 0, sysctl_time_since_reset, "I", - "Continuous time since last SOC boot/wake started"); + CTLFLAG_RD | CTLTYPE_QUAD | CTLFLAG_LOCKED, + 0, 0, sysctl_time_since_reset, "I", + "Continuous time since last SOC boot/wake started"); static int sysctl_wake_conttime SYSCTL_HANDLER_ARGS { #pragma unused(arg1, arg2, oidp) - int error = 0; - uint64_t return_value = 0; + uint64_t return_value = ml_get_conttime_wake_time(); + return SYSCTL_OUT(req, &return_value, sizeof(return_value)); +} + +SYSCTL_PROC(_machdep, OID_AUTO, wake_conttime, + CTLFLAG_RD | CTLTYPE_QUAD | CTLFLAG_LOCKED, + 0, 0, sysctl_wake_conttime, "I", + "Continuous Time at the last wakeup"); + +#if defined(HAS_IPI) +static int +cpu_signal_deferred_timer(__unused struct sysctl_oid *oidp, __unused void *arg1, __unused int arg2, struct sysctl_req *req) +{ + int new_value = 0; + int changed = 0; - return_value = ml_get_conttime_wake_time(); + int old_value = (int)ml_cpu_signal_deferred_get_timer(); - SYSCTL_OUT(req, &return_value, sizeof(return_value)); + int error = sysctl_io_number(req, old_value, sizeof(int), &new_value, &changed); + + if (error == 0 && changed) { + ml_cpu_signal_deferred_adjust_timer((uint64_t)new_value); + } return error; } -SYSCTL_PROC(_machdep, OID_AUTO, wake_conttime, - CTLFLAG_RD | CTLTYPE_QUAD | CTLFLAG_LOCKED, - 0, 0, sysctl_wake_conttime, "I", - "Continuous Time at the last wakeup"); +SYSCTL_PROC(_machdep, OID_AUTO, deferred_ipi_timeout, + CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_LOCKED, + 0, 0, + cpu_signal_deferred_timer, "I", "Deferred IPI timeout (nanoseconds)"); +#endif /* defined(HAS_IPI) */ /* * For source compatibility, here's some machdep.cpu mibs that * use host_info() to simulate reasonable answers. */ -SYSCTL_NODE(_machdep, OID_AUTO, cpu, CTLFLAG_RW|CTLFLAG_LOCKED, 0, - "CPU info"); +SYSCTL_NODE(_machdep, OID_AUTO, cpu, CTLFLAG_RW | CTLFLAG_LOCKED, 0, + "CPU info"); static int arm_host_info SYSCTL_HANDLER_ARGS @@ -73,18 +92,20 @@ arm_host_info SYSCTL_HANDLER_ARGS host_basic_info_data_t hinfo; mach_msg_type_number_t count = HOST_BASIC_INFO_COUNT; -#define BSD_HOST 1 +#define BSD_HOST 1 kern_return_t kret = host_info((host_t)BSD_HOST, - HOST_BASIC_INFO, (host_info_t)&hinfo, &count); - if (KERN_SUCCESS != kret) - return (EINVAL); + HOST_BASIC_INFO, (host_info_t)&hinfo, &count); + if (KERN_SUCCESS != kret) { + return EINVAL; + } - if (sizeof (uint32_t) != arg2) + if (sizeof(uint32_t) != arg2) { panic("size mismatch"); + } - uintptr_t woffset = (uintptr_t)arg1 / sizeof (uint32_t); + uintptr_t woffset = (uintptr_t)arg1 / sizeof(uint32_t); uint32_t datum = *(uint32_t *)(((uint32_t *)&hinfo) + woffset); - return (SYSCTL_OUT(req, &datum, sizeof (datum))); + return SYSCTL_OUT(req, &datum, sizeof(datum)); } /* @@ -95,10 +116,10 @@ arm_host_info SYSCTL_HANDLER_ARGS */ static SYSCTL_PROC(_machdep_cpu, OID_AUTO, cores_per_package, - CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_LOCKED, - (void *)offsetof(host_basic_info_data_t, physical_cpu_max), - sizeof (integer_t), - arm_host_info, "I", "CPU cores per package"); + CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_LOCKED, + (void *)offsetof(host_basic_info_data_t, physical_cpu_max), + sizeof(integer_t), + arm_host_info, "I", "CPU cores per package"); /* * machdep.cpu.core_count @@ -108,10 +129,10 @@ SYSCTL_PROC(_machdep_cpu, OID_AUTO, cores_per_package, */ static SYSCTL_PROC(_machdep_cpu, OID_AUTO, core_count, - CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_LOCKED, - (void *)offsetof(host_basic_info_data_t, physical_cpu), - sizeof (integer_t), - arm_host_info, "I", "Number of enabled cores per package"); + CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_LOCKED, + (void *)offsetof(host_basic_info_data_t, physical_cpu), + sizeof(integer_t), + arm_host_info, "I", "Number of enabled cores per package"); /* * machdep.cpu.logical_per_package @@ -122,10 +143,10 @@ SYSCTL_PROC(_machdep_cpu, OID_AUTO, core_count, */ static SYSCTL_PROC(_machdep_cpu, OID_AUTO, logical_per_package, - CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_LOCKED, - (void *)offsetof(host_basic_info_data_t, logical_cpu_max), - sizeof (integer_t), - arm_host_info, "I", "CPU logical cpus per package"); + CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_LOCKED, + (void *)offsetof(host_basic_info_data_t, logical_cpu_max), + sizeof(integer_t), + arm_host_info, "I", "CPU logical cpus per package"); /* * machdep.cpu.thread_count @@ -135,17 +156,54 @@ SYSCTL_PROC(_machdep_cpu, OID_AUTO, logical_per_package, */ static SYSCTL_PROC(_machdep_cpu, OID_AUTO, thread_count, - CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_LOCKED, - (void *)offsetof(host_basic_info_data_t, logical_cpu), - sizeof (integer_t), - arm_host_info, "I", "Number of enabled threads per package"); + CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_LOCKED, + (void *)offsetof(host_basic_info_data_t, logical_cpu), + sizeof(integer_t), + arm_host_info, "I", "Number of enabled threads per package"); + +static SECURITY_READ_ONLY_LATE(char*) brand_string = NULL; +static SECURITY_READ_ONLY_LATE(size_t) brand_string_len = 0; + +/* + * SecureDTLookupEntry() is only guaranteed to work before PE_init_iokit(), + * so we load the brand string (if available) in a startup handler. + */ +__startup_func +static void +sysctl_load_brand_string(void) +{ + DTEntry node; + void const *value = NULL; + unsigned int size = 0; + + if (kSuccess != SecureDTLookupEntry(0, "/product", &node)) { + return; + } + + if (kSuccess != SecureDTGetProperty(node, "product-soc-name", (void const **) &value, &size)) { + return; + } + + if (size == 0) { + return; + } + + brand_string = zalloc_permanent(size, ZALIGN_NONE); + if (brand_string == NULL) { + return; + } + + memcpy(brand_string, value, size); + brand_string_len = size; +} +STARTUP(SYSCTL, STARTUP_RANK_MIDDLE, sysctl_load_brand_string); /* * machdep.cpu.brand_string * * x86: derived from CPUID data. - * ARM: cons something up from the CPUID register. Could include cpufamily - * here and map it to a "marketing" name, but there's no obvious need; + * ARM: Grab the product string from the device tree, if it exists. + * Otherwise, cons something up from the CPUID register. * the value is already exported via the commpage. So keep it simple. */ static int @@ -155,6 +213,10 @@ make_brand_string SYSCTL_HANDLER_ARGS __unused void *unused_arg1 = arg1; __unused int unused_arg2 = arg2; + if (brand_string != NULL) { + return SYSCTL_OUT(req, brand_string, brand_string_len); + } + const char *impl; switch (cpuid_info()->arm_info.arm_implementor) { @@ -168,11 +230,77 @@ make_brand_string SYSCTL_HANDLER_ARGS impl = "ARM architecture"; break; } + + char buf[80]; - snprintf(buf, sizeof (buf), "%s processor", impl); - return (SYSCTL_OUT(req, buf, strlen(buf) + 1)); + snprintf(buf, sizeof(buf), "%s processor", impl); + return SYSCTL_OUT(req, buf, strlen(buf) + 1); } SYSCTL_PROC(_machdep_cpu, OID_AUTO, brand_string, - CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_LOCKED, - 0, 0, make_brand_string, "A", "CPU brand string"); + CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_LOCKED, + 0, 0, make_brand_string, "A", "CPU brand string"); + + +static +SYSCTL_INT(_machdep, OID_AUTO, lck_mtx_adaptive_spin_mode, + CTLFLAG_RW, &lck_mtx_adaptive_spin_mode, 0, + "Enable adaptive spin behavior for kernel mutexes"); + +static int +virtual_address_size SYSCTL_HANDLER_ARGS +{ +#pragma unused(arg1, arg2, oidp) + int return_value = 64 - T0SZ_BOOT; + return SYSCTL_OUT(req, &return_value, sizeof(return_value)); +} + +static +SYSCTL_PROC(_machdep, OID_AUTO, virtual_address_size, + CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_LOCKED, + 0, 0, virtual_address_size, "I", + "Number of addressable bits in userspace virtual addresses"); + + +#if DEVELOPMENT || DEBUG +extern uint64_t TLockTimeOut; +SYSCTL_QUAD(_machdep, OID_AUTO, tlto, + CTLFLAG_RW | CTLFLAG_LOCKED, &TLockTimeOut, + "Ticket spinlock timeout (MATUs): use with care"); + +/* + * macro to generate a sysctl machdep.cpu.sysreg_* for a given system register + * using __builtin_arm_rsr64. + */ +#define SYSCTL_PROC_MACHDEP_CPU_SYSREG(name) \ +static int \ +sysctl_sysreg_##name SYSCTL_HANDLER_ARGS \ +{ \ +_Pragma("unused(arg1, arg2, oidp)") \ + uint64_t return_value = __builtin_arm_rsr64(#name); \ + return SYSCTL_OUT(req, &return_value, sizeof(return_value)); \ +} \ +SYSCTL_PROC(_machdep_cpu, OID_AUTO, sysreg_##name, \ + CTLFLAG_RD | CTLTYPE_QUAD | CTLFLAG_LOCKED, \ + 0, 0, sysctl_sysreg_##name, "Q", \ + #name " register on the current CPU"); + + +// CPU system registers +// ARM64: AArch64 Vector Base Address Register +SYSCTL_PROC_MACHDEP_CPU_SYSREG(VBAR_EL1); +// ARM64: AArch64 Memory Attribute Indirection Register +SYSCTL_PROC_MACHDEP_CPU_SYSREG(MAIR_EL1); +// ARM64: AArch64 Translation table base register 1 +SYSCTL_PROC_MACHDEP_CPU_SYSREG(TTBR1_EL1); +// ARM64: AArch64 System Control Register +SYSCTL_PROC_MACHDEP_CPU_SYSREG(SCTLR_EL1); +// ARM64: AArch64 Translation Control Register +SYSCTL_PROC_MACHDEP_CPU_SYSREG(TCR_EL1); +// ARM64: AArch64 Memory Model Feature Register 0 +SYSCTL_PROC_MACHDEP_CPU_SYSREG(ID_AA64MMFR0_EL1); +// ARM64: AArch64 Instruction Set Attribute Register 1 +SYSCTL_PROC_MACHDEP_CPU_SYSREG(ID_AA64ISAR1_EL1); + +#endif /* DEVELOPMENT || DEBUG */ +