xref: /xnu-10063.121.3/osfmk/kern/startup.h (revision 2c2f96dc2b9a4408a43d3150ae9c105355ca3daa)
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