]> git.saurik.com Git - apple/xnu.git/blame - osfmk/kern/startup.h
xnu-7195.101.1.tar.gz
[apple/xnu.git] / osfmk / kern / startup.h
CommitLineData
1c79356b 1/*
f427ee49 2 * Copyright (c) 2000-2020 Apple Inc. All rights reserved.
1c79356b 3 *
2d21ac55 4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
0a7de745 5 *
2d21ac55
A
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.
0a7de745 14 *
2d21ac55
A
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
0a7de745 17 *
2d21ac55
A
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
8f6c56a5
A
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
2d21ac55
A
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.
0a7de745 25 *
2d21ac55 26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
1c79356b
A
27 */
28/*
29 * @OSF_COPYRIGHT@
30 */
91447636 31
0a7de745 32#ifdef XNU_KERNEL_PRIVATE
1c79356b 33
0a7de745
A
34#ifndef _KERN_STARTUP_H_
35#define _KERN_STARTUP_H_
1c79356b 36
f427ee49
A
37#include <stdbool.h>
38#include <stdint.h>
39
40#include <libkern/section_keywords.h>
41
91447636 42__BEGIN_DECLS
1c79356b 43
f427ee49
A
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_LOCKS_EARLY, /**< early locking, before zalloc */
62 STARTUP_SUB_KPRINTF, /**< kprintf initialization */
63
64 STARTUP_SUB_PMAP_STEAL, /**< to perform various pmap carveouts */
65 STARTUP_SUB_VM_KERNEL, /**< once the kernel VM is ready */
66 STARTUP_SUB_KMEM, /**< once kmem is ready */
67 STARTUP_SUB_KMEM_ALLOC, /**< once kmem_alloc is ready */
68 STARTUP_SUB_ZALLOC, /**< initialize zalloc and kalloc */
69 STARTUP_SUB_PERCPU, /**< initialize the percpu subsystem */
70 STARTUP_SUB_LOCKS, /**< various subsystem locks */
71
72 STARTUP_SUB_CODESIGNING, /**< codesigning subsystem */
73 STARTUP_SUB_OSLOG, /**< oslog and kernel loggging */
74 STARTUP_SUB_MACH_IPC, /**< Mach IPC */
2a1bd2d3 75 STARTUP_SUB_SYSCTL, /**< registers sysctls */
f427ee49
A
76 STARTUP_SUB_EARLY_BOOT, /**< interrupts/premption are turned on */
77
78 STARTUP_SUB_LOCKDOWN = ~0u, /**< reserved for the startup subsystem */
79});
80
81/*!
82 * Stores the last subsystem to have been fully initialized;
83 */
84extern startup_subsystem_id_t startup_phase;
85
86/*!
87 * @enum startup_debug_t
88 *
89 * @abstract
90 * Flags set in the @c startup_debug global to configure startup debugging.
91 */
92__options_decl(startup_debug_t, uint32_t, {
93 STARTUP_DEBUG_NONE = 0x00000000,
94 STARTUP_DEBUG_VERBOSE = 0x00000001,
95});
96
97#if DEBUG || DEVELOPMENT
98extern startup_debug_t startup_debug;
99#else
100#define startup_debug STARTUP_DEBUG_NONE
101#endif
102
103/*!
104 * @enum startup_rank
105 *
106 * @abstract
107 * Specifies in which rank a given initializer runs within a given section
108 * to register initializers for a specific rank within the subsystem.
109 *
110 * @description
111 * A startup function, declared with @c STARTUP or @c STARTUP_ARG, can specify
112 * an rank within the subsystem they initialize.
113 *
114 * @c STARTUP_RANK_NTH(n) will let callbacks be run at stage @c n (0-based).
115 *
116 * @c STARTUP_RANK_FIRST, @c STARTUP_RANK_SECOND, @c STARTUP_RANK_THIRD and
117 * @c STARTUP_RANK_FOURTH are given as conveniency names for these.
118 *
119 * @c STARTUP_RANK_MIDDLE is a reserved value that will let startup functions
120 * run after all the @c STARTUP_RANK_NTH(n) ones have.
121 *
122 * @c STARTUP_RANK_NTH_LATE_NTH(n) will let callbacks be run then in @c n rank
123 * after the @c STARTUP_RANK_MIDDLE ones (0-based).
124 *
125 * @c STARTUP_RANK_LAST callbacks will run absolutely last after everything
126 * else did for this subsystem.
127 */
128__enum_decl(startup_rank_t, uint32_t, {
129#define STARTUP_RANK_NTH(n) \
130 (enum startup_rank)(n)
131 STARTUP_RANK_FIRST = 0,
132 STARTUP_RANK_SECOND = 1,
133 STARTUP_RANK_THIRD = 2,
134 STARTUP_RANK_FOURTH = 3,
135
136 STARTUP_RANK_MIDDLE = 0x7fffffff,
137
138#define STARTUP_RANK_LATE_NTH(n) \
139 (enum startup_rank)(STARTUP_RANK_MIDDLE + 1 + (n))
140
141 STARTUP_RANK_LAST = 0xffffffff,
142});
143
144#if KASAN
145/*
146 * The use of weird sections that get unmapped confuse the hell out of kasan,
147 * so for KASAN leave things in regular __TEXT/__DATA segments
148 */
149#define STARTUP_CODE_SEGSECT "__TEXT,__text"
150#define STARTUP_DATA_SEGSECT "__DATA,__init"
151#define STARTUP_HOOK_SEGMENT "__DATA"
152#define STARTUP_HOOK_SECTION "__init_entry_set"
153#elif defined(__x86_64__)
154/* Intel doesn't have a __BOOTDATA but doesn't protect __KLD */
155#define STARTUP_CODE_SEGSECT "__TEXT,__text"
c3c9b80d
A
156#define STARTUP_DATA_SEGSECT "__KLDDATA,__init"
157#define STARTUP_HOOK_SEGMENT "__KLDDATA"
f427ee49
A
158#define STARTUP_HOOK_SECTION "__init_entry_set"
159#else
160/* arm protects __KLD early, so use __BOOTDATA for data */
161#define STARTUP_CODE_SEGSECT "__TEXT,__text"
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) \
c3c9b80d 178 __attribute__((cold, visibility("hidden")))
f427ee49
A
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
194 *
195 * @abstract
196 * Declares a kernel startup callback.
197 */
198#define STARTUP(subsystem, rank, func) \
199 __STARTUP(func, __LINE__, subsystem, rank, func)
200
201/*!
202 * @macro STARTUP_ARG
203 *
204 * @abstract
205 * Declares a kernel startup callback that takes an argument.
206 */
207#define STARTUP_ARG(subsystem, rank, func, arg) \
208 __STARTUP_ARG(func, __LINE__, subsystem, rank, func, arg)
209
210/*!
211 * @macro TUNABLE
212 *
213 * @abstract
214 * Declares a read-only kernel tunable that is read from a boot-arg with
215 * a default value, without further processing.
216 *
217 * @param type_t
218 * Should be an integer type or bool.
219 *
220 * @param var
221 * The name of the C variable to use for storage.
222 *
223 * @param key
224 * The name of the boot-arg to parse for initialization
225 *
226 * @param default_value
227 * The default value for the tunable if the boot-arg is absent.
228 */
229#define TUNABLE(type_t, var, key, default_value) \
230 SECURITY_READ_ONLY_LATE(type_t) var = default_value; \
231 __TUNABLE(type_t, var, key)
232
233/*!
234 * @macro TUNABLE_WRITEABLE
235 *
236 * @abstract
237 * Declares a writeable kernel tunable that is read from a boot-arg with
238 * a default value, without further processing.
239 *
240 * @param type_t
241 * Should be an integer type or bool.
242 *
243 * @param var
244 * The name of the C variable to use for storage.
245 *
246 * @param key
247 * The name of the boot-arg to parse for initialization
248 *
249 * @param default_value
250 * The default value for the tunable if the boot-arg is absent.
251 */
252#define TUNABLE_WRITEABLE(type_t, var, key, default_value) \
253 type_t var = default_value; \
254 __TUNABLE(type_t, var, key)
255
256#pragma mark - internals
257
258#define __TUNABLE(type_t, var, key) \
259 static __startup_data char __startup_TUNABLES_name_ ## var[] = key; \
260 static __startup_data struct startup_tunable_spec \
261 __startup_TUNABLES_spec_ ## var = { \
262 .name = __startup_TUNABLES_name_ ## var, \
c3c9b80d 263 .var_addr = (void *)&var, \
f427ee49
A
264 .var_len = sizeof(type_t), \
265 .var_is_bool = __builtin_types_compatible_p(bool, type_t), \
266 }; \
267 __STARTUP_ARG(var, __LINE__, TUNABLES, STARTUP_RANK_FIRST, \
268 kernel_startup_tunable_init, &__startup_TUNABLES_spec_ ## var)
269
c3c9b80d
A
270#ifdef __cplusplus
271#define __STARTUP_FUNC_CAST(func, a) \
272 (void(*)(const void *))func
273#else
274#define __STARTUP_FUNC_CAST(func, a) \
275 (typeof(func(a))(*)(const void *))func
276#endif
277
f427ee49
A
278
279#define __STARTUP1(name, line, subsystem, rank, func, a, b) \
280 __PLACE_IN_SECTION(STARTUP_HOOK_SEGMENT "," STARTUP_HOOK_SECTION) \
281 static const struct startup_entry \
282 __startup_ ## subsystem ## _entry_ ## name ## _ ## line = { \
283 STARTUP_SUB_ ## subsystem, \
c3c9b80d 284 rank, __STARTUP_FUNC_CAST(func, a), b, \
f427ee49
A
285 }
286
287#define __STARTUP(name, line, subsystem, rank, func) \
288 __STARTUP1(name, line, subsystem, rank, func, , NULL)
289
290#define __STARTUP_ARG(name, line, subsystem, rank, func, arg) \
291 __STARTUP1(name, line, subsystem, rank, func, arg, arg)
292
293struct startup_entry {
294 startup_subsystem_id_t subsystem;
295 startup_rank_t rank;
296 void (*func)(const void *);
297 const void *arg;
298};
299
300struct startup_tunable_spec {
301 const char *name;
302 void *var_addr;
303 int var_len;
304 bool var_is_bool;
305};
306
1c79356b
A
307/*
308 * Kernel and machine startup declarations
309 */
310
311/* Initialize kernel */
f427ee49
A
312extern void kernel_startup_bootstrap(void);
313extern void kernel_startup_initialize_upto(startup_subsystem_id_t upto);
314extern void kernel_startup_tunable_init(const struct startup_tunable_spec *);
39236c6e 315extern void kernel_bootstrap(void);
1c79356b
A
316
317/* Initialize machine dependent stuff */
f427ee49 318extern void machine_init(void);
1c79356b 319
f427ee49 320extern void slave_main(void *machine_param);
1c79356b
A
321
322/*
323 * The following must be implemented in machine dependent code.
324 */
325
326/* Slave cpu initialization */
f427ee49 327extern void slave_machine_init(void *machine_param);
1c79356b 328
91447636 329/* Device subystem initialization */
f427ee49 330extern void device_service_create(void);
91447636 331
0a7de745 332#ifdef MACH_BSD
91447636
A
333
334/* BSD subsystem initialization */
f427ee49 335extern void bsd_init(void);
91447636 336
0a7de745 337#endif /* MACH_BSD */
91447636 338
f427ee49
A
339#pragma GCC visibility pop
340
91447636 341__END_DECLS
1c79356b 342
0a7de745 343#endif /* _KERN_STARTUP_H_ */
91447636 344
0a7de745 345#endif /* XNU_KERNEL_PRIVATE */