DUJINLABS.COM

Linux v6.18.37 · ARM64

include/linux/arm-smccc.h

전체 목록

Linux v6.18.37 · 원본 파일 · 온라인 원본

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	0x28b46fb6, 0x2ec5, 0x11e9, \
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*/
맨 위로 ↑