644 lines · c
1/* SPDX-License-Identifier: GPL-2.0-only */2/*3 * Copyright (c) 2015, Linaro Limited4 */5#ifndef __LINUX_ARM_SMCCC_H6#define __LINUX_ARM_SMCCC_H7 8#include <linux/args.h>9#include <linux/init.h>10#include <uapi/linux/const.h>11 12/*13 * This file provides common defines for ARM SMC Calling Convention as14 * specified in15 * https://developer.arm.com/docs/den0028/latest16 *17 * This code is up-to-date with version DEN 0028 C18 */19 20#define ARM_SMCCC_STD_CALL _AC(0,U)21#define ARM_SMCCC_FAST_CALL _AC(1,U)22#define ARM_SMCCC_TYPE_SHIFT 3123 24#define ARM_SMCCC_SMC_32 025#define ARM_SMCCC_SMC_64 126#define ARM_SMCCC_CALL_CONV_SHIFT 3027 28#define ARM_SMCCC_OWNER_MASK 0x3F29#define ARM_SMCCC_OWNER_SHIFT 2430 31#define ARM_SMCCC_FUNC_MASK 0xFFFF32 33#define ARM_SMCCC_IS_FAST_CALL(smc_val) \34 ((smc_val) & (ARM_SMCCC_FAST_CALL << ARM_SMCCC_TYPE_SHIFT))35#define ARM_SMCCC_IS_64(smc_val) \36 ((smc_val) & (ARM_SMCCC_SMC_64 << ARM_SMCCC_CALL_CONV_SHIFT))37#define ARM_SMCCC_FUNC_NUM(smc_val) ((smc_val) & ARM_SMCCC_FUNC_MASK)38#define ARM_SMCCC_OWNER_NUM(smc_val) \39 (((smc_val) >> ARM_SMCCC_OWNER_SHIFT) & ARM_SMCCC_OWNER_MASK)40 41#define ARM_SMCCC_CALL_VAL(type, calling_convention, owner, func_num) \42 (((type) << ARM_SMCCC_TYPE_SHIFT) | \43 ((calling_convention) << ARM_SMCCC_CALL_CONV_SHIFT) | \44 (((owner) & ARM_SMCCC_OWNER_MASK) << ARM_SMCCC_OWNER_SHIFT) | \45 ((func_num) & ARM_SMCCC_FUNC_MASK))46 47#define ARM_SMCCC_OWNER_ARCH 048#define ARM_SMCCC_OWNER_CPU 149#define ARM_SMCCC_OWNER_SIP 250#define ARM_SMCCC_OWNER_OEM 351#define ARM_SMCCC_OWNER_STANDARD 452#define ARM_SMCCC_OWNER_STANDARD_HYP 553#define ARM_SMCCC_OWNER_VENDOR_HYP 654#define ARM_SMCCC_OWNER_TRUSTED_APP 4855#define ARM_SMCCC_OWNER_TRUSTED_APP_END 4956#define ARM_SMCCC_OWNER_TRUSTED_OS 5057#define ARM_SMCCC_OWNER_TRUSTED_OS_END 6358 59#define ARM_SMCCC_FUNC_QUERY_CALL_UID 0xff0160 61#define ARM_SMCCC_QUIRK_NONE 062#define ARM_SMCCC_QUIRK_QCOM_A6 1 /* Save/restore register a6 */63 64#define ARM_SMCCC_VERSION_1_0 0x1000065#define ARM_SMCCC_VERSION_1_1 0x1000166#define ARM_SMCCC_VERSION_1_2 0x1000267#define ARM_SMCCC_VERSION_1_3 0x1000368 69#define ARM_SMCCC_1_3_SVE_HINT 0x1000070#define ARM_SMCCC_CALL_HINTS ARM_SMCCC_1_3_SVE_HINT71 72 73#define ARM_SMCCC_VERSION_FUNC_ID \74 ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, \75 ARM_SMCCC_SMC_32, \76 0, 0)77 78#define ARM_SMCCC_ARCH_FEATURES_FUNC_ID \79 ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, \80 ARM_SMCCC_SMC_32, \81 0, 1)82 83#define ARM_SMCCC_ARCH_SOC_ID \84 ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, \85 ARM_SMCCC_SMC_32, \86 0, 2)87 88#define ARM_SMCCC_ARCH_WORKAROUND_1 \89 ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, \90 ARM_SMCCC_SMC_32, \91 0, 0x8000)92 93#define ARM_SMCCC_ARCH_WORKAROUND_2 \94 ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, \95 ARM_SMCCC_SMC_32, \96 0, 0x7fff)97 98#define ARM_SMCCC_ARCH_WORKAROUND_3 \99 ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, \100 ARM_SMCCC_SMC_32, \101 0, 0x3fff)102 103#define ARM_SMCCC_VENDOR_HYP_CALL_UID_FUNC_ID \104 ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, \105 ARM_SMCCC_SMC_32, \106 ARM_SMCCC_OWNER_VENDOR_HYP, \107 ARM_SMCCC_FUNC_QUERY_CALL_UID)108 109/* KVM UID value: 28b46fb6-2ec5-11e9-a9ca-4b564d003a74 */110#define ARM_SMCCC_VENDOR_HYP_UID_KVM_REG_0 0xb66fb428U111#define ARM_SMCCC_VENDOR_HYP_UID_KVM_REG_1 0xe911c52eU112#define ARM_SMCCC_VENDOR_HYP_UID_KVM_REG_2 0x564bcaa9U113#define ARM_SMCCC_VENDOR_HYP_UID_KVM_REG_3 0x743a004dU114 115/* KVM "vendor specific" services */116#define ARM_SMCCC_KVM_FUNC_FEATURES 0117#define ARM_SMCCC_KVM_FUNC_PTP 1118/* Start of pKVM hypercall range */119#define ARM_SMCCC_KVM_FUNC_HYP_MEMINFO 2120#define ARM_SMCCC_KVM_FUNC_MEM_SHARE 3121#define ARM_SMCCC_KVM_FUNC_MEM_UNSHARE 4122#define ARM_SMCCC_KVM_FUNC_PKVM_RESV_5 5123#define ARM_SMCCC_KVM_FUNC_PKVM_RESV_6 6124#define ARM_SMCCC_KVM_FUNC_MMIO_GUARD 7125#define ARM_SMCCC_KVM_FUNC_PKVM_RESV_8 8126#define ARM_SMCCC_KVM_FUNC_PKVM_RESV_9 9127#define ARM_SMCCC_KVM_FUNC_PKVM_RESV_10 10128#define ARM_SMCCC_KVM_FUNC_PKVM_RESV_11 11129#define ARM_SMCCC_KVM_FUNC_PKVM_RESV_12 12130#define ARM_SMCCC_KVM_FUNC_PKVM_RESV_13 13131#define ARM_SMCCC_KVM_FUNC_PKVM_RESV_14 14132#define ARM_SMCCC_KVM_FUNC_PKVM_RESV_15 15133#define ARM_SMCCC_KVM_FUNC_PKVM_RESV_16 16134#define ARM_SMCCC_KVM_FUNC_PKVM_RESV_17 17135#define ARM_SMCCC_KVM_FUNC_PKVM_RESV_18 18136#define ARM_SMCCC_KVM_FUNC_PKVM_RESV_19 19137#define ARM_SMCCC_KVM_FUNC_PKVM_RESV_20 20138#define ARM_SMCCC_KVM_FUNC_PKVM_RESV_21 21139#define ARM_SMCCC_KVM_FUNC_PKVM_RESV_22 22140#define ARM_SMCCC_KVM_FUNC_PKVM_RESV_23 23141#define ARM_SMCCC_KVM_FUNC_PKVM_RESV_24 24142#define ARM_SMCCC_KVM_FUNC_PKVM_RESV_25 25143#define ARM_SMCCC_KVM_FUNC_PKVM_RESV_26 26144#define ARM_SMCCC_KVM_FUNC_PKVM_RESV_27 27145#define ARM_SMCCC_KVM_FUNC_PKVM_RESV_28 28146#define ARM_SMCCC_KVM_FUNC_PKVM_RESV_29 29147#define ARM_SMCCC_KVM_FUNC_PKVM_RESV_30 30148#define ARM_SMCCC_KVM_FUNC_PKVM_RESV_31 31149#define ARM_SMCCC_KVM_FUNC_PKVM_RESV_32 32150#define ARM_SMCCC_KVM_FUNC_PKVM_RESV_33 33151#define ARM_SMCCC_KVM_FUNC_PKVM_RESV_34 34152#define ARM_SMCCC_KVM_FUNC_PKVM_RESV_35 35153#define ARM_SMCCC_KVM_FUNC_PKVM_RESV_36 36154#define ARM_SMCCC_KVM_FUNC_PKVM_RESV_37 37155#define ARM_SMCCC_KVM_FUNC_PKVM_RESV_38 38156#define ARM_SMCCC_KVM_FUNC_PKVM_RESV_39 39157#define ARM_SMCCC_KVM_FUNC_PKVM_RESV_40 40158#define ARM_SMCCC_KVM_FUNC_PKVM_RESV_41 41159#define ARM_SMCCC_KVM_FUNC_PKVM_RESV_42 42160#define ARM_SMCCC_KVM_FUNC_PKVM_RESV_43 43161#define ARM_SMCCC_KVM_FUNC_PKVM_RESV_44 44162#define ARM_SMCCC_KVM_FUNC_PKVM_RESV_45 45163#define ARM_SMCCC_KVM_FUNC_PKVM_RESV_46 46164#define ARM_SMCCC_KVM_FUNC_PKVM_RESV_47 47165#define ARM_SMCCC_KVM_FUNC_PKVM_RESV_48 48166#define ARM_SMCCC_KVM_FUNC_PKVM_RESV_49 49167#define ARM_SMCCC_KVM_FUNC_PKVM_RESV_50 50168#define ARM_SMCCC_KVM_FUNC_PKVM_RESV_51 51169#define ARM_SMCCC_KVM_FUNC_PKVM_RESV_52 52170#define ARM_SMCCC_KVM_FUNC_PKVM_RESV_53 53171#define ARM_SMCCC_KVM_FUNC_PKVM_RESV_54 54172#define ARM_SMCCC_KVM_FUNC_PKVM_RESV_55 55173#define ARM_SMCCC_KVM_FUNC_PKVM_RESV_56 56174#define ARM_SMCCC_KVM_FUNC_PKVM_RESV_57 57175#define ARM_SMCCC_KVM_FUNC_PKVM_RESV_58 58176#define ARM_SMCCC_KVM_FUNC_PKVM_RESV_59 59177#define ARM_SMCCC_KVM_FUNC_PKVM_RESV_60 60178#define ARM_SMCCC_KVM_FUNC_PKVM_RESV_61 61179#define ARM_SMCCC_KVM_FUNC_PKVM_RESV_62 62180#define ARM_SMCCC_KVM_FUNC_PKVM_RESV_63 63181/* End of pKVM hypercall range */182#define ARM_SMCCC_KVM_FUNC_FEATURES_2 127183#define ARM_SMCCC_KVM_NUM_FUNCS 128184 185#define ARM_SMCCC_VENDOR_HYP_KVM_FEATURES_FUNC_ID \186 ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, \187 ARM_SMCCC_SMC_32, \188 ARM_SMCCC_OWNER_VENDOR_HYP, \189 ARM_SMCCC_KVM_FUNC_FEATURES)190 191#define SMCCC_ARCH_WORKAROUND_RET_UNAFFECTED 1192 193/*194 * ptp_kvm is a feature used for time sync between vm and host.195 * ptp_kvm module in guest kernel will get service from host using196 * this hypercall ID.197 */198#define ARM_SMCCC_VENDOR_HYP_KVM_PTP_FUNC_ID \199 ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, \200 ARM_SMCCC_SMC_32, \201 ARM_SMCCC_OWNER_VENDOR_HYP, \202 ARM_SMCCC_KVM_FUNC_PTP)203 204#define ARM_SMCCC_VENDOR_HYP_KVM_HYP_MEMINFO_FUNC_ID \205 ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, \206 ARM_SMCCC_SMC_64, \207 ARM_SMCCC_OWNER_VENDOR_HYP, \208 ARM_SMCCC_KVM_FUNC_HYP_MEMINFO)209 210#define ARM_SMCCC_VENDOR_HYP_KVM_MEM_SHARE_FUNC_ID \211 ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, \212 ARM_SMCCC_SMC_64, \213 ARM_SMCCC_OWNER_VENDOR_HYP, \214 ARM_SMCCC_KVM_FUNC_MEM_SHARE)215 216#define ARM_SMCCC_VENDOR_HYP_KVM_MEM_UNSHARE_FUNC_ID \217 ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, \218 ARM_SMCCC_SMC_64, \219 ARM_SMCCC_OWNER_VENDOR_HYP, \220 ARM_SMCCC_KVM_FUNC_MEM_UNSHARE)221 222#define ARM_SMCCC_VENDOR_HYP_KVM_MMIO_GUARD_FUNC_ID \223 ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, \224 ARM_SMCCC_SMC_64, \225 ARM_SMCCC_OWNER_VENDOR_HYP, \226 ARM_SMCCC_KVM_FUNC_MMIO_GUARD)227 228/* ptp_kvm counter type ID */229#define KVM_PTP_VIRT_COUNTER 0230#define KVM_PTP_PHYS_COUNTER 1231 232/* Paravirtualised time calls (defined by ARM DEN0057A) */233#define ARM_SMCCC_HV_PV_TIME_FEATURES \234 ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, \235 ARM_SMCCC_SMC_64, \236 ARM_SMCCC_OWNER_STANDARD_HYP, \237 0x20)238 239#define ARM_SMCCC_HV_PV_TIME_ST \240 ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, \241 ARM_SMCCC_SMC_64, \242 ARM_SMCCC_OWNER_STANDARD_HYP, \243 0x21)244 245/* TRNG entropy source calls (defined by ARM DEN0098) */246#define ARM_SMCCC_TRNG_VERSION \247 ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, \248 ARM_SMCCC_SMC_32, \249 ARM_SMCCC_OWNER_STANDARD, \250 0x50)251 252#define ARM_SMCCC_TRNG_FEATURES \253 ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, \254 ARM_SMCCC_SMC_32, \255 ARM_SMCCC_OWNER_STANDARD, \256 0x51)257 258#define ARM_SMCCC_TRNG_GET_UUID \259 ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, \260 ARM_SMCCC_SMC_32, \261 ARM_SMCCC_OWNER_STANDARD, \262 0x52)263 264#define ARM_SMCCC_TRNG_RND32 \265 ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, \266 ARM_SMCCC_SMC_32, \267 ARM_SMCCC_OWNER_STANDARD, \268 0x53)269 270#define ARM_SMCCC_TRNG_RND64 \271 ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, \272 ARM_SMCCC_SMC_64, \273 ARM_SMCCC_OWNER_STANDARD, \274 0x53)275 276/*277 * Return codes defined in ARM DEN 0070A278 * ARM DEN 0070A is now merged/consolidated into ARM DEN 0028 C279 */280#define SMCCC_RET_SUCCESS 0281#define SMCCC_RET_NOT_SUPPORTED -1282#define SMCCC_RET_NOT_REQUIRED -2283#define SMCCC_RET_INVALID_PARAMETER -3284 285#ifndef __ASSEMBLY__286 287#include <linux/linkage.h>288#include <linux/types.h>289 290enum arm_smccc_conduit {291 SMCCC_CONDUIT_NONE,292 SMCCC_CONDUIT_SMC,293 SMCCC_CONDUIT_HVC,294};295 296/**297 * arm_smccc_1_1_get_conduit()298 *299 * Returns the conduit to be used for SMCCCv1.1 or later.300 *301 * When SMCCCv1.1 is not present, returns SMCCC_CONDUIT_NONE.302 */303enum arm_smccc_conduit arm_smccc_1_1_get_conduit(void);304 305/**306 * arm_smccc_get_version()307 *308 * Returns the version to be used for SMCCCv1.1 or later.309 *310 * When SMCCCv1.1 or above is not present, returns SMCCCv1.0, but this311 * does not imply the presence of firmware or a valid conduit. Caller312 * handling SMCCCv1.0 must determine the conduit by other means.313 */314u32 arm_smccc_get_version(void);315 316void __init arm_smccc_version_init(u32 version, enum arm_smccc_conduit conduit);317 318/**319 * arm_smccc_get_soc_id_version()320 *321 * Returns the SOC ID version.322 *323 * When ARM_SMCCC_ARCH_SOC_ID is not present, returns SMCCC_RET_NOT_SUPPORTED.324 */325s32 arm_smccc_get_soc_id_version(void);326 327/**328 * arm_smccc_get_soc_id_revision()329 *330 * Returns the SOC ID revision.331 *332 * When ARM_SMCCC_ARCH_SOC_ID is not present, returns SMCCC_RET_NOT_SUPPORTED.333 */334s32 arm_smccc_get_soc_id_revision(void);335 336/**337 * struct arm_smccc_res - Result from SMC/HVC call338 * @a0-a3 result values from registers 0 to 3339 */340struct arm_smccc_res {341 unsigned long a0;342 unsigned long a1;343 unsigned long a2;344 unsigned long a3;345};346 347#ifdef CONFIG_ARM64348/**349 * struct arm_smccc_1_2_regs - Arguments for or Results from SMC/HVC call350 * @a0-a17 argument values from registers 0 to 17351 */352struct arm_smccc_1_2_regs {353 unsigned long a0;354 unsigned long a1;355 unsigned long a2;356 unsigned long a3;357 unsigned long a4;358 unsigned long a5;359 unsigned long a6;360 unsigned long a7;361 unsigned long a8;362 unsigned long a9;363 unsigned long a10;364 unsigned long a11;365 unsigned long a12;366 unsigned long a13;367 unsigned long a14;368 unsigned long a15;369 unsigned long a16;370 unsigned long a17;371};372 373/**374 * arm_smccc_1_2_hvc() - make HVC calls375 * @args: arguments passed via struct arm_smccc_1_2_regs376 * @res: result values via struct arm_smccc_1_2_regs377 *378 * This function is used to make HVC calls following SMC Calling Convention379 * v1.2 or above. The content of the supplied param are copied from the380 * structure to registers prior to the HVC instruction. The return values381 * are updated with the content from registers on return from the HVC382 * instruction.383 */384asmlinkage void arm_smccc_1_2_hvc(const struct arm_smccc_1_2_regs *args,385 struct arm_smccc_1_2_regs *res);386 387/**388 * arm_smccc_1_2_smc() - make SMC calls389 * @args: arguments passed via struct arm_smccc_1_2_regs390 * @res: result values via struct arm_smccc_1_2_regs391 *392 * This function is used to make SMC calls following SMC Calling Convention393 * v1.2 or above. The content of the supplied param are copied from the394 * structure to registers prior to the SMC instruction. The return values395 * are updated with the content from registers on return from the SMC396 * instruction.397 */398asmlinkage void arm_smccc_1_2_smc(const struct arm_smccc_1_2_regs *args,399 struct arm_smccc_1_2_regs *res);400#endif401 402/**403 * struct arm_smccc_quirk - Contains quirk information404 * @id: quirk identification405 * @state: quirk specific information406 * @a6: Qualcomm quirk entry for returning post-smc call contents of a6407 */408struct arm_smccc_quirk {409 int id;410 union {411 unsigned long a6;412 } state;413};414 415/**416 * __arm_smccc_smc() - make SMC calls417 * @a0-a7: arguments passed in registers 0 to 7418 * @res: result values from registers 0 to 3419 * @quirk: points to an arm_smccc_quirk, or NULL when no quirks are required.420 *421 * This function is used to make SMC calls following SMC Calling Convention.422 * The content of the supplied param are copied to registers 0 to 7 prior423 * to the SMC instruction. The return values are updated with the content424 * from register 0 to 3 on return from the SMC instruction. An optional425 * quirk structure provides vendor specific behavior.426 */427#ifdef CONFIG_HAVE_ARM_SMCCC428asmlinkage void __arm_smccc_smc(unsigned long a0, unsigned long a1,429 unsigned long a2, unsigned long a3, unsigned long a4,430 unsigned long a5, unsigned long a6, unsigned long a7,431 struct arm_smccc_res *res, struct arm_smccc_quirk *quirk);432#else433static inline void __arm_smccc_smc(unsigned long a0, unsigned long a1,434 unsigned long a2, unsigned long a3, unsigned long a4,435 unsigned long a5, unsigned long a6, unsigned long a7,436 struct arm_smccc_res *res, struct arm_smccc_quirk *quirk)437{438 *res = (struct arm_smccc_res){};439}440#endif441 442/**443 * __arm_smccc_hvc() - make HVC calls444 * @a0-a7: arguments passed in registers 0 to 7445 * @res: result values from registers 0 to 3446 * @quirk: points to an arm_smccc_quirk, or NULL when no quirks are required.447 *448 * This function is used to make HVC calls following SMC Calling449 * Convention. The content of the supplied param are copied to registers 0450 * to 7 prior to the HVC instruction. The return values are updated with451 * the content from register 0 to 3 on return from the HVC instruction. An452 * optional quirk structure provides vendor specific behavior.453 */454asmlinkage void __arm_smccc_hvc(unsigned long a0, unsigned long a1,455 unsigned long a2, unsigned long a3, unsigned long a4,456 unsigned long a5, unsigned long a6, unsigned long a7,457 struct arm_smccc_res *res, struct arm_smccc_quirk *quirk);458 459#define arm_smccc_smc(...) __arm_smccc_smc(__VA_ARGS__, NULL)460 461#define arm_smccc_smc_quirk(...) __arm_smccc_smc(__VA_ARGS__)462 463#define arm_smccc_hvc(...) __arm_smccc_hvc(__VA_ARGS__, NULL)464 465#define arm_smccc_hvc_quirk(...) __arm_smccc_hvc(__VA_ARGS__)466 467/* SMCCC v1.1 implementation madness follows */468#ifdef CONFIG_ARM64469 470#define SMCCC_SMC_INST "smc #0"471#define SMCCC_HVC_INST "hvc #0"472 473#elif defined(CONFIG_ARM)474#include <asm/opcodes-sec.h>475#include <asm/opcodes-virt.h>476 477#define SMCCC_SMC_INST __SMC(0)478#define SMCCC_HVC_INST __HVC(0)479 480#endif481 482#define __constraint_read_2 "r" (arg0)483#define __constraint_read_3 __constraint_read_2, "r" (arg1)484#define __constraint_read_4 __constraint_read_3, "r" (arg2)485#define __constraint_read_5 __constraint_read_4, "r" (arg3)486#define __constraint_read_6 __constraint_read_5, "r" (arg4)487#define __constraint_read_7 __constraint_read_6, "r" (arg5)488#define __constraint_read_8 __constraint_read_7, "r" (arg6)489#define __constraint_read_9 __constraint_read_8, "r" (arg7)490 491#define __declare_arg_2(a0, res) \492 struct arm_smccc_res *___res = res; \493 register unsigned long arg0 asm("r0") = (u32)a0494 495#define __declare_arg_3(a0, a1, res) \496 typeof(a1) __a1 = a1; \497 struct arm_smccc_res *___res = res; \498 register unsigned long arg0 asm("r0") = (u32)a0; \499 register typeof(a1) arg1 asm("r1") = __a1500 501#define __declare_arg_4(a0, a1, a2, res) \502 typeof(a1) __a1 = a1; \503 typeof(a2) __a2 = a2; \504 struct arm_smccc_res *___res = res; \505 register unsigned long arg0 asm("r0") = (u32)a0; \506 register typeof(a1) arg1 asm("r1") = __a1; \507 register typeof(a2) arg2 asm("r2") = __a2508 509#define __declare_arg_5(a0, a1, a2, a3, res) \510 typeof(a1) __a1 = a1; \511 typeof(a2) __a2 = a2; \512 typeof(a3) __a3 = a3; \513 struct arm_smccc_res *___res = res; \514 register unsigned long arg0 asm("r0") = (u32)a0; \515 register typeof(a1) arg1 asm("r1") = __a1; \516 register typeof(a2) arg2 asm("r2") = __a2; \517 register typeof(a3) arg3 asm("r3") = __a3518 519#define __declare_arg_6(a0, a1, a2, a3, a4, res) \520 typeof(a4) __a4 = a4; \521 __declare_arg_5(a0, a1, a2, a3, res); \522 register typeof(a4) arg4 asm("r4") = __a4523 524#define __declare_arg_7(a0, a1, a2, a3, a4, a5, res) \525 typeof(a5) __a5 = a5; \526 __declare_arg_6(a0, a1, a2, a3, a4, res); \527 register typeof(a5) arg5 asm("r5") = __a5528 529#define __declare_arg_8(a0, a1, a2, a3, a4, a5, a6, res) \530 typeof(a6) __a6 = a6; \531 __declare_arg_7(a0, a1, a2, a3, a4, a5, res); \532 register typeof(a6) arg6 asm("r6") = __a6533 534#define __declare_arg_9(a0, a1, a2, a3, a4, a5, a6, a7, res) \535 typeof(a7) __a7 = a7; \536 __declare_arg_8(a0, a1, a2, a3, a4, a5, a6, res); \537 register typeof(a7) arg7 asm("r7") = __a7538 539/*540 * We have an output list that is not necessarily used, and GCC feels541 * entitled to optimise the whole sequence away. "volatile" is what542 * makes it stick.543 */544#define __arm_smccc_1_1(inst, ...) \545 do { \546 register unsigned long r0 asm("r0"); \547 register unsigned long r1 asm("r1"); \548 register unsigned long r2 asm("r2"); \549 register unsigned long r3 asm("r3"); \550 CONCATENATE(__declare_arg_, \551 COUNT_ARGS(__VA_ARGS__))(__VA_ARGS__); \552 asm volatile(inst "\n" : \553 "=r" (r0), "=r" (r1), "=r" (r2), "=r" (r3) \554 : CONCATENATE(__constraint_read_, \555 COUNT_ARGS(__VA_ARGS__)) \556 : "memory"); \557 if (___res) \558 *___res = (typeof(*___res)){r0, r1, r2, r3}; \559 } while (0)560 561/*562 * arm_smccc_1_1_smc() - make an SMCCC v1.1 compliant SMC call563 *564 * This is a variadic macro taking one to eight source arguments, and565 * an optional return structure.566 *567 * @a0-a7: arguments passed in registers 0 to 7568 * @res: result values from registers 0 to 3569 *570 * This macro is used to make SMC calls following SMC Calling Convention v1.1.571 * The content of the supplied param are copied to registers 0 to 7 prior572 * to the SMC instruction. The return values are updated with the content573 * from register 0 to 3 on return from the SMC instruction if not NULL.574 */575#define arm_smccc_1_1_smc(...) __arm_smccc_1_1(SMCCC_SMC_INST, __VA_ARGS__)576 577/*578 * arm_smccc_1_1_hvc() - make an SMCCC v1.1 compliant HVC call579 *580 * This is a variadic macro taking one to eight source arguments, and581 * an optional return structure.582 *583 * @a0-a7: arguments passed in registers 0 to 7584 * @res: result values from registers 0 to 3585 *586 * This macro is used to make HVC calls following SMC Calling Convention v1.1.587 * The content of the supplied param are copied to registers 0 to 7 prior588 * to the HVC instruction. The return values are updated with the content589 * from register 0 to 3 on return from the HVC instruction if not NULL.590 */591#define arm_smccc_1_1_hvc(...) __arm_smccc_1_1(SMCCC_HVC_INST, __VA_ARGS__)592 593/*594 * Like arm_smccc_1_1* but always returns SMCCC_RET_NOT_SUPPORTED.595 * Used when the SMCCC conduit is not defined. The empty asm statement596 * avoids compiler warnings about unused variables.597 */598#define __fail_smccc_1_1(...) \599 do { \600 CONCATENATE(__declare_arg_, \601 COUNT_ARGS(__VA_ARGS__))(__VA_ARGS__); \602 asm ("" : \603 : CONCATENATE(__constraint_read_, \604 COUNT_ARGS(__VA_ARGS__)) \605 : "memory"); \606 if (___res) \607 ___res->a0 = SMCCC_RET_NOT_SUPPORTED; \608 } while (0)609 610/*611 * arm_smccc_1_1_invoke() - make an SMCCC v1.1 compliant call612 *613 * This is a variadic macro taking one to eight source arguments, and614 * an optional return structure.615 *616 * @a0-a7: arguments passed in registers 0 to 7617 * @res: result values from registers 0 to 3618 *619 * This macro will make either an HVC call or an SMC call depending on the620 * current SMCCC conduit. If no valid conduit is available then -1621 * (SMCCC_RET_NOT_SUPPORTED) is returned in @res.a0 (if supplied).622 *623 * The return value also provides the conduit that was used.624 */625#define arm_smccc_1_1_invoke(...) ({ \626 int method = arm_smccc_1_1_get_conduit(); \627 switch (method) { \628 case SMCCC_CONDUIT_HVC: \629 arm_smccc_1_1_hvc(__VA_ARGS__); \630 break; \631 case SMCCC_CONDUIT_SMC: \632 arm_smccc_1_1_smc(__VA_ARGS__); \633 break; \634 default: \635 __fail_smccc_1_1(__VA_ARGS__); \636 method = SMCCC_CONDUIT_NONE; \637 break; \638 } \639 method; \640 })641 642#endif /*__ASSEMBLY__*/643#endif /*__LINUX_ARM_SMCCC_H*/644