1 /*
2  * Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are met:
6  *
7  * Redistributions of source code must retain the above copyright notice, this
8  * list of conditions and the following disclaimer.
9  *
10  * Redistributions in binary form must reproduce the above copyright notice,
11  * this list of conditions and the following disclaimer in the documentation
12  * and/or other materials provided with the distribution.
13  *
14  * Neither the name of ARM nor the names of its contributors may be used
15  * to endorse or promote products derived from this software without specific
16  * prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
22  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28  * POSSIBILITY OF SUCH DAMAGE.
29  */
30 
31 #ifndef __RUNTIME_SVC_H__
32 #define __RUNTIME_SVC_H__
33 
34 /*******************************************************************************
35  * Bit definitions inside the function id as per the SMC calling convention
36  ******************************************************************************/
37 #define FUNCID_TYPE_SHIFT		31
38 #define FUNCID_CC_SHIFT			30
39 #define FUNCID_OEN_SHIFT		24
40 #define FUNCID_NUM_SHIFT		0
41 
42 #define FUNCID_TYPE_MASK		0x1
43 #define FUNCID_CC_MASK			0x1
44 #define FUNCID_OEN_MASK			0x3f
45 #define FUNCID_NUM_MASK			0xffff
46 
47 #define FUNCID_TYPE_WIDTH		1
48 #define FUNCID_CC_WIDTH			1
49 #define FUNCID_OEN_WIDTH		6
50 #define FUNCID_NUM_WIDTH		16
51 
52 #define GET_SMC_CC(id)			((id >> FUNCID_CC_SHIFT) & \
53 					 FUNCID_CC_MASK)
54 #define GET_SMC_TYPE(id)		((id >> FUNCID_TYPE_SHIFT) & \
55 					 FUNCID_TYPE_MASK)
56 
57 #define SMC_64				1
58 #define SMC_32				0
59 #define SMC_UNK				0xffffffff
60 #define SMC_TYPE_FAST			1
61 #define SMC_TYPE_STD			0
62 #define SMC_PREEMPTED		0xfffffffe
63 /*******************************************************************************
64  * Owning entity number definitions inside the function id as per the SMC
65  * calling convention
66  ******************************************************************************/
67 #define OEN_ARM_START			0
68 #define OEN_ARM_END			0
69 #define OEN_CPU_START			1
70 #define OEN_CPU_END			1
71 #define OEN_SIP_START			2
72 #define OEN_SIP_END			2
73 #define OEN_OEM_START			3
74 #define OEN_OEM_END			3
75 #define OEN_STD_START			4	/* Standard Calls */
76 #define OEN_STD_END			4
77 #define OEN_TAP_START			48	/* Trusted Applications */
78 #define OEN_TAP_END			49
79 #define OEN_TOS_START			50	/* Trusted OS */
80 #define OEN_TOS_END			63
81 #define OEN_LIMIT			64
82 
83 /*******************************************************************************
84  * Constants to indicate type of exception to the common exception handler.
85  ******************************************************************************/
86 #define SYNC_EXCEPTION_SP_EL0		0x0
87 #define IRQ_SP_EL0			0x1
88 #define FIQ_SP_EL0			0x2
89 #define SERROR_SP_EL0			0x3
90 #define SYNC_EXCEPTION_SP_ELX		0x4
91 #define IRQ_SP_ELX			0x5
92 #define FIQ_SP_ELX			0x6
93 #define SERROR_SP_ELX			0x7
94 #define SYNC_EXCEPTION_AARCH64		0x8
95 #define IRQ_AARCH64			0x9
96 #define FIQ_AARCH64			0xa
97 #define SERROR_AARCH64			0xb
98 #define SYNC_EXCEPTION_AARCH32		0xc
99 #define IRQ_AARCH32			0xd
100 #define FIQ_AARCH32			0xe
101 #define SERROR_AARCH32			0xf
102 
103 /*******************************************************************************
104  * Structure definition, typedefs & constants for the runtime service framework
105  ******************************************************************************/
106 
107 /*
108  * Constants to allow the assembler access a runtime service
109  * descriptor
110  */
111 #define RT_SVC_SIZE_LOG2	5
112 #define SIZEOF_RT_SVC_DESC	(1 << RT_SVC_SIZE_LOG2)
113 #define RT_SVC_DESC_INIT	16
114 #define RT_SVC_DESC_HANDLE	24
115 
116 /*
117  * The function identifier has 6 bits for the owning entity number and
118  * single bit for the type of smc call. When taken together these
119  * values limit the maximum number of runtime services to 128.
120  */
121 #define MAX_RT_SVCS		128
122 
123 #ifndef __ASSEMBLY__
124 
125 #include <cassert.h>
126 #include <context.h>
127 #include <stdint.h>
128 
129 /* Various flags passed to SMC handlers */
130 #define SMC_FROM_SECURE		(0 << 0)
131 #define SMC_FROM_NON_SECURE	(1 << 0)
132 
133 #define is_caller_non_secure(_f)	(!!(_f & SMC_FROM_NON_SECURE))
134 #define is_caller_secure(_f)		(!(is_caller_non_secure(_f)))
135 
136 /* Prototype for runtime service initializing function */
137 typedef int32_t (*rt_svc_init_t)(void);
138 
139 /* Convenience macros to return from SMC handler */
140 #define SMC_RET0(_h)	{ \
141 	return (uint64_t) (_h);		\
142 }
143 #define SMC_RET1(_h, _x0)	{ \
144 	write_ctx_reg(get_gpregs_ctx(_h), CTX_GPREG_X0, (_x0)); \
145 	SMC_RET0(_h);						\
146 }
147 #define SMC_RET2(_h, _x0, _x1)	{ \
148 	write_ctx_reg(get_gpregs_ctx(_h), CTX_GPREG_X1, (_x1)); \
149 	SMC_RET1(_h, (_x0)); \
150 }
151 #define SMC_RET3(_h, _x0, _x1, _x2)	{ \
152 	write_ctx_reg(get_gpregs_ctx(_h), CTX_GPREG_X2, (_x2)); \
153 	SMC_RET2(_h, (_x0), (_x1)); \
154 }
155 #define SMC_RET4(_h, _x0, _x1, _x2, _x3)	{ \
156 	write_ctx_reg(get_gpregs_ctx(_h), CTX_GPREG_X3, (_x3)); \
157 	SMC_RET3(_h, (_x0), (_x1), (_x2)); \
158 }
159 
160 
161 /*
162  * Convenience macros to access general purpose registers using handle provided
163  * to SMC handler. These takes the offset values defined in context.h
164  */
165 #define SMC_GET_GP(_h, _g) \
166 	read_ctx_reg(get_gpregs_ctx(_h), (_g));
167 #define SMC_SET_GP(_h, _g, _v) \
168 	write_ctx_reg(get_gpregs_ctx(_h), (_g), (_v));
169 
170 /*
171  * Convenience macros to access EL3 context registers using handle provided to
172  * SMC handler. These takes the offset values defined in context.h
173  */
174 #define SMC_GET_EL3(_h, _e) \
175 	read_ctx_reg(get_el3state_ctx(_h), (_e));
176 #define SMC_SET_EL3(_h, _e, _v) \
177 	write_ctx_reg(get_el3state_ctx(_h), (_e), (_v));
178 
179 /* The macro below is used to identify a Standard Service SMC call */
180 #define is_std_svc_call(_fid)		((((_fid) >> FUNCID_OEN_SHIFT) & \
181 					   FUNCID_OEN_MASK) == OEN_STD_START)
182 
183 /* The macro below is used to identify a valid Fast SMC call */
184 #define is_valid_fast_smc(_fid)		((!(((_fid) >> 16) & 0xff)) && \
185 					   (GET_SMC_TYPE(_fid) == SMC_TYPE_FAST))
186 
187 /*
188  * Prototype for runtime service SMC handler function. x0 (SMC Function ID) to
189  * x4 are as passed by the caller. Rest of the arguments to SMC and the context
190  * can be accessed using the handle pointer. The cookie parameter is reserved
191  * for future use
192  */
193 typedef uint64_t (*rt_svc_handle_t)(uint32_t smc_fid,
194 				  uint64_t x1,
195 				  uint64_t x2,
196 				  uint64_t x3,
197 				  uint64_t x4,
198 				  void *cookie,
199 				  void *handle,
200 				  uint64_t flags);
201 typedef struct rt_svc_desc {
202 	uint8_t start_oen;
203 	uint8_t end_oen;
204 	uint8_t call_type;
205 	const char *name;
206 	rt_svc_init_t init;
207 	rt_svc_handle_t handle;
208 } rt_svc_desc_t;
209 
210 /*
211  * Convenience macro to declare a service descriptor
212  */
213 #define DECLARE_RT_SVC(_name, _start, _end, _type, _setup, _smch) \
214 	static const rt_svc_desc_t __svc_desc_ ## _name \
215 		__attribute__ ((section("rt_svc_descs"), used)) = { \
216 			_start, \
217 			_end, \
218 			_type, \
219 			#_name, \
220 			_setup, \
221 			_smch }
222 
223 /*
224  * Compile time assertions related to the 'rt_svc_desc' structure to:
225  * 1. ensure that the assembler and the compiler view of the size
226  *    of the structure are the same.
227  * 2. ensure that the assembler and the compiler see the initialisation
228  *    routine at the same offset.
229  * 3. ensure that the assembler and the compiler see the handler
230  *    routine at the same offset.
231  */
232 CASSERT((sizeof(rt_svc_desc_t) == SIZEOF_RT_SVC_DESC), \
233 	assert_sizeof_rt_svc_desc_mismatch);
234 CASSERT(RT_SVC_DESC_INIT == __builtin_offsetof(rt_svc_desc_t, init), \
235 	assert_rt_svc_desc_init_offset_mismatch);
236 CASSERT(RT_SVC_DESC_HANDLE == __builtin_offsetof(rt_svc_desc_t, handle), \
237 	assert_rt_svc_desc_handle_offset_mismatch);
238 
239 
240 /*
241  * This macro combines the call type and the owning entity number corresponding
242  * to a runtime service to generate a unique owning entity number. This unique
243  * oen is used to access an entry in the 'rt_svc_descs_indices' array. The entry
244  * contains the index of the service descriptor in the 'rt_svc_descs' array.
245  */
246 #define get_unique_oen(oen, call_type)	((oen & FUNCID_OEN_MASK) |	\
247 					((call_type & FUNCID_TYPE_MASK) \
248 					 << FUNCID_OEN_WIDTH))
249 
250 
251 /*
252  * Macro to define UUID for services. Apart from defining and initializing a
253  * uuid_t structure, this macro verifies that the first word of the defined UUID
254  * does not equal SMC_UNK. This is to ensure that the caller won't mistake the
255  * returned UUID in x0 for an invalid SMC error return
256  */
257 #define DEFINE_SVC_UUID(_name, _tl, _tm, _th, _cl, _ch, \
258 		_n0, _n1, _n2, _n3, _n4, _n5) \
259 	CASSERT(_tl != SMC_UNK, invalid_svc_uuid);\
260 	static const uuid_t _name = { \
261 		_tl, _tm, _th, _cl, _ch, \
262 		{ _n0, _n1, _n2, _n3, _n4, _n5 } \
263 	}
264 
265 /* Return a UUID in the SMC return registers */
266 #define SMC_UUID_RET(_h, _uuid) \
267 	SMC_RET4(handle, ((const uint32_t *) &(_uuid))[0], \
268 			 ((const uint32_t *) &(_uuid))[1], \
269 			 ((const uint32_t *) &(_uuid))[2], \
270 			 ((const uint32_t *) &(_uuid))[3])
271 
272 /*******************************************************************************
273  * Function & variable prototypes
274  ******************************************************************************/
275 void runtime_svc_init(void);
276 extern uint64_t __RT_SVC_DESCS_START__;
277 extern uint64_t __RT_SVC_DESCS_END__;
278 void init_crash_reporting(void);
279 
280 #endif /*__ASSEMBLY__*/
281 #endif /* __RUNTIME_SVC_H__ */
282