]> git.saurik.com Git - apple/xnu.git/blobdiff - bsd/dev/arm64/sysctl.c
xnu-7195.101.1.tar.gz
[apple/xnu.git] / bsd / dev / arm64 / sysctl.c
index deb952d44aaef2ad793a7d4cc239cbc7bdbc4b84..70c3bf468433334425a4fd0b1177352c137c7228 100644 (file)
 #include <mach/host_info.h>
 #include <mach/mach_host.h>
 #include <arm/cpuid.h>
+#include <kern/zalloc.h>
 #include <libkern/libkern.h>
+#include <pexpert/device_tree.h>
 
-extern uint64_t        wake_abstime;
+#if HYPERVISOR
+#include <kern/hv_support.h>
+#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 */
+