KVM: arm/arm64: Factor out hypercall handling from PSCI code
[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
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
48#define ARM_SMCCC_OWNER_TRUSTED_APP 48
49#define ARM_SMCCC_OWNER_TRUSTED_APP_END 49
50#define ARM_SMCCC_OWNER_TRUSTED_OS 50
51#define ARM_SMCCC_OWNER_TRUSTED_OS_END 63
52
82bcd087
AG
53#define ARM_SMCCC_QUIRK_NONE 0
54#define ARM_SMCCC_QUIRK_QCOM_A6 1 /* Save/restore register a6 */
55
09e6be12
MZ
56#define ARM_SMCCC_VERSION_1_0 0x10000
57#define ARM_SMCCC_VERSION_1_1 0x10001
58
59#define ARM_SMCCC_VERSION_FUNC_ID \
60 ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, \
61 ARM_SMCCC_SMC_32, \
62 0, 0)
63
64#define ARM_SMCCC_ARCH_FEATURES_FUNC_ID \
65 ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, \
66 ARM_SMCCC_SMC_32, \
67 0, 1)
68
6167ec5c
MZ
69#define ARM_SMCCC_ARCH_WORKAROUND_1 \
70 ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, \
71 ARM_SMCCC_SMC_32, \
72 0, 0x8000)
73
8e290624
MZ
74#define ARM_SMCCC_ARCH_WORKAROUND_2 \
75 ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, \
76 ARM_SMCCC_SMC_32, \
77 0, 0x7fff)
78
82bcd087
AG
79#ifndef __ASSEMBLY__
80
81#include <linux/linkage.h>
82#include <linux/types.h>
6b7fe77c
MR
83
84enum arm_smccc_conduit {
85 SMCCC_CONDUIT_NONE,
86 SMCCC_CONDUIT_SMC,
87 SMCCC_CONDUIT_HVC,
88};
89
90/**
91 * arm_smccc_1_1_get_conduit()
92 *
93 * Returns the conduit to be used for SMCCCv1.1 or later.
94 *
95 * When SMCCCv1.1 is not present, returns SMCCC_CONDUIT_NONE.
96 */
97enum arm_smccc_conduit arm_smccc_1_1_get_conduit(void);
98
98dd64f3
JW
99/**
100 * struct arm_smccc_res - Result from SMC/HVC call
101 * @a0-a3 result values from registers 0 to 3
102 */
103struct arm_smccc_res {
104 unsigned long a0;
105 unsigned long a1;
106 unsigned long a2;
107 unsigned long a3;
108};
109
110/**
680a0873
AG
111 * struct arm_smccc_quirk - Contains quirk information
112 * @id: quirk identification
113 * @state: quirk specific information
114 * @a6: Qualcomm quirk entry for returning post-smc call contents of a6
115 */
116struct arm_smccc_quirk {
117 int id;
118 union {
119 unsigned long a6;
120 } state;
121};
122
123/**
124 * __arm_smccc_smc() - make SMC calls
98dd64f3
JW
125 * @a0-a7: arguments passed in registers 0 to 7
126 * @res: result values from registers 0 to 3
680a0873 127 * @quirk: points to an arm_smccc_quirk, or NULL when no quirks are required.
98dd64f3
JW
128 *
129 * This function is used to make SMC calls following SMC Calling Convention.
130 * The content of the supplied param are copied to registers 0 to 7 prior
131 * to the SMC instruction. The return values are updated with the content
680a0873
AG
132 * from register 0 to 3 on return from the SMC instruction. An optional
133 * quirk structure provides vendor specific behavior.
98dd64f3 134 */
680a0873 135asmlinkage void __arm_smccc_smc(unsigned long a0, unsigned long a1,
98dd64f3
JW
136 unsigned long a2, unsigned long a3, unsigned long a4,
137 unsigned long a5, unsigned long a6, unsigned long a7,
680a0873 138 struct arm_smccc_res *res, struct arm_smccc_quirk *quirk);
98dd64f3
JW
139
140/**
680a0873 141 * __arm_smccc_hvc() - make HVC calls
98dd64f3
JW
142 * @a0-a7: arguments passed in registers 0 to 7
143 * @res: result values from registers 0 to 3
3046ec67 144 * @quirk: points to an arm_smccc_quirk, or NULL when no quirks are required.
98dd64f3
JW
145 *
146 * This function is used to make HVC calls following SMC Calling
147 * Convention. The content of the supplied param are copied to registers 0
148 * to 7 prior to the HVC instruction. The return values are updated with
680a0873
AG
149 * the content from register 0 to 3 on return from the HVC instruction. An
150 * optional quirk structure provides vendor specific behavior.
98dd64f3 151 */
680a0873 152asmlinkage void __arm_smccc_hvc(unsigned long a0, unsigned long a1,
98dd64f3
JW
153 unsigned long a2, unsigned long a3, unsigned long a4,
154 unsigned long a5, unsigned long a6, unsigned long a7,
680a0873
AG
155 struct arm_smccc_res *res, struct arm_smccc_quirk *quirk);
156
157#define arm_smccc_smc(...) __arm_smccc_smc(__VA_ARGS__, NULL)
158
159#define arm_smccc_smc_quirk(...) __arm_smccc_smc(__VA_ARGS__)
160
161#define arm_smccc_hvc(...) __arm_smccc_hvc(__VA_ARGS__, NULL)
162
163#define arm_smccc_hvc_quirk(...) __arm_smccc_hvc(__VA_ARGS__)
98dd64f3 164
f2d3b2e8
MZ
165/* SMCCC v1.1 implementation madness follows */
166#ifdef CONFIG_ARM64
167
168#define SMCCC_SMC_INST "smc #0"
169#define SMCCC_HVC_INST "hvc #0"
170
171#elif defined(CONFIG_ARM)
172#include <asm/opcodes-sec.h>
173#include <asm/opcodes-virt.h>
174
175#define SMCCC_SMC_INST __SMC(0)
176#define SMCCC_HVC_INST __HVC(0)
177
178#endif
179
180#define ___count_args(_0, _1, _2, _3, _4, _5, _6, _7, _8, x, ...) x
181
182#define __count_args(...) \
183 ___count_args(__VA_ARGS__, 7, 6, 5, 4, 3, 2, 1, 0)
184
185#define __constraint_write_0 \
186 "+r" (r0), "=&r" (r1), "=&r" (r2), "=&r" (r3)
187#define __constraint_write_1 \
188 "+r" (r0), "+r" (r1), "=&r" (r2), "=&r" (r3)
189#define __constraint_write_2 \
190 "+r" (r0), "+r" (r1), "+r" (r2), "=&r" (r3)
191#define __constraint_write_3 \
192 "+r" (r0), "+r" (r1), "+r" (r2), "+r" (r3)
193#define __constraint_write_4 __constraint_write_3
194#define __constraint_write_5 __constraint_write_4
195#define __constraint_write_6 __constraint_write_5
196#define __constraint_write_7 __constraint_write_6
197
198#define __constraint_read_0
199#define __constraint_read_1
200#define __constraint_read_2
201#define __constraint_read_3
202#define __constraint_read_4 "r" (r4)
203#define __constraint_read_5 __constraint_read_4, "r" (r5)
204#define __constraint_read_6 __constraint_read_5, "r" (r6)
205#define __constraint_read_7 __constraint_read_6, "r" (r7)
206
207#define __declare_arg_0(a0, res) \
208 struct arm_smccc_res *___res = res; \
1d8f5747 209 register unsigned long r0 asm("r0") = (u32)a0; \
f2d3b2e8
MZ
210 register unsigned long r1 asm("r1"); \
211 register unsigned long r2 asm("r2"); \
212 register unsigned long r3 asm("r3")
213
214#define __declare_arg_1(a0, a1, res) \
755a8bf5 215 typeof(a1) __a1 = a1; \
f2d3b2e8 216 struct arm_smccc_res *___res = res; \
1d8f5747 217 register unsigned long r0 asm("r0") = (u32)a0; \
755a8bf5 218 register unsigned long r1 asm("r1") = __a1; \
f2d3b2e8
MZ
219 register unsigned long r2 asm("r2"); \
220 register unsigned long r3 asm("r3")
221
222#define __declare_arg_2(a0, a1, a2, res) \
755a8bf5
MZ
223 typeof(a1) __a1 = a1; \
224 typeof(a2) __a2 = a2; \
f2d3b2e8 225 struct arm_smccc_res *___res = res; \
1d8f5747 226 register unsigned long r0 asm("r0") = (u32)a0; \
755a8bf5
MZ
227 register unsigned long r1 asm("r1") = __a1; \
228 register unsigned long r2 asm("r2") = __a2; \
f2d3b2e8
MZ
229 register unsigned long r3 asm("r3")
230
231#define __declare_arg_3(a0, a1, a2, a3, res) \
755a8bf5
MZ
232 typeof(a1) __a1 = a1; \
233 typeof(a2) __a2 = a2; \
234 typeof(a3) __a3 = a3; \
f2d3b2e8 235 struct arm_smccc_res *___res = res; \
1d8f5747 236 register unsigned long r0 asm("r0") = (u32)a0; \
755a8bf5
MZ
237 register unsigned long r1 asm("r1") = __a1; \
238 register unsigned long r2 asm("r2") = __a2; \
239 register unsigned long r3 asm("r3") = __a3
f2d3b2e8
MZ
240
241#define __declare_arg_4(a0, a1, a2, a3, a4, res) \
755a8bf5 242 typeof(a4) __a4 = a4; \
f2d3b2e8 243 __declare_arg_3(a0, a1, a2, a3, res); \
755a8bf5 244 register unsigned long r4 asm("r4") = __a4
f2d3b2e8
MZ
245
246#define __declare_arg_5(a0, a1, a2, a3, a4, a5, res) \
755a8bf5 247 typeof(a5) __a5 = a5; \
f2d3b2e8 248 __declare_arg_4(a0, a1, a2, a3, a4, res); \
755a8bf5 249 register unsigned long r5 asm("r5") = __a5
f2d3b2e8
MZ
250
251#define __declare_arg_6(a0, a1, a2, a3, a4, a5, a6, res) \
755a8bf5 252 typeof(a6) __a6 = a6; \
f2d3b2e8 253 __declare_arg_5(a0, a1, a2, a3, a4, a5, res); \
755a8bf5 254 register unsigned long r6 asm("r6") = __a6
f2d3b2e8
MZ
255
256#define __declare_arg_7(a0, a1, a2, a3, a4, a5, a6, a7, res) \
755a8bf5 257 typeof(a7) __a7 = a7; \
f2d3b2e8 258 __declare_arg_6(a0, a1, a2, a3, a4, a5, a6, res); \
755a8bf5 259 register unsigned long r7 asm("r7") = __a7
f2d3b2e8
MZ
260
261#define ___declare_args(count, ...) __declare_arg_ ## count(__VA_ARGS__)
262#define __declare_args(count, ...) ___declare_args(count, __VA_ARGS__)
263
264#define ___constraints(count) \
265 : __constraint_write_ ## count \
266 : __constraint_read_ ## count \
267 : "memory"
268#define __constraints(count) ___constraints(count)
269
270/*
271 * We have an output list that is not necessarily used, and GCC feels
272 * entitled to optimise the whole sequence away. "volatile" is what
273 * makes it stick.
274 */
275#define __arm_smccc_1_1(inst, ...) \
276 do { \
277 __declare_args(__count_args(__VA_ARGS__), __VA_ARGS__); \
278 asm volatile(inst "\n" \
279 __constraints(__count_args(__VA_ARGS__))); \
280 if (___res) \
281 *___res = (typeof(*___res)){r0, r1, r2, r3}; \
282 } while (0)
283
284/*
285 * arm_smccc_1_1_smc() - make an SMCCC v1.1 compliant SMC call
286 *
287 * This is a variadic macro taking one to eight source arguments, and
288 * an optional return structure.
289 *
290 * @a0-a7: arguments passed in registers 0 to 7
291 * @res: result values from registers 0 to 3
292 *
293 * This macro is used to make SMC calls following SMC Calling Convention v1.1.
294 * The content of the supplied param are copied to registers 0 to 7 prior
295 * to the SMC instruction. The return values are updated with the content
296 * from register 0 to 3 on return from the SMC instruction if not NULL.
297 */
298#define arm_smccc_1_1_smc(...) __arm_smccc_1_1(SMCCC_SMC_INST, __VA_ARGS__)
299
300/*
301 * arm_smccc_1_1_hvc() - make an SMCCC v1.1 compliant HVC call
302 *
303 * This is a variadic macro taking one to eight source arguments, and
304 * an optional return structure.
305 *
306 * @a0-a7: arguments passed in registers 0 to 7
307 * @res: result values from registers 0 to 3
308 *
309 * This macro is used to make HVC calls following SMC Calling Convention v1.1.
310 * The content of the supplied param are copied to registers 0 to 7 prior
311 * to the HVC instruction. The return values are updated with the content
312 * from register 0 to 3 on return from the HVC instruction if not NULL.
313 */
314#define arm_smccc_1_1_hvc(...) __arm_smccc_1_1(SMCCC_HVC_INST, __VA_ARGS__)
315
eff0e9e1
MZ
316/* Return codes defined in ARM DEN 0070A */
317#define SMCCC_RET_SUCCESS 0
318#define SMCCC_RET_NOT_SUPPORTED -1
319#define SMCCC_RET_NOT_REQUIRED -2
320
82bcd087 321#endif /*__ASSEMBLY__*/
98dd64f3 322#endif /*__LINUX_ARM_SMCCC_H*/