Blame view

include/linux/arm-smccc.h 10.5 KB
98dd64f34   Jens Wiklander   ARM: 8478/2: arm/...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
  /*
   * Copyright (c) 2015, Linaro Limited
   *
   * This software is licensed under the terms of the GNU General Public
   * License version 2, as published by the Free Software Foundation, and
   * may be copied, distributed, and modified under those terms.
   *
   * This program is distributed in the hope that it will be useful,
   * but WITHOUT ANY WARRANTY; without even the implied warranty of
   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   * GNU General Public License for more details.
   *
   */
  #ifndef __LINUX_ARM_SMCCC_H
  #define __LINUX_ARM_SMCCC_H
37dc3e6c1   Marc Zyngier   arm/arm64: smccc:...
16
  #include <uapi/linux/const.h>
98dd64f34   Jens Wiklander   ARM: 8478/2: arm/...
17
18
19
20
21
  /*
   * This file provides common defines for ARM SMC Calling Convention as
   * specified in
   * http://infocenter.arm.com/help/topic/com.arm.doc.den0028a/index.html
   */
37dc3e6c1   Marc Zyngier   arm/arm64: smccc:...
22
23
  #define ARM_SMCCC_STD_CALL	        _AC(0,U)
  #define ARM_SMCCC_FAST_CALL	        _AC(1,U)
98dd64f34   Jens Wiklander   ARM: 8478/2: arm/...
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
  #define ARM_SMCCC_TYPE_SHIFT		31
  
  #define ARM_SMCCC_SMC_32		0
  #define ARM_SMCCC_SMC_64		1
  #define ARM_SMCCC_CALL_CONV_SHIFT	30
  
  #define ARM_SMCCC_OWNER_MASK		0x3F
  #define ARM_SMCCC_OWNER_SHIFT		24
  
  #define ARM_SMCCC_FUNC_MASK		0xFFFF
  
  #define ARM_SMCCC_IS_FAST_CALL(smc_val)	\
  	((smc_val) & (ARM_SMCCC_FAST_CALL << ARM_SMCCC_TYPE_SHIFT))
  #define ARM_SMCCC_IS_64(smc_val) \
  	((smc_val) & (ARM_SMCCC_SMC_64 << ARM_SMCCC_CALL_CONV_SHIFT))
  #define ARM_SMCCC_FUNC_NUM(smc_val)	((smc_val) & ARM_SMCCC_FUNC_MASK)
  #define ARM_SMCCC_OWNER_NUM(smc_val) \
  	(((smc_val) >> ARM_SMCCC_OWNER_SHIFT) & ARM_SMCCC_OWNER_MASK)
  
  #define ARM_SMCCC_CALL_VAL(type, calling_convention, owner, func_num) \
  	(((type) << ARM_SMCCC_TYPE_SHIFT) | \
  	((calling_convention) << ARM_SMCCC_CALL_CONV_SHIFT) | \
  	(((owner) & ARM_SMCCC_OWNER_MASK) << ARM_SMCCC_OWNER_SHIFT) | \
  	((func_num) & ARM_SMCCC_FUNC_MASK))
  
  #define ARM_SMCCC_OWNER_ARCH		0
  #define ARM_SMCCC_OWNER_CPU		1
  #define ARM_SMCCC_OWNER_SIP		2
  #define ARM_SMCCC_OWNER_OEM		3
  #define ARM_SMCCC_OWNER_STANDARD	4
  #define ARM_SMCCC_OWNER_TRUSTED_APP	48
  #define ARM_SMCCC_OWNER_TRUSTED_APP_END	49
  #define ARM_SMCCC_OWNER_TRUSTED_OS	50
  #define ARM_SMCCC_OWNER_TRUSTED_OS_END	63
82bcd0870   Andy Gross   firmware: qcom: s...
58
59
  #define ARM_SMCCC_QUIRK_NONE		0
  #define ARM_SMCCC_QUIRK_QCOM_A6		1 /* Save/restore register a6 */
