arm-smccc.h 14.8 KB
Newer Older
1
/* SPDX-License-Identifier: GPL-2.0-only */
2 3 4 5 6 7
/*
 * Copyright (c) 2015, Linaro Limited
 */
#ifndef __LINUX_ARM_SMCCC_H
#define __LINUX_ARM_SMCCC_H

8
#include <linux/init.h>
9 10
#include <uapi/linux/const.h>

11 12 13
/*
 * This file provides common defines for ARM SMC Calling Convention as
 * specified in
14 15
 * https://developer.arm.com/docs/den0028/latest
 *
16
 * This code is up-to-date with version DEN 0028 C
17 18
 */

19 20
#define ARM_SMCCC_STD_CALL	        _AC(0,U)
#define ARM_SMCCC_FAST_CALL	        _AC(1,U)
21 22 23 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
#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
51
#define ARM_SMCCC_OWNER_STANDARD_HYP	5
52
#define ARM_SMCCC_OWNER_VENDOR_HYP	6
53 54 55 56 57
#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

58 59
#define ARM_SMCCC_FUNC_QUERY_CALL_UID  0xff01

60 61 62
#define ARM_SMCCC_QUIRK_NONE		0
#define ARM_SMCCC_QUIRK_QCOM_A6		1 /* Save/restore register a6 */

63 64
#define ARM_SMCCC_VERSION_1_0		0x10000
#define ARM_SMCCC_VERSION_1_1		0x10001
65
#define ARM_SMCCC_VERSION_1_2		0x10002
66 67 68 69 70 71 72 73 74 75 76

#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)

77 78 79 80 81
#define ARM_SMCCC_ARCH_SOC_ID						\
	ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL,				\
			   ARM_SMCCC_SMC_32,				\
			   0, 2)

82 83 84 85 86
#define ARM_SMCCC_ARCH_WORKAROUND_1					\
	ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL,				\
			   ARM_SMCCC_SMC_32,				\
			   0, 0x8000)

87 88 89 90 91
#define ARM_SMCCC_ARCH_WORKAROUND_2					\
	ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL,				\
			   ARM_SMCCC_SMC_32,				\
			   0, 0x7fff)

92 93 94 95 96 97 98 99 100 101 102 103 104 105
#define ARM_SMCCC_VENDOR_HYP_CALL_UID_FUNC_ID				\
	ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL,				\
			   ARM_SMCCC_SMC_32,				\
			   ARM_SMCCC_OWNER_VENDOR_HYP,			\
			   ARM_SMCCC_FUNC_QUERY_CALL_UID)

/* KVM UID value: 28b46fb6-2ec5-11e9-a9ca-4b564d003a74 */
#define ARM_SMCCC_VENDOR_HYP_UID_KVM_REG_0	0xb66fb428U
#define ARM_SMCCC_VENDOR_HYP_UID_KVM_REG_1	0xe911c52eU
#define ARM_SMCCC_VENDOR_HYP_UID_KVM_REG_2	0x564bcaa9U
#define ARM_SMCCC_VENDOR_HYP_UID_KVM_REG_3	0x743a004dU

/* KVM "vendor specific" services */
#define ARM_SMCCC_KVM_FUNC_FEATURES		0
106
#define ARM_SMCCC_KVM_FUNC_PTP			1
107 108 109 110 111 112 113 114 115
#define ARM_SMCCC_KVM_FUNC_FEATURES_2		127
#define ARM_SMCCC_KVM_NUM_FUNCS			128

#define ARM_SMCCC_VENDOR_HYP_KVM_FEATURES_FUNC_ID			\
	ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL,				\
			   ARM_SMCCC_SMC_32,				\
			   ARM_SMCCC_OWNER_VENDOR_HYP,			\
			   ARM_SMCCC_KVM_FUNC_FEATURES)

116 117
#define SMCCC_ARCH_WORKAROUND_RET_UNAFFECTED	1

