xref: /rk3399_ARM-atf/include/common/runtime_svc.h (revision c948f77136c42a92d0bb660543a3600c36dcf7f1)
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 <common/bl_common.h>		/* to include exception types */
11 #include <lib/cassert.h>
12 #include <lib/utils_def.h>
13 #include <smccc_helpers.h>	/* to include SMCCC definitions */
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	U(4)
25 #define RT_SVC_DESC_INIT	U(8)
26 #define RT_SVC_DESC_HANDLE	U(12)
27 #else
28 #define RT_SVC_SIZE_LOG2	U(5)
29 #define RT_SVC_DESC_INIT	U(16)
30 #define RT_SVC_DESC_HANDLE	U(24)
31 #endif /* AARCH32 */
32 #define SIZEOF_RT_SVC_DESC	(U(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		U(128)
47 #elif SMCCC_MAJOR_VERSION == 2
48 #define MAX_RT_SVCS		U(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 function combines the call type and the owning entity number
150  * corresponding to a runtime service to generate a unique owning entity number.
151  * This unique oen is used to access an entry in the 'rt_svc_descs_indices'
152  * array. The entry contains the index of the service descriptor in the
153  * 'rt_svc_descs' array.
154  */
155 static inline uint32_t get_unique_oen(uint32_t oen, uint32_t call_type)
156 {
157 	return ((call_type & FUNCID_TYPE_MASK) << FUNCID_OEN_WIDTH) |
158 		(oen & FUNCID_OEN_MASK);
159 }
160 
161 /*
162  * This function generates the unique owning entity number from the SMC Function
163  * ID. This unique oen is used to access an entry in the 'rt_svc_descs_indices'
164  * array to invoke the corresponding runtime service handler during SMC
165  * handling.
166  */
167 static inline uint32_t get_unique_oen_from_smc_fid(uint32_t fid)
168 {
169 	return get_unique_oen(GET_SMC_OEN(fid), GET_SMC_TYPE(fid));
170 }
171 
172 #elif SMCCC_MAJOR_VERSION == 2
173 
174 /*
175  * This function combines the owning entity number corresponding to a runtime
176  * service with one extra bit for the vendor namespace to generate an index into
177  * the 'rt_svc_descs_indices' array. The entry contains the index of the service
178  * descriptor in the 'rt_svc_descs' array.
179  */
180 static inline uint32_t get_rt_desc_idx(uint32_t oen, uint32_t is_vendor)
181 {
182 	return ((is_vendor & 1U) << FUNCID_OEN_WIDTH) |
183 		(oen & FUNCID_OEN_MASK);
184 }
185 
186 #endif
187 
188 /*******************************************************************************
189  * Function & variable prototypes
190  ******************************************************************************/
191 void runtime_svc_init(void);
192 uintptr_t handle_runtime_svc(uint32_t smc_fid, void *cookie, void *handle,
193 						unsigned int flags);
194 IMPORT_SYM(uintptr_t, __RT_SVC_DESCS_START__,		RT_SVC_DESCS_START);
195 IMPORT_SYM(uintptr_t, __RT_SVC_DESCS_END__,		RT_SVC_DESCS_END);
196 void init_crash_reporting(void);
197 
198 extern uint8_t rt_svc_descs_indices[MAX_RT_SVCS];
199 
200 #endif /*__ASSEMBLY__*/
201 #endif /* RUNTIME_SVC_H */
202