45e206114   Marc Zyngier   arm/arm64: KVM: A...
60
61
62
63
64
65
66
67
68
69
70
71
  #define ARM_SMCCC_VERSION_1_0		0x10000
  #define ARM_SMCCC_VERSION_1_1		0x10001
  
  #define ARM_SMCCC_VERSION_FUNC_ID					\
  	ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL,				\
  			   ARM_SMCCC_SMC_32,				\
  			   0, 0)
  
  #define ARM_SMCCC_ARCH_FEATURES_FUNC_ID					\
  	ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL,				\
  			   ARM_SMCCC_SMC_32,				\
  			   0, 1)
e47273d08   Marc Zyngier   arm64: KVM: Repor...
72
73
74
75
  #define ARM_SMCCC_ARCH_WORKAROUND_1					\
  	ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL,				\
  			   ARM_SMCCC_SMC_32,				\
  			   0, 0x8000)
5ad09d2ab   Marc Zyngier   arm64: Call ARCH_...
76
77
78
79
  #define ARM_SMCCC_ARCH_WORKAROUND_2					\
  	ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL,				\
  			   ARM_SMCCC_SMC_32,				\
  			   0, 0x7fff)
82bcd0870   Andy Gross   firmware: qcom: s...
80
81
82
83
  #ifndef __ASSEMBLY__
  
  #include <linux/linkage.h>
  #include <linux/types.h>
98dd64f34   Jens Wiklander   ARM: 8478/2: arm/...
84
85
86
87
88
89
90
91
92
93
94
95
  /**
   * struct arm_smccc_res - Result from SMC/HVC call
   * @a0-a3 result values from registers 0 to 3
   */
  struct arm_smccc_res {
  	unsigned long a0;
  	unsigned long a1;
  	unsigned long a2;
  	unsigned long a3;
  };
  
  /**
680a0873e   Andy Gross   arm: kernel: Add ...
96
97
98
99
100
101
102
103
104
105
106
107
108
109
   * struct arm_smccc_quirk - Contains quirk information
   * @id: quirk identification
   * @state: quirk specific information
   * @a6: Qualcomm quirk entry for returning post-smc call contents of a6
   */
  struct arm_smccc_quirk {
  	int	id;
  	union {
  		unsigned long a6;
  	} state;
  };
  
  /**
   * __arm_smccc_smc() - make SMC calls
98dd64f34   Jens Wiklander   ARM: 8478/2: arm/...
110
111
   * @a0-a7: arguments passed in registers 0 to 7
   * @res: result values from registers 0 to 3
680a0873e   Andy Gross   arm: kernel: Add ...
112
   * @quirk: points to an arm_smccc_quirk, or NULL when no quirks are required.
98dd64f34   Jens Wiklander   ARM: 8478/2: arm/...
113
114
115
116
   *
   * This function is used to make SMC calls following SMC Calling Convention.
   * The content of the supplied param are copied to registers 0 to 7 prior
   * to the SMC instruction. The return values are updated with the content
680a0873e   Andy Gross   arm: kernel: Add ...
117
118
   * from register 0 to 3 on return from the SMC instruction.  An optional
   * quirk structure provides vendor specific behavior.
98dd64f34   Jens Wiklander   ARM: 8478/2: arm/...
119
   */
680a0873e   Andy Gross   arm: kernel: Add ...
120
  asmlinkage void __arm_smccc_smc(unsigned long a0, unsigned long a1,
98dd64f34   Jens Wiklander   ARM: 8478/2: arm/...
121
122
  			unsigned long a2, unsigned long a3, unsigned long a4,
  			unsigned long a5, unsigned long a6, unsigned long a7,
680a0873e   Andy Gross   arm: kernel: Add ...
123
  			struct arm_smccc_res *res, struct arm_smccc_quirk *quirk);
