linux/include/linux/arm-smccc.h
<<
>>
Prefs
   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 <uapi/linux/const.h>
   9
  10/*
  11 * This file provides common defines for ARM SMC Calling Convention as
  12 * specified in
  13 * http://infocenter.arm.com/help/topic/com.arm.doc.den0028a/index.html
  14 */
  15
  16#define ARM_SMCCC_STD_CALL              _AC(0,U)
  17#define ARM_SMCCC_FAST_CALL             _AC(1,U)
  18#define ARM_SMCCC_TYPE_SHIFT            31
  19
  20#define ARM_SMCCC_SMC_32                0
  21#define ARM_SMCCC_SMC_64                1
  22#define ARM_SMCCC_CALL_CONV_SHIFT       30
  23
  24#define ARM_SMCCC_OWNER_MASK            0x3F
  25#define ARM_SMCCC_OWNER_SHIFT           24
  26
  27#define ARM_SMCCC_FUNC_MASK             0xFFFF
  28
  29#define ARM_SMCCC_IS_FAST_CALL(smc_val) \
  30        ((smc_val) & (ARM_SMCCC_FAST_CALL << ARM_SMCCC_TYPE_SHIFT))
  31#define ARM_SMCCC_IS_64(smc_val) \
  32        ((smc_val) & (ARM_SMCCC_SMC_64 << ARM_SMCCC_CALL_CONV_SHIFT))
  33#define ARM_SMCCC_FUNC_NUM(smc_val)     ((smc_val) & ARM_SMCCC_FUNC_MASK)
  34#define ARM_SMCCC_OWNER_NUM(smc_val) \
  35        (((smc_val) >> ARM_SMCCC_OWNER_SHIFT) & ARM_SMCCC_OWNER_MASK)
  36
  37#define ARM_SMCCC_CALL_VAL(type, calling_convention, owner, func_num) \
  38        (((type) << ARM_SMCCC_TYPE_SHIFT) | \
  39        ((calling_convention) << ARM_SMCCC_CALL_CONV_SHIFT) | \
  40        (((owner) & ARM_SMCCC_OWNER_MASK) << ARM_SMCCC_OWNER_SHIFT) | \
  41        ((func_num) & ARM_SMCCC_FUNC_MASK))
  42
  43#define ARM_SMCCC_OWNER_ARCH            0
  44#define ARM_SMCCC_OWNER_CPU             1
  45#define ARM_SMCCC_OWNER_SIP             2
  46#define ARM_SMCCC_OWNER_OEM             3
  47#define ARM_SMCCC_OWNER_STANDARD        4
  48#define ARM_SMCCC_OWNER_TRUSTED_APP     48
  49#define ARM_SMCCC_OWNER_TRUSTED_APP_END 49
  50#define ARM_SMCCC_OWNER_TRUSTED_OS      50
  51#define ARM_SMCCC_OWNER_TRUSTED_OS_END  63
  52
  53#define ARM_SMCCC_QUIRK_NONE            0
  54#define ARM_SMCCC_QUIRK_QCOM_A6         1 /* Save/restore register a6 */
  55
  56#define ARM_SMCCC_VERSION_1_0           0x10000
  57#define ARM_SMCCC_VERSION_1_1           0x10001
  58
  59#define ARM_SMCCC_VERSION_FUNC_ID                                       \
  60        ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL,                         \
  61                           ARM_SMCCC_SMC_32,                            \
  62                           0, 0)
  63
  64#define ARM_SMCCC_ARCH_FEATURES_FUNC_ID                                 \
  65        ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL,                         \
  66                           ARM_SMCCC_SMC_32,                            \
  67                           0, 1)
  68
  69#define ARM_SMCCC_ARCH_WORKAROUND_1                                     \
  70        ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL,                         \
  71                           ARM_SMCCC_SMC_32,                            \
  72                           0, 0x8000)
  73
  74#define ARM_SMCCC_ARCH_WORKAROUND_2                                     \
  75        ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL,                         \
  76                           ARM_SMCCC_SMC_32,                            \
  77                           0, 0x7fff)
  78
  79#ifndef __ASSEMBLY__
  80
  81#include <linux/linkage.h>
  82#include <linux/types.h>
  83/**
  84 * struct arm_smccc_res - Result from SMC/HVC call
  85 * @a0-a3 result values from registers 0 to 3
  86 */
  87struct arm_smccc_res {
  88        unsigned long a0;
  89        unsigned long a1;
  90        unsigned long a2;
  91        unsigned long a3;
  92};
  93
  94/**
  95 * struct arm_smccc_quirk - Contains quirk information
  96 * @id: quirk identification
  97 * @state: quirk specific information
  98 * @a6: Qualcomm quirk entry for returning post-smc call contents of a6
  99 */
 100struct arm_smccc_quirk {
 101        int     id;
 102        union {
 103                unsigned long a6;
 104        } state;
 105};
 106
 107/**
 108 * __arm_smccc_smc() - make SMC calls
 109 * @a0-a7: arguments passed in registers 0 to 7
 110 * @res: result values from registers 0 to 3
 111 * @quirk: points to an arm_smccc_quirk, or NULL when no quirks are required.
 112 *
 113 * This function is used to make SMC calls following SMC Calling Convention.
 114 * The content of the supplied param are copied to registers 0 to 7 prior
 115 * to the SMC instruction. The return values are updated with the content
 116 * from register 0 to 3 on return from the SMC instruction.  An optional
 117 * quirk structure provides vendor specific behavior.
 118 */
 119asmlinkage void __arm_smccc_smc(unsigned long a0, unsigned long a1,
 120                        unsigned long a2, unsigned long a3, unsigned long a4,
 121                        unsigned long a5, unsigned long a6, unsigned long a7,
 122                        struct arm_smccc_res *res, struct arm_smccc_quirk *quirk);
 123
 124/**
 125 * __arm_smccc_hvc() - make HVC calls
 126 * @a0-a7: arguments passed in registers 0 to 7
 127 * @res: result values from registers 0 to 3
 128 * @quirk: points to an arm_smccc_quirk, or NULL when no quirks are required.
 129 *
 130 * This function is used to make HVC calls following SMC Calling
 131 * Convention.  The content of the supplied param are copied to registers 0
 132 * to 7 prior to the HVC instruction. The return values are updated with
 133 * the content from register 0 to 3 on return from the HVC instruction.  An
 134 * optional quirk structure provides vendor specific behavior.
 135 */
 136asmlinkage void __arm_smccc_hvc(unsigned long a0, unsigned long a1,
 137                        unsigned long a2, unsigned long a3, unsigned long a4,
 138                        unsigned long a5, unsigned long a6, unsigned long a7,
 139                        struct arm_smccc_res *res, struct arm_smccc_quirk *quirk);
 140
 141#define arm_smccc_smc(...) __arm_smccc_smc(__VA_ARGS__, NULL)
 142
 143#define arm_smccc_smc_quirk(...) __arm_smccc_smc(__VA_ARGS__)
 144
 145#define arm_smccc_hvc(...) __arm_smccc_hvc(__VA_ARGS__, NULL)
 146
 147#define arm_smccc_hvc_quirk(...) __arm_smccc_hvc(__VA_ARGS__)
 148
 149/* SMCCC v1.1 implementation madness follows */
 150#ifdef CONFIG_ARM64
 151
 152#define SMCCC_SMC_INST  "smc    #0"
 153#define SMCCC_HVC_INST  "hvc    #0"
 154
 155#elif defined(CONFIG_ARM)
 156#include <asm/opcodes-sec.h>
 157#include <asm/opcodes-virt.h>
 158
 159#define SMCCC_SMC_INST  __SMC(0)
 160#define SMCCC_HVC_INST  __HVC(0)
 161
 162#endif
 163
 164#define ___count_args(_0, _1, _2, _3, _4, _5, _6, _7, _8, x, ...) x
 165
 166#define __count_args(...)                                               \
 167        ___count_args(__VA_ARGS__, 7, 6, 5, 4, 3, 2, 1, 0)
 168
 169#define __constraint_write_0                                            \
 170        "+r" (r0), "=&r" (r1), "=&r" (r2), "=&r" (r3)
 171#define __constraint_write_1                                            \
 172        "+r" (r0), "+r" (r1), "=&r" (r2), "=&r" (r3)
 173#define __constraint_write_2                                            \
 174        "+r" (r0), "+r" (r1), "+r" (r2), "=&r" (r3)
 175#define __constraint_write_3                                            \
 176        "+r" (r0), "+r" (r1), "+r" (r2), "+r" (r3)
 177#define __constraint_write_4    __constraint_write_3
 178#define __constraint_write_5    __constraint_write_4
 179#define __constraint_write_6    __constraint_write_5
 180#define __constraint_write_7    __constraint_write_6
 181
 182#define __constraint_read_0
 183#define __constraint_read_1
 184#define __constraint_read_2
 185#define __constraint_read_3
 186#define __constraint_read_4     "r" (r4)
 187#define __constraint_read_5     __constraint_read_4, "r" (r5)
 188#define __constraint_read_6     __constraint_read_5, "r" (r6)
 189#define __constraint_read_7     __constraint_read_6, "r" (r7)
 190
 191#define __declare_arg_0(a0, res)                                        \
 192        struct arm_smccc_res   *___res = res;                           \
 193        register unsigned long r0 asm("r0") = (u32)a0;                  \
 194        register unsigned long r1 asm("r1");                            \
 195        register unsigned long r2 asm("r2");                            \
 196        register unsigned long r3 asm("r3")
 197
 198#define __declare_arg_1(a0, a1, res)                                    \
 199        typeof(a1) __a1 = a1;                                           \
 200        struct arm_smccc_res   *___res = res;                           \
 201        register unsigned long r0 asm("r0") = (u32)a0;                  \
 202        register unsigned long r1 asm("r1") = __a1;                     \
 203        register unsigned long r2 asm("r2");                            \
 204        register unsigned long r3 asm("r3")
 205
 206#define __declare_arg_2(a0, a1, a2, res)                                \
 207        typeof(a1) __a1 = a1;                                           \
 208        typeof(a2) __a2 = a2;                                           \
 209        struct arm_smccc_res   *___res = res;                           \
 210        register unsigned long r0 asm("r0") = (u32)a0;                  \
 211        register unsigned long r1 asm("r1") = __a1;                     \
 212        register unsigned long r2 asm("r2") = __a2;                     \
 213        register unsigned long r3 asm("r3")
 214
 215#define __declare_arg_3(a0, a1, a2, a3, res)                            \
 216        typeof(a1) __a1 = a1;                                           \
 217        typeof(a2) __a2 = a2;                                           \
 218        typeof(a3) __a3 = a3;                                           \
 219        struct arm_smccc_res   *___res = res;                           \
 220        register unsigned long r0 asm("r0") = (u32)a0;                  \
 221        register unsigned long r1 asm("r1") = __a1;                     \
 222        register unsigned long r2 asm("r2") = __a2;                     \
 223        register unsigned long r3 asm("r3") = __a3
 224
 225#define __declare_arg_4(a0, a1, a2, a3, a4, res)                        \
 226        typeof(a4) __a4 = a4;                                           \
 227        __declare_arg_3(a0, a1, a2, a3, res);                           \
 228        register unsigned long r4 asm("r4") = __a4
 229
 230#define __declare_arg_5(a0, a1, a2, a3, a4, a5, res)                    \
 231        typeof(a5) __a5 = a5;                                           \
 232        __declare_arg_4(a0, a1, a2, a3, a4, res);                       \
 233        register unsigned long r5 asm("r5") = __a5
 234
 235#define __declare_arg_6(a0, a1, a2, a3, a4, a5, a6, res)                \
 236        typeof(a6) __a6 = a6;                                           \
 237        __declare_arg_5(a0, a1, a2, a3, a4, a5, res);                   \
 238        register unsigned long r6 asm("r6") = __a6
 239
 240#define __declare_arg_7(a0, a1, a2, a3, a4, a5, a6, a7, res)            \
 241        typeof(a7) __a7 = a7;                                           \
 242        __declare_arg_6(a0, a1, a2, a3, a4, a5, a6, res);               \
 243        register unsigned long r7 asm("r7") = __a7
 244
 245#define ___declare_args(count, ...) __declare_arg_ ## count(__VA_ARGS__)
 246#define __declare_args(count, ...)  ___declare_args(count, __VA_ARGS__)
 247
 248#define ___constraints(count)                                           \
 249        : __constraint_write_ ## count                                  \
 250        : __constraint_read_ ## count                                   \
 251        : "memory"
 252#define __constraints(count)    ___constraints(count)
 253
 254/*
 255 * We have an output list that is not necessarily used, and GCC feels
 256 * entitled to optimise the whole sequence away. "volatile" is what
 257 * makes it stick.
 258 */
 259#define __arm_smccc_1_1(inst, ...)                                      \
 260        do {                                                            \
 261                __declare_args(__count_args(__VA_ARGS__), __VA_ARGS__); \
 262                asm volatile(inst "\n"                                  \
 263                             __constraints(__count_args(__VA_ARGS__))); \
 264                if (___res)                                             \
 265                        *___res = (typeof(*___res)){r0, r1, r2, r3};    \
 266        } while (0)
 267
 268/*
 269 * arm_smccc_1_1_smc() - make an SMCCC v1.1 compliant SMC call
 270 *
 271 * This is a variadic macro taking one to eight source arguments, and
 272 * an optional return structure.
 273 *
 274 * @a0-a7: arguments passed in registers 0 to 7
 275 * @res: result values from registers 0 to 3
 276 *
 277 * This macro is used to make SMC calls following SMC Calling Convention v1.1.
 278 * The content of the supplied param are copied to registers 0 to 7 prior
 279 * to the SMC instruction. The return values are updated with the content
 280 * from register 0 to 3 on return from the SMC instruction if not NULL.
 281 */
 282#define arm_smccc_1_1_smc(...)  __arm_smccc_1_1(SMCCC_SMC_INST, __VA_ARGS__)
 283
 284/*
 285 * arm_smccc_1_1_hvc() - make an SMCCC v1.1 compliant HVC call
 286 *
 287 * This is a variadic macro taking one to eight source arguments, and
 288 * an optional return structure.
 289 *
 290 * @a0-a7: arguments passed in registers 0 to 7
 291 * @res: result values from registers 0 to 3
 292 *
 293 * This macro is used to make HVC calls following SMC Calling Convention v1.1.
 294 * The content of the supplied param are copied to registers 0 to 7 prior
 295 * to the HVC instruction. The return values are updated with the content
 296 * from register 0 to 3 on return from the HVC instruction if not NULL.
 297 */
 298#define arm_smccc_1_1_hvc(...)  __arm_smccc_1_1(SMCCC_HVC_INST, __VA_ARGS__)
 299
 300/* Return codes defined in ARM DEN 0070A */
 301#define SMCCC_RET_SUCCESS                       0
 302#define SMCCC_RET_NOT_SUPPORTED                 -1
 303#define SMCCC_RET_NOT_REQUIRED                  -2
 304
 305#endif /*__ASSEMBLY__*/
 306#endif /*__LINUX_ARM_SMCCC_H*/
 307