1 /*
2 * Copyright (c) 2015, Linaro Limited
3 * Copyright (c) 2017, EPAM Systems
4 *
5 * This software is licensed under the terms of the GNU General Public
6 * License version 2, as published by the Free Software Foundation, and
7 * may be copied, distributed, and modified under those terms.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 */
15
16 #ifndef __ASM_ARM_SMCCC_H__
17 #define __ASM_ARM_SMCCC_H__
18
19 #include <asm/alternative.h>
20 #include <asm/cpufeature.h>
21
22 #define SMCCC_VERSION_MAJOR_SHIFT 16
23 #define SMCCC_VERSION_MINOR_MASK \
24 ((1U << SMCCC_VERSION_MAJOR_SHIFT) - 1)
25 #define SMCCC_VERSION_MAJOR_MASK ~SMCCC_VERSION_MINOR_MASK
26 #define SMCCC_VERSION_MAJOR(ver) \
27 (((ver) & SMCCC_VERSION_MAJOR_MASK) >> SMCCC_VERSION_MAJOR_SHIFT)
28 #define SMCCC_VERSION_MINOR(ver) \
29 ((ver) & SMCCC_VERSION_MINOR_MASK)
30
31 #define SMCCC_VERSION(major, minor) \
32 (((major) << SMCCC_VERSION_MAJOR_SHIFT) | (minor))
33
34 #define ARM_SMCCC_VERSION_1_0 SMCCC_VERSION(1, 0)
35 #define ARM_SMCCC_VERSION_1_1 SMCCC_VERSION(1, 1)
36
37 /*
38 * This file provides common defines for ARM SMC Calling Convention as
39 * specified in
40 * http://infocenter.arm.com/help/topic/com.arm.doc.den0028a/index.html
41 */
42
43 #define ARM_SMCCC_STD_CALL _AC(0,U)
44 #define ARM_SMCCC_FAST_CALL _AC(1,U)
45 #define ARM_SMCCC_TYPE_SHIFT 31
46
47 #define ARM_SMCCC_CONV_32 _AC(0,U)
48 #define ARM_SMCCC_CONV_64 _AC(1,U)
49 #define ARM_SMCCC_CONV_SHIFT 30
50
51 #define ARM_SMCCC_OWNER_MASK _AC(0x3F,U)
52 #define ARM_SMCCC_OWNER_SHIFT 24
53
54 #define ARM_SMCCC_FUNC_MASK _AC(0xFFFF,U)
55
56 #ifndef __ASSEMBLY__
57
58 extern uint32_t smccc_ver;
59
60 /* Check if this is fast call. */
smccc_is_fast_call(register_t funcid)61 static inline bool smccc_is_fast_call(register_t funcid)
62 {
63 return funcid & (ARM_SMCCC_FAST_CALL << ARM_SMCCC_TYPE_SHIFT);
64 }
65
66 /* Chek if this is 64-bit call. */
smccc_is_conv_64(register_t funcid)67 static inline bool smccc_is_conv_64(register_t funcid)
68 {
69 return funcid & (ARM_SMCCC_CONV_64 << ARM_SMCCC_CONV_SHIFT);
70 }
71
72 /* Get function number from function identifier. */
smccc_get_fn(register_t funcid)73 static inline uint32_t smccc_get_fn(register_t funcid)
74 {
75 return funcid & ARM_SMCCC_FUNC_MASK;
76 }
77
78 /* Get service owner number from function identifier. */
smccc_get_owner(register_t funcid)79 static inline uint32_t smccc_get_owner(register_t funcid)
80 {
81 return (funcid >> ARM_SMCCC_OWNER_SHIFT) & ARM_SMCCC_OWNER_MASK;
82 }
83
84 /*
85 * struct arm_smccc_res - Result from SMC call
86 * @a0 - @a3 result values from registers 0 to 3
87 */
88 struct arm_smccc_res {
89 unsigned long a0;
90 unsigned long a1;
91 unsigned long a2;
92 unsigned long a3;
93 };
94
95 /* SMCCC v1.1 implementation madness follows */
96 #define ___count_args(_0, _1, _2, _3, _4, _5, _6, _7, _8, x, ...) x
97
98 #define __count_args(...) \
99 ___count_args(__VA_ARGS__, 7, 6, 5, 4, 3, 2, 1, 0)
100
101 #define __constraint_write_0 \
102 "+r" (r0), "=&r" (r1), "=&r" (r2), "=&r" (r3)
103 #define __constraint_write_1 \
104 "+r" (r0), "+r" (r1), "=&r" (r2), "=&r" (r3)
105 #define __constraint_write_2 \
106 "+r" (r0), "+r" (r1), "+r" (r2), "=&r" (r3)
107 #define __constraint_write_3 \
108 "+r" (r0), "+r" (r1), "+r" (r2), "+r" (r3)
109 #define __constraint_write_4 __constraint_write_3
110 #define __constraint_write_5 __constraint_write_4
111 #define __constraint_write_6 __constraint_write_5
112 #define __constraint_write_7 __constraint_write_6
113
114 #define __constraint_read_0
115 #define __constraint_read_1
116 #define __constraint_read_2
117 #define __constraint_read_3
118 #define __constraint_read_4 "r" (r4)
119 #define __constraint_read_5 __constraint_read_4, "r" (r5)
120 #define __constraint_read_6 __constraint_read_5, "r" (r6)
121 #define __constraint_read_7 __constraint_read_6, "r" (r7)
122
123 #define __declare_arg_0(a0, res) \
124 struct arm_smccc_res *___res = res; \
125 register unsigned long r0 ASM_REG(0) = (uint32_t)a0; \
126 register unsigned long r1 ASM_REG(1); \
127 register unsigned long r2 ASM_REG(2); \
128 register unsigned long r3 ASM_REG(3)
129
130 #define __declare_arg_1(a0, a1, res) \
131 typeof(a1) __a1 = a1; \
132 struct arm_smccc_res *___res = res; \
133 register unsigned long r0 ASM_REG(0) = (uint32_t)a0; \
134 register unsigned long r1 ASM_REG(1) = __a1; \
135 register unsigned long r2 ASM_REG(2); \
136 register unsigned long r3 ASM_REG(3)
137
138 #define __declare_arg_2(a0, a1, a2, res) \
139 typeof(a1) __a1 = a1; \
140 typeof(a2) __a2 = a2; \
141 struct arm_smccc_res *___res = res; \
142 register unsigned long r0 ASM_REG(0) = (uint32_t)a0; \
143 register unsigned long r1 ASM_REG(1) = __a1; \
144 register unsigned long r2 ASM_REG(2) = __a2; \
145 register unsigned long r3 ASM_REG(3)
146
147 #define __declare_arg_3(a0, a1, a2, a3, res) \
148 typeof(a1) __a1 = a1; \
149 typeof(a2) __a2 = a2; \
150 typeof(a3) __a3 = a3; \
151 struct arm_smccc_res *___res = res; \
152 register unsigned long r0 ASM_REG(0) = (uint32_t)a0; \
153 register unsigned long r1 ASM_REG(1) = __a1; \
154 register unsigned long r2 ASM_REG(2) = __a2; \
155 register unsigned long r3 ASM_REG(3) = __a3
156
157 #define __declare_arg_4(a0, a1, a2, a3, a4, res) \
158 typeof(a4) __a4 = a4; \
159 __declare_arg_3(a0, a1, a2, a3, res); \
160 register unsigned long r4 ASM_REG(4) = __a4
161
162 #define __declare_arg_5(a0, a1, a2, a3, a4, a5, res) \
163 typeof(a5) __a5 = a5; \
164 __declare_arg_4(a0, a1, a2, a3, a4, res); \
165 register typeof(a5) r5 ASM_REG(5) = __a5
166
167 #define __declare_arg_6(a0, a1, a2, a3, a4, a5, a6, res) \
168 typeof(a6) __a6 = a6; \
169 __declare_arg_5(a0, a1, a2, a3, a4, a5, res); \
170 register typeof(a6) r6 ASM_REG(6) = __a6
171
172 #define __declare_arg_7(a0, a1, a2, a3, a4, a5, a6, a7, res) \
173 typeof(a7) __a7 = a7; \
174 __declare_arg_6(a0, a1, a2, a3, a4, a5, a6, res); \
175 register typeof(a7) r7 ASM_REG(7) = __a7
176
177 #define ___declare_args(count, ...) __declare_arg_ ## count(__VA_ARGS__)
178 #define __declare_args(count, ...) ___declare_args(count, __VA_ARGS__)
179
180 #define ___constraints(count) \
181 : __constraint_write_ ## count \
182 : __constraint_read_ ## count \
183 : "memory"
184 #define __constraints(count) ___constraints(count)
185
186 /*
187 * arm_smccc_1_1_smc() - make an SMCCC v1.1 compliant SMC call
188 *
189 * This is a variadic macro taking one to eight source arguments, and
190 * an optional return structure.
191 *
192 * @a0-a7: arguments passed in registers 0 to 7
193 * @res: result values from registers 0 to 3
194 *
195 * This macro is used to make SMC calls following SMC Calling Convention v1.1.
196 * The content of the supplied param are copied to registers 0 to 7 prior
197 * to the SMC instruction. The return values are updated with the content
198 * from register 0 to 3 on return from the SMC instruction if not NULL.
199 *
200 * We have an output list that is not necessarily used, and GCC feels
201 * entitled to optimise the whole sequence away. "volatile" is what
202 * makes it stick.
203 */
204 #define arm_smccc_1_1_smc(...) \
205 do { \
206 __declare_args(__count_args(__VA_ARGS__), __VA_ARGS__); \
207 asm volatile("smc #0\n" \
208 __constraints(__count_args(__VA_ARGS__))); \
209 if ( ___res ) \
210 *___res = (typeof(*___res)){r0, r1, r2, r3}; \
211 } while ( 0 )
212
213 /*
214 * The calling convention for arm32 is the same for both SMCCC v1.0 and
215 * v1.1.
216 */
217 #ifdef CONFIG_ARM_32
218 #define arm_smccc_1_0_smc(...) arm_smccc_1_1_smc(__VA_ARGS__)
219 #define arm_smccc_smc(...) arm_smccc_1_1_smc(__VA_ARGS__)
220 #else
221
222 void __arm_smccc_1_0_smc(register_t a0, register_t a1, register_t a2,
223 register_t a3, register_t a4, register_t a5,
224 register_t a6, register_t a7,
225 struct arm_smccc_res *res);
226
227 /* Macros to handle variadic parameter for SMCCC v1.0 helper */
228 #define __arm_smccc_1_0_smc_7(a0, a1, a2, a3, a4, a5, a6, a7, res) \
229 __arm_smccc_1_0_smc(a0, a1, a2, a3, a4, a5, a6, a7, res)
230
231 #define __arm_smccc_1_0_smc_6(a0, a1, a2, a3, a4, a5, a6, res) \
232 __arm_smccc_1_0_smc_7(a0, a1, a2, a3, a4, a5, a6, 0, res)
233
234 #define __arm_smccc_1_0_smc_5(a0, a1, a2, a3, a4, a5, res) \
235 __arm_smccc_1_0_smc_6(a0, a1, a2, a3, a4, a5, 0, res)
236
237 #define __arm_smccc_1_0_smc_4(a0, a1, a2, a3, a4, res) \
238 __arm_smccc_1_0_smc_5(a0, a1, a2, a3, a4, 0, res)
239
240 #define __arm_smccc_1_0_smc_3(a0, a1, a2, a3, res) \
241 __arm_smccc_1_0_smc_4(a0, a1, a2, a3, 0, res)
242
243 #define __arm_smccc_1_0_smc_2(a0, a1, a2, res) \
244 __arm_smccc_1_0_smc_3(a0, a1, a2, 0, res)
245
246 #define __arm_smccc_1_0_smc_1(a0, a1, res) \
247 __arm_smccc_1_0_smc_2(a0, a1, 0, res)
248
249 #define __arm_smccc_1_0_smc_0(a0, res) \
250 __arm_smccc_1_0_smc_1(a0, 0, res)
251
252 #define ___arm_smccc_1_0_smc_count(count, ...) \
253 __arm_smccc_1_0_smc_ ## count(__VA_ARGS__)
254
255 #define __arm_smccc_1_0_smc_count(count, ...) \
256 ___arm_smccc_1_0_smc_count(count, __VA_ARGS__)
257
258 #define arm_smccc_1_0_smc(...) \
259 __arm_smccc_1_0_smc_count(__count_args(__VA_ARGS__), __VA_ARGS__)
260
261 #define arm_smccc_smc(...) \
262 do { \
263 if ( cpus_have_const_cap(ARM_SMCCC_1_1) ) \
264 arm_smccc_1_1_smc(__VA_ARGS__); \
265 else \
266 arm_smccc_1_0_smc(__VA_ARGS__); \
267 } while ( 0 )
268 #endif /* CONFIG_ARM_64 */
269
270 #endif /* __ASSEMBLY__ */
271
272 /*
273 * Construct function identifier from call type (fast or standard),
274 * calling convention (32 or 64 bit), service owner and function number.
275 */
276 #define ARM_SMCCC_CALL_VAL(type, calling_convention, owner, func_num) \
277 (((type) << ARM_SMCCC_TYPE_SHIFT) | \
278 ((calling_convention) << ARM_SMCCC_CONV_SHIFT) | \
279 (((owner) & ARM_SMCCC_OWNER_MASK) << ARM_SMCCC_OWNER_SHIFT) | \
280 (func_num))
281
282 /* List of known service owners */
283 #define ARM_SMCCC_OWNER_ARCH 0
284 #define ARM_SMCCC_OWNER_CPU 1
285 #define ARM_SMCCC_OWNER_SIP 2
286 #define ARM_SMCCC_OWNER_OEM 3
287 #define ARM_SMCCC_OWNER_STANDARD 4
288 #define ARM_SMCCC_OWNER_HYPERVISOR 5
289 #define ARM_SMCCC_OWNER_TRUSTED_APP 48
290 #define ARM_SMCCC_OWNER_TRUSTED_APP_END 49
291 #define ARM_SMCCC_OWNER_TRUSTED_OS 50
292 #define ARM_SMCCC_OWNER_TRUSTED_OS_END 63
293
294 /* List of generic function numbers */
295 #define ARM_SMCCC_CALL_COUNT_FID(owner) \
296 ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, \
297 ARM_SMCCC_CONV_32, \
298 ARM_SMCCC_OWNER_##owner, \
299 0xFF00)
300
301 #define ARM_SMCCC_CALL_UID_FID(owner) \
302 ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, \
303 ARM_SMCCC_CONV_32, \
304 ARM_SMCCC_OWNER_##owner, \
305 0xFF01)
306
307 #define ARM_SMCCC_REVISION_FID(owner) \
308 ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, \
309 ARM_SMCCC_CONV_32, \
310 ARM_SMCCC_OWNER_##owner, \
311 0xFF03)
312
313 #define ARM_SMCCC_VERSION_FID \
314 ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, \
315 ARM_SMCCC_CONV_32, \
316 ARM_SMCCC_OWNER_ARCH, \
317 0x0) \
318
319 #define ARM_SMCCC_ARCH_FEATURES_FID \
320 ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, \
321 ARM_SMCCC_CONV_32, \
322 ARM_SMCCC_OWNER_ARCH, \
323 0x1)
324
325 #define ARM_SMCCC_ARCH_WORKAROUND_1_FID \
326 ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, \
327 ARM_SMCCC_CONV_32, \
328 ARM_SMCCC_OWNER_ARCH, \
329 0x8000)
330
331 #define ARM_SMCCC_ARCH_WORKAROUND_2_FID \
332 ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, \
333 ARM_SMCCC_CONV_32, \
334 ARM_SMCCC_OWNER_ARCH, \
335 0x7FFF)
336
337 /* SMCCC error codes */
338 #define ARM_SMCCC_NOT_REQUIRED (-2)
339 #define ARM_SMCCC_ERR_UNKNOWN_FUNCTION (-1)
340 #define ARM_SMCCC_NOT_SUPPORTED (-1)
341 #define ARM_SMCCC_SUCCESS (0)
342
343 /* SMCCC function identifier range which is reserved for existing APIs */
344 #define ARM_SMCCC_RESERVED_RANGE_START 0x0
345 #define ARM_SMCCC_RESERVED_RANGE_END 0x0100FFFF
346
347 #endif /* __ASM_ARM_SMCCC_H__ */
348
349 /*
350 * Local variables:
351 * mode: C
352 * c-file-style: "BSD"
353 * c-basic-offset: 4
354 * indent-tabs-mode: nil
355 * End:b
356 */
357