arm-smccc.h 11 KB

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