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