98dd64f34   Jens Wiklander   ARM: 8478/2: arm/...
124
125
  
  /**
680a0873e   Andy Gross   arm: kernel: Add ...
126
   * __arm_smccc_hvc() - make HVC calls
98dd64f34   Jens Wiklander   ARM: 8478/2: arm/...
127
128
   * @a0-a7: arguments passed in registers 0 to 7
   * @res: result values from registers 0 to 3
3046ec674   Will Deacon   ARM: smccc: Updat...
129
   * @quirk: points to an arm_smccc_quirk, or NULL when no quirks are required.
98dd64f34   Jens Wiklander   ARM: 8478/2: arm/...
130
131
132
133
   *
   * This function is used to make HVC calls following SMC Calling
   * Convention.  The content of the supplied param are copied to registers 0
   * to 7 prior to the HVC instruction. The return values are updated with
680a0873e   Andy Gross   arm: kernel: Add ...
134
135
   * the content from register 0 to 3 on return from the HVC instruction.  An
   * optional quirk structure provides vendor specific behavior.
98dd64f34   Jens Wiklander   ARM: 8478/2: arm/...
136
   */
680a0873e   Andy Gross   arm: kernel: Add ...
137
  asmlinkage void __arm_smccc_hvc(unsigned long a0, unsigned long a1,
98dd64f34   Jens Wiklander   ARM: 8478/2: arm/...
138
139
  			unsigned long a2, unsigned long a3, unsigned long a4,
  			unsigned long a5, unsigned long a6, unsigned long a7,
680a0873e   Andy Gross   arm: kernel: Add ...
140
141
142
143
144
145
146
147
148
  			struct arm_smccc_res *res, struct arm_smccc_quirk *quirk);
  
  #define arm_smccc_smc(...) __arm_smccc_smc(__VA_ARGS__, NULL)
  
  #define arm_smccc_smc_quirk(...) __arm_smccc_smc(__VA_ARGS__)
  
  #define arm_smccc_hvc(...) __arm_smccc_hvc(__VA_ARGS__, NULL)
  
  #define arm_smccc_hvc_quirk(...) __arm_smccc_hvc(__VA_ARGS__)
98dd64f34   Jens Wiklander   ARM: 8478/2: arm/...
149

ac63fdb4a   Marc Zyngier   arm/arm64: smccc:...
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
  /* SMCCC v1.1 implementation madness follows */
  #ifdef CONFIG_ARM64
  
  #define SMCCC_SMC_INST	"smc	#0"
  #define SMCCC_HVC_INST	"hvc	#0"
  
  #elif defined(CONFIG_ARM)
  #include <asm/opcodes-sec.h>
  #include <asm/opcodes-virt.h>
  
  #define SMCCC_SMC_INST	__SMC(0)
  #define SMCCC_HVC_INST	__HVC(0)
  
  #endif
  
  #define ___count_args(_0, _1, _2, _3, _4, _5, _6, _7, _8, x, ...) x
  
  #define __count_args(...)						\
  	___count_args(__VA_ARGS__, 7, 6, 5, 4, 3, 2, 1, 0)
  
  #define __constraint_write_0						\
  	"+r" (r0), "=&r" (r1), "=&r" (r2), "=&r" (r3)
  #define __constraint_write_1						\
  	"+r" (r0), "+r" (r1), "=&r" (r2), "=&r" (r3)
  #define __constraint_write_2						\
  	"+r" (r0), "+r" (r1), "+r" (r2), "=&r" (r3)
  #define __constraint_write_3						\
  	"+r" (r0), "+r" (r1), "+r" (r2), "+r" (r3)
  #define __constraint_write_4	__constraint_write_3
  #define __constraint_write_5	__constraint_write_4
  #define __constraint_write_6	__constraint_write_5
  #define __constraint_write_7	__constraint_write_6
  
  #define __constraint_read_0
  #define __constraint_read_1
  #define __constraint_read_2
  #define __constraint_read_3
  #define __constraint_read_4	"r" (r4)
  #define __constraint_read_5	__constraint_read_4, "r" (r5)
  #define __constraint_read_6	__constraint_read_5, "r" (r6)
  #define __constraint_read_7	__constraint_read_6, "r" (r7)
  
  #define __declare_arg_0(a0, res)					\
  	struct arm_smccc_res   *___res = res;				\
826d8678c   Marc Zyngier   arm/arm64: smccc-...
194
  	register unsigned long r0 asm("r0") = (u32)a0;			\