118 119 120 121 122 123 124 125 126 127 128 129 130 131 132
/*
 * ptp_kvm is a feature used for time sync between vm and host.
 * ptp_kvm module in guest kernel will get service from host using
 * this hypercall ID.
 */
#define ARM_SMCCC_VENDOR_HYP_KVM_PTP_FUNC_ID				\
	ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL,				\
			   ARM_SMCCC_SMC_32,				\
			   ARM_SMCCC_OWNER_VENDOR_HYP,			\
			   ARM_SMCCC_KVM_FUNC_PTP)

/* ptp_kvm counter type ID */
#define KVM_PTP_VIRT_COUNTER			0
#define KVM_PTP_PHYS_COUNTER			1

133 134 135 136 137 138 139 140 141 142 143 144 145
/* Paravirtualised time calls (defined by ARM DEN0057A) */
#define ARM_SMCCC_HV_PV_TIME_FEATURES				\
	ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL,			\
			   ARM_SMCCC_SMC_64,			\
			   ARM_SMCCC_OWNER_STANDARD_HYP,	\
			   0x20)

#define ARM_SMCCC_HV_PV_TIME_ST					\
	ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL,			\
			   ARM_SMCCC_SMC_64,			\
			   ARM_SMCCC_OWNER_STANDARD_HYP,	\
			   0x21)

146 147 148 149 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
/* TRNG entropy source calls (defined by ARM DEN0098) */
#define ARM_SMCCC_TRNG_VERSION					\
	ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL,			\
			   ARM_SMCCC_SMC_32,			\
			   ARM_SMCCC_OWNER_STANDARD,		\
			   0x50)

#define ARM_SMCCC_TRNG_FEATURES					\
	ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL,			\
			   ARM_SMCCC_SMC_32,			\
			   ARM_SMCCC_OWNER_STANDARD,		\
			   0x51)

#define ARM_SMCCC_TRNG_GET_UUID					\
	ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL,			\
			   ARM_SMCCC_SMC_32,			\
			   ARM_SMCCC_OWNER_STANDARD,		\
			   0x52)

#define ARM_SMCCC_TRNG_RND32					\
	ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL,			\
			   ARM_SMCCC_SMC_32,			\
			   ARM_SMCCC_OWNER_STANDARD,		\
			   0x53)

#define ARM_SMCCC_TRNG_RND64					\
	ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL,			\
			   ARM_SMCCC_SMC_64,			\
			   ARM_SMCCC_OWNER_STANDARD,		\
			   0x53)

177 178 179 180 181 182 183 184 185
/*
 * Return codes defined in ARM DEN 0070A
 * ARM DEN 0070A is now merged/consolidated into ARM DEN 0028 C
 */
#define SMCCC_RET_SUCCESS			0
#define SMCCC_RET_NOT_SUPPORTED			-1
#define SMCCC_RET_NOT_REQUIRED			-2
#define SMCCC_RET_INVALID_PARAMETER		-3

186 187 188 189
#ifndef __ASSEMBLY__

#include <linux/linkage.h>
#include <linux/types.h>
190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205

enum arm_smccc_conduit {
	SMCCC_CONDUIT_NONE,
	SMCCC_CONDUIT_SMC,
	SMCCC_CONDUIT_HVC,
};

/**
 * arm_smccc_1_1_get_conduit()
 *
 * Returns the conduit to be used for SMCCCv1.1 or later.
 *
 * When SMCCCv1.1 is not present, returns SMCCC_CONDUIT_NONE.
 */
enum arm_smccc_conduit arm_smccc_1_1_get_conduit(void);

206 207 208 209 210 211 212 213 214 215 216
/**
 * arm_smccc_get_version()
 *
 * Returns the version to be used for SMCCCv1.1 or later.
 *
 * When SMCCCv1.1 or above is not present, returns SMCCCv1.0, but this
 * does not imply the presence of firmware or a valid conduit. Caller
 * handling SMCCCv1.0 must determine the conduit by other means.
 */
