Linux 5.12-rc3
[linux-block.git] / include / linux / arm-smccc.h
CommitLineData
9c92ab61 1/* SPDX-License-Identifier: GPL-2.0-only */
98dd64f3
JW
2/*
3 * Copyright (c) 2015, Linaro Limited
98dd64f3
JW
4 */
5#ifndef __LINUX_ARM_SMCCC_H
6#define __LINUX_ARM_SMCCC_H
7
269fd61e 8#include <linux/init.h>
ded4c39e
MZ
9#include <uapi/linux/const.h>
10
98dd64f3
JW
11/*
12 * This file provides common defines for ARM SMC Calling Convention as
13 * specified in
15c704ab
SH
14 * https://developer.arm.com/docs/den0028/latest
15 *
0441bfe7 16 * This code is up-to-date with version DEN 0028 C
98dd64f3
JW
17 */
18
ded4c39e
MZ
19#define ARM_SMCCC_STD_CALL _AC(0,U)
20#define ARM_SMCCC_FAST_CALL _AC(1,U)
98dd64f3
JW
21#define ARM_SMCCC_TYPE_SHIFT 31
22
23#define ARM_SMCCC_SMC_32 0
24#define ARM_SMCCC_SMC_64 1
25#define ARM_SMCCC_CALL_CONV_SHIFT 30
26
27#define ARM_SMCCC_OWNER_MASK 0x3F
28#define ARM_SMCCC_OWNER_SHIFT 24
29
30#define ARM_SMCCC_FUNC_MASK 0xFFFF
31
32#define ARM_SMCCC_IS_FAST_CALL(smc_val) \
33 ((smc_val) & (ARM_SMCCC_FAST_CALL << ARM_SMCCC_TYPE_SHIFT))
34#define ARM_SMCCC_IS_64(smc_val) \
35 ((smc_val) & (ARM_SMCCC_SMC_64 << ARM_SMCCC_CALL_CONV_SHIFT))
36#define ARM_SMCCC_FUNC_NUM(smc_val) ((smc_val) & ARM_SMCCC_FUNC_MASK)
37#define ARM_SMCCC_OWNER_NUM(smc_val) \
38 (((smc_val) >> ARM_SMCCC_OWNER_SHIFT) & ARM_SMCCC_OWNER_MASK)
39
40#define ARM_SMCCC_CALL_VAL(type, calling_convention, owner, func_num) \
41 (((type) << ARM_SMCCC_TYPE_SHIFT) | \
42 ((calling_convention) << ARM_SMCCC_CALL_CONV_SHIFT) | \
43 (((owner) & ARM_SMCCC_OWNER_MASK) << ARM_SMCCC_OWNER_SHIFT) | \
44 ((func_num) & ARM_SMCCC_FUNC_MASK))
45
46#define ARM_SMCCC_OWNER_ARCH 0
47#define ARM_SMCCC_OWNER_CPU 1
48#define ARM_SMCCC_OWNER_SIP 2
49#define ARM_SMCCC_OWNER_OEM 3
50#define ARM_SMCCC_OWNER_STANDARD 4
b48c1a45 51#define ARM_SMCCC_OWNER_STANDARD_HYP 5
cf650168 52#define ARM_SMCCC_OWNER_VENDOR_HYP 6
98dd64f3
JW
53#define ARM_SMCCC_OWNER_TRUSTED_APP 48
54#define ARM_SMCCC_OWNER_TRUSTED_APP_END 49
55#define ARM_SMCCC_OWNER_TRUSTED_OS 50
56#define ARM_SMCCC_OWNER_TRUSTED_OS_END 63
57
82bcd087
AG
58#define ARM_SMCCC_QUIRK_NONE 0
59#define ARM_SMCCC_QUIRK_QCOM_A6 1 /* Save/restore register a6 */
60
09e6be12
MZ
61#define ARM_SMCCC_VERSION_1_0 0x10000
62#define ARM_SMCCC_VERSION_1_1 0x10001
0441bfe7 63#define ARM_SMCCC_VERSION_1_2 0x10002
09e6be12
MZ
64
65#define ARM_SMCCC_VERSION_FUNC_ID \
66 ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, \
67 ARM_SMCCC_SMC_32, \
68 0, 0)
69
70#define ARM_SMCCC_ARCH_FEATURES_FUNC_ID \
71 ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, \
72 ARM_SMCCC_SMC_32, \
73 0, 1)
74
821b67fa
SH
75#define ARM_SMCCC_ARCH_SOC_ID \
76 ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, \
77 ARM_SMCCC_SMC_32, \
78 0, 2)
79
6167ec5c
MZ
80#define ARM_SMCCC_ARCH_WORKAROUND_1 \
81 ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, \
82 ARM_SMCCC_SMC_32, \
83 0, 0x8000)
84
8e290624
MZ
85#define ARM_SMCCC_ARCH_WORKAROUND_2 \
86 ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, \
87 ARM_SMCCC_SMC_32, \
88 0, 0x7fff)
89
1de111b5
SB
90#define SMCCC_ARCH_WORKAROUND_RET_UNAFFECTED 1
91
7af92885
AS
92/* Paravirtualised time calls (defined by ARM DEN0057A) */
93#define ARM_SMCCC_HV_PV_TIME_FEATURES \
94 ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, \
95 ARM_SMCCC_SMC_64, \
96 ARM_SMCCC_OWNER_STANDARD_HYP, \
97 0x20)
98
99#define ARM_SMCCC_HV_PV_TIME_ST \
100 ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, \
101 ARM_SMCCC_SMC_64, \
102 ARM_SMCCC_OWNER_STANDARD_HYP, \
103 0x21)
104
67c6bb56
AB
105/* TRNG entropy source calls (defined by ARM DEN0098) */
106#define ARM_SMCCC_TRNG_VERSION \
107 ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, \
108 ARM_SMCCC_SMC_32, \
109 ARM_SMCCC_OWNER_STANDARD, \
110 0x50)
111
112#define ARM_SMCCC_TRNG_FEATURES \
113 ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, \
114 ARM_SMCCC_SMC_32, \
115 ARM_SMCCC_OWNER_STANDARD, \
116 0x51)
117
118#define ARM_SMCCC_TRNG_GET_UUID \
119 ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, \
120 ARM_SMCCC_SMC_32, \
121 ARM_SMCCC_OWNER_STANDARD, \
122 0x52)
123
124#define ARM_SMCCC_TRNG_RND32 \
125 ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, \
126 ARM_SMCCC_SMC_32, \
127 ARM_SMCCC_OWNER_STANDARD, \
128 0x53)
129
130#define ARM_SMCCC_TRNG_RND64 \
131 ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, \
132 ARM_SMCCC_SMC_64, \
133 ARM_SMCCC_OWNER_STANDARD, \
134 0x53)
135
7af92885
AS
136/*
137 * Return codes defined in ARM DEN 0070A
138 * ARM DEN 0070A is now merged/consolidated into ARM DEN 0028 C
139 */
140#define SMCCC_RET_SUCCESS 0
141#define SMCCC_RET_NOT_SUPPORTED -1
142#define SMCCC_RET_NOT_REQUIRED -2
143#define SMCCC_RET_INVALID_PARAMETER -3
144
82bcd087
AG
145#ifndef __ASSEMBLY__
146
147#include <linux/linkage.h>
148#include <linux/types.h>
6b7fe77c
MR
149
150enum arm_smccc_conduit {
151 SMCCC_CONDUIT_NONE,
152 SMCCC_CONDUIT_SMC,
153 SMCCC_CONDUIT_HVC,
154};
155
156/**
157 * arm_smccc_1_1_get_conduit()
158 *
159 * Returns the conduit to be used for SMCCCv1.1 or later.
160 *
161 * When SMCCCv1.1 is not present, returns SMCCC_CONDUIT_NONE.
162 */
163enum arm_smccc_conduit arm_smccc_1_1_get_conduit(void);
164
a4fb1746
SH
165/**
166 * arm_smccc_get_version()
167 *
168 * Returns the version to be used for SMCCCv1.1 or later.
169 *
170 * When SMCCCv1.1 or above is not present, returns SMCCCv1.0, but this
171 * does not imply the presence of firmware or a valid conduit. Caller
172 * handling SMCCCv1.0 must determine the conduit by other means.
173 */
174u32 arm_smccc_get_version(void);
175
269fd61e
SH
176void __init arm_smccc_version_init(u32 version, enum arm_smccc_conduit conduit);
177
98dd64f3
JW
178/**
179 * struct arm_smccc_res - Result from SMC/HVC call
180 * @a0-a3 result values from registers 0 to 3
181 */
182struct arm_smccc_res {
183 unsigned long a0;
184 unsigned long a1;
185 unsigned long a2;
186 unsigned long a3;
187};
188
189/**
680a0873
AG
190 * struct arm_smccc_quirk - Contains quirk information
191 * @id: quirk identification
192 * @state: quirk specific information
193 * @a6: Qualcomm quirk entry for returning post-smc call contents of a6
194 */
195struct arm_smccc_quirk {
196 int id;
197 union {
198 unsigned long a6;
199 } state;
200};
201
202/**
203 * __arm_smccc_smc() - make SMC calls
98dd64f3
JW
204 * @a0-a7: arguments passed in registers 0 to 7
205 * @res: result values from registers 0 to 3
680a0873 206 * @quirk: points to an arm_smccc_quirk, or NULL when no quirks are required.
98dd64f3
JW
207 *
208 * This function is used to make SMC calls following SMC Calling Convention.
209 * The content of the supplied param are copied to registers 0 to 7 prior
210 * to the SMC instruction. The return values are updated with the content
680a0873
AG
211 * from register 0 to 3 on return from the SMC instruction. An optional
212 * quirk structure provides vendor specific behavior.
98dd64f3 213 */
680a0873 214asmlinkage void __arm_smccc_smc(unsigned long a0, unsigned long a1,
98dd64f3
JW
215 unsigned long a2, unsigned long a3, unsigned long a4,
216 unsigned long a5, unsigned long a6, unsigned long a7,
680a0873 217 struct arm_smccc_res *res, struct arm_smccc_quirk *quirk);
98dd64f3
JW
218
219/**
680a0873 220 * __arm_smccc_hvc() - make HVC calls
98dd64f3
JW
221 * @a0-a7: arguments passed in registers 0 to 7
222 * @res: result values from registers 0 to 3
3046ec67 223 * @quirk: points to an arm_smccc_quirk, or NULL when no quirks are required.
98dd64f3
JW
224 *
225 * This function is used to make HVC calls following SMC Calling
226 * Convention. The content of the supplied param are copied to registers 0
227 * to 7 prior to the HVC instruction. The return values are updated with
680a0873
AG
228 * the content from register 0 to 3 on return from the HVC instruction. An
229 * optional quirk structure provides vendor specific behavior.
98dd64f3 230 */
680a0873 231asmlinkage void __arm_smccc_hvc(unsigned long a0, unsigned long a1,
98dd64f3
JW
232 unsigned long a2, unsigned long a3, unsigned long a4,
233 unsigned long a5, unsigned long a6, unsigned long a7,
680a0873
AG
234 struct arm_smccc_res *res, struct arm_smccc_quirk *quirk);
235
236#define arm_smccc_smc(...) __arm_smccc_smc(__VA_ARGS__, NULL)
237
238#define arm_smccc_smc_quirk(...) __arm_smccc_smc(__VA_ARGS__)
239
240#define arm_smccc_hvc(...) __arm_smccc_hvc(__VA_ARGS__, NULL)
241
242#define arm_smccc_hvc_quirk(...) __arm_smccc_hvc(__VA_ARGS__)
98dd64f3 243
f2d3b2e8
MZ
244/* SMCCC v1.1 implementation madness follows */
245#ifdef CONFIG_ARM64
246
247#define SMCCC_SMC_INST "smc #0"
248#define SMCCC_HVC_INST "hvc #0"
249
250#elif defined(CONFIG_ARM)
251#include <asm/opcodes-sec.h>
252#include <asm/opcodes-virt.h>
253
254#define SMCCC_SMC_INST __SMC(0)
255#define SMCCC_HVC_INST __HVC(0)
256
257#endif
258
259#define ___count_args(_0, _1, _2, _3, _4, _5, _6, _7, _8, x, ...) x
260
261#define __count_args(...) \
262 ___count_args(__VA_ARGS__, 7, 6, 5, 4, 3, 2, 1, 0)
263
0794a974
AS
264#define __constraint_read_0 "r" (arg0)
265#define __constraint_read_1 __constraint_read_0, "r" (arg1)
266#define __constraint_read_2 __constraint_read_1, "r" (arg2)
267#define __constraint_read_3 __constraint_read_2, "r" (arg3)
268#define __constraint_read_4 __constraint_read_3, "r" (arg4)
269#define __constraint_read_5 __constraint_read_4, "r" (arg5)
270#define __constraint_read_6 __constraint_read_5, "r" (arg6)
271#define __constraint_read_7 __constraint_read_6, "r" (arg7)
f2d3b2e8
MZ
272
273#define __declare_arg_0(a0, res) \
274 struct arm_smccc_res *___res = res; \
0794a974 275 register unsigned long arg0 asm("r0") = (u32)a0
f2d3b2e8
MZ
276
277#define __declare_arg_1(a0, a1, res) \
755a8bf5 278 typeof(a1) __a1 = a1; \
f2d3b2e8 279 struct arm_smccc_res *___res = res; \
0794a974
AS
280 register unsigned long arg0 asm("r0") = (u32)a0; \
281 register typeof(a1) arg1 asm("r1") = __a1
f2d3b2e8
MZ
282
283#define __declare_arg_2(a0, a1, a2, res) \
755a8bf5
MZ
284 typeof(a1) __a1 = a1; \
285 typeof(a2) __a2 = a2; \
f2d3b2e8 286 struct arm_smccc_res *___res = res; \
0794a974
AS
287 register unsigned long arg0 asm("r0") = (u32)a0; \
288 register typeof(a1) arg1 asm("r1") = __a1; \
289 register typeof(a2) arg2 asm("r2") = __a2
f2d3b2e8
MZ
290
291#define __declare_arg_3(a0, a1, a2, a3, res) \
755a8bf5
MZ
292 typeof(a1) __a1 = a1; \
293 typeof(a2) __a2 = a2; \
294 typeof(a3) __a3 = a3; \
f2d3b2e8 295 struct arm_smccc_res *___res = res; \
0794a974
AS
296 register unsigned long arg0 asm("r0") = (u32)a0; \
297 register typeof(a1) arg1 asm("r1") = __a1; \
298 register typeof(a2) arg2 asm("r2") = __a2; \
299 register typeof(a3) arg3 asm("r3") = __a3
f2d3b2e8
MZ
300
301#define __declare_arg_4(a0, a1, a2, a3, a4, res) \
755a8bf5 302 typeof(a4) __a4 = a4; \
f2d3b2e8 303 __declare_arg_3(a0, a1, a2, a3, res); \
0794a974 304 register typeof(a4) arg4 asm("r4") = __a4
f2d3b2e8
MZ
305
306#define __declare_arg_5(a0, a1, a2, a3, a4, a5, res) \
755a8bf5 307 typeof(a5) __a5 = a5; \
f2d3b2e8 308 __declare_arg_4(a0, a1, a2, a3, a4, res); \
0794a974 309 register typeof(a5) arg5 asm("r5") = __a5
f2d3b2e8
MZ
310
311#define __declare_arg_6(a0, a1, a2, a3, a4, a5, a6, res) \
755a8bf5 312 typeof(a6) __a6 = a6; \
f2d3b2e8 313 __declare_arg_5(a0, a1, a2, a3, a4, a5, res); \
0794a974 314 register typeof(a6) arg6 asm("r6") = __a6
f2d3b2e8
MZ
315
316#define __declare_arg_7(a0, a1, a2, a3, a4, a5, a6, a7, res) \
755a8bf5 317 typeof(a7) __a7 = a7; \
f2d3b2e8 318 __declare_arg_6(a0, a1, a2, a3, a4, a5, a6, res); \
0794a974 319 register typeof(a7) arg7 asm("r7") = __a7
f2d3b2e8
MZ
320
321#define ___declare_args(count, ...) __declare_arg_ ## count(__VA_ARGS__)
322#define __declare_args(count, ...) ___declare_args(count, __VA_ARGS__)
323
324#define ___constraints(count) \
f2d3b2e8
MZ
325 : __constraint_read_ ## count \
326 : "memory"
327#define __constraints(count) ___constraints(count)
328
329/*
330 * We have an output list that is not necessarily used, and GCC feels
331 * entitled to optimise the whole sequence away. "volatile" is what
332 * makes it stick.
333 */
334#define __arm_smccc_1_1(inst, ...) \
335 do { \
0794a974
AS
336 register unsigned long r0 asm("r0"); \
337 register unsigned long r1 asm("r1"); \
338 register unsigned long r2 asm("r2"); \
339 register unsigned long r3 asm("r3"); \
f2d3b2e8 340 __declare_args(__count_args(__VA_ARGS__), __VA_ARGS__); \
0794a974
AS
341 asm volatile(inst "\n" : \
342 "=r" (r0), "=r" (r1), "=r" (r2), "=r" (r3) \
f2d3b2e8
MZ
343 __constraints(__count_args(__VA_ARGS__))); \
344 if (___res) \
345 *___res = (typeof(*___res)){r0, r1, r2, r3}; \
346 } while (0)
347
348/*
349 * arm_smccc_1_1_smc() - make an SMCCC v1.1 compliant SMC call
350 *
351 * This is a variadic macro taking one to eight source arguments, and
352 * an optional return structure.
353 *
354 * @a0-a7: arguments passed in registers 0 to 7
355 * @res: result values from registers 0 to 3
356 *
357 * This macro is used to make SMC calls following SMC Calling Convention v1.1.
358 * The content of the supplied param are copied to registers 0 to 7 prior
359 * to the SMC instruction. The return values are updated with the content
360 * from register 0 to 3 on return from the SMC instruction if not NULL.
361 */
362#define arm_smccc_1_1_smc(...) __arm_smccc_1_1(SMCCC_SMC_INST, __VA_ARGS__)
363
364/*
365 * arm_smccc_1_1_hvc() - make an SMCCC v1.1 compliant HVC call
366 *
367 * This is a variadic macro taking one to eight source arguments, and
368 * an optional return structure.
369 *
370 * @a0-a7: arguments passed in registers 0 to 7
371 * @res: result values from registers 0 to 3
372 *
373 * This macro is used to make HVC calls following SMC Calling Convention v1.1.
374 * The content of the supplied param are copied to registers 0 to 7 prior
375 * to the HVC instruction. The return values are updated with the content
376 * from register 0 to 3 on return from the HVC instruction if not NULL.
377 */
378#define arm_smccc_1_1_hvc(...) __arm_smccc_1_1(SMCCC_HVC_INST, __VA_ARGS__)
379
541625ac
SP
380/*
381 * Like arm_smccc_1_1* but always returns SMCCC_RET_NOT_SUPPORTED.
382 * Used when the SMCCC conduit is not defined. The empty asm statement
383 * avoids compiler warnings about unused variables.
384 */
385#define __fail_smccc_1_1(...) \
386 do { \
387 __declare_args(__count_args(__VA_ARGS__), __VA_ARGS__); \
0794a974 388 asm ("" : __constraints(__count_args(__VA_ARGS__))); \
541625ac
SP
389 if (___res) \
390 ___res->a0 = SMCCC_RET_NOT_SUPPORTED; \
391 } while (0)
392
393/*
394 * arm_smccc_1_1_invoke() - make an SMCCC v1.1 compliant call
395 *
396 * This is a variadic macro taking one to eight source arguments, and
397 * an optional return structure.
398 *
399 * @a0-a7: arguments passed in registers 0 to 7
400 * @res: result values from registers 0 to 3
401 *
402 * This macro will make either an HVC call or an SMC call depending on the
403 * current SMCCC conduit. If no valid conduit is available then -1
404 * (SMCCC_RET_NOT_SUPPORTED) is returned in @res.a0 (if supplied).
405 *
406 * The return value also provides the conduit that was used.
407 */
408#define arm_smccc_1_1_invoke(...) ({ \
409 int method = arm_smccc_1_1_get_conduit(); \
410 switch (method) { \
411 case SMCCC_CONDUIT_HVC: \
412 arm_smccc_1_1_hvc(__VA_ARGS__); \
413 break; \
414 case SMCCC_CONDUIT_SMC: \
415 arm_smccc_1_1_smc(__VA_ARGS__); \
416 break; \
417 default: \
418 __fail_smccc_1_1(__VA_ARGS__); \
419 method = SMCCC_CONDUIT_NONE; \
420 break; \
421 } \
422 method; \
423 })
424
82bcd087 425#endif /*__ASSEMBLY__*/
98dd64f3 426#endif /*__LINUX_ARM_SMCCC_H*/