xref: /optee_os/core/include/initcall.h (revision bd59a6ad7593cfac9075a9e7e854620ba80dada3)
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 
33*bd59a6adSJens Wiklander #define preinitcall_begin \
34*bd59a6adSJens Wiklander 			SCATTERED_ARRAY_BEGIN(preinitcall, struct initcall)
35*bd59a6adSJens Wiklander #define preinitcall_end SCATTERED_ARRAY_END(preinitcall, struct initcall)
36*bd59a6adSJens 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 
43*bd59a6adSJens Wiklander /*
44*bd59a6adSJens Wiklander  * The preinit_*(), *_init() and boot_final() macros are used to register
45*bd59a6adSJens Wiklander  * callback functions to be called at different stages during
46*bd59a6adSJens Wiklander  * initialization.
47*bd59a6adSJens Wiklander  *
48*bd59a6adSJens Wiklander  * Functions registered with preinit_*() are always called before functions
49*bd59a6adSJens Wiklander  * registered with *_init().
50*bd59a6adSJens Wiklander  *
51*bd59a6adSJens Wiklander  * Functions registered with boot_final() are called before exiting to
52*bd59a6adSJens Wiklander  * normal world the first time.
53*bd59a6adSJens Wiklander  *
54*bd59a6adSJens Wiklander  * Without virtualization this happens in the order of the defines below.
55*bd59a6adSJens Wiklander  *
56*bd59a6adSJens Wiklander  * However, with virtualization things are a bit different. boot_final()
57*bd59a6adSJens Wiklander  * functions are called first before exiting to normal world the first
58*bd59a6adSJens Wiklander  * time. Functions registered with boot_final() can only operate on the
59*bd59a6adSJens Wiklander  * nexus. preinit_*() functions are called early before the first yielding
60*bd59a6adSJens Wiklander  * call into the partition, in the newly created partition. *_init()
61*bd59a6adSJens Wiklander  * functions are called at the first yielding call.
62*bd59a6adSJens Wiklander  *
63*bd59a6adSJens Wiklander  *  +-------------------------------+-----------------------------------+
64*bd59a6adSJens Wiklander  *  | Without virtualization        | With virtualization               |
65*bd59a6adSJens Wiklander  *  +-------------------------------+-----------------------------------+
66*bd59a6adSJens Wiklander  *  | At the end of boot_init_primary_late() just before the print:     |
67*bd59a6adSJens Wiklander  *  | "Primary CPU switching to normal world boot"                      |
68*bd59a6adSJens Wiklander  *  +-------------------------------+-----------------------------------+
69*bd59a6adSJens Wiklander  *  | 1. call_preinitcalls()        | In the nexus                      |
70*bd59a6adSJens Wiklander  *  | 2. call_initcalls()           +-----------------------------------+
71*bd59a6adSJens Wiklander  *  | 3. call_finalcalls()          | 1. call_finalcalls()              |
72*bd59a6adSJens Wiklander  *  +-------------------------------+-----------------------------------+
73*bd59a6adSJens Wiklander  *  | "Primary CPU switching to normal world boot" is printed           |
74*bd59a6adSJens Wiklander  *  +-------------------------------+-----------------------------------+
75*bd59a6adSJens Wiklander  *                                  | A guest is created and            |
76*bd59a6adSJens Wiklander  *                                  | virt_guest_created() is called.   |
77*bd59a6adSJens Wiklander  *                                  | After the partition has been      |
78*bd59a6adSJens Wiklander  *                                  | created and activated.            |
79*bd59a6adSJens Wiklander  *                                  +-----------------------------------+
80*bd59a6adSJens Wiklander  *                                  | 2. call_preinitcalls()            |
81*bd59a6adSJens Wiklander  *                                  +-----------------------------------+
82*bd59a6adSJens Wiklander  *                                  | When the partition is receiving   |
83*bd59a6adSJens Wiklander  *                                  | the first yielding call           |
84*bd59a6adSJens Wiklander  *                                  | virt_on_stdcall() is called.      |
85*bd59a6adSJens Wiklander  *                                  +-----------------------------------+
86*bd59a6adSJens Wiklander  *                                  | 3. call_initcalls()               |
87*bd59a6adSJens Wiklander  *                                  +-----------------------------------+
88*bd59a6adSJens Wiklander  */
89*bd59a6adSJens Wiklander 
90*bd59a6adSJens Wiklander #define preinit_early(fn)		__define_initcall(preinit, 1, fn)
91*bd59a6adSJens Wiklander #define preinit(fn)			__define_initcall(preinit, 2, fn)
92*bd59a6adSJens Wiklander #define preinit_late(fn)		__define_initcall(preinit, 3, fn)
93*bd59a6adSJens 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)
100e3172f9dSJens Wiklander 
101e3172f9dSJens Wiklander #define boot_final(fn)			__define_initcall(final, 1, fn)
1029e592338SJens Wiklander 
103*bd59a6adSJens Wiklander void call_preinitcalls(void);
104c5c56024SJens Wiklander void call_initcalls(void);
105e3172f9dSJens Wiklander void call_finalcalls(void);
10603c21dc9SSY Chiu 
10703c21dc9SSY Chiu #endif
108