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