xref: /optee_os/core/include/initcall.h (revision 94d4f61d55388414bc2b144acdfb47d66f57dbb0)
11bb92983SJerome Forissier /* SPDX-License-Identifier: BSD-2-Clause */
203c21dc9SSY Chiu /*
303c21dc9SSY Chiu  * Copyright (c) 2014, Linaro Limited
403c21dc9SSY Chiu  */
503c21dc9SSY Chiu 
603c21dc9SSY Chiu #ifndef INITCALL_H
703c21dc9SSY Chiu #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 
379f0a24daSJens Wiklander #define initcall_begin	SCATTERED_ARRAY_BEGIN(initcall, struct initcall)
389f0a24daSJens Wiklander #define initcall_end	SCATTERED_ARRAY_END(initcall, struct initcall)
399e592338SJens Wiklander 
40e3172f9dSJens Wiklander #define finalcall_begin	SCATTERED_ARRAY_BEGIN(finalcall, struct initcall)
41e3172f9dSJens Wiklander #define finalcall_end	SCATTERED_ARRAY_END(finalcall, struct initcall)
42e3172f9dSJens Wiklander 
43bd59a6adSJens Wiklander /*
44bd59a6adSJens Wiklander  * The preinit_*(), *_init() and boot_final() macros are used to register
45bd59a6adSJens Wiklander  * callback functions to be called at different stages during
46bd59a6adSJens Wiklander  * initialization.
47bd59a6adSJens Wiklander  *
48bd59a6adSJens Wiklander  * Functions registered with preinit_*() are always called before functions
49bd59a6adSJens Wiklander  * registered with *_init().
50bd59a6adSJens Wiklander  *
51bd59a6adSJens Wiklander  * Functions registered with boot_final() are called before exiting to
52bd59a6adSJens Wiklander  * normal world the first time.
53bd59a6adSJens Wiklander  *
54bd59a6adSJens Wiklander  * Without virtualization this happens in the order of the defines below.
55bd59a6adSJens Wiklander  *
56bd59a6adSJens Wiklander  * However, with virtualization things are a bit different. boot_final()
57bd59a6adSJens Wiklander  * functions are called first before exiting to normal world the first
58bd59a6adSJens Wiklander  * time. Functions registered with boot_final() can only operate on the
59bd59a6adSJens Wiklander  * nexus. preinit_*() functions are called early before the first yielding
60bd59a6adSJens Wiklander  * call into the partition, in the newly created partition. *_init()
61bd59a6adSJens Wiklander  * functions are called at the first yielding call.
62bd59a6adSJens Wiklander  *
63bd59a6adSJens Wiklander  *  +-------------------------------+-----------------------------------+
64bd59a6adSJens Wiklander  *  | Without virtualization        | With virtualization               |
65bd59a6adSJens Wiklander  *  +-------------------------------+-----------------------------------+
66bd59a6adSJens Wiklander  *  | At the end of boot_init_primary_late() just before the print:     |
67bd59a6adSJens Wiklander  *  | "Primary CPU switching to normal world boot"                      |
68bd59a6adSJens Wiklander  *  +-------------------------------+-----------------------------------+
69bd59a6adSJens Wiklander  *  | 1. call_preinitcalls()        | In the nexus                      |
70bd59a6adSJens Wiklander  *  | 2. call_initcalls()           +-----------------------------------+
71bd59a6adSJens Wiklander  *  | 3. call_finalcalls()          | 1. call_finalcalls()              |
72bd59a6adSJens Wiklander  *  +-------------------------------+-----------------------------------+
73bd59a6adSJens Wiklander  *  | "Primary CPU switching to normal world boot" is printed           |
74bd59a6adSJens Wiklander  *  +-------------------------------+-----------------------------------+
75bd59a6adSJens Wiklander  *                                  | A guest is created and            |
76bd59a6adSJens Wiklander  *                                  | virt_guest_created() is called.   |
77bd59a6adSJens Wiklander  *                                  | After the partition has been      |
78bd59a6adSJens Wiklander  *                                  | created and activated.            |
79bd59a6adSJens Wiklander  *                                  +-----------------------------------+
80bd59a6adSJens Wiklander  *                                  | 2. call_preinitcalls()            |
81bd59a6adSJens Wiklander  *                                  +-----------------------------------+
82bd59a6adSJens Wiklander  *                                  | When the partition is receiving   |
83bd59a6adSJens Wiklander  *                                  | the first yielding call           |
84bd59a6adSJens Wiklander  *                                  | virt_on_stdcall() is called.      |
85bd59a6adSJens Wiklander  *                                  +-----------------------------------+
86bd59a6adSJens Wiklander  *                                  | 3. call_initcalls()               |
87bd59a6adSJens Wiklander  *                                  +-----------------------------------+
88bd59a6adSJens Wiklander  */
89bd59a6adSJens Wiklander 
90bd59a6adSJens Wiklander #define preinit_early(fn)		__define_initcall(preinit, 1, fn)
91bd59a6adSJens Wiklander #define preinit(fn)			__define_initcall(preinit, 2, fn)
92bd59a6adSJens Wiklander #define preinit_late(fn)		__define_initcall(preinit, 3, fn)
93bd59a6adSJens Wiklander 
94e3172f9dSJens Wiklander #define early_init(fn)			__define_initcall(init, 1, fn)
95e3172f9dSJens Wiklander #define early_init_late(fn)		__define_initcall(init, 2, fn)
96e3172f9dSJens Wiklander #define service_init(fn)		__define_initcall(init, 3, fn)
97e3172f9dSJens Wiklander #define service_init_late(fn)		__define_initcall(init, 4, fn)
98e3172f9dSJens Wiklander #define driver_init(fn)			__define_initcall(init, 5, fn)
99e3172f9dSJens Wiklander #define driver_init_late(fn)		__define_initcall(init, 6, fn)
100*94d4f61dSEtienne Carriere #define release_init_resource(fn)	__define_initcall(init, 7, fn)
101e3172f9dSJens Wiklander 
102e3172f9dSJens Wiklander #define boot_final(fn)			__define_initcall(final, 1, fn)
1039e592338SJens Wiklander 
104bd59a6adSJens Wiklander void call_preinitcalls(void);
105c5c56024SJens Wiklander void call_initcalls(void);
106e3172f9dSJens Wiklander void call_finalcalls(void);
10703c21dc9SSY Chiu 
10803c21dc9SSY Chiu #endif
109