ac63fdb4a   Marc Zyngier   arm/arm64: smccc:...
195
196
197
198
199
  	register unsigned long r1 asm("r1");				\
  	register unsigned long r2 asm("r2");				\
  	register unsigned long r3 asm("r3")
  
  #define __declare_arg_1(a0, a1, res)					\
647b6d4ff   Marc Zyngier   arm/arm64: smccc-...
200
  	typeof(a1) __a1 = a1;						\
ac63fdb4a   Marc Zyngier   arm/arm64: smccc:...
201
  	struct arm_smccc_res   *___res = res;				\
826d8678c   Marc Zyngier   arm/arm64: smccc-...
202
  	register unsigned long r0 asm("r0") = (u32)a0;			\
647b6d4ff   Marc Zyngier   arm/arm64: smccc-...
203
  	register unsigned long r1 asm("r1") = __a1;			\
ac63fdb4a   Marc Zyngier   arm/arm64: smccc:...
204
205
206
207
  	register unsigned long r2 asm("r2");				\
  	register unsigned long r3 asm("r3")
  
  #define __declare_arg_2(a0, a1, a2, res)				\
647b6d4ff   Marc Zyngier   arm/arm64: smccc-...
208
209
  	typeof(a1) __a1 = a1;						\
  	typeof(a2) __a2 = a2;						\
ac63fdb4a   Marc Zyngier   arm/arm64: smccc:...
210
  	struct arm_smccc_res   *___res = res;				\
826d8678c   Marc Zyngier   arm/arm64: smccc-...
211
  	register unsigned long r0 asm("r0") = (u32)a0;			\
647b6d4ff   Marc Zyngier   arm/arm64: smccc-...
212
213
  	register unsigned long r1 asm("r1") = __a1;			\
  	register unsigned long r2 asm("r2") = __a2;			\
ac63fdb4a   Marc Zyngier   arm/arm64: smccc:...
214
215
216
  	register unsigned long r3 asm("r3")
  
  #define __declare_arg_3(a0, a1, a2, a3, res)				\
647b6d4ff   Marc Zyngier   arm/arm64: smccc-...
217
218
219
  	typeof(a1) __a1 = a1;						\
  	typeof(a2) __a2 = a2;						\
  	typeof(a3) __a3 = a3;						\
ac63fdb4a   Marc Zyngier   arm/arm64: smccc:...
220
  	struct arm_smccc_res   *___res = res;				\
826d8678c   Marc Zyngier   arm/arm64: smccc-...
221
  	register unsigned long r0 asm("r0") = (u32)a0;			\
647b6d4ff   Marc Zyngier   arm/arm64: smccc-...
222
223
224
  	register unsigned long r1 asm("r1") = __a1;			\
  	register unsigned long r2 asm("r2") = __a2;			\
  	register unsigned long r3 asm("r3") = __a3
ac63fdb4a   Marc Zyngier   arm/arm64: smccc:...
225
226
  
  #define __declare_arg_4(a0, a1, a2, a3, a4, res)			\
647b6d4ff   Marc Zyngier   arm/arm64: smccc-...
227
  	typeof(a4) __a4 = a4;						\
ac63fdb4a   Marc Zyngier   arm/arm64: smccc:...
228
  	__declare_arg_3(a0, a1, a2, a3, res);				\
647b6d4ff   Marc Zyngier   arm/arm64: smccc-...
229
  	register unsigned long r4 asm("r4") = __a4
ac63fdb4a   Marc Zyngier   arm/arm64: smccc:...
230
231
  
  #define __declare_arg_5(a0, a1, a2, a3, a4, a5, res)			\
647b6d4ff   Marc Zyngier   arm/arm64: smccc-...
232
  	typeof(a5) __a5 = a5;						\
ac63fdb4a   Marc Zyngier   arm/arm64: smccc:...
233
  	__declare_arg_4(a0, a1, a2, a3, a4, res);			\
647b6d4ff   Marc Zyngier   arm/arm64: smccc-...
234
  	register unsigned long r5 asm("r5") = __a5
ac63fdb4a   Marc Zyngier   arm/arm64: smccc:...
235
236
  
  #define __declare_arg_6(a0, a1, a2, a3, a4, a5, a6, res)		\
