| 1 | /* |
| 2 | * Copyright (c) 2000-2020 Apple Inc. All rights reserved. |
| 3 | * |
| 4 | * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ |
| 5 | * |
| 6 | * This file contains Original Code and/or Modifications of Original Code |
| 7 | * as defined in and that are subject to the Apple Public Source License |
| 8 | * Version 2.0 (the 'License'). You may not use this file except in |
| 9 | * compliance with the License. The rights granted to you under the License |
| 10 | * may not be used to create, or enable the creation or redistribution of, |
| 11 | * unlawful or unlicensed copies of an Apple operating system, or to |
| 12 | * circumvent, violate, or enable the circumvention or violation of, any |
| 13 | * terms of an Apple operating system software license agreement. |
| 14 | * |
| 15 | * Please obtain a copy of the License at |
| 16 | * http://www.opensource.apple.com/apsl/ and read it before using this file. |
| 17 | * |
| 18 | * The Original Code and all software distributed under the License are |
| 19 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER |
| 20 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, |
| 21 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, |
| 22 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. |
| 23 | * Please see the License for the specific language governing rights and |
| 24 | * limitations under the License. |
| 25 | * |
| 26 | * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ |
| 27 | */ |
| 28 | /* |
| 29 | * @OSF_COPYRIGHT@ |
| 30 | */ |
| 31 | |
| 32 | #ifdef XNU_KERNEL_PRIVATE |
| 33 | |
| 34 | #ifndef _KERN_STARTUP_H_ |
| 35 | #define _KERN_STARTUP_H_ |
| 36 | |
| 37 | #include <stdbool.h> |
| 38 | #include <stddef.h> |
| 39 | #include <stdint.h> |
| 40 | |
| 41 | #include <libkern/section_keywords.h> |
| 42 | |
| 43 | __BEGIN_DECLS |
| 44 | |
| 45 | #pragma GCC visibility push(hidden) |
| 46 | |
| 47 | /*! |
| 48 | * @enum startup_subsystem_id_t |
| 49 | * |
| 50 | * @abstract |
| 51 | * Represents a stage of kernel intialization, ubnd allows for subsystems |
| 52 | * to register initializers for a specific stage. |
| 53 | * |
| 54 | * @discussion |
| 55 | * Documentation of each subsystem initialization sequence exists in |
| 56 | * @file doc/startup.md. |
| 57 | */ |
| 58 | __enum_decl(startup_subsystem_id_t, uint32_t, { |
| 59 | STARTUP_SUB_NONE = 0, /**< reserved for the startup subsystem */ |
| 60 | |
| 61 | STARTUP_SUB_TUNABLES, /**< support for the tunables subsystem */ |
| 62 | STARTUP_SUB_TIMEOUTS, /**< configurable machine timeouts */ |
| 63 | STARTUP_SUB_LOCKS, /**< various subsystem locks */ |
| 64 | STARTUP_SUB_KPRINTF, /**< kprintf initialization */ |
| 65 | |
| 66 | STARTUP_SUB_PMAP_STEAL, /**< to perform various pmap carveouts */ |
| 67 | STARTUP_SUB_KMEM, /**< once kmem_alloc is ready */ |
| 68 | STARTUP_SUB_ZALLOC, /**< initialize zalloc and kalloc */ |
| 69 | STARTUP_SUB_KTRACE, /**< initialize kernel trace */ |
| 70 | STARTUP_SUB_PERCPU, /**< initialize the percpu subsystem */ |
| 71 | STARTUP_SUB_EVENT, /**< initiailze the event subsystem */ |
| 72 | |
| 73 | STARTUP_SUB_CODESIGNING, /**< codesigning subsystem */ |
| 74 | STARTUP_SUB_OSLOG, /**< oslog and kernel logging */ |
| 75 | STARTUP_SUB_MACH_IPC, /**< Mach IPC */ |
| 76 | STARTUP_SUB_THREAD_CALL, /**< Thread calls */ |
| 77 | STARTUP_SUB_SYSCTL, /**< registers sysctls */ |
| 78 | STARTUP_SUB_EARLY_BOOT, /**< interrupts/preemption are turned on */ |
| 79 | |
| 80 | STARTUP_SUB_LOCKDOWN = ~0u, /**< reserved for the startup subsystem */ |
| 81 | }); |
| 82 | |
| 83 | /*! |
| 84 | * Stores the last subsystem to have been fully initialized; |
| 85 | */ |
| 86 | extern startup_subsystem_id_t startup_phase; |
| 87 | |
| 88 | /*! |
| 89 | * @enum startup_debug_t |
| 90 | * |
| 91 | * @abstract |
| 92 | * Flags set in the @c startup_debug global to configure startup debugging. |
| 93 | */ |
| 94 | __options_decl(startup_debug_t, uint32_t, { |
| 95 | STARTUP_DEBUG_NONE = 0x00000000, |
| 96 | STARTUP_DEBUG_VERBOSE = 0x00000001, |
| 97 | }); |
| 98 | |
| 99 | extern startup_debug_t startup_debug; |
| 100 | |
| 101 | /*! |
| 102 | * @enum startup_rank |
| 103 | * |
| 104 | * @abstract |
| 105 | * Specifies in which rank a given initializer runs within a given section |
| 106 | * to register initializers for a specific rank within the subsystem. |
| 107 | * |
| 108 | * @description |
| 109 | * A startup function, declared with @c STARTUP or @c STARTUP_ARG, can specify |
| 110 | * a rank within the subsystem they initialize. |
| 111 | * |
| 112 | * @c STARTUP_RANK_NTH(n) will let callbacks be run at stage @c n (0-based). |
| 113 | * |
| 114 | * @c STARTUP_RANK_FIRST, @c STARTUP_RANK_SECOND, @c STARTUP_RANK_THIRD and |
| 115 | * @c STARTUP_RANK_FOURTH are given as convenient names for these. |
| 116 | * |
| 117 | * @c STARTUP_RANK_MIDDLE is a reserved value that will let startup functions |
| 118 | * run after all the @c STARTUP_RANK_NTH(n) ones have. |
| 119 | * |
| 120 | * @c STARTUP_RANK_NTH_LATE_NTH(n) will let callbacks be run then in @c n rank |
| 121 | * after the @c STARTUP_RANK_MIDDLE ones (0-based). |
| 122 | * |
| 123 | * @c STARTUP_RANK_LAST callbacks will run absolutely last after everything |
| 124 | * else did for this subsystem. |
| 125 | */ |
| 126 | __enum_decl(startup_rank_t, uint32_t, { |
| 127 | #define STARTUP_RANK_NTH(n) ((startup_rank_t)(n - 1)) |
| 128 | STARTUP_RANK_FIRST = 0, |
| 129 | STARTUP_RANK_SECOND = 1, |
| 130 | STARTUP_RANK_THIRD = 2, |
| 131 | STARTUP_RANK_FOURTH = 3, |
| 132 | |
| 133 | STARTUP_RANK_MIDDLE = 0x7fffffff, |
| 134 | |
| 135 | #define STARTUP_RANK_LATE_NTH(n) \ |
| 136 | ((startup_rank_t)(STARTUP_RANK_MIDDLE + 1 + (n))) |
| 137 | |
| 138 | STARTUP_RANK_LAST = 0xffffffff, |
| 139 | }); |
| 140 | |
| 141 | #if KASAN |
| 142 | /* |
| 143 | * The use of weird sections that get unmapped confuse the hell out of kasan, |
| 144 | * so for KASAN leave things in regular __TEXT/__DATA segments |
| 145 | */ |
| 146 | #define STARTUP_CODE_SEGSECT "__TEXT,__text" |
| 147 | #define STARTUP_CONST_SEGSECT "__DATA_CONST,__init" |
| 148 | #define STARTUP_DATA_SEGSECT "__DATA,__init" |
| 149 | #define STARTUP_HOOK_SEGMENT "__DATA" |
| 150 | #define STARTUP_HOOK_SECTION "__init_entry_set" |
| 151 | #elif defined(__x86_64__) |
| 152 | /* Intel doesn't have a __BOOTDATA but doesn't protect __KLD */ |
| 153 | #define STARTUP_CODE_SEGSECT "__TEXT,__text" |
| 154 | #define STARTUP_CONST_SEGSECT "__KLDDATA,__const" |
| 155 | #define STARTUP_DATA_SEGSECT "__KLDDATA,__init" |
| 156 | #define STARTUP_HOOK_SEGMENT "__KLDDATA" |
| 157 | #define STARTUP_HOOK_SECTION "__init_entry_set" |
| 158 | #else |
| 159 | /* arm protects __KLD early, so use __BOOTDATA for data */ |
| 160 | #define STARTUP_CODE_SEGSECT "__TEXT,__text" |
| 161 | #define STARTUP_CONST_SEGSECT "__KLDDATA,__const" |
| 162 | #define STARTUP_DATA_SEGSECT "__BOOTDATA,__init" |
| 163 | #define STARTUP_HOOK_SEGMENT "__BOOTDATA" |
| 164 | #define STARTUP_HOOK_SECTION "__init_entry_set" |
| 165 | #endif |
| 166 | |
| 167 | /*! |
| 168 | * @macro __startup_func |
| 169 | * |
| 170 | * @abstract |
| 171 | * Attribute to place on functions used only during the kernel startup phase. |
| 172 | * |
| 173 | * @description |
| 174 | * Code marked with this attribute will be unmapped after kernel lockdown. |
| 175 | */ |
| 176 | #define __startup_func \ |
| 177 | __PLACE_IN_SECTION(STARTUP_CODE_SEGSECT) \ |
| 178 | __attribute__((cold, visibility("hidden"))) |
| 179 | |
| 180 | /*! |
| 181 | * @macro __startup_data |
| 182 | * |
| 183 | * @abstract |
| 184 | * Attribute to place on globals used during the kernel startup phase. |
| 185 | * |
| 186 | * @description |
| 187 | * Data marked with this attribute will be unmapped after kernel lockdown. |
| 188 | */ |
| 189 | #define __startup_data \ |
| 190 | __PLACE_IN_SECTION(STARTUP_DATA_SEGSECT) |
| 191 | |
| 192 | /*! |
| 193 | * @macro __startup_const |
| 194 | * |
| 195 | * @abstract |
| 196 | * Attribute to place on global constants used during the kernel startup phase. |
| 197 | * |
| 198 | * @description |
| 199 | * Data marked with this attribute will be unmapped after kernel lockdown. |
| 200 | * |
| 201 | * __startup_const implies const. Be mindful that for pointers, the `const` |
| 202 | * will end up on the wrong side of the star if you put __startup_const at the |
| 203 | * start of the declaration. |
| 204 | */ |
| 205 | #define __startup_const \ |
| 206 | __PLACE_IN_SECTION(STARTUP_CONST_SEGSECT) const |
| 207 | |
| 208 | /*! |
| 209 | * @macro STARTUP |
| 210 | * |
| 211 | * @abstract |
| 212 | * Declares a kernel startup callback. |
| 213 | */ |
| 214 | #define STARTUP(subsystem, rank, func) \ |
| 215 | __STARTUP(func, __LINE__, subsystem, rank, func) |
| 216 | |
| 217 | /*! |
| 218 | * @macro STARTUP_ARG |
| 219 | * |
| 220 | * @abstract |
| 221 | * Declares a kernel startup callback that takes an argument. |
| 222 | */ |
| 223 | #define STARTUP_ARG(subsystem, rank, func, arg) \ |
| 224 | __STARTUP_ARG(func, __LINE__, subsystem, rank, func, arg) |
| 225 | |
| 226 | /*! |
| 227 | * @macro TUNABLE |
| 228 | * |
| 229 | * @abstract |
| 230 | * Declares a read-only kernel tunable that is read from a boot-arg with |
| 231 | * a default value, without further processing. |
| 232 | * |
| 233 | * @param type_t |
| 234 | * Should be an integer type or bool. |
| 235 | * |
| 236 | * @param var |
| 237 | * The name of the C variable to use for storage. |
| 238 | * |
| 239 | * @param boot_arg |
| 240 | * The name of the boot-arg to parse for initialization |
| 241 | * |
| 242 | * @param default_value |
| 243 | * The default value for the tunable if the boot-arg is absent. |
| 244 | */ |
| 245 | #define TUNABLE(type_t, var, boot_arg, default_value) \ |
| 246 | SECURITY_READ_ONLY_LATE(type_t) var = default_value; \ |
| 247 | __TUNABLE(type_t, var, boot_arg) |
| 248 | |
| 249 | /*! |
| 250 | * @macro TUNABLE_WRITEABLE |
| 251 | * |
| 252 | * @abstract |
| 253 | * Declares a writeable kernel tunable that is read from a boot-arg with |
| 254 | * a default value, without further processing. |
| 255 | * |
| 256 | * @param type_t |
| 257 | * Should be an integer type or bool. |
| 258 | * |
| 259 | * @param var |
| 260 | * The name of the C variable to use for storage. |
| 261 | * |
| 262 | * @param boot_arg |
| 263 | * The name of the boot-arg to parse for initialization |
| 264 | * |
| 265 | * @param default_value |
| 266 | * The default value for the tunable if the boot-arg is absent. |
| 267 | */ |
| 268 | #define TUNABLE_WRITEABLE(type_t, var, boot_arg, default_value) \ |
| 269 | type_t var = default_value; \ |
| 270 | __TUNABLE(type_t, var, boot_arg) |
| 271 | |
| 272 | #if DEBUG || DEVELOPMENT |
| 273 | #define TUNABLE_DEV_WRITEABLE(type_t, var, boot_arg, default_value) \ |
| 274 | TUNABLE_WRITEABLE(type_t, var, boot_arg, default_value) |
| 275 | #else |
| 276 | #define TUNABLE_DEV_WRITEABLE(type_t, var, boot_arg, default_value) \ |
| 277 | TUNABLE(type_t, var, boot_arg, default_value) |
| 278 | #endif |
| 279 | |
| 280 | /*! |
| 281 | * @macro TUNABLE_STR |
| 282 | * |
| 283 | * @abstract |
| 284 | * Declares a read-only kernel tunable that is read from a boot-arg with |
| 285 | * a default value, without further processing. |
| 286 | * |
| 287 | * @param var |
| 288 | * The name of the C variable to use for storage. |
| 289 | * |
| 290 | * @param count |
| 291 | * The number of bytes in the buffer. |
| 292 | * |
| 293 | * @param boot_arg |
| 294 | * The name of the boot-arg to parse for initialization |
| 295 | * |
| 296 | * @param default_value |
| 297 | * The default value for the tunable if the boot-arg is absent. |
| 298 | */ |
| 299 | #define TUNABLE_STR(var, count, boot_arg, default_value) \ |
| 300 | char __security_const_late var[count] = default_value; \ |
| 301 | __TUNABLE_STR(var, boot_arg) |
| 302 | |
| 303 | /*! |
| 304 | * @enum tunable_dt_flags_t |
| 305 | * |
| 306 | * @abstract |
| 307 | * Flags used with the @c TUNABLE_DT* macros. |
| 308 | * |
| 309 | * @description |
| 310 | * If TUNABLE_DT_CHECK_CHOSEN is set, a value in |
| 311 | * /chosen/<dt_base>/<dt_name> takes precedence over any value in |
| 312 | * /<dt_base>/<dt_name>. /chosen is by convention the area where |
| 313 | * synthesized values not coming from the serialized device tree are |
| 314 | * being added, so this provides a way for e.g. the boot-loader to |
| 315 | * set/override tunables. |
| 316 | */ |
| 317 | __options_decl(tunable_dt_flags_t, uint32_t, { |
| 318 | TUNABLE_DT_NONE = 0x00000000, |
| 319 | TUNABLE_DT_CHECK_CHOSEN = 0x00000001, |
| 320 | }); |
| 321 | |
| 322 | /*! |
| 323 | * @macro TUNABLE_DT |
| 324 | * |
| 325 | * @abstract |
| 326 | * Like TUNABLE, but gets the initial value from both Device Tree and |
| 327 | * boot-args. The order in which the initial value is resolved is as |
| 328 | * follows, with later steps overriding previous ones (if they are |
| 329 | * specified): |
| 330 | * |
| 331 | * 1. Device Tree Entry "/<dt_base>/<dt_name>", |
| 332 | * 2. If TUNABLE_DT_CHECK_CHOSEN is set, Device Tree Entry |
| 333 | * "/chosen/<dt_base>/<dt_name>" (see the description for |
| 334 | * @c tunable_dt_flags_t), |
| 335 | * 3. boot-args. |
| 336 | * |
| 337 | * @param type_t |
| 338 | * Should be an integer type or bool. |
| 339 | * |
| 340 | * @param var |
| 341 | * The name of the C variable to use for storage. |
| 342 | * |
| 343 | * @param dt_base |
| 344 | * The name of the DT node containing the property. |
| 345 | * |
| 346 | * @param dt_name |
| 347 | * The name of the DT property containing the default value. |
| 348 | * |
| 349 | * @param boot_arg |
| 350 | * The name of the boot-arg overriding the initial value from the DT. |
| 351 | * |
| 352 | * @param default_value |
| 353 | * The default value for the tunable if both DT entry and boot-arg are |
| 354 | * absent. |
| 355 | * |
| 356 | * @param flags |
| 357 | * See the description for @c tunable_dt_flags_t. |
| 358 | */ |
| 359 | #define TUNABLE_DT(type_t, var, dt_base, dt_name, boot_arg, default_value, flags) \ |
| 360 | SECURITY_READ_ONLY_LATE(type_t) var = default_value; \ |
| 361 | __TUNABLE_DT(type_t, var, dt_base, dt_name, boot_arg, flags) |
| 362 | |
| 363 | /*! |
| 364 | * @macro TUNABLE_DT_WRITEABLE |
| 365 | * |
| 366 | * @abstract |
| 367 | * Like TUNABLE_WRITEABLE, but gets the initial value from both Device |
| 368 | * Tree and boot-args. The order in which the initial value is |
| 369 | * resolved is as follows, with later steps overriding previous ones |
| 370 | * (if they are specified): |
| 371 | * |
| 372 | * 1. Device Tree Entry "/<dt_base>/<dt_name>", |
| 373 | * 2. If TUNABLE_DT_CHECK_CHOSEN is set, Device Tree Entry |
| 374 | * "/chosen/<dt_base>/<dt_name>" (see the description for |
| 375 | * @c tunable_dt_flags_t), |
| 376 | * 3. boot-args. |
| 377 | * |
| 378 | * @param type_t |
| 379 | * Should be an integer type or bool. |
| 380 | * |
| 381 | * @param var |
| 382 | * The name of the C variable to use for storage. |
| 383 | * |
| 384 | * @param dt_base |
| 385 | * The name of the DT node containing the property. |
| 386 | * |
| 387 | * @param dt_name |
| 388 | * The name of the DT property containing the default value. |
| 389 | * |
| 390 | * @param boot_arg |
| 391 | * The name of the boot-arg overriding the initial value from the DT. |
| 392 | * |
| 393 | * @param default_value |
| 394 | * The default value for the tunable if both DT entry and boot-arg are |
| 395 | * absent. |
| 396 | * |
| 397 | * @param flags |
| 398 | * See the description for @c tunable_dt_flags_t. |
| 399 | */ |
| 400 | #define TUNABLE_DT_WRITEABLE(type_t, var, dt_base, dt_name, boot_arg, default_value, flags) \ |
| 401 | type_t var = default_value; \ |
| 402 | __TUNABLE_DT(type_t, var, dt_base, dt_name, boot_arg, flags) |
| 403 | |
| 404 | #if DEBUG || DEVELOPMENT |
| 405 | #define TUNABLE_DT_DEV_WRITEABLE(type_t, var, dt_base, dt_name, boot_arg, default_value, flags) \ |
| 406 | TUNABLE_DT_WRITEABLE(type_t, var, dt_base, dt_name, boot_arg, default_value, flags) |
| 407 | #else |
| 408 | #define TUNABLE_DT_DEV_WRITEABLE(type_t, var, dt_base, dt_name, boot_arg, default_value, flags) \ |
| 409 | TUNABLE_DT(type_t, var, dt_base, dt_name, boot_arg, default_value, flags) |
| 410 | #endif |
| 411 | |
| 412 | /* |
| 413 | * Machine Timeouts |
| 414 | * |
| 415 | * Machine Timeouts are timeouts for low level kernel code manifesting |
| 416 | * as _Atomic uint64_t variables, whose default value can be |
| 417 | * overridden and scaled via the device tree and boot-args. |
| 418 | * |
| 419 | * Each timeout has a name, looked up directly as the property name in |
| 420 | * the device tree in both the "/machine-timeouts" and |
| 421 | * "/chosen/machine-timeouts" nodes. The "chosen" property always |
| 422 | * overrides the other one. This allows fixed per-device timeouts in |
| 423 | * the device tree to be overridden by iBoot in "chosen". |
| 424 | * |
| 425 | * Additionally, the same name with "-scale" appended is looked up as |
| 426 | * properties for optional scale factors. Scale factors are not |
| 427 | * overridden by chosen, instead all scale factors (including global |
| 428 | * and/or boot-arg scale factors) combine by multiplication. |
| 429 | * |
| 430 | * The special name "global-scale" provides a scale that applies to |
| 431 | * every timeout. |
| 432 | * |
| 433 | * All property names can be used as boot-args by prefixing |
| 434 | * "ml-timeout-", e.g. th global scale is available as the |
| 435 | * "ml-timeout-global-scale" boot-arg. |
| 436 | * |
| 437 | * By convention, if the timeout value resolves to 0, the timeout |
| 438 | * should be disabled. |
| 439 | */ |
| 440 | |
| 441 | /* |
| 442 | * Machine Timeouts types. See the next section for what unit |
| 443 | * they are in. |
| 444 | * |
| 445 | * We use _Atomic, but only with relaxed ordering: This is just to |
| 446 | * make sure all devices see consistent values all the time. Since |
| 447 | * the actual timeout value will be seen as 0 before initializaton, |
| 448 | * relaxed ordering means that code that runs concurrently with |
| 449 | * initialization only risks to see a disabled timeout during early |
| 450 | * boot. |
| 451 | */ |
| 452 | typedef _Atomic uint64_t machine_timeout_t; |
| 453 | |
| 454 | /* |
| 455 | * Units |
| 456 | * |
| 457 | * Machine Timeouts are ALWAYS in picoseconds in the device tree or |
| 458 | * boot-args, to avoid confusion when changing or comparing timeouts |
| 459 | * as a user, but the actual storage value might contain the same |
| 460 | * duration in another unit, calculated by the initialization code. |
| 461 | * |
| 462 | * This is done because otherwise we would likely introduce another |
| 463 | * multiplication in potentially hot code paths, given that code that |
| 464 | * actually uses the timeout storage variable is unlikely to work with |
| 465 | * picosecond values when comparing against the timeout deadline. |
| 466 | * |
| 467 | * This unit scale is *only* applied during initialization at early |
| 468 | * boot, and only if the timeout's default value was overridden |
| 469 | * through the device tree or a boot-arg. |
| 470 | */ |
| 471 | #define MACHINE_TIMEOUT_UNIT_PSEC 1 |
| 472 | #define MACHINE_TIMEOUT_UNIT_NSEC 1000 |
| 473 | #define MACHINE_TIMEOUT_UNIT_USEC (1000*1000) |
| 474 | #define MACHINE_TIMEOUT_UNIT_MSEC (1000*1000*1000) |
| 475 | // Special unit for timebase ticks (usually 1/24MHz) |
| 476 | #define MACHINE_TIMEOUT_UNIT_TIMEBASE 0 |
| 477 | |
| 478 | // DT property names are limited to 31 chars, minus "-global" suffix |
| 479 | #define MACHINE_TIMEOUT_MAX_NAME_LEN 25 |
| 480 | struct machine_timeout_spec { |
| 481 | void *ptr; |
| 482 | uint64_t default_value; |
| 483 | uint64_t unit_scale; |
| 484 | char name[MACHINE_TIMEOUT_MAX_NAME_LEN + 1]; |
| 485 | bool (*skip_predicate)(struct machine_timeout_spec const *); |
| 486 | }; |
| 487 | |
| 488 | extern void |
| 489 | machine_timeout_init_with_suffix(const struct machine_timeout_spec *spec, char const *phase_suffix); |
| 490 | |
| 491 | extern void |
| 492 | machine_timeout_init(const struct machine_timeout_spec *spec); |
| 493 | |
| 494 | #if DEVELOPMENT || DEBUG |
| 495 | // Late timeout (re-)initialization, at the end of bsd_init() |
| 496 | extern void |
| 497 | machine_timeout_bsd_init(void); |
| 498 | #endif /* DEVELOPMENT || DEBUG */ |
| 499 | |
| 500 | /*! |
| 501 | * @macro MACHINE_TIMEOUT and MACHINE_TIMEOUT_DEV_WRITEABLE |
| 502 | * |
| 503 | * @abstract |
| 504 | * Defines a Machine Timeout that can be overridden and |
| 505 | * scaled through the device tree and boot-args. |
| 506 | * |
| 507 | * The variant with the _DEV_WRITEABLE suffix does not mark the timeout as |
| 508 | * SECURITY_READ_ONLY_LATE on DEVELOPMENT kernels, so that e.g. |
| 509 | * machine_timeout_init_with_suffix or sysctls can change it after lockdown. |
| 510 | * |
| 511 | * @param var |
| 512 | * The name of the C variable to use for storage. If the storage value |
| 513 | * contains 0, the timeout is considered disabled by convention. |
| 514 | * |
| 515 | * @param timeout_name |
| 516 | * The name of the timeout, used for property and boot-arg names. See |
| 517 | * the general description of Machine Timeouts above for how this name |
| 518 | * ends up being used. |
| 519 | * |
| 520 | * @param timeout_default |
| 521 | * The default value for the timeout if not specified through device |
| 522 | * tree or boot-arg. Will still be scaled if a scale factor exists. |
| 523 | * |
| 524 | * @param var_unit |
| 525 | * The unit that the storage variable is in. Note that timeout values |
| 526 | * must always be specified as picoseconds in the device tree and |
| 527 | * boot-args, but timeout initialization will convert the value to the |
| 528 | * unit specified here before writing it to the storage variable. |
| 529 | * |
| 530 | * @param skip_predicate |
| 531 | * Optionally, a function to call to decide whether the timeout should |
| 532 | * be set or not. If NULL, the timeout will always be set (if |
| 533 | * specified anywhere). A predicate has the following signature: |
| 534 | * bool skip_predicate (struct machine_timeout_spec const *) |
| 535 | */ |
| 536 | |
| 537 | #define _MACHINE_TIMEOUT(var, timeout_name, timeout_default, var_unit, skip_pred) \ |
| 538 | struct machine_timeout_spec \ |
| 539 | __machine_timeout_spec_ ## var = { \ |
| 540 | .ptr = &var, \ |
| 541 | .default_value = timeout_default, \ |
| 542 | .unit_scale = var_unit, \ |
| 543 | .name = timeout_name, \ |
| 544 | .skip_predicate = skip_pred, \ |
| 545 | }; \ |
| 546 | __STARTUP_ARG(var, __LINE__, TIMEOUTS, STARTUP_RANK_FIRST, \ |
| 547 | machine_timeout_init, &__machine_timeout_spec_ ## var) |
| 548 | |
| 549 | #define MACHINE_TIMEOUT(var, name, default, unit, skip_predicate) \ |
| 550 | SECURITY_READ_ONLY_LATE(machine_timeout_t) var = 0; \ |
| 551 | _MACHINE_TIMEOUT(var, name, default, unit, skip_predicate) |
| 552 | |
| 553 | #if DEVELOPMENT || DEBUG |
| 554 | #define MACHINE_TIMEOUT_DEV_WRITEABLE(var, name, default, unit, skip_predicate) \ |
| 555 | machine_timeout_t var = 0; \ |
| 556 | _MACHINE_TIMEOUT(var, name, default, unit, skip_predicate) |
| 557 | #else |
| 558 | #define MACHINE_TIMEOUT_DEV_WRITEABLE(var, name, default, unit, skip_predicate) \ |
| 559 | MACHINE_TIMEOUT(var, name, default, unit, skip_predicate) |
| 560 | #endif /* DEVELOPMENT || DEBUG */ |
| 561 | |
| 562 | /*! |
| 563 | * @macro MACHINE_TIMEOUT_SPEC_REF |
| 564 | * |
| 565 | * @abstract |
| 566 | * References a previously defined MACHINE_TIMEOUT. |
| 567 | * |
| 568 | * This is primarily useful for overriding individual timeouts |
| 569 | * at arbitrary times (even after boot), by manually calling |
| 570 | * machine_timeout_init_with_suffix() with this macro |
| 571 | * as first argument, and a suffix to apply to both device tree and |
| 572 | * boot-arg as second argument. |
| 573 | * |
| 574 | * @param var |
| 575 | * The name of the C variable used for storage, as it was specified |
| 576 | * in MACHINE_TIMEOUT. |
| 577 | */ |
| 578 | #define MACHINE_TIMEOUT_SPEC_REF(var) (&__machine_timeout_spec_ ## var) |
| 579 | |
| 580 | /*! |
| 581 | * @macro MACHINE_TIMEOUT_SPEC_DECL |
| 582 | * |
| 583 | * @abstract |
| 584 | * Declaration of machine timeout spec, mostly useful to make it known |
| 585 | * for MACHINE_TIMEOUT_SPEC_REF. |
| 586 | * |
| 587 | * @param var |
| 588 | * The name of the C variable used for storage, as it was specified |
| 589 | * in MACHINE_TIMEOUT. |
| 590 | */ |
| 591 | #define MACHINE_TIMEOUT_SPEC_DECL(var) extern struct machine_timeout_spec __machine_timeout_spec_ ## var |
| 592 | |
| 593 | /* |
| 594 | * Event subsystem |
| 595 | * |
| 596 | * This allows to define a few system-wide events that allow for loose coupling |
| 597 | * between subsystems interested in those events and the emitter. |
| 598 | */ |
| 599 | |
| 600 | /*! |
| 601 | * @macro EVENT_DECLARE() |
| 602 | * |
| 603 | * @brief |
| 604 | * Declares an event namespace with a given callback type. |
| 605 | * |
| 606 | * @param name The name for the event (typically in all caps). |
| 607 | * @param cb_type_t A function type for the callbacks. |
| 608 | */ |
| 609 | #define EVENT_DECLARE(name, cb_type_t) \ |
| 610 | struct name##_event { \ |
| 611 | struct event_hdr evt_link; \ |
| 612 | cb_type_t *evt_cb; \ |
| 613 | }; \ |
| 614 | extern struct event_hdr name##_HEAD |
| 615 | |
| 616 | /*! |
| 617 | * @macro EVENT_DEFINE() |
| 618 | * |
| 619 | * @brief |
| 620 | * Defines the head for the event corresponding to an EVENT_DECLARE() |
| 621 | */ |
| 622 | #define EVENT_DEFINE(name) \ |
| 623 | __security_const_late struct event_hdr name##_HEAD |
| 624 | |
| 625 | /*! |
| 626 | * @macro EVENT_REGISTER_HANDLER() |
| 627 | * |
| 628 | * @brief |
| 629 | * Registers a handler for a given event. |
| 630 | * |
| 631 | * @param name The name for the event as declared in EVENT_DECLARE() |
| 632 | * @param handler The handler to register for this event. |
| 633 | */ |
| 634 | #define EVENT_REGISTER_HANDLER(name, handler) \ |
| 635 | __EVENT_REGISTER(name, __LINE__, handler) |
| 636 | |
| 637 | |
| 638 | /*! |
| 639 | * @macro EVENT_INVOKE() |
| 640 | * |
| 641 | * @brief |
| 642 | * Call all the events handlers with the specified arguments. |
| 643 | * |
| 644 | * @param name The name for the event as declared in EVENT_DECLARE() |
| 645 | * @param handler The handler to register for this event. |
| 646 | */ |
| 647 | #define EVENT_INVOKE(name, ...) \ |
| 648 | for (struct event_hdr *__e = &name##_HEAD; (__e = __e->next);) { \ |
| 649 | __container_of(__e, struct name##_event, \ |
| 650 | evt_link)->evt_cb(__VA_ARGS__); \ |
| 651 | } |
| 652 | |
| 653 | |
| 654 | #if DEBUG || DEVELOPMENT |
| 655 | |
| 656 | /*! |
| 657 | * @macro SYSCTL_TEST_REGISTER |
| 658 | * |
| 659 | * @abstract |
| 660 | * Declares a test that will appear under @c debug.test.${name}. |
| 661 | * |
| 662 | * @param name |
| 663 | * An identifier that will be stringified to form the sysctl test name. |
| 664 | * |
| 665 | * @param cb |
| 666 | * The callback to run, of type: |
| 667 | * <code> |
| 668 | * int (callback *)(int64_t value, int64_t *); |
| 669 | * </code> |
| 670 | */ |
| 671 | #define SYSCTL_TEST_REGISTER(name, cb) \ |
| 672 | static __startup_data struct sysctl_test_setup_spec \ |
| 673 | __startup_SYSCTL_TEST_ ## name = { \ |
| 674 | .st_name = #name, \ |
| 675 | .st_func = &cb, \ |
| 676 | }; \ |
| 677 | STARTUP_ARG(SYSCTL, STARTUP_RANK_MIDDLE, \ |
| 678 | sysctl_register_test_startup, &__startup_SYSCTL_TEST_ ## name) |
| 679 | |
| 680 | #endif /* DEBUG || DEVELOPMENT */ |
| 681 | #pragma mark - internals |
| 682 | |
| 683 | __END_DECLS |
| 684 | |
| 685 | #ifdef __cplusplus |
| 686 | template <typename T> |
| 687 | struct __startup_tunable { |
| 688 | static const bool value = false; |
| 689 | }; |
| 690 | |
| 691 | template <> |
| 692 | struct __startup_tunable <bool>{ |
| 693 | static const bool value = true; |
| 694 | }; |
| 695 | #define __startup_type_is_bool(type_t) __startup_tunable<type_t>::value |
| 696 | #else |
| 697 | #define __startup_type_is_bool(type_t) __builtin_types_compatible_p(bool, type_t) |
| 698 | #endif |
| 699 | |
| 700 | __BEGIN_DECLS |
| 701 | |
| 702 | #define __TUNABLE(type_t, var, key) \ |
| 703 | static __startup_const char __startup_TUNABLES_name_ ## var[] = key; \ |
| 704 | static __startup_const struct startup_tunable_spec \ |
| 705 | __startup_TUNABLES_spec_ ## var = { \ |
| 706 | .name = __startup_TUNABLES_name_ ## var, \ |
| 707 | .var_addr = (void *)&var, \ |
| 708 | .var_len = sizeof(type_t), \ |
| 709 | .var_is_bool = __startup_type_is_bool(type_t), \ |
| 710 | }; \ |
| 711 | __STARTUP_ARG(var, __LINE__, TUNABLES, STARTUP_RANK_FIRST, \ |
| 712 | kernel_startup_tunable_init, &__startup_TUNABLES_spec_ ## var) |
| 713 | |
| 714 | #define __TUNABLE_STR(var, key) \ |
| 715 | static __startup_const char __startup_TUNABLES_name_ ## var[] = key; \ |
| 716 | static __startup_const struct startup_tunable_spec \ |
| 717 | __startup_TUNABLES_spec_ ## var = { \ |
| 718 | .name = __startup_TUNABLES_name_ ## var, \ |
| 719 | .var_addr = (void *)&var, \ |
| 720 | .var_len = sizeof(var), \ |
| 721 | .var_is_str = true, \ |
| 722 | }; \ |
| 723 | __STARTUP_ARG(var, __LINE__, TUNABLES, STARTUP_RANK_FIRST, \ |
| 724 | kernel_startup_tunable_init, &__startup_TUNABLES_spec_ ## var) |
| 725 | |
| 726 | #define __TUNABLE_DT(type_t, var, dt_base_key, dt_name_key, boot_arg_key, flags) \ |
| 727 | static __startup_const char __startup_TUNABLES_dt_base_ ## var[] = dt_base_key; \ |
| 728 | static __startup_const char __startup_TUNABLES_dt_name_ ## var[] = dt_name_key; \ |
| 729 | static __startup_const char __startup_TUNABLES_name_ ## var[] = boot_arg_key; \ |
| 730 | static __startup_const struct startup_tunable_dt_spec \ |
| 731 | __startup_TUNABLES_DT_spec_ ## var = { \ |
| 732 | .dt_base = __startup_TUNABLES_dt_base_ ## var, \ |
| 733 | .dt_name = __startup_TUNABLES_dt_name_ ## var, \ |
| 734 | .dt_chosen_override = (bool)((flags) & TUNABLE_DT_CHECK_CHOSEN), \ |
| 735 | .boot_arg_name = __startup_TUNABLES_name_ ## var, \ |
| 736 | .var_addr = (void *)&var, \ |
| 737 | .var_len = sizeof(type_t), \ |
| 738 | .var_is_bool = __startup_type_is_bool(type_t), \ |
| 739 | }; \ |
| 740 | __STARTUP_ARG(var, __LINE__, TUNABLES, STARTUP_RANK_FIRST, \ |
| 741 | kernel_startup_tunable_dt_init, &__startup_TUNABLES_DT_spec_ ## var) |
| 742 | |
| 743 | #ifdef __cplusplus |
| 744 | #define __STARTUP_FUNC_CAST(func, a) \ |
| 745 | (void(*)(const void *))func |
| 746 | #else |
| 747 | #define __STARTUP_FUNC_CAST(func, a) \ |
| 748 | (typeof(func(a))(*)(const void *))func |
| 749 | #endif |
| 750 | |
| 751 | |
| 752 | #define __STARTUP1(name, line, subsystem, rank, func, a, b) \ |
| 753 | __PLACE_IN_SECTION(STARTUP_HOOK_SEGMENT "," STARTUP_HOOK_SECTION) \ |
| 754 | static const struct startup_entry \ |
| 755 | __startup_ ## subsystem ## _entry_ ## name ## _ ## line = { \ |
| 756 | STARTUP_SUB_ ## subsystem, \ |
| 757 | rank, __STARTUP_FUNC_CAST(func, a), b, \ |
| 758 | } |
| 759 | |
| 760 | #define __STARTUP(name, line, subsystem, rank, func) \ |
| 761 | __STARTUP1(name, line, subsystem, rank, func, , NULL) |
| 762 | |
| 763 | #define __STARTUP_ARG(name, line, subsystem, rank, func, arg) \ |
| 764 | __STARTUP1(name, line, subsystem, rank, func, arg, arg) |
| 765 | |
| 766 | struct startup_entry { |
| 767 | startup_subsystem_id_t subsystem; |
| 768 | startup_rank_t rank; |
| 769 | void (*func)(const void *); |
| 770 | const void *arg; |
| 771 | }; |
| 772 | |
| 773 | struct startup_tunable_spec { |
| 774 | const char *name; |
| 775 | void *var_addr; |
| 776 | int var_len; |
| 777 | bool var_is_bool; |
| 778 | bool var_is_str; |
| 779 | }; |
| 780 | |
| 781 | struct startup_tunable_dt_spec { |
| 782 | const char *dt_base; |
| 783 | const char *dt_name; |
| 784 | bool dt_chosen_override; |
| 785 | const char *boot_arg_name; |
| 786 | void *var_addr; |
| 787 | int var_len; |
| 788 | bool var_is_bool; |
| 789 | }; |
| 790 | |
| 791 | #if DEBUG || DEVELOPMENT |
| 792 | struct sysctl_test_setup_spec { |
| 793 | const char *st_name; |
| 794 | int (*st_func)(int64_t, int64_t *); |
| 795 | }; |
| 796 | |
| 797 | extern void sysctl_register_test_startup( |
| 798 | struct sysctl_test_setup_spec *spec); |
| 799 | #endif /* DEBUG || DEVELOPMENT */ |
| 800 | |
| 801 | /* |
| 802 | * Kernel and machine startup declarations |
| 803 | */ |
| 804 | |
| 805 | /* Initialize kernel */ |
| 806 | extern void kernel_startup_bootstrap(void); |
| 807 | extern void kernel_startup_initialize_upto(startup_subsystem_id_t upto); |
| 808 | extern void kernel_startup_tunable_init(const struct startup_tunable_spec *); |
| 809 | extern void kernel_startup_tunable_dt_init(const struct startup_tunable_dt_spec *); |
| 810 | extern void kernel_bootstrap(void); |
| 811 | |
| 812 | /* Initialize machine dependent stuff */ |
| 813 | extern void machine_init(void); |
| 814 | |
| 815 | extern void slave_main(void *machine_param); |
| 816 | |
| 817 | /* |
| 818 | * The following must be implemented in machine dependent code. |
| 819 | */ |
| 820 | |
| 821 | /* Slave cpu initialization */ |
| 822 | extern void slave_machine_init(void *machine_param); |
| 823 | |
| 824 | /* Device subsystem initialization */ |
| 825 | extern void device_service_create(void); |
| 826 | |
| 827 | struct event_hdr { |
| 828 | struct event_hdr *next; |
| 829 | }; |
| 830 | |
| 831 | extern void event_register_handler(struct event_hdr *event_hdr); |
| 832 | |
| 833 | #define __EVENT_REGISTER(name, lno, handler) \ |
| 834 | static __security_const_late struct name##_event name##_event_##lno = { \ |
| 835 | .evt_link.next = &name##_HEAD, \ |
| 836 | .evt_cb = (handler), \ |
| 837 | }; \ |
| 838 | __STARTUP_ARG(name, lno, EVENT, STARTUP_RANK_FIRST, \ |
| 839 | event_register_handler, &name##_event_##lno.evt_link) |
| 840 | |
| 841 | #ifdef MACH_BSD |
| 842 | |
| 843 | /* BSD subsystem initialization */ |
| 844 | extern void bsd_init(void); |
| 845 | |
| 846 | #endif /* MACH_BSD */ |
| 847 | |
| 848 | #pragma GCC visibility pop |
| 849 | |
| 850 | __END_DECLS |
| 851 | |
| 852 | #endif /* _KERN_STARTUP_H_ */ |
| 853 | |
| 854 | #endif /* XNU_KERNEL_PRIVATE */ |
| 855 | |