xref: /rk3399_ARM-atf/include/common/runtime_svc.h (revision ff2743e544f0f82381ebb9dff8f14eacb837d2e0)
1 /*
2  * Copyright (c) 2013-2018, ARM Limited and Contributors. All rights reserved.
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 
7 #ifndef __RUNTIME_SVC_H__
8 #define __RUNTIME_SVC_H__
9 
10 #include <bl_common.h>		/* to include exception types */
11 #include <cassert.h>
12 #include <smccc_helpers.h>	/* to include SMCCC definitions */
13 #include <utils_def.h>
14 
15 /*******************************************************************************
16  * Structure definition, typedefs & constants for the runtime service framework
17  ******************************************************************************/
18 
19 /*
20  * Constants to allow the assembler access a runtime service
21  * descriptor
22  */
23 #ifdef AARCH32
24 #define RT_SVC_SIZE_LOG2	4
25 #define RT_SVC_DESC_INIT	8
26 #define RT_SVC_DESC_HANDLE	12
27 #else
28 #define RT_SVC_SIZE_LOG2	5
29 #define RT_SVC_DESC_INIT	16
30 #define RT_SVC_DESC_HANDLE	24
31 #endif /* AARCH32 */
32 #define SIZEOF_RT_SVC_DESC	(1 << RT_SVC_SIZE_LOG2)
33 
34 
35 /*
36  * In SMCCC 1.X, the function identifier has 6 bits for the owning entity number
37  * and a single bit for the type of smc call. When taken together, those values
38  * limit the maximum number of runtime services to 128.
39  *
40  * In SMCCC 2.X the type bit is always 1 and there are only 4 OEN bits in the
41  * compatibility namespace, so the total number of services is 16. The LSB of
42  * namespace is also added to these 4 bits to make space for the vendor service
43  * handler and so the total number of runtime services is 32.
44  */
45 #if SMCCC_MAJOR_VERSION == 1
46 #define MAX_RT_SVCS		128
47 #elif SMCCC_MAJOR_VERSION == 2
48 #define MAX_RT_SVCS		32
49 #endif
50 
51 #ifndef __ASSEMBLY__
52 
53 /* Prototype for runtime service initializing function */
54 typedef int32_t (*rt_svc_init_t)(void);
55 
56 /*
57  * Prototype for runtime service SMC handler function. x0 (SMC Function ID) to
58  * x4 are as passed by the caller. Rest of the arguments to SMC and the context
59  * can be accessed using the handle pointer. The cookie parameter is reserved
60  * for future use
61  */
62 typedef uintptr_t (*rt_svc_handle_t)(uint32_t smc_fid,
63 				  u_register_t x1,
64 				  u_register_t x2,
65 				  u_register_t x3,
66 				  u_register_t x4,
67 				  void *cookie,
68 				  void *handle,
69 				  u_register_t flags);
70 typedef struct rt_svc_desc {
71 	uint8_t start_oen;
72 	uint8_t end_oen;
73 #if SMCCC_MAJOR_VERSION == 1
74 	uint8_t call_type;
75 #elif SMCCC_MAJOR_VERSION == 2
76 	uint8_t is_vendor;
77 #endif
78 	const char *name;
79 	rt_svc_init_t init;
80 	rt_svc_handle_t handle;
81 } rt_svc_desc_t;
82 
83 /*
84  * Convenience macros to declare a service descriptor
85  */
86 #if SMCCC_MAJOR_VERSION == 1
87 
88 #define DECLARE_RT_SVC(_name, _start, _end, _type, _setup, _smch)	\
89 	static const rt_svc_desc_t __svc_desc_ ## _name			\
90 		__section("rt_svc_descs") __used = {			\
91 			.start_oen = _start,				\
92 			.end_oen = _end,				\
93 			.call_type = _type,				\
94 			.name = #_name,					\
95 			.init = _setup,					\
96 			.handle = _smch					\
97 		}
98 
99 #elif SMCCC_MAJOR_VERSION == 2
100 
101 #define DECLARE_RT_SVC(_name, _start, _end, _type, _setup, _smch)	\
102 	static const rt_svc_desc_t __svc_desc_ ## _name			\
103 		__section("rt_svc_descs") __used = {			\
104 			.start_oen = _start,				\
105 			.end_oen = _end,				\
106 			.is_vendor = 0,					\
107 			.name = #_name,					\
108 			.init = _setup,					\
109 			.handle = _smch,				\
110 		};							\
111 	CASSERT((_type) == SMC_TYPE_FAST, rt_svc_type_check_ ## _name)
112 
113 /*
114  * The higher 16 entries of the runtime services are used for the vendor
115  * specific descriptor.
116  */
117 #define DECLARE_RT_SVC_VENDOR(_setup, _smch)				\
118 	static const rt_svc_desc_t __svc_desc_vendor			\
119 		__section("rt_svc_descs") __used = {			\
120 			.start_oen = 0,					\
121 			.end_oen = 15,					\
122 			.is_vendor = 1,					\
123 			.name = "vendor_rt_svc",			\
124 			.init = _setup,					\
125 			.handle = _smch,				\
126 		}
127 
128 #endif /* SMCCC_MAJOR_VERSION */
129 
130 /*
131  * Compile time assertions related to the 'rt_svc_desc' structure to:
132  * 1. ensure that the assembler and the compiler view of the size
133  *    of the structure are the same.
134  * 2. ensure that the assembler and the compiler see the initialisation
135  *    routine at the same offset.
136  * 3. ensure that the assembler and the compiler see the handler
137  *    routine at the same offset.
138  */
139 CASSERT((sizeof(rt_svc_desc_t) == SIZEOF_RT_SVC_DESC), \
140 	assert_sizeof_rt_svc_desc_mismatch);
141 CASSERT(RT_SVC_DESC_INIT == __builtin_offsetof(rt_svc_desc_t, init), \
142 	assert_rt_svc_desc_init_offset_mismatch);
143 CASSERT(RT_SVC_DESC_HANDLE == __builtin_offsetof(rt_svc_desc_t, handle), \
144 	assert_rt_svc_desc_handle_offset_mismatch);
145 
146 
147 #if SMCCC_MAJOR_VERSION == 1
148 /*
149  * This macro combines the call type and the owning entity number corresponding
150  * to a runtime service to generate a unique owning entity number. This unique
151  * oen is used to access an entry in the 'rt_svc_descs_indices' array. The entry
152  * contains the index of the service descriptor in the 'rt_svc_descs' array.
153  */
154 #define get_unique_oen(oen, call_type)				\
155 	(((uint32_t)(oen) & FUNCID_OEN_MASK) |			\
156 	(((uint32_t)(call_type) & FUNCID_TYPE_MASK) << FUNCID_OEN_WIDTH))
157 
158 /*
159  * This macro generates the unique owning entity number from the SMC Function
160  * ID. This unique oen is used to access an entry in the 'rt_svc_descs_indices'
161  * array to invoke the corresponding runtime service handler during SMC
162  * handling.
163  */
164 #define get_unique_oen_from_smc_fid(fid)			\
165 	get_unique_oen(GET_SMC_OEN(fid), GET_SMC_TYPE(fid))
166 
167 #elif SMCCC_MAJOR_VERSION == 2
168 
169 /*
170  * This macro combines the owning entity number corresponding to a runtime
171  * service with one extra bit for the vendor namespace to generate an index into
172  * the 'rt_svc_descs_indices' array. The entry contains the index of the service
173  * descriptor in the 'rt_svc_descs' array.
174  */
175 #define get_rt_desc_idx(oen, is_vendor)				\
176 	(((uint32_t)(oen) & FUNCID_OEN_MASK) |			\
177 	(((uint32_t)(is_vendor) & 1U) << FUNCID_OEN_WIDTH))
178 
179 #endif
180 
181 /*******************************************************************************
182  * Function & variable prototypes
183  ******************************************************************************/
184 void runtime_svc_init(void);
185 uintptr_t handle_runtime_svc(uint32_t smc_fid, void *cookie, void *handle,
186 						unsigned int flags);
187 IMPORT_SYM(uintptr_t, __RT_SVC_DESCS_START__,		RT_SVC_DESCS_START);
188 IMPORT_SYM(uintptr_t, __RT_SVC_DESCS_END__,		RT_SVC_DESCS_END);
189 void init_crash_reporting(void);
190 
191 extern uint8_t rt_svc_descs_indices[MAX_RT_SVCS];
192 
193 #endif /*__ASSEMBLY__*/
194 #endif /* __RUNTIME_SVC_H__ */
195