xref: /optee_os/core/include/initcall.h (revision 913d93a4ed64002a523d9a3bf6d4344259b216b9)
11bb92983SJerome Forissier /* SPDX-License-Identifier: BSD-2-Clause */
203c21dc9SSY Chiu /*
303c21dc9SSY Chiu  * Copyright (c) 2014, Linaro Limited
403c21dc9SSY Chiu  */
503c21dc9SSY Chiu 
6d50fee03SEtienne Carriere #ifndef __INITCALL_H
7d50fee03SEtienne Carriere #define __INITCALL_H
803c21dc9SSY Chiu 
99e592338SJens Wiklander #include <scattered_array.h>
1003c21dc9SSY Chiu #include <tee_api_types.h>
119f0a24daSJens Wiklander #include <trace.h>
1203c21dc9SSY Chiu 
139f0a24daSJens Wiklander struct initcall {
149f0a24daSJens Wiklander 	TEE_Result (*func)(void);
159f0a24daSJens Wiklander #if TRACE_LEVEL >= TRACE_DEBUG
169f0a24daSJens Wiklander 	int level;
179f0a24daSJens Wiklander 	const char *func_name;
189f0a24daSJens Wiklander #endif
199f0a24daSJens Wiklander };
2003c21dc9SSY Chiu 
219f0a24daSJens Wiklander #if TRACE_LEVEL >= TRACE_DEBUG
22e3172f9dSJens Wiklander #define __define_initcall(type, lvl, fn) \
23e3172f9dSJens Wiklander 	SCATTERED_ARRAY_DEFINE_PG_ITEM_ORDERED(type ## call, lvl, \
249f0a24daSJens Wiklander 					       struct initcall) = \
259f0a24daSJens Wiklander 		{ .func = (fn), .level = (lvl), .func_name = #fn, }
269f0a24daSJens Wiklander #else
27e3172f9dSJens Wiklander #define __define_initcall(type, lvl, fn) \
28e3172f9dSJens Wiklander 	SCATTERED_ARRAY_DEFINE_PG_ITEM_ORDERED(type ## call, lvl, \
299f0a24daSJens Wiklander 					       struct initcall) = \
309f0a24daSJens Wiklander 		{ .func = (fn), }
319f0a24daSJens Wiklander #endif
3203c21dc9SSY Chiu 
33bd59a6adSJens Wiklander #define preinitcall_begin \
34bd59a6adSJens Wiklander 			SCATTERED_ARRAY_BEGIN(preinitcall, struct initcall)
35bd59a6adSJens Wiklander #define preinitcall_end SCATTERED_ARRAY_END(preinitcall, struct initcall)
36bd59a6adSJens Wiklander 
37*913d93a4SJens Wiklander #define early_initcall_begin \
38*913d93a4SJens Wiklander 			SCATTERED_ARRAY_BEGIN(early_initcall, struct initcall)
39*913d93a4SJens Wiklander #define early_initcall_end \
40*913d93a4SJens Wiklander 			SCATTERED_ARRAY_END(early_initcall, struct initcall)
41*913d93a4SJens Wiklander 
42*913d93a4SJens Wiklander #define service_initcall_begin \
43*913d93a4SJens Wiklander 			SCATTERED_ARRAY_BEGIN(service_initcall, struct initcall)
44*913d93a4SJens Wiklander #define service_initcall_end \
45*913d93a4SJens Wiklander 			SCATTERED_ARRAY_END(service_initcall, struct initcall)
46*913d93a4SJens Wiklander 
47*913d93a4SJens Wiklander #define driver_initcall_begin \
48*913d93a4SJens Wiklander 			SCATTERED_ARRAY_BEGIN(driver_initcall, struct initcall)
49*913d93a4SJens Wiklander #define driver_initcall_end \
50*913d93a4SJens Wiklander 			SCATTERED_ARRAY_END(driver_initcall, struct initcall)
519e592338SJens Wiklander 
52e3172f9dSJens Wiklander #define finalcall_begin	SCATTERED_ARRAY_BEGIN(finalcall, struct initcall)
53e3172f9dSJens Wiklander #define finalcall_end	SCATTERED_ARRAY_END(finalcall, struct initcall)
54e3172f9dSJens Wiklander 
55bd59a6adSJens Wiklander /*
56bd59a6adSJens Wiklander  * The preinit_*(), *_init() and boot_final() macros are used to register
57bd59a6adSJens Wiklander  * callback functions to be called at different stages during
58bd59a6adSJens Wiklander  * initialization.
59bd59a6adSJens Wiklander  *
60bd59a6adSJens Wiklander  * Functions registered with preinit_*() are always called before functions
61bd59a6adSJens Wiklander  * registered with *_init().
62bd59a6adSJens Wiklander  *
63bd59a6adSJens Wiklander  * Functions registered with boot_final() are called before exiting to
64bd59a6adSJens Wiklander  * normal world the first time.
65bd59a6adSJens Wiklander  *
66bd59a6adSJens Wiklander  * Without virtualization this happens in the order of the defines below.
67bd59a6adSJens Wiklander  *
68bd59a6adSJens Wiklander  * However, with virtualization things are a bit different. boot_final()
69bd59a6adSJens Wiklander  * functions are called first before exiting to normal world the first
70bd59a6adSJens Wiklander  * time. Functions registered with boot_final() can only operate on the
71bd59a6adSJens Wiklander  * nexus. preinit_*() functions are called early before the first yielding
72bd59a6adSJens Wiklander  * call into the partition, in the newly created partition. *_init()
73bd59a6adSJens Wiklander  * functions are called at the first yielding call.
74bd59a6adSJens Wiklander  *
75bd59a6adSJens Wiklander  *  +-------------------------------+-----------------------------------+
76bd59a6adSJens Wiklander  *  | Without virtualization        | With virtualization               |
77bd59a6adSJens Wiklander  *  +-------------------------------+-----------------------------------+
78bd59a6adSJens Wiklander  *  | At the end of boot_init_primary_late() just before the print:     |
79bd59a6adSJens Wiklander  *  | "Primary CPU switching to normal world boot"                      |
80bd59a6adSJens Wiklander  *  +-------------------------------+-----------------------------------+
81dcad1800SJens Wiklander  *  | 1. call_preinitcalls()        | In the nexus, final calls         |
82bd59a6adSJens Wiklander  *  | 2. call_initcalls()           +-----------------------------------+
83dcad1800SJens Wiklander  *  | 3. call_finalcalls()          | 1. boot_final() / nex_*init*()    |
84bd59a6adSJens Wiklander  *  +-------------------------------+-----------------------------------+
85bd59a6adSJens Wiklander  *  | "Primary CPU switching to normal world boot" is printed           |
86bd59a6adSJens Wiklander  *  +-------------------------------+-----------------------------------+
87bd59a6adSJens Wiklander  *                                  | A guest is created and            |
88bd59a6adSJens Wiklander  *                                  | virt_guest_created() is called.   |
89bd59a6adSJens Wiklander  *                                  | After the partition has been      |
90bd59a6adSJens Wiklander  *                                  | created and activated.            |
91bd59a6adSJens Wiklander  *                                  +-----------------------------------+
92bd59a6adSJens Wiklander  *                                  | 2. call_preinitcalls()            |
93bd59a6adSJens Wiklander  *                                  +-----------------------------------+
94bd59a6adSJens Wiklander  *                                  | When the partition is receiving   |
95bd59a6adSJens Wiklander  *                                  | the first yielding call           |
96bd59a6adSJens Wiklander  *                                  | virt_on_stdcall() is called.      |
97bd59a6adSJens Wiklander  *                                  +-----------------------------------+
98bd59a6adSJens Wiklander  *                                  | 3. call_initcalls()               |
99bd59a6adSJens Wiklander  *                                  +-----------------------------------+
100bd59a6adSJens Wiklander  */
101bd59a6adSJens Wiklander 
102bd59a6adSJens Wiklander #define preinit_early(fn)		__define_initcall(preinit, 1, fn)
103bd59a6adSJens Wiklander #define preinit(fn)			__define_initcall(preinit, 2, fn)
104bd59a6adSJens Wiklander #define preinit_late(fn)		__define_initcall(preinit, 3, fn)
105bd59a6adSJens Wiklander 
106*913d93a4SJens Wiklander #define early_init(fn)			__define_initcall(early_init, 1, fn)
107*913d93a4SJens Wiklander #define early_init_late(fn)		__define_initcall(early_init, 2, fn)
108*913d93a4SJens Wiklander #define service_init(fn)		__define_initcall(service_init, 1, fn)
109*913d93a4SJens Wiklander #define service_init_late(fn)		__define_initcall(service_init, 2, fn)
110*913d93a4SJens Wiklander #define driver_init(fn)			__define_initcall(driver_init, 1, fn)
111*913d93a4SJens Wiklander #define driver_init_late(fn)		__define_initcall(driver_init, 2, fn)
112*913d93a4SJens Wiklander #define release_init_resource(fn)	__define_initcall(driver_init, 3, fn)
113e3172f9dSJens Wiklander 
114e3172f9dSJens Wiklander #define boot_final(fn)			__define_initcall(final, 1, fn)
1159e592338SJens Wiklander 
116dcad1800SJens Wiklander /*
117dcad1800SJens Wiklander  * These nex_* init-calls are provided for drivers and services that reside
118dcad1800SJens Wiklander  * in the nexus in case of virtualization. The init-calls are performed
119dcad1800SJens Wiklander  * before exiting to the non-secure world at the end of boot
120dcad1800SJens Wiklander  * initialization. In case of virtualization the init-calls are based on
121dcad1800SJens Wiklander  * final calls, while otherwise are the same as the non-nex counterpart.
122dcad1800SJens Wiklander  */
123dcad1800SJens Wiklander #ifdef CFG_NS_VIRTUALIZATION
124dcad1800SJens Wiklander #define nex_early_init(fn)		boot_final(fn)
125dcad1800SJens Wiklander #define nex_early_init_late(fn)		__define_initcall(final, 2, fn)
126dcad1800SJens Wiklander #define nex_service_init(fn)		__define_initcall(final, 3, fn)
127dcad1800SJens Wiklander #define nex_service_init_late(fn)	__define_initcall(final, 4, fn)
128dcad1800SJens Wiklander #define nex_driver_init(fn)		__define_initcall(final, 5, fn)
129dcad1800SJens Wiklander #define nex_driver_init_late(fn)	__define_initcall(final, 6, fn)
130dcad1800SJens Wiklander #define nex_release_init_resource(fn)	__define_initcall(final, 7, fn)
131dcad1800SJens Wiklander #else
132dcad1800SJens Wiklander #define nex_early_init(fn)		early_init(fn)
133dcad1800SJens Wiklander #define nex_early_init_late(fn)		early_init_late(fn)
134dcad1800SJens Wiklander #define nex_service_init(fn)		service_init(fn)
135dcad1800SJens Wiklander #define nex_service_init_late(fn)	service_init_late(fn)
136dcad1800SJens Wiklander #define nex_driver_init(fn)		driver_init(fn)
137dcad1800SJens Wiklander #define nex_driver_init_late(fn)	driver_init_late(fn)
138dcad1800SJens Wiklander #define nex_release_init_resource(fn)	release_init_resource(fn)
139dcad1800SJens Wiklander #endif
140dcad1800SJens Wiklander 
141bd59a6adSJens Wiklander void call_preinitcalls(void);
142*913d93a4SJens Wiklander void call_early_initcalls(void);
143*913d93a4SJens Wiklander void call_service_initcalls(void);
144*913d93a4SJens Wiklander void call_driver_initcalls(void);
145c5c56024SJens Wiklander void call_initcalls(void);
146e3172f9dSJens Wiklander void call_finalcalls(void);
14703c21dc9SSY Chiu 
14803c21dc9SSY Chiu #endif
149