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