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 <stdint.h> 39 40 #include <libkern/section_keywords.h> 41 42 __BEGIN_DECLS 43 44 #pragma GCC visibility push(hidden) 45 46 /*! 47 * @enum startup_subsystem_id_t 48 * 49 * @abstract 50 * Represents a stage of kernel intialization, ubnd allows for subsystems 51 * to register initializers for a specific stage. 52 * 53 * @discussion 54 * Documentation of each subsystem initialization sequence exists in 55 * @file doc/startup.md. 56 */ 57 __enum_decl(startup_subsystem_id_t, uint32_t, { 58 STARTUP_SUB_NONE = 0, /**< reserved for the startup subsystem */ 59 60 STARTUP_SUB_TUNABLES, /**< support for the tunables subsystem */ 61 STARTUP_SUB_TIMEOUTS, /**< configurable machine timeouts */ 62 STARTUP_SUB_LOCKS_EARLY, /**< early locking, before zalloc */ 63 STARTUP_SUB_KPRINTF, /**< kprintf initialization */ 64 65 STARTUP_SUB_PMAP_STEAL, /**< to perform various pmap carveouts */ 66 STARTUP_SUB_VM_KERNEL, /**< once the kernel VM is ready */ 67 STARTUP_SUB_KMEM, /**< once kmem is ready */ 68 STARTUP_SUB_KMEM_ALLOC, /**< once kmem_alloc is ready */ 69 STARTUP_SUB_ZALLOC, /**< initialize zalloc and kalloc */ 70 STARTUP_SUB_PERCPU, /**< initialize the percpu subsystem */ 71 STARTUP_SUB_LOCKS, /**< various subsystem locks */ 72 73 STARTUP_SUB_CODESIGNING, /**< codesigning subsystem */ 74 STARTUP_SUB_OSLOG, /**< oslog and kernel loggging */ 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/premption 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 * an 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 conveniency 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) \ 128 (enum startup_rank)(n) 129 STARTUP_RANK_FIRST = 0, 130 STARTUP_RANK_SECOND = 1, 131 STARTUP_RANK_THIRD = 2, 132 STARTUP_RANK_FOURTH = 3, 133 134 STARTUP_RANK_MIDDLE = 0x7fffffff, 135 136 #define STARTUP_RANK_LATE_NTH(n) \ 137 (enum startup_rank)(STARTUP_RANK_MIDDLE + 1 + (n)) 138 139 STARTUP_RANK_LAST = 0xffffffff, 140 }); 141 142 #if KASAN 143 /* 144 * The use of weird sections that get unmapped confuse the hell out of kasan, 145 * so for KASAN leave things in regular __TEXT/__DATA segments 146 */ 147 #define STARTUP_CODE_SEGSECT "__TEXT,__text" 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_DATA_SEGSECT "__KLDDATA,__init" 155 #define STARTUP_HOOK_SEGMENT "__KLDDATA" 156 #define STARTUP_HOOK_SECTION "__init_entry_set" 157 #else 158 /* arm protects __KLD early, so use __BOOTDATA for data */ 159 #define STARTUP_CODE_SEGSECT "__TEXT,__text" 160 #define STARTUP_DATA_SEGSECT "__BOOTDATA,__init" 161 #define STARTUP_HOOK_SEGMENT "__BOOTDATA" 162 #define STARTUP_HOOK_SECTION "__init_entry_set" 163 #endif 164 165 /*! 166 * @macro __startup_func 167 * 168 * @abstract 169 * Attribute to place on functions used only during the kernel startup phase. 170 * 171 * @description 172 * Code marked with this attribute will be unmapped after kernel lockdown. 173 */ 174 #define __startup_func \ 175 __PLACE_IN_SECTION(STARTUP_CODE_SEGSECT) \ 176 __attribute__((cold, visibility("hidden"))) 177 178 /*! 179 * @macro __startup_data 180 * 181 * @abstract 182 * Attribute to place on globals used during the kernel startup phase. 183 * 184 * @description 185 * Data marked with this attribute will be unmapped after kernel lockdown. 186 */ 187 #define __startup_data \ 188 __PLACE_IN_SECTION(STARTUP_DATA_SEGSECT) 189 190 /*! 191 * @macro STARTUP 192 * 193 * @abstract 194 * Declares a kernel startup callback. 195 */ 196 #define STARTUP(subsystem, rank, func) \ 197 __STARTUP(func, __LINE__, subsystem, rank, func) 198 199 /*! 200 * @macro STARTUP_ARG 201 * 202 * @abstract 203 * Declares a kernel startup callback that takes an argument. 204 */ 205 #define STARTUP_ARG(subsystem, rank, func, arg) \ 206 __STARTUP_ARG(func, __LINE__, subsystem, rank, func, arg) 207 208 /*! 209 * @macro TUNABLE 210 * 211 * @abstract 212 * Declares a read-only kernel tunable that is read from a boot-arg with 213 * a default value, without further processing. 214 * 215 * @param type_t 216 * Should be an integer type or bool. 217 * 218 * @param var 219 * The name of the C variable to use for storage. 220 * 221 * @param boot_arg 222 * The name of the boot-arg to parse for initialization 223 * 224 * @param default_value 225 * The default value for the tunable if the boot-arg is absent. 226 */ 227 #define TUNABLE(type_t, var, boot_arg, default_value) \ 228 SECURITY_READ_ONLY_LATE(type_t) var = default_value; \ 229 __TUNABLE(type_t, var, boot_arg) 230 231 /*! 232 * @macro TUNABLE_WRITEABLE 233 * 234 * @abstract 235 * Declares a writeable kernel tunable that is read from a boot-arg with 236 * a default value, without further processing. 237 * 238 * @param type_t 239 * Should be an integer type or bool. 240 * 241 * @param var 242 * The name of the C variable to use for storage. 243 * 244 * @param boot_arg 245 * The name of the boot-arg to parse for initialization 246 * 247 * @param default_value 248 * The default value for the tunable if the boot-arg is absent. 249 */ 250 #define TUNABLE_WRITEABLE(type_t, var, boot_arg, default_value) \ 251 type_t var = default_value; \ 252 __TUNABLE(type_t, var, boot_arg) 253 254 #if DEBUG || DEVELOPMENT 255 #define TUNABLE_DEV_WRITEABLE(type_t, var, boot_arg, default_value) \ 256 TUNABLE_WRITEABLE(type_t, var, boot_arg, default_value) 257 #else 258 #define TUNABLE_DEV_WRITEABLE(type_t, var, boot_arg, default_value) \ 259 TUNABLE(type_t, var, boot_arg, default_value) 260 #endif 261 262 /*! 263 * @macro TUNABLE_STR 264 * 265 * @abstract 266 * Declares a read-only kernel tunable that is read from a boot-arg with 267 * a default value, without further processing. 268 * 269 * @param var 270 * The name of the C variable to use for storage. 271 * 272 * @param count 273 * The number of bytes in the buffer. 274 * 275 * @param boot_arg 276 * The name of the boot-arg to parse for initialization 277 * 278 * @param default_value 279 * The default value for the tunable if the boot-arg is absent. 280 */ 281 #define TUNABLE_STR(var, count, boot_arg, default_value) \ 282 char __security_const_late var[count] = default_value; \ 283 __TUNABLE_STR(var, boot_arg) 284 285 /*! 286 * @enum tunable_dt_flags_t 287 * 288 * @abstract 289 * Flags used with the @c TUNABLE_DT* macros. 290 * 291 * @description 292 * If TUNABLE_DT_CHECK_CHOSEN is set, a value in 293 * /chosen/<dt_base>/<dt_name> takes precedence over any value in 294 * /<dt_base>/<dt_name>. /chosen is by convention the area where 295 * synthesized values not coming from the serialized device tree are 296 * being added, so this provides a way for e.g. the boot-loader to 297 * set/override tunables. 298 */ 299 __options_decl(tunable_dt_flags_t, uint32_t, { 300 TUNABLE_DT_NONE = 0x00000000, 301 TUNABLE_DT_CHECK_CHOSEN = 0x00000001, 302 }); 303 304 /*! 305 * @macro TUNABLE_DT 306 * 307 * @abstract 308 * Like TUNABLE, but gets the initial value from both Device Tree and 309 * boot-args. The order in which the initial value is resolved is as 310 * follows, with later steps overriding previous ones (if they are 311 * specified): 312 * 313 * 1. Device Tree Entry "/<dt_base>/<dt_name>", 314 * 2. If TUNABLE_DT_CHECK_CHOSEN is set, Device Tree Entry 315 * "/chosen/<dt_base>/<dt_name>" (see the description for 316 * @c tunable_dt_flags_t), 317 * 3. boot-args. 318 * 319 * @param type_t 320 * Should be an integer type or bool. 321 * 322 * @param var 323 * The name of the C variable to use for storage. 324 * 325 * @param dt_base 326 * The name of the DT node containing the property. 327 * 328 * @param dt_name 329 * The name of the DT property containing the default value. 330 * 331 * @param boot_arg 332 * The name of the boot-arg overriding the initial value from the DT. 333 * 334 * @param default_value 335 * The default value for the tunable if both DT entry and boot-arg are 336 * absent. 337 * 338 * @param flags 339 * See the description for @c tunable_dt_flags_t. 340 */ 341 #define TUNABLE_DT(type_t, var, dt_base, dt_name, boot_arg, default_value, flags) \ 342 SECURITY_READ_ONLY_LATE(type_t) var = default_value; \ 343 __TUNABLE_DT(type_t, var, dt_base, dt_name, boot_arg, flags) 344 345 /*! 346 * @macro TUNABLE_DT_WRITEABLE 347 * 348 * @abstract 349 * Like TUNABLE_WRITEABLE, but gets the initial value from both Device 350 * Tree and boot-args. The order in which the initial value is 351 * resolved is as follows, with later steps overriding previous ones 352 * (if they are specified): 353 * 354 * 1. Device Tree Entry "/<dt_base>/<dt_name>", 355 * 2. If TUNABLE_DT_CHECK_CHOSEN is set, Device Tree Entry 356 * "/chosen/<dt_base>/<dt_name>" (see the description for 357 * @c tunable_dt_flags_t), 358 * 3. boot-args. 359 * 360 * @param type_t 361 * Should be an integer type or bool. 362 * 363 * @param var 364 * The name of the C variable to use for storage. 365 * 366 * @param dt_base 367 * The name of the DT node containing the property. 368 * 369 * @param dt_name 370 * The name of the DT property containing the default value. 371 * 372 * @param boot_arg 373 * The name of the boot-arg overriding the initial value from the DT. 374 * 375 * @param default_value 376 * The default value for the tunable if both DT entry and boot-arg are 377 * absent. 378 * 379 * @param flags 380 * See the description for @c tunable_dt_flags_t. 381 */ 382 #define TUNABLE_DT_WRITEABLE(type_t, var, dt_base, dt_name, boot_arg, default_value, flags) \ 383 type_t var = default_value; \ 384 __TUNABLE_DT(type_t, var, dt_base, dt_name, boot_arg, flags) 385 386 /* 387 * Machine Timeouts 388 * 389 * Machine Timeouts are timeouts for low level kernel code manifesting 390 * as _Atomic uint64_t variables, whose default value can be 391 * overridden and scaled via the device tree and boot-args. 392 * 393 * Each timeout has a name, looked up directly as the property name in 394 * the device tree in both the "/machine-timeouts" and 395 * "/chosen/machine-timeouts" nodes. The "chosen" property always 396 * overrides the other one. This allows fixed per-device timeouts in 397 * the device tree to be overridden by iBoot in "chosen". 398 * 399 * Additionally, the same name with "-scale" appended is looked up as 400 * properties for optional scale factors. Scale factors are not 401 * overridden by chosen, instead all scale factors (including global 402 * and/or boot-arg scale factors) combine by multiplication. 403 * 404 * The special name "global-scale" provides a scale that applies to 405 * every timeout. 406 * 407 * All property names can be used as boot-args by prefixing 408 * "ml-timeout-", e.g. th global scale is available as the 409 * "ml-timeout-global-scale" boot-arg. 410 * 411 * By convention, if the timeout value resolves to 0, the timeout 412 * should be disabled. 413 */ 414 415 /* 416 * Machine Timeouts types. See the next section for what unit 417 * they are in. 418 * 419 * We use _Atomic, but only with relaxed ordering: This is just to 420 * make sure all devices see consistent values all the time. Since 421 * the actual timeout value will be seen as 0 before initializaton, 422 * relaxed ordering means that code that runs concurrently with 423 * initialization only risks to see a disabled timeout during early 424 * boot. 425 * 426 * On 64bit devices, _Atomic with relaxed should have no effect. On 427 * 32bit devices, _Atomic uint64_t will incur synchronization, so it 428 * might be better to use machine_timeout32_t instead. 429 */ 430 typedef _Atomic uint64_t machine_timeout_t; 431 typedef _Atomic uint32_t machine_timeout32_t; 432 433 /* 434 * Units 435 * 436 * Machine Timeouts are ALWAYS in picoseconds in the device tree or 437 * boot-args, to avoid confusion when changing or comparing timeouts 438 * as a user, but the actual storage value might contain the same 439 * duration in another unit, calculated by the initialization code. 440 * 441 * This is done because otherwise we would likely introduce another 442 * multiplication in potentially hot code paths, given that code that 443 * actually uses the timeout storage variable is unlikely to work with 444 * picosecond values when comparing against the timeout deadline. 445 * 446 * This unit scale is *only* applied during initialization at early 447 * boot, and only if the timeout's default value was overridden 448 * through the device tree or a boot-arg. 449 */ 450 #define MACHINE_TIMEOUT_UNIT_PSEC 1 451 #define MACHINE_TIMEOUT_UNIT_NSEC 1000 452 #define MACHINE_TIMEOUT_UNIT_USEC (1000*1000) 453 #define MACHINE_TIMEOUT_UNIT_MSEC (1000*1000*1000) 454 // Special unit for timebase ticks (usually 1/24MHz) 455 #define MACHINE_TIMEOUT_UNIT_TIMEBASE 0 456 457 // DT property names are limited to 31 chars, minus "-global" suffix 458 #define MACHINE_TIMEOUT_MAX_NAME_LEN 25 459 struct machine_timeout_spec { 460 void *ptr; 461 uint64_t default_value; 462 uint64_t unit_scale; 463 bool is32; 464 char name[MACHINE_TIMEOUT_MAX_NAME_LEN + 1]; 465 bool (*skip_predicate)(struct machine_timeout_spec const *); 466 }; 467 468 extern void 469 machine_timeout_init_with_suffix(const struct machine_timeout_spec *spec, char const *phase_suffix); 470 471 extern void 472 machine_timeout_init(const struct machine_timeout_spec *spec); 473 474 // Late timeout (re-)initialization, at the end of bsd_init() 475 extern void 476 machine_timeout_bsd_init(void); 477 478 /*! 479 * @macro MACHINE_TIMEOUT and MACHINE_TIMEOUT_WRITEABLE 480 * 481 * @abstract 482 * Defines a Machine Timeout that can be overridden and 483 * scaled through the device tree and boot-args. 484 * 485 * The variant with the _WRITEABLE suffix does not mark the timeout as 486 * SECURITY_READ_ONLY_LATE, so that e.g. machine_timeout_init_with_suffix 487 * or sysctls can change it after lockdown. 488 * 489 * @param var 490 * The name of the C variable to use for storage. If the storage value 491 * contains 0, the timeout is considered disabled by convention. 492 * 493 * @param timeout_name 494 * The name of the timeout, used for property and boot-arg names. See 495 * the general description of Machine Timeouts above for how this name 496 * ends up being used. 497 * 498 * @param timeout_default 499 * The default value for the timeout if not specified through device 500 * tree or boot-arg. Will still be scaled if a scale factor exists. 501 * 502 * @param var_unit 503 * The unit that the storage variable is in. Note that timeout values 504 * must always be specified as picoseconds in the device tree and 505 * boot-args, but timeout initialization will convert the value to the 506 * unit specified here before writing it to the storage variable. 507 * 508 * @param skip_predicate 509 * Optionally, a function to call to decide whether the timeout should 510 * be set or not. If NULL, the timeout will always be set (if 511 * specified anywhere). A predicate has the following signature: 512 * bool skip_predicate (struct machine_timeout_spec const *) 513 */ 514 515 #define _MACHINE_TIMEOUT(var, timeout_name, timeout_default, var_unit, var_is32, skip_pred) \ 516 struct machine_timeout_spec \ 517 __machine_timeout_spec_ ## var = { \ 518 .ptr = &var, \ 519 .default_value = timeout_default, \ 520 .unit_scale = var_unit, \ 521 .is32 = var_is32, \ 522 .name = timeout_name, \ 523 .skip_predicate = skip_pred, \ 524 }; \ 525 __STARTUP_ARG(var, __LINE__, TIMEOUTS, STARTUP_RANK_FIRST, \ 526 machine_timeout_init, &__machine_timeout_spec_ ## var) 527 528 #define MACHINE_TIMEOUT(var, name, default, unit, skip_predicate) \ 529 SECURITY_READ_ONLY_LATE(machine_timeout_t) var = 0; \ 530 _MACHINE_TIMEOUT(var, name, default, unit, false, skip_predicate) 531 532 #define MACHINE_TIMEOUT32(var, name, default, unit, skip_predicate) \ 533 SECURITY_READ_ONLY_LATE(machine_timeout32_t) var = 0; \ 534 _MACHINE_TIMEOUT(var, name, default, unit, true, skip_predicate) 535 536 #define MACHINE_TIMEOUT_WRITEABLE(var, name, default, unit, skip_predicate) \ 537 machine_timeout_t var = 0; \ 538 _MACHINE_TIMEOUT(var, name, default, unit, false, skip_predicate) 539 540 #define MACHINE_TIMEOUT32_WRITEABLE(var, name, default, unit, skip_predicate) \ 541 machine_timeout32_t var = 0; \ 542 _MACHINE_TIMEOUT(var, name, default, unit, true, skip_predicate) 543 544 /*! 545 * @macro MACHINE_TIMEOUT_SPEC_REF 546 * 547 * @abstract 548 * References a previously defined MACHINE_TIMEOUT or 549 * MACHINE_TIMEOUT32. This is primarily useful for overriding 550 * individual timeouts at arbitrary times (even after boot), by 551 * manually calling machine_timeout_init_with_suffix() with this macro 552 * as first argument, and a suffix to apply to both device tree and 553 * boot-arg as second argument. 554 * 555 * @param var 556 * The name of the C variable used for storage, as it was specified 557 * in MACHINE_TIMEOUT or MACHINE_TIMEOUT32. 558 */ 559 #define MACHINE_TIMEOUT_SPEC_REF(var) (&__machine_timeout_spec_ ## var) 560 561 /*! 562 * @macro MACHINE_TIMEOUT_SPEC_DECL 563 * 564 * @abstract 565 * Declaration of machine timeout spec, mostly useful to make it known 566 * for MACHINE_TIMEOUT_SPEC_REF. 567 * 568 * @param var 569 * The name of the C variable used for storage, as it was specified 570 * in MACHINE_TIMEOUT or MACHINE_TIMEOUT32. 571 */ 572 #define MACHINE_TIMEOUT_SPEC_DECL(var) extern struct machine_timeout_spec __machine_timeout_spec_ ## var 573 574 #if DEBUG || DEVELOPMENT 575 576 /*! 577 * @macro SYSCTL_TEST_REGISTER 578 * 579 * @abstract 580 * Declares a test that will appear under @c debug.test.${name}. 581 * 582 * @param name 583 * An indentifier that will be stringified to form the sysctl test name. 584 * 585 * @param cb 586 * The callback to run, of type: 587 * <code> 588 * int (callback *)(int64_t value, int64_t *); 589 * </code> 590 */ 591 #define SYSCTL_TEST_REGISTER(name, cb) \ 592 static __startup_data struct sysctl_test_setup_spec \ 593 __startup_SYSCTL_TEST_ ## name = { \ 594 .st_name = #name, \ 595 .st_func = &cb, \ 596 }; \ 597 STARTUP_ARG(SYSCTL, STARTUP_RANK_MIDDLE, \ 598 sysctl_register_test_startup, &__startup_SYSCTL_TEST_ ## name) 599 600 #endif /* DEBUG || DEVELOPMENT */ 601 #pragma mark - internals 602 603 __END_DECLS 604 605 #ifdef __cplusplus 606 template <typename T> 607 struct __startup_tunable { 608 static const bool value = false; 609 }; 610 611 template <> 612 struct __startup_tunable <bool>{ 613 static const bool value = true; 614 }; 615 #define __startup_type_is_bool(type_t) __startup_tunable<type_t>::value 616 #else 617 #define __startup_type_is_bool(type_t) __builtin_types_compatible_p(bool, type_t) 618 #endif 619 620 __BEGIN_DECLS 621 622 #define __TUNABLE(type_t, var, key) \ 623 static __startup_data char __startup_TUNABLES_name_ ## var[] = key; \ 624 static __startup_data struct startup_tunable_spec \ 625 __startup_TUNABLES_spec_ ## var = { \ 626 .name = __startup_TUNABLES_name_ ## var, \ 627 .var_addr = (void *)&var, \ 628 .var_len = sizeof(type_t), \ 629 .var_is_bool = __startup_type_is_bool(type_t), \ 630 }; \ 631 __STARTUP_ARG(var, __LINE__, TUNABLES, STARTUP_RANK_FIRST, \ 632 kernel_startup_tunable_init, &__startup_TUNABLES_spec_ ## var) 633 634 #define __TUNABLE_STR(var, key) \ 635 static __startup_data char __startup_TUNABLES_name_ ## var[] = key; \ 636 static __startup_data struct startup_tunable_spec \ 637 __startup_TUNABLES_spec_ ## var = { \ 638 .name = __startup_TUNABLES_name_ ## var, \ 639 .var_addr = (void *)&var, \ 640 .var_len = sizeof(var), \ 641 .var_is_str = true, \ 642 }; \ 643 __STARTUP_ARG(var, __LINE__, TUNABLES, STARTUP_RANK_FIRST, \ 644 kernel_startup_tunable_init, &__startup_TUNABLES_spec_ ## var) 645 646 #define __TUNABLE_DT(type_t, var, dt_base_key, dt_name_key, boot_arg_key, flags) \ 647 static __startup_data char __startup_TUNABLES_dt_base_ ## var[] = dt_base_key; \ 648 static __startup_data char __startup_TUNABLES_dt_name_ ## var[] = dt_name_key; \ 649 static __startup_data char __startup_TUNABLES_name_ ## var[] = boot_arg_key; \ 650 static __startup_data struct startup_tunable_dt_spec \ 651 __startup_TUNABLES_DT_spec_ ## var = { \ 652 .dt_base = __startup_TUNABLES_dt_base_ ## var, \ 653 .dt_name = __startup_TUNABLES_dt_name_ ## var, \ 654 .dt_chosen_override = (bool)((flags) & TUNABLE_DT_CHECK_CHOSEN), \ 655 .boot_arg_name = __startup_TUNABLES_name_ ## var, \ 656 .var_addr = (void *)&var, \ 657 .var_len = sizeof(type_t), \ 658 .var_is_bool = __startup_type_is_bool(type_t), \ 659 }; \ 660 __STARTUP_ARG(var, __LINE__, TUNABLES, STARTUP_RANK_FIRST, \ 661 kernel_startup_tunable_dt_init, &__startup_TUNABLES_DT_spec_ ## var) 662 663 #ifdef __cplusplus 664 #define __STARTUP_FUNC_CAST(func, a) \ 665 (void(*)(const void *))func 666 #else 667 #define __STARTUP_FUNC_CAST(func, a) \ 668 (typeof(func(a))(*)(const void *))func 669 #endif 670 671 672 #define __STARTUP1(name, line, subsystem, rank, func, a, b) \ 673 __PLACE_IN_SECTION(STARTUP_HOOK_SEGMENT "," STARTUP_HOOK_SECTION) \ 674 static const struct startup_entry \ 675 __startup_ ## subsystem ## _entry_ ## name ## _ ## line = { \ 676 STARTUP_SUB_ ## subsystem, \ 677 rank, __STARTUP_FUNC_CAST(func, a), b, \ 678 } 679 680 #define __STARTUP(name, line, subsystem, rank, func) \ 681 __STARTUP1(name, line, subsystem, rank, func, , NULL) 682 683 #define __STARTUP_ARG(name, line, subsystem, rank, func, arg) \ 684 __STARTUP1(name, line, subsystem, rank, func, arg, arg) 685 686 struct startup_entry { 687 startup_subsystem_id_t subsystem; 688 startup_rank_t rank; 689 void (*func)(const void *); 690 const void *arg; 691 }; 692 693 struct startup_tunable_spec { 694 const char *name; 695 void *var_addr; 696 int var_len; 697 bool var_is_bool; 698 bool var_is_str; 699 }; 700 701 struct startup_tunable_dt_spec { 702 const char *dt_base; 703 const char *dt_name; 704 bool dt_chosen_override; 705 const char *boot_arg_name; 706 void *var_addr; 707 int var_len; 708 bool var_is_bool; 709 }; 710 711 #if DEBUG || DEVELOPMENT 712 struct sysctl_test_setup_spec { 713 const char *st_name; 714 int (*st_func)(int64_t, int64_t *); 715 }; 716 717 extern void sysctl_register_test_startup( 718 struct sysctl_test_setup_spec *spec); 719 #endif /* DEBUG || DEVELOPMENT */ 720 721 /* 722 * Kernel and machine startup declarations 723 */ 724 725 /* Initialize kernel */ 726 extern void kernel_startup_bootstrap(void); 727 extern void kernel_startup_initialize_upto(startup_subsystem_id_t upto); 728 extern void kernel_startup_tunable_init(const struct startup_tunable_spec *); 729 extern void kernel_startup_tunable_dt_init(const struct startup_tunable_dt_spec *); 730 extern void kernel_bootstrap(void); 731 732 /* Initialize machine dependent stuff */ 733 extern void machine_init(void); 734 735 extern void slave_main(void *machine_param); 736 737 /* 738 * The following must be implemented in machine dependent code. 739 */ 740 741 /* Slave cpu initialization */ 742 extern void slave_machine_init(void *machine_param); 743 744 /* Device subystem initialization */ 745 extern void device_service_create(void); 746 747 #ifdef MACH_BSD 748 749 /* BSD subsystem initialization */ 750 extern void bsd_init(void); 751 752 #endif /* MACH_BSD */ 753 754 #pragma GCC visibility pop 755 756 __END_DECLS 757 758 #endif /* _KERN_STARTUP_H_ */ 759 760 #endif /* XNU_KERNEL_PRIVATE */ 761