1 /*
2 * Copyright (c) 2013-2015 Travis Geiselbrecht
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining
5 * a copy of this software and associated documentation files
6 * (the "Software"), to deal in the Software without restriction,
7 * including without limitation the rights to use, copy, modify, merge,
8 * publish, distribute, sublicense, and/or sell copies of the Software,
9 * and to permit persons to whom the Software is furnished to do so,
10 * subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be
13 * included in all copies or substantial portions of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
18 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
19 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
20 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
21 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 */
23 #pragma once
24
25 #include <compiler.h>
26 #include <sys/types.h>
27
28 /*
29 * LK's init system
30 */
31
32 typedef void (*lk_init_hook)(uint level);
33
34 enum lk_init_level {
35 LK_INIT_LEVEL_EARLIEST = 1,
36
37 LK_INIT_LEVEL_ARCH_EARLY = 0x10000,
38 LK_INIT_LEVEL_PLATFORM_EARLY = 0x20000,
39 LK_INIT_LEVEL_TARGET_EARLY = 0x30000,
40 LK_INIT_LEVEL_HEAP = 0x40000,
41 LK_INIT_LEVEL_VM = 0x50000,
42 LK_INIT_LEVEL_KERNEL = 0x60000,
43 LK_INIT_LEVEL_THREADING = 0x70000,
44 LK_INIT_LEVEL_ARCH = 0x80000,
45 LK_INIT_LEVEL_PLATFORM = 0x90000,
46 LK_INIT_LEVEL_TARGET = 0xa0000,
47 LK_INIT_LEVEL_APPS = 0xb0000,
48
49 LK_INIT_LEVEL_LAST = UINT_MAX,
50 };
51
52 /**
53 * enum lk_init_flags - Flags specifying init hook type.
54 *
55 * Flags passed to LK_INIT_HOOK_FLAGS to specify when the hook should be called.
56 */
57 enum lk_init_flags {
58 /**
59 * @LK_INIT_FLAG_PRIMARY_CPU: Call init hook when booting primary CPU.
60 */
61 LK_INIT_FLAG_PRIMARY_CPU = 0x1,
62
63 /**
64 * @LK_INIT_FLAG_SECONDARY_CPUS: Call init hook when booting secondary CPUs.
65 */
66 LK_INIT_FLAG_SECONDARY_CPUS = 0x2,
67
68 /**
69 * @LK_INIT_FLAG_ALL_CPUS: Call init hook when booting any CPU.
70 */
71 LK_INIT_FLAG_ALL_CPUS = LK_INIT_FLAG_PRIMARY_CPU | LK_INIT_FLAG_SECONDARY_CPUS,
72
73 /**
74 * @LK_INIT_FLAG_CPU_ENTER_IDLE: Call init hook before a CPU enters idle.
75 *
76 * The CPU may lose state after this, but it should respond to interrupts.
77 */
78 LK_INIT_FLAG_CPU_ENTER_IDLE = 0x4,
79
80 /**
81 * @LK_INIT_FLAG_CPU_OFF: Call init hook before a CPU goes offline.
82 *
83 * The CPU may lose state after this, and it should not respond to
84 * interrupts.
85 */
86 LK_INIT_FLAG_CPU_OFF = 0x8,
87
88 /**
89 * @LK_INIT_FLAG_CPU_SUSPEND: Call init hook before a CPU loses state.
90 *
91 * Alias to call hook for both LK_INIT_FLAG_CPU_ENTER_IDLE and
92 * LK_INIT_FLAG_CPU_OFF events.
93 */
94 LK_INIT_FLAG_CPU_SUSPEND = LK_INIT_FLAG_CPU_ENTER_IDLE | LK_INIT_FLAG_CPU_OFF,
95
96 /**
97 * @LK_INIT_FLAG_CPU_EXIT_IDLE: Call init hook after a CPU exits idle.
98 *
99 * LK_INIT_FLAG_CPU_ENTER_IDLE should have been called before this.
100 */
101 LK_INIT_FLAG_CPU_EXIT_IDLE = 0x10,
102
103 /**
104 * @LK_INIT_FLAG_CPU_ON: Call init hook after a CPU turns on.
105 *
106 * LK_INIT_FLAG_CPU_OFF should have been called before this. The first time
107 * a CPU turns on LK_INIT_FLAG_PRIMARY_CPU or LK_INIT_FLAG_SECONDARY_CPUS
108 * is called instead of this.
109 */
110 LK_INIT_FLAG_CPU_ON = 0x20,
111
112 /**
113 * @LK_INIT_FLAG_CPU_RESUME: Call init hook after a CPU exits idle.
114 *
115 * Alias to call hook for both LK_INIT_FLAG_CPU_EXIT_IDLE and
116 * LK_INIT_FLAG_CPU_ON events.
117 */
118 LK_INIT_FLAG_CPU_RESUME = LK_INIT_FLAG_CPU_EXIT_IDLE | LK_INIT_FLAG_CPU_ON,
119 };
120
121 void lk_init_level(enum lk_init_flags flags, uint start_level, uint stop_level);
122
lk_primary_cpu_init_level(uint start_level,uint stop_level)123 static inline void lk_primary_cpu_init_level(uint start_level, uint stop_level)
124 {
125 lk_init_level(LK_INIT_FLAG_PRIMARY_CPU, start_level, stop_level);
126 }
127
lk_init_level_all(enum lk_init_flags flags)128 static inline void lk_init_level_all(enum lk_init_flags flags)
129 {
130 lk_init_level(flags, LK_INIT_LEVEL_EARLIEST, LK_INIT_LEVEL_LAST);
131 }
132
133 struct lk_init_struct {
134 uint level;
135 uint flags;
136 lk_init_hook hook;
137 const char *name;
138 };
139
140 #define LK_INIT_HOOK_FLAGS(_name, _hook, _level, _flags) \
141 const struct lk_init_struct _init_struct_##_name __ALIGNED(sizeof(void *)) __attribute__((used)) __attribute__((visibility("default"))) __SECTION(".lk_init") = { \
142 .level = _level, \
143 .flags = _flags, \
144 .hook = _hook, \
145 .name = #_name, \
146 };
147
148 #define LK_INIT_HOOK(_name, _hook, _level) \
149 LK_INIT_HOOK_FLAGS(_name, _hook, _level, LK_INIT_FLAG_PRIMARY_CPU)
150