u32 arm_smccc_get_version(void);

217 218
void __init arm_smccc_version_init(u32 version, enum arm_smccc_conduit conduit);

219 220 221 222 223 224 225 226 227 228 229 230
/**
 * 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;
};

/**
231 232 233 234 235 236 237 238 239 240 241 242 243 244
 * 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
245 246
 * @a0-a7: arguments passed in registers 0 to 7
 * @res: result values from registers 0 to 3
247
 * @quirk: points to an arm_smccc_quirk, or NULL when no quirks are required.
248 249 250 251
 *
 * 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
252 253
 * from register 0 to 3 on return from the SMC instruction.  An optional
 * quirk structure provides vendor specific behavior.
254
 */
255
asmlinkage void __arm_smccc_smc(unsigned long a0, unsigned long a1,
256 257
			unsigned long a2, unsigned long a3, unsigned long a4,
			unsigned long a5, unsigned long a6, unsigned long a7,
258
			struct arm_smccc_res *res, struct arm_smccc_quirk *quirk);
259 260

/**
261
 * __arm_smccc_hvc() - make HVC calls
262 263
 * @a0-a7: arguments passed in registers 0 to 7
 * @res: result values from registers 0 to 3
264
 * @quirk: points to an arm_smccc_quirk, or NULL when no quirks are required.
265 266 267 268
 *
 * 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
269 270
 * the content from register 0 to 3 on return from the HVC instruction.  An
 * optional quirk structure provides vendor specific behavior.
271
 */
272
asmlinkage void __arm_smccc_hvc(unsigned long a0, unsigned long a1,
273 274
			unsigned long a2, unsigned long a3, unsigned long a4,
			unsigned long a5, unsigned long a6, unsigned long a7,
275 276 277 278 279 280 281 282 283
			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__)
284