647b6d4ff   Marc Zyngier   arm/arm64: smccc-...
237
  	typeof(a6) __a6 = a6;						\
ac63fdb4a   Marc Zyngier   arm/arm64: smccc:...
238
  	__declare_arg_5(a0, a1, a2, a3, a4, a5, res);			\
647b6d4ff   Marc Zyngier   arm/arm64: smccc-...
239
  	register unsigned long r6 asm("r6") = __a6
ac63fdb4a   Marc Zyngier   arm/arm64: smccc:...
240
241
  
  #define __declare_arg_7(a0, a1, a2, a3, a4, a5, a6, a7, res)		\
647b6d4ff   Marc Zyngier   arm/arm64: smccc-...
242
  	typeof(a7) __a7 = a7;						\
ac63fdb4a   Marc Zyngier   arm/arm64: smccc:...
243
  	__declare_arg_6(a0, a1, a2, a3, a4, a5, a6, res);		\
647b6d4ff   Marc Zyngier   arm/arm64: smccc-...
244
  	register unsigned long r7 asm("r7") = __a7
ac63fdb4a   Marc Zyngier   arm/arm64: smccc:...
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
  
  #define ___declare_args(count, ...) __declare_arg_ ## count(__VA_ARGS__)
  #define __declare_args(count, ...)  ___declare_args(count, __VA_ARGS__)
  
  #define ___constraints(count)						\
  	: __constraint_write_ ## count					\
  	: __constraint_read_ ## count					\
  	: "memory"
  #define __constraints(count)	___constraints(count)
  
  /*
   * We have an output list that is not necessarily used, and GCC feels
   * entitled to optimise the whole sequence away. "volatile" is what
   * makes it stick.
   */
  #define __arm_smccc_1_1(inst, ...)					\
  	do {								\
  		__declare_args(__count_args(__VA_ARGS__), __VA_ARGS__);	\
  		asm volatile(inst "
  "					\
  			     __constraints(__count_args(__VA_ARGS__)));	\
  		if (___res)						\
  			*___res = (typeof(*___res)){r0, r1, r2, r3};	\
  	} while (0)
  
  /*
   * arm_smccc_1_1_smc() - make an SMCCC v1.1 compliant SMC call
   *
   * This is a variadic macro taking one to eight source arguments, and
   * an optional return structure.
   *
   * @a0-a7: arguments passed in registers 0 to 7
   * @res: result values from registers 0 to 3
   *
   * This macro is used to make SMC calls following SMC Calling Convention v1.1.
   * The content of the supplied param are copied to registers 0 to 7 prior
   * to the SMC instruction. The return values are updated with the content
   * from register 0 to 3 on return from the SMC instruction if not NULL.
   */
  #define arm_smccc_1_1_smc(...)	__arm_smccc_1_1(SMCCC_SMC_INST, __VA_ARGS__)
  
  /*
   * arm_smccc_1_1_hvc() - make an SMCCC v1.1 compliant HVC call
   *
   * This is a variadic macro taking one to eight source arguments, and
   * an optional return structure.
   *
   * @a0-a7: arguments passed in registers 0 to 7
   * @res: result values from registers 0 to 3
   *
   * This macro is used to make HVC calls following SMC Calling Convention v1.1.
   * The content of the supplied param are copied to registers 0 to 7 prior
   * to the HVC instruction. The return values are updated with the content
   * from register 0 to 3 on return from the HVC instruction if not NULL.
   */
  #define arm_smccc_1_1_hvc(...)	__arm_smccc_1_1(SMCCC_HVC_INST, __VA_ARGS__)
1de271913   Marc Zyngier   arm/arm64: smccc:...
301
302
303
304
  /* Return codes defined in ARM DEN 0070A */
  #define SMCCC_RET_SUCCESS			0
  #define SMCCC_RET_NOT_SUPPORTED			-1
  #define SMCCC_RET_NOT_REQUIRED			-2
82bcd0870   Andy Gross   firmware: qcom: s...
305
  #endif /*__ASSEMBLY__*/
98dd64f34   Jens Wiklander   ARM: 8478/2: arm/...
306
  #endif /*__LINUX_ARM_SMCCC_H*/