1/* SPDX-License-Identifier: GPL-2.0-only */
2/*
3 * Copyright (c) 2015, Linaro Limited
4 */
5#ifndef __LINUX_ARM_SMCCC_H
6#define __LINUX_ARM_SMCCC_H
7
8#include <linux/args.h>
9#include <linux/init.h>
10
11#ifndef __ASSEMBLY__
12#include <linux/uuid.h>
13#endif
14
15#include <uapi/linux/const.h>
16
17/*
18 * This file provides common defines for ARM SMC Calling Convention as
19 * specified in
20 * https://developer.arm.com/docs/den0028/latest
21 *
22 * This code is up-to-date with version DEN 0028 C
23 */
24
25#define ARM_SMCCC_STD_CALL _AC(0,U)
26#define ARM_SMCCC_FAST_CALL _AC(1,U)
27#define ARM_SMCCC_TYPE_SHIFT 31
28
29#define ARM_SMCCC_SMC_32 0
30#define ARM_SMCCC_SMC_64 1
31#define ARM_SMCCC_CALL_CONV_SHIFT 30
32
33#define ARM_SMCCC_OWNER_MASK 0x3F
34#define ARM_SMCCC_OWNER_SHIFT 24
35
36#define ARM_SMCCC_FUNC_MASK 0xFFFF
37
38#define ARM_SMCCC_IS_FAST_CALL(smc_val) \
39 ((smc_val) & (ARM_SMCCC_FAST_CALL << ARM_SMCCC_TYPE_SHIFT))
40#define ARM_SMCCC_IS_64(smc_val) \
41 ((smc_val) & (ARM_SMCCC_SMC_64 << ARM_SMCCC_CALL_CONV_SHIFT))
42#define ARM_SMCCC_FUNC_NUM(smc_val) ((smc_val) & ARM_SMCCC_FUNC_MASK)
43#define ARM_SMCCC_OWNER_NUM(smc_val) \
44 (((smc_val) >> ARM_SMCCC_OWNER_SHIFT) & ARM_SMCCC_OWNER_MASK)
45
46#define ARM_SMCCC_CALL_VAL(type, calling_convention, owner, func_num) \
47 (((type) << ARM_SMCCC_TYPE_SHIFT) | \
48 ((calling_convention) << ARM_SMCCC_CALL_CONV_SHIFT) | \
49 (((owner) & ARM_SMCCC_OWNER_MASK) << ARM_SMCCC_OWNER_SHIFT) | \
50 ((func_num) & ARM_SMCCC_FUNC_MASK))
51
52#define ARM_SMCCC_OWNER_ARCH 0
53#define ARM_SMCCC_OWNER_CPU 1
54#define ARM_SMCCC_OWNER_SIP 2
55#define ARM_SMCCC_OWNER_OEM 3
56#define ARM_SMCCC_OWNER_STANDARD 4
57#define ARM_SMCCC_OWNER_STANDARD_HYP 5
58#define ARM_SMCCC_OWNER_VENDOR_HYP 6
59#define ARM_SMCCC_OWNER_TRUSTED_APP 48
60#define ARM_SMCCC_OWNER_TRUSTED_APP_END 49
61#define ARM_SMCCC_OWNER_TRUSTED_OS 50
62#define ARM_SMCCC_OWNER_TRUSTED_OS_END 63
63
64#define ARM_SMCCC_FUNC_QUERY_CALL_UID 0xff01
65
66#define ARM_SMCCC_QUIRK_NONE 0
67#define ARM_SMCCC_QUIRK_QCOM_A6 1 /* Save/restore register a6 */
68
69#define ARM_SMCCC_VERSION_1_0 0x10000
70#define ARM_SMCCC_VERSION_1_1 0x10001
71#define ARM_SMCCC_VERSION_1_2 0x10002
72#define ARM_SMCCC_VERSION_1_3 0x10003
73
74#define ARM_SMCCC_1_3_SVE_HINT 0x10000
75#define ARM_SMCCC_CALL_HINTS ARM_SMCCC_1_3_SVE_HINT
76
77
78#define ARM_SMCCC_VERSION_FUNC_ID \
79 ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, \
80 ARM_SMCCC_SMC_32, \
81 0, 0)
82
83#define ARM_SMCCC_ARCH_FEATURES_FUNC_ID \
84 ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, \
85 ARM_SMCCC_SMC_32, \
86 0, 1)
87
88#define ARM_SMCCC_ARCH_SOC_ID \
89 ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, \
90 ARM_SMCCC_SMC_32, \
91 0, 2)
92
93#define ARM_SMCCC_ARCH_WORKAROUND_1 \
94 ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, \
95 ARM_SMCCC_SMC_32, \
96 0, 0x8000)
97
98#define ARM_SMCCC_ARCH_WORKAROUND_2 \
99 ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, \
100 ARM_SMCCC_SMC_32, \
101 0, 0x7fff)
102
103#define ARM_SMCCC_ARCH_WORKAROUND_3 \
104 ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, \
105 ARM_SMCCC_SMC_32, \
106 0, 0x3fff)
107
108#define ARM_SMCCC_VENDOR_HYP_CALL_UID_FUNC_ID \
109 ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, \
110 ARM_SMCCC_SMC_32, \
111 ARM_SMCCC_OWNER_VENDOR_HYP, \
112 ARM_SMCCC_FUNC_QUERY_CALL_UID)
113
114/* KVM UID value: 28b46fb6-2ec5-11e9-a9ca-4b564d003a74 */
115#define ARM_SMCCC_VENDOR_HYP_UID_KVM UUID_INIT(\
116 0xb66fb428, 0xc52e, 0xe911, \
117 0xa9, 0xca, 0x4b, 0x56, \
118 0x4d, 0x00, 0x3a, 0x74)
119
120/* KVM "vendor specific" services */
121#define ARM_SMCCC_KVM_FUNC_FEATURES 0
122#define ARM_SMCCC_KVM_FUNC_PTP 1
123/* Start of pKVM hypercall range */
124#define ARM_SMCCC_KVM_FUNC_HYP_MEMINFO 2
125#define ARM_SMCCC_KVM_FUNC_MEM_SHARE 3
126#define ARM_SMCCC_KVM_FUNC_MEM_UNSHARE 4
127#define ARM_SMCCC_KVM_FUNC_PKVM_RESV_5 5
128#define ARM_SMCCC_KVM_FUNC_PKVM_RESV_6 6
129#define ARM_SMCCC_KVM_FUNC_MMIO_GUARD 7
130#define ARM_SMCCC_KVM_FUNC_PKVM_RESV_8 8
131#define ARM_SMCCC_KVM_FUNC_PKVM_RESV_9 9
132#define ARM_SMCCC_KVM_FUNC_PKVM_RESV_10 10
133#define ARM_SMCCC_KVM_FUNC_PKVM_RESV_11 11
134#define ARM_SMCCC_KVM_FUNC_PKVM_RESV_12 12
135#define ARM_SMCCC_KVM_FUNC_PKVM_RESV_13 13
136#define ARM_SMCCC_KVM_FUNC_PKVM_RESV_14 14
137#define ARM_SMCCC_KVM_FUNC_PKVM_RESV_15 15
138#define ARM_SMCCC_KVM_FUNC_PKVM_RESV_16 16
139#define ARM_SMCCC_KVM_FUNC_PKVM_RESV_17 17
140#define ARM_SMCCC_KVM_FUNC_PKVM_RESV_18 18
141#define ARM_SMCCC_KVM_FUNC_PKVM_RESV_19 19
142#define ARM_SMCCC_KVM_FUNC_PKVM_RESV_20 20
143#define ARM_SMCCC_KVM_FUNC_PKVM_RESV_21 21
144#define ARM_SMCCC_KVM_FUNC_PKVM_RESV_22 22
145#define ARM_SMCCC_KVM_FUNC_PKVM_RESV_23 23
146#define ARM_SMCCC_KVM_FUNC_PKVM_RESV_24 24
147#define ARM_SMCCC_KVM_FUNC_PKVM_RESV_25 25
148#define ARM_SMCCC_KVM_FUNC_PKVM_RESV_26 26
149#define ARM_SMCCC_KVM_FUNC_PKVM_RESV_27 27
150#define ARM_SMCCC_KVM_FUNC_PKVM_RESV_28 28
151#define ARM_SMCCC_KVM_FUNC_PKVM_RESV_29 29
152#define ARM_SMCCC_KVM_FUNC_PKVM_RESV_30 30
153#define ARM_SMCCC_KVM_FUNC_PKVM_RESV_31 31
154#define ARM_SMCCC_KVM_FUNC_PKVM_RESV_32 32
155#define ARM_SMCCC_KVM_FUNC_PKVM_RESV_33 33
156#define ARM_SMCCC_KVM_FUNC_PKVM_RESV_34 34
157#define ARM_SMCCC_KVM_FUNC_PKVM_RESV_35 35
158#define ARM_SMCCC_KVM_FUNC_PKVM_RESV_36 36
159#define ARM_SMCCC_KVM_FUNC_PKVM_RESV_37 37
160#define ARM_SMCCC_KVM_FUNC_PKVM_RESV_38 38
161#define ARM_SMCCC_KVM_FUNC_PKVM_RESV_39 39
162#define ARM_SMCCC_KVM_FUNC_PKVM_RESV_40 40
163#define ARM_SMCCC_KVM_FUNC_PKVM_RESV_41 41
164#define ARM_SMCCC_KVM_FUNC_PKVM_RESV_42 42
165#define ARM_SMCCC_KVM_FUNC_PKVM_RESV_43 43
166#define ARM_SMCCC_KVM_FUNC_PKVM_RESV_44 44
167#define ARM_SMCCC_KVM_FUNC_PKVM_RESV_45 45
168#define ARM_SMCCC_KVM_FUNC_PKVM_RESV_46 46
169#define ARM_SMCCC_KVM_FUNC_PKVM_RESV_47 47
170#define ARM_SMCCC_KVM_FUNC_PKVM_RESV_48 48
171#define ARM_SMCCC_KVM_FUNC_PKVM_RESV_49 49
172#define ARM_SMCCC_KVM_FUNC_PKVM_RESV_50 50
173#define ARM_SMCCC_KVM_FUNC_PKVM_RESV_51 51
174#define ARM_SMCCC_KVM_FUNC_PKVM_RESV_52 52
175#define ARM_SMCCC_KVM_FUNC_PKVM_RESV_53 53
176#define ARM_SMCCC_KVM_FUNC_PKVM_RESV_54 54
177#define ARM_SMCCC_KVM_FUNC_PKVM_RESV_55 55
178#define ARM_SMCCC_KVM_FUNC_PKVM_RESV_56 56
179#define ARM_SMCCC_KVM_FUNC_PKVM_RESV_57 57
180#define ARM_SMCCC_KVM_FUNC_PKVM_RESV_58 58
181#define ARM_SMCCC_KVM_FUNC_PKVM_RESV_59 59
182#define ARM_SMCCC_KVM_FUNC_PKVM_RESV_60 60
183#define ARM_SMCCC_KVM_FUNC_PKVM_RESV_61 61
184#define ARM_SMCCC_KVM_FUNC_PKVM_RESV_62 62
185#define ARM_SMCCC_KVM_FUNC_PKVM_RESV_63 63
186/* End of pKVM hypercall range */
187#define ARM_SMCCC_KVM_FUNC_DISCOVER_IMPL_VER 64
188#define ARM_SMCCC_KVM_FUNC_DISCOVER_IMPL_CPUS 65
189
190#define ARM_SMCCC_KVM_FUNC_FEATURES_2 127
191#define ARM_SMCCC_KVM_NUM_FUNCS 128
192
193#define ARM_SMCCC_VENDOR_HYP_KVM_FEATURES_FUNC_ID \
194 ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, \
195 ARM_SMCCC_SMC_32, \
196 ARM_SMCCC_OWNER_VENDOR_HYP, \
197 ARM_SMCCC_KVM_FUNC_FEATURES)
198
199#define SMCCC_ARCH_WORKAROUND_RET_UNAFFECTED 1
200
201/*
202 * ptp_kvm is a feature used for time sync between vm and host.
203 * ptp_kvm module in guest kernel will get service from host using
204 * this hypercall ID.
205 */
206#define ARM_SMCCC_VENDOR_HYP_KVM_PTP_FUNC_ID \
207 ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, \
208 ARM_SMCCC_SMC_32, \
209 ARM_SMCCC_OWNER_VENDOR_HYP, \
210 ARM_SMCCC_KVM_FUNC_PTP)
211
212#define ARM_SMCCC_VENDOR_HYP_KVM_HYP_MEMINFO_FUNC_ID \
213 ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, \
214 ARM_SMCCC_SMC_64, \
215 ARM_SMCCC_OWNER_VENDOR_HYP, \
216 ARM_SMCCC_KVM_FUNC_HYP_MEMINFO)
217
218#define ARM_SMCCC_VENDOR_HYP_KVM_MEM_SHARE_FUNC_ID \
219 ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, \
220 ARM_SMCCC_SMC_64, \
221 ARM_SMCCC_OWNER_VENDOR_HYP, \
222 ARM_SMCCC_KVM_FUNC_MEM_SHARE)
223
224#define ARM_SMCCC_VENDOR_HYP_KVM_MEM_UNSHARE_FUNC_ID \
225 ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, \
226 ARM_SMCCC_SMC_64, \
227 ARM_SMCCC_OWNER_VENDOR_HYP, \
228 ARM_SMCCC_KVM_FUNC_MEM_UNSHARE)
229
230#define ARM_SMCCC_VENDOR_HYP_KVM_MMIO_GUARD_FUNC_ID \
231 ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, \
232 ARM_SMCCC_SMC_64, \
233 ARM_SMCCC_OWNER_VENDOR_HYP, \
234 ARM_SMCCC_KVM_FUNC_MMIO_GUARD)
235
236#define ARM_SMCCC_VENDOR_HYP_KVM_DISCOVER_IMPL_VER_FUNC_ID \
237 ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, \
238 ARM_SMCCC_SMC_64, \
239 ARM_SMCCC_OWNER_VENDOR_HYP, \
240 ARM_SMCCC_KVM_FUNC_DISCOVER_IMPL_VER)
241
242#define ARM_SMCCC_VENDOR_HYP_KVM_DISCOVER_IMPL_CPUS_FUNC_ID \
243 ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, \
244 ARM_SMCCC_SMC_64, \
245 ARM_SMCCC_OWNER_VENDOR_HYP, \
246 ARM_SMCCC_KVM_FUNC_DISCOVER_IMPL_CPUS)
247
248/* ptp_kvm counter type ID */
249#define KVM_PTP_VIRT_COUNTER 0
250#define KVM_PTP_PHYS_COUNTER 1
251
252/* Paravirtualised time calls (defined by ARM DEN0057A) */
253#define ARM_SMCCC_HV_PV_TIME_FEATURES \
254 ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, \
255 ARM_SMCCC_SMC_64, \
256 ARM_SMCCC_OWNER_STANDARD_HYP, \
257 0x20)
258
259#define ARM_SMCCC_HV_PV_TIME_ST \
260 ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, \
261 ARM_SMCCC_SMC_64, \
262 ARM_SMCCC_OWNER_STANDARD_HYP, \
263 0x21)
264
265/* TRNG entropy source calls (defined by ARM DEN0098) */
266#define ARM_SMCCC_TRNG_VERSION \
267 ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, \
268 ARM_SMCCC_SMC_32, \
269 ARM_SMCCC_OWNER_STANDARD, \
270 0x50)
271
272#define ARM_SMCCC_TRNG_FEATURES \
273 ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, \
274 ARM_SMCCC_SMC_32, \
275 ARM_SMCCC_OWNER_STANDARD, \
276 0x51)
277
278#define ARM_SMCCC_TRNG_GET_UUID \
279 ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, \
280 ARM_SMCCC_SMC_32, \
281 ARM_SMCCC_OWNER_STANDARD, \
282 0x52)
283
284#define ARM_SMCCC_TRNG_RND32 \
285 ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, \
286 ARM_SMCCC_SMC_32, \
287 ARM_SMCCC_OWNER_STANDARD, \
288 0x53)
289
290#define ARM_SMCCC_TRNG_RND64 \
291 ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, \
292 ARM_SMCCC_SMC_64, \
293 ARM_SMCCC_OWNER_STANDARD, \
294 0x53)
295
296/*
297 * Return codes defined in ARM DEN 0070A
298 * ARM DEN 0070A is now merged/consolidated into ARM DEN 0028 C
299 */
300#define SMCCC_RET_SUCCESS 0
301#define SMCCC_RET_NOT_SUPPORTED -1
302#define SMCCC_RET_NOT_REQUIRED -2
303#define SMCCC_RET_INVALID_PARAMETER -3
304
305#ifndef __ASSEMBLY__
306
307#include <linux/linkage.h>
308#include <linux/types.h>
309
310enum arm_smccc_conduit {
311 SMCCC_CONDUIT_NONE,
312 SMCCC_CONDUIT_SMC,
313 SMCCC_CONDUIT_HVC,
314};
315
316/**
317 * arm_smccc_1_1_get_conduit()
318 *
319 * Returns the conduit to be used for SMCCCv1.1 or later.
320 *
321 * When SMCCCv1.1 is not present, returns SMCCC_CONDUIT_NONE.
322 */
323enum arm_smccc_conduit arm_smccc_1_1_get_conduit(void);
324
325/**
326 * arm_smccc_get_version()
327 *
328 * Returns the version to be used for SMCCCv1.1 or later.
329 *
330 * When SMCCCv1.1 or above is not present, returns SMCCCv1.0, but this
331 * does not imply the presence of firmware or a valid conduit. Caller
332 * handling SMCCCv1.0 must determine the conduit by other means.
333 */
334u32 arm_smccc_get_version(void);
335
336void __init arm_smccc_version_init(u32 version, enum arm_smccc_conduit conduit);
337
338/**
339 * arm_smccc_get_soc_id_version()
340 *
341 * Returns the SOC ID version.
342 *
343 * When ARM_SMCCC_ARCH_SOC_ID is not present, returns SMCCC_RET_NOT_SUPPORTED.
344 */
345s32 arm_smccc_get_soc_id_version(void);
346
347/**
348 * arm_smccc_get_soc_id_revision()
349 *
350 * Returns the SOC ID revision.
351 *
352 * When ARM_SMCCC_ARCH_SOC_ID is not present, returns SMCCC_RET_NOT_SUPPORTED.
353 */
354s32 arm_smccc_get_soc_id_revision(void);
355
356#ifndef __ASSEMBLY__
357
358/*
359 * Returns whether a specific hypervisor UUID is advertised for the
360 * Vendor Specific Hypervisor Service range.
361 */
362bool arm_smccc_hypervisor_has_uuid(const uuid_t *uuid);
363
364static inline uuid_t smccc_res_to_uuid(u32 r0, u32 r1, u32 r2, u32 r3)
365{
366 uuid_t uuid = {
367 .b = {
368 [0] = (r0 >> 0) & 0xff,
369 [1] = (r0 >> 8) & 0xff,
370 [2] = (r0 >> 16) & 0xff,
371 [3] = (r0 >> 24) & 0xff,
372
373 [4] = (r1 >> 0) & 0xff,
374 [5] = (r1 >> 8) & 0xff,
375 [6] = (r1 >> 16) & 0xff,
376 [7] = (r1 >> 24) & 0xff,
377
378 [8] = (r2 >> 0) & 0xff,
379 [9] = (r2 >> 8) & 0xff,
380 [10] = (r2 >> 16) & 0xff,
381 [11] = (r2 >> 24) & 0xff,
382
383 [12] = (r3 >> 0) & 0xff,
384 [13] = (r3 >> 8) & 0xff,
385 [14] = (r3 >> 16) & 0xff,
386 [15] = (r3 >> 24) & 0xff,
387 },
388 };
389
390 return uuid;
391}
392
393static inline u32 smccc_uuid_to_reg(const uuid_t *uuid, int reg)
394{
395 u32 val = 0;
396
397 val |= (u32)(uuid->b[4 * reg + 0] << 0);
398 val |= (u32)(uuid->b[4 * reg + 1] << 8);
399 val |= (u32)(uuid->b[4 * reg + 2] << 16);
400 val |= (u32)(uuid->b[4 * reg + 3] << 24);
401
402 return val;
403}
404
405#endif /* !__ASSEMBLY__ */
406
407/**
408 * struct arm_smccc_res - Result from SMC/HVC call
409 * @a0-a3 result values from registers 0 to 3
410 */
411struct arm_smccc_res {
412 unsigned long a0;
413 unsigned long a1;
414 unsigned long a2;
415 unsigned long a3;
416};
417
418#ifdef CONFIG_ARM64
419/**
420 * struct arm_smccc_1_2_regs - Arguments for or Results from SMC/HVC call
421 * @a0-a17 argument values from registers 0 to 17
422 */
423struct arm_smccc_1_2_regs {
424 unsigned long a0;
425 unsigned long a1;
426 unsigned long a2;
427 unsigned long a3;
428 unsigned long a4;
429 unsigned long a5;
430 unsigned long a6;
431 unsigned long a7;
432 unsigned long a8;
433 unsigned long a9;
434 unsigned long a10;
435 unsigned long a11;
436 unsigned long a12;
437 unsigned long a13;
438 unsigned long a14;
439 unsigned long a15;
440 unsigned long a16;
441 unsigned long a17;
442};
443
444/**
445 * arm_smccc_1_2_hvc() - make HVC calls
446 * @args: arguments passed via struct arm_smccc_1_2_regs
447 * @res: result values via struct arm_smccc_1_2_regs
448 *
449 * This function is used to make HVC calls following SMC Calling Convention
450 * v1.2 or above. The content of the supplied param are copied from the
451 * structure to registers prior to the HVC instruction. The return values
452 * are updated with the content from registers on return from the HVC
453 * instruction.
454 */
455asmlinkage void arm_smccc_1_2_hvc(const struct arm_smccc_1_2_regs *args,
456 struct arm_smccc_1_2_regs *res);
457
458/**
459 * arm_smccc_1_2_smc() - make SMC calls
460 * @args: arguments passed via struct arm_smccc_1_2_regs
461 * @res: result values via struct arm_smccc_1_2_regs
462 *
463 * This function is used to make SMC calls following SMC Calling Convention
464 * v1.2 or above. The content of the supplied param are copied from the
465 * structure to registers prior to the SMC instruction. The return values
466 * are updated with the content from registers on return from the SMC
467 * instruction.
468 */
469asmlinkage void arm_smccc_1_2_smc(const struct arm_smccc_1_2_regs *args,
470 struct arm_smccc_1_2_regs *res);
471#endif
472
473/**
474 * struct arm_smccc_quirk - Contains quirk information
475 * @id: quirk identification
476 * @state: quirk specific information
477 * @a6: Qualcomm quirk entry for returning post-smc call contents of a6
478 */
479struct arm_smccc_quirk {
480 int id;
481 union {
482 unsigned long a6;
483 } state;
484};
485
486/**
487 * __arm_smccc_smc() - make SMC calls
488 * @a0-a7: arguments passed in registers 0 to 7
489 * @res: result values from registers 0 to 3
490 * @quirk: points to an arm_smccc_quirk, or NULL when no quirks are required.
491 *
492 * This function is used to make SMC calls following SMC Calling Convention.
493 * The content of the supplied param are copied to registers 0 to 7 prior
494 * to the SMC instruction. The return values are updated with the content
495 * from register 0 to 3 on return from the SMC instruction. An optional
496 * quirk structure provides vendor specific behavior.
497 */
498#ifdef CONFIG_HAVE_ARM_SMCCC
499asmlinkage void __arm_smccc_smc(unsigned long a0, unsigned long a1,
500 unsigned long a2, unsigned long a3, unsigned long a4,
501 unsigned long a5, unsigned long a6, unsigned long a7,
502 struct arm_smccc_res *res, struct arm_smccc_quirk *quirk);
503#else
504static inline void __arm_smccc_smc(unsigned long a0, unsigned long a1,
505 unsigned long a2, unsigned long a3, unsigned long a4,
506 unsigned long a5, unsigned long a6, unsigned long a7,
507 struct arm_smccc_res *res, struct arm_smccc_quirk *quirk)
508{
509 *res = (struct arm_smccc_res){};
510}
511#endif
512
513/**
514 * __arm_smccc_hvc() - make HVC calls
515 * @a0-a7: arguments passed in registers 0 to 7
516 * @res: result values from registers 0 to 3
517 * @quirk: points to an arm_smccc_quirk, or NULL when no quirks are required.
518 *
519 * This function is used to make HVC calls following SMC Calling
520 * Convention. The content of the supplied param are copied to registers 0
521 * to 7 prior to the HVC instruction. The return values are updated with
522 * the content from register 0 to 3 on return from the HVC instruction. An
523 * optional quirk structure provides vendor specific behavior.
524 */
525asmlinkage void __arm_smccc_hvc(unsigned long a0, unsigned long a1,
526 unsigned long a2, unsigned long a3, unsigned long a4,
527 unsigned long a5, unsigned long a6, unsigned long a7,
528 struct arm_smccc_res *res, struct arm_smccc_quirk *quirk);
529
530#define arm_smccc_smc(...) __arm_smccc_smc(__VA_ARGS__, NULL)
531
532#define arm_smccc_smc_quirk(...) __arm_smccc_smc(__VA_ARGS__)
533
534#define arm_smccc_hvc(...) __arm_smccc_hvc(__VA_ARGS__, NULL)
535
536#define arm_smccc_hvc_quirk(...) __arm_smccc_hvc(__VA_ARGS__)
537
538/* SMCCC v1.1 implementation madness follows */
539#ifdef CONFIG_ARM64
540
541#define SMCCC_SMC_INST "smc #0"
542#define SMCCC_HVC_INST "hvc #0"
543
544#elif defined(CONFIG_ARM)
545#include <asm/opcodes-sec.h>
546#include <asm/opcodes-virt.h>
547
548#define SMCCC_SMC_INST __SMC(0)
549#define SMCCC_HVC_INST __HVC(0)
550
551#endif
552
553#define __constraint_read_2 "r" (arg0)
554#define __constraint_read_3 __constraint_read_2, "r" (arg1)
555#define __constraint_read_4 __constraint_read_3, "r" (arg2)
556#define __constraint_read_5 __constraint_read_4, "r" (arg3)
557#define __constraint_read_6 __constraint_read_5, "r" (arg4)
558#define __constraint_read_7 __constraint_read_6, "r" (arg5)
559#define __constraint_read_8 __constraint_read_7, "r" (arg6)
560#define __constraint_read_9 __constraint_read_8, "r" (arg7)
561
562#define __declare_arg_2(a0, res) \
563 struct arm_smccc_res *___res = res; \
564 register unsigned long arg0 asm("r0") = (u32)a0
565
566#define __declare_arg_3(a0, a1, res) \
567 typeof(a1) __a1 = a1; \
568 struct arm_smccc_res *___res = res; \
569 register unsigned long arg0 asm("r0") = (u32)a0; \
570 register typeof(a1) arg1 asm("r1") = __a1
571
572#define __declare_arg_4(a0, a1, a2, res) \
573 typeof(a1) __a1 = a1; \
574 typeof(a2) __a2 = a2; \
575 struct arm_smccc_res *___res = res; \
576 register unsigned long arg0 asm("r0") = (u32)a0; \
577 register typeof(a1) arg1 asm("r1") = __a1; \
578 register typeof(a2) arg2 asm("r2") = __a2
579
580#define __declare_arg_5(a0, a1, a2, a3, res) \
581 typeof(a1) __a1 = a1; \
582 typeof(a2) __a2 = a2; \
583 typeof(a3) __a3 = a3; \
584 struct arm_smccc_res *___res = res; \
585 register unsigned long arg0 asm("r0") = (u32)a0; \
586 register typeof(a1) arg1 asm("r1") = __a1; \
587 register typeof(a2) arg2 asm("r2") = __a2; \
588 register typeof(a3) arg3 asm("r3") = __a3
589
590#define __declare_arg_6(a0, a1, a2, a3, a4, res) \
591 typeof(a4) __a4 = a4; \
592 __declare_arg_5(a0, a1, a2, a3, res); \
593 register typeof(a4) arg4 asm("r4") = __a4
594
595#define __declare_arg_7(a0, a1, a2, a3, a4, a5, res) \
596 typeof(a5) __a5 = a5; \
597 __declare_arg_6(a0, a1, a2, a3, a4, res); \
598 register typeof(a5) arg5 asm("r5") = __a5
599
600#define __declare_arg_8(a0, a1, a2, a3, a4, a5, a6, res) \
601 typeof(a6) __a6 = a6; \
602 __declare_arg_7(a0, a1, a2, a3, a4, a5, res); \
603 register typeof(a6) arg6 asm("r6") = __a6
604
605#define __declare_arg_9(a0, a1, a2, a3, a4, a5, a6, a7, res) \
606 typeof(a7) __a7 = a7; \
607 __declare_arg_8(a0, a1, a2, a3, a4, a5, a6, res); \
608 register typeof(a7) arg7 asm("r7") = __a7
609
610/*
611 * We have an output list that is not necessarily used, and GCC feels
612 * entitled to optimise the whole sequence away. "volatile" is what
613 * makes it stick.
614 */
615#define __arm_smccc_1_1(inst, ...) \
616 do { \
617 register unsigned long r0 asm("r0"); \
618 register unsigned long r1 asm("r1"); \
619 register unsigned long r2 asm("r2"); \
620 register unsigned long r3 asm("r3"); \
621 CONCATENATE(__declare_arg_, \
622 COUNT_ARGS(__VA_ARGS__))(__VA_ARGS__); \
623 asm volatile(inst "\n" : \
624 "=r" (r0), "=r" (r1), "=r" (r2), "=r" (r3) \
625 : CONCATENATE(__constraint_read_, \
626 COUNT_ARGS(__VA_ARGS__)) \
627 : "memory"); \
628 if (___res) \
629 *___res = (typeof(*___res)){r0, r1, r2, r3}; \
630 } while (0)
631
632/*
633 * arm_smccc_1_1_smc() - make an SMCCC v1.1 compliant SMC call
634 *
635 * This is a variadic macro taking one to eight source arguments, and
636 * an optional return structure.
637 *
638 * @a0-a7: arguments passed in registers 0 to 7
639 * @res: result values from registers 0 to 3
640 *
641 * This macro is used to make SMC calls following SMC Calling Convention v1.1.
642 * The content of the supplied param are copied to registers 0 to 7 prior
643 * to the SMC instruction. The return values are updated with the content
644 * from register 0 to 3 on return from the SMC instruction if not NULL.
645 */
646#define arm_smccc_1_1_smc(...) __arm_smccc_1_1(SMCCC_SMC_INST, __VA_ARGS__)
647
648/*
649 * arm_smccc_1_1_hvc() - make an SMCCC v1.1 compliant HVC call
650 *
651 * This is a variadic macro taking one to eight source arguments, and
652 * an optional return structure.
653 *
654 * @a0-a7: arguments passed in registers 0 to 7
655 * @res: result values from registers 0 to 3
656 *
657 * This macro is used to make HVC calls following SMC Calling Convention v1.1.
658 * The content of the supplied param are copied to registers 0 to 7 prior
659 * to the HVC instruction. The return values are updated with the content
660 * from register 0 to 3 on return from the HVC instruction if not NULL.
661 */
662#define arm_smccc_1_1_hvc(...) __arm_smccc_1_1(SMCCC_HVC_INST, __VA_ARGS__)
663
664/*
665 * Like arm_smccc_1_1* but always returns SMCCC_RET_NOT_SUPPORTED.
666 * Used when the SMCCC conduit is not defined. The empty asm statement
667 * avoids compiler warnings about unused variables.
668 */
669#define __fail_smccc_1_1(...) \
670 do { \
671 CONCATENATE(__declare_arg_, \
672 COUNT_ARGS(__VA_ARGS__))(__VA_ARGS__); \
673 asm ("" : \
674 : CONCATENATE(__constraint_read_, \
675 COUNT_ARGS(__VA_ARGS__)) \
676 : "memory"); \
677 if (___res) \
678 ___res->a0 = SMCCC_RET_NOT_SUPPORTED; \
679 } while (0)
680
681/*
682 * arm_smccc_1_1_invoke() - make an SMCCC v1.1 compliant call
683 *
684 * This is a variadic macro taking one to eight source arguments, and
685 * an optional return structure.
686 *
687 * @a0-a7: arguments passed in registers 0 to 7
688 * @res: result values from registers 0 to 3
689 *
690 * This macro will make either an HVC call or an SMC call depending on the
691 * current SMCCC conduit. If no valid conduit is available then -1
692 * (SMCCC_RET_NOT_SUPPORTED) is returned in @res.a0 (if supplied).
693 *
694 * The return value also provides the conduit that was used.
695 */
696#define arm_smccc_1_1_invoke(...) ({ \
697 int method = arm_smccc_1_1_get_conduit(); \
698 switch (method) { \
699 case SMCCC_CONDUIT_HVC: \
700 arm_smccc_1_1_hvc(__VA_ARGS__); \
701 break; \
702 case SMCCC_CONDUIT_SMC: \
703 arm_smccc_1_1_smc(__VA_ARGS__); \
704 break; \
705 default: \
706 __fail_smccc_1_1(__VA_ARGS__); \
707 method = SMCCC_CONDUIT_NONE; \
708 break; \
709 } \
710 method; \
711 })
712
713#ifdef CONFIG_ARM64
714
715#define __fail_smccc_1_2(___res) \
716 do { \
717 if (___res) \
718 ___res->a0 = SMCCC_RET_NOT_SUPPORTED; \
719 } while (0)
720
721/*
722 * arm_smccc_1_2_invoke() - make an SMCCC v1.2 compliant call
723 *
724 * @args: SMC args are in the a0..a17 fields of the arm_smcc_1_2_regs structure
725 * @res: result values from registers 0 to 17
726 *
727 * This macro will make either an HVC call or an SMC call depending on the
728 * current SMCCC conduit. If no valid conduit is available then -1
729 * (SMCCC_RET_NOT_SUPPORTED) is returned in @res.a0 (if supplied).
730 *
731 * The return value also provides the conduit that was used.
732 */
733#define arm_smccc_1_2_invoke(args, res) ({ \
734 struct arm_smccc_1_2_regs *__args = args; \
735 struct arm_smccc_1_2_regs *__res = res; \
736 int method = arm_smccc_1_1_get_conduit(); \
737 switch (method) { \
738 case SMCCC_CONDUIT_HVC: \
739 arm_smccc_1_2_hvc(__args, __res); \
740 break; \
741 case SMCCC_CONDUIT_SMC: \
742 arm_smccc_1_2_smc(__args, __res); \
743 break; \
744 default: \
745 __fail_smccc_1_2(__res); \
746 method = SMCCC_CONDUIT_NONE; \
747 break; \
748 } \
749 method; \
750 })
751#endif /*CONFIG_ARM64*/
752
753#endif /*__ASSEMBLY__*/
754#endif /*__LINUX_ARM_SMCCC_H*/
755

source code of linux/include/linux/arm-smccc.h