285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304
/* 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)

305 306 307 308 309 310 311 312
#define __constraint_read_0	"r" (arg0)
#define __constraint_read_1	__constraint_read_0, "r" (arg1)
#define __constraint_read_2	__constraint_read_1, "r" (arg2)
#define __constraint_read_3	__constraint_read_2, "r" (arg3)
#define __constraint_read_4	__constraint_read_3, "r" (arg4)
#define __constraint_read_5	__constraint_read_4, "r" (arg5)
#define __constraint_read_6	__constraint_read_5, "r" (arg6)
#define __constraint_read_7	__constraint_read_6, "r" (arg7)
313 314 315

#define __declare_arg_0(a0, res)					\
	struct arm_smccc_res   *___res = res;				\
316
	register unsigned long arg0 asm("r0") = (u32)a0
317 318

#define __declare_arg_1(a0, a1, res)					\
319
	typeof(a1) __a1 = a1;						\
320
	struct arm_smccc_res   *___res = res;				\
321 322
	register unsigned long arg0 asm("r0") = (u32)a0;			\
	register typeof(a1) arg1 asm("r1") = __a1
323 324

#define __declare_arg_2(a0, a1, a2, res)				\
325 326
	typeof(a1) __a1 = a1;						\
	typeof(a2) __a2 = a2;						\
327
	struct arm_smccc_res   *___res = res;				\
328 329 330
	register unsigned long arg0 asm("r0") = (u32)a0;			\
	register typeof(a1) arg1 asm("r1") = __a1;			\
	register typeof(a2) arg2 asm("r2") = __a2
331 332

#define __declare_arg_3(a0, a1, a2, a3, res)				\
333 334 335
	typeof(a1) __a1 = a1;						\
	typeof(a2) __a2 = a2;						\
	typeof(a3) __a3 = a3;						\
336
	struct arm_smccc_res   *___res = res;				\
337 338 339 340
	register unsigned long arg0 asm("r0") = (u32)a0;			\
	register typeof(a1) arg1 asm("r1") = __a1;			\
	register typeof(a2) arg2 asm("r2") = __a2;			\
	register typeof(a3) arg3 asm("r3") = __a3
341 342

#define __declare_arg_4(a0, a1, a2, a3, a4, res)			\
343
	typeof(a4) __a4 = a4;						\
344
	__declare_arg_3(a0, a1, a2, a3, res);				\
345
	register typeof(a4) arg4 asm("r4") = __a4
346 347

#define __declare_arg_5(a0, a1, a2, a3, a4, a5, res)			\
348
	typeof(a5) __a5 = a5;						\
349
	__declare_arg_4(a0, a1, a2, a3, a4, res);			\
350
	register typeof(a5) arg5 asm("r5") = __a5
351 352

#define __declare_arg_6(a0, a1, a2, a3, a4, a5, a6, res)		\
353
	typeof(a6) __a6 = a6;						\
354
	__declare_arg_5(a0, a1, a2, a3, a4, a5, res);			\
355
	register typeof(a6) arg6 asm("r6") = __a6
356 357

#define __declare_arg_7(a0, a1, a2, a3, a4, a5, a6, a7, res)		\
358
	typeof(a7) __a7 = a7;						\
359
	__declare_arg_6(a0, a1, a2, a3, a4, a5, a6, res);		\
360
	register typeof(a7) arg7 asm("r7") = __a7
361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376

#define ___declare_args(count, ...) __declare_arg_ ## count(__VA_ARGS__)
#define __declare_args(count, ...)  ___declare_args(count, __VA_ARGS__)

#define ___constraints(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 {								\
377 378 379 380
		register unsigned long r0 asm("r0");			\
		register unsigned long r1 asm("r1");			\
		register unsigned long r2 asm("r2");			\
		register unsigned long r3 asm("r3"); 			\
381
		__declare_args(__count_args(__VA_ARGS__), __VA_ARGS__);	\
382 383
		asm volatile(inst "\n" :				\
			     "=r" (r0), "=r" (r1), "=r" (r2), "=r" (r3)	\
384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420
			     __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__)

421 422 423 424 425 426 427 428
/*
 * Like arm_smccc_1_1* but always returns SMCCC_RET_NOT_SUPPORTED.
 * Used when the SMCCC conduit is not defined. The empty asm statement
 * avoids compiler warnings about unused variables.
 */
#define __fail_smccc_1_1(...)						\
	do {								\
		__declare_args(__count_args(__VA_ARGS__), __VA_ARGS__);	\
429
		asm ("" : __constraints(__count_args(__VA_ARGS__)));	\
430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465
		if (___res)						\
			___res->a0 = SMCCC_RET_NOT_SUPPORTED;		\
	} while (0)

/*
 * arm_smccc_1_1_invoke() - make an SMCCC v1.1 compliant 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 will make either an HVC call or an SMC call depending on the
 * current SMCCC conduit. If no valid conduit is available then -1
 * (SMCCC_RET_NOT_SUPPORTED) is returned in @res.a0 (if supplied).
 *
 * The return value also provides the conduit that was used.
 */
#define arm_smccc_1_1_invoke(...) ({					\
		int method = arm_smccc_1_1_get_conduit();		\
		switch (method) {					\
		case SMCCC_CONDUIT_HVC:					\
			arm_smccc_1_1_hvc(__VA_ARGS__);			\
			break;						\
		case SMCCC_CONDUIT_SMC:					\
			arm_smccc_1_1_smc(__VA_ARGS__);			\
			break;						\
		default:						\
			__fail_smccc_1_1(__VA_ARGS__);			\
			method = SMCCC_CONDUIT_NONE;			\
			break;						\
		}							\
		method;							\
	})

466
#endif /*__ASSEMBLY__*/
467
#endif /*__LINUX_ARM_SMCCC_H*/