encls.h 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236
  1. /* SPDX-License-Identifier: GPL-2.0 */
  2. #ifndef _X86_ENCLS_H
  3. #define _X86_ENCLS_H
  4. #include <linux/bitops.h>
  5. #include <linux/err.h>
  6. #include <linux/io.h>
  7. #include <linux/rwsem.h>
  8. #include <linux/types.h>
  9. #include <asm/asm.h>
  10. #include <asm/traps.h>
  11. #include "sgx.h"
  12. /* Retrieve the encoded trapnr from the specified return code. */
  13. #define ENCLS_TRAPNR(r) ((r) & ~SGX_ENCLS_FAULT_FLAG)
  14. /* Issue a WARN() about an ENCLS function. */
  15. #define ENCLS_WARN(r, name) { \
  16. do { \
  17. int _r = (r); \
  18. WARN_ONCE(_r, "%s returned %d (0x%x)\n", (name), _r, _r); \
  19. } while (0); \
  20. }
  21. /*
  22. * encls_faulted() - Check if an ENCLS leaf faulted given an error code
  23. * @ret: the return value of an ENCLS leaf function call
  24. *
  25. * Return:
  26. * - true: ENCLS leaf faulted.
  27. * - false: Otherwise.
  28. */
  29. static inline bool encls_faulted(int ret)
  30. {
  31. return ret & SGX_ENCLS_FAULT_FLAG;
  32. }
  33. /**
  34. * encls_failed() - Check if an ENCLS function failed
  35. * @ret: the return value of an ENCLS function call
  36. *
  37. * Check if an ENCLS function failed. This happens when the function causes a
  38. * fault that is not caused by an EPCM conflict or when the function returns a
  39. * non-zero value.
  40. */
  41. static inline bool encls_failed(int ret)
  42. {
  43. if (encls_faulted(ret))
  44. return ENCLS_TRAPNR(ret) != X86_TRAP_PF;
  45. return !!ret;
  46. }
  47. /**
  48. * __encls_ret_N - encode an ENCLS function that returns an error code in EAX
  49. * @rax: function number
  50. * @inputs: asm inputs for the function
  51. *
  52. * Emit assembly for an ENCLS function that returns an error code, e.g. EREMOVE.
  53. * And because SGX isn't complex enough as it is, function that return an error
  54. * code also modify flags.
  55. *
  56. * Return:
  57. * 0 on success,
  58. * SGX error code on failure
  59. */
  60. #define __encls_ret_N(rax, inputs...) \
  61. ({ \
  62. int ret; \
  63. asm volatile( \
  64. "1: .byte 0x0f, 0x01, 0xcf;\n\t" \
  65. "2:\n" \
  66. _ASM_EXTABLE_TYPE(1b, 2b, EX_TYPE_FAULT_SGX) \
  67. : "=a"(ret) \
  68. : "a"(rax), inputs \
  69. : "memory", "cc"); \
  70. ret; \
  71. })
  72. #define __encls_ret_1(rax, rcx) \
  73. ({ \
  74. __encls_ret_N(rax, "c"(rcx)); \
  75. })
  76. #define __encls_ret_2(rax, rbx, rcx) \
  77. ({ \
  78. __encls_ret_N(rax, "b"(rbx), "c"(rcx)); \
  79. })
  80. #define __encls_ret_3(rax, rbx, rcx, rdx) \
  81. ({ \
  82. __encls_ret_N(rax, "b"(rbx), "c"(rcx), "d"(rdx)); \
  83. })
  84. /**
  85. * __encls_N - encode an ENCLS function that doesn't return an error code
  86. * @rax: function number
  87. * @rbx_out: optional output variable
  88. * @inputs: asm inputs for the function
  89. *
  90. * Emit assembly for an ENCLS function that does not return an error code, e.g.
  91. * ECREATE. Leaves without error codes either succeed or fault. @rbx_out is an
  92. * optional parameter for use by EDGBRD, which returns the requested value in
  93. * RBX.
  94. *
  95. * Return:
  96. * 0 on success,
  97. * trapnr with SGX_ENCLS_FAULT_FLAG set on fault
  98. */
  99. #define __encls_N(rax, rbx_out, inputs...) \
  100. ({ \
  101. int ret; \
  102. asm volatile( \
  103. "1: .byte 0x0f, 0x01, 0xcf;\n\t" \
  104. " xor %%eax,%%eax;\n" \
  105. "2:\n" \
  106. _ASM_EXTABLE_TYPE(1b, 2b, EX_TYPE_FAULT_SGX) \
  107. : "=a"(ret), "=b"(rbx_out) \
  108. : "a"(rax), inputs \
  109. : "memory"); \
  110. ret; \
  111. })
  112. #define __encls_2(rax, rbx, rcx) \
  113. ({ \
  114. unsigned long ign_rbx_out; \
  115. __encls_N(rax, ign_rbx_out, "b"(rbx), "c"(rcx)); \
  116. })
  117. #define __encls_1_1(rax, data, rcx) \
  118. ({ \
  119. unsigned long rbx_out; \
  120. int ret = __encls_N(rax, rbx_out, "c"(rcx)); \
  121. if (!ret) \
  122. data = rbx_out; \
  123. ret; \
  124. })
  125. /* Initialize an EPC page into an SGX Enclave Control Structure (SECS) page. */
  126. static inline int __ecreate(struct sgx_pageinfo *pginfo, void *secs)
  127. {
  128. return __encls_2(ECREATE, pginfo, secs);
  129. }
  130. /* Hash a 256 byte region of an enclave page to SECS:MRENCLAVE. */
  131. static inline int __eextend(void *secs, void *addr)
  132. {
  133. return __encls_2(EEXTEND, secs, addr);
  134. }
  135. /*
  136. * Associate an EPC page to an enclave either as a REG or TCS page
  137. * populated with the provided data.
  138. */
  139. static inline int __eadd(struct sgx_pageinfo *pginfo, void *addr)
  140. {
  141. return __encls_2(EADD, pginfo, addr);
  142. }
  143. /* Finalize enclave build, initialize enclave for user code execution. */
  144. static inline int __einit(void *sigstruct, void *token, void *secs)
  145. {
  146. return __encls_ret_3(EINIT, sigstruct, secs, token);
  147. }
  148. /* Disassociate EPC page from its enclave and mark it as unused. */
  149. static inline int __eremove(void *addr)
  150. {
  151. return __encls_ret_1(EREMOVE, addr);
  152. }
  153. /* Copy data to an EPC page belonging to a debug enclave. */
  154. static inline int __edbgwr(void *addr, unsigned long *data)
  155. {
  156. return __encls_2(EDGBWR, *data, addr);
  157. }
  158. /* Copy data from an EPC page belonging to a debug enclave. */
  159. static inline int __edbgrd(void *addr, unsigned long *data)
  160. {
  161. return __encls_1_1(EDGBRD, *data, addr);
  162. }
  163. /* Track that software has completed the required TLB address clears. */
  164. static inline int __etrack(void *addr)
  165. {
  166. return __encls_ret_1(ETRACK, addr);
  167. }
  168. /* Load, verify, and unblock an EPC page. */
  169. static inline int __eldu(struct sgx_pageinfo *pginfo, void *addr,
  170. void *va)
  171. {
  172. return __encls_ret_3(ELDU, pginfo, addr, va);
  173. }
  174. /* Make EPC page inaccessible to enclave, ready to be written to memory. */
  175. static inline int __eblock(void *addr)
  176. {
  177. return __encls_ret_1(EBLOCK, addr);
  178. }
  179. /* Initialize an EPC page into a Version Array (VA) page. */
  180. static inline int __epa(void *addr)
  181. {
  182. unsigned long rbx = SGX_PAGE_TYPE_VA;
  183. return __encls_2(EPA, rbx, addr);
  184. }
  185. /* Invalidate an EPC page and write it out to main memory. */
  186. static inline int __ewb(struct sgx_pageinfo *pginfo, void *addr,
  187. void *va)
  188. {
  189. return __encls_ret_3(EWB, pginfo, addr, va);
  190. }
  191. /* Restrict the EPCM permissions of an EPC page. */
  192. static inline int __emodpr(struct sgx_secinfo *secinfo, void *addr)
  193. {
  194. return __encls_ret_2(EMODPR, secinfo, addr);
  195. }
  196. /* Change the type of an EPC page. */
  197. static inline int __emodt(struct sgx_secinfo *secinfo, void *addr)
  198. {
  199. return __encls_ret_2(EMODT, secinfo, addr);
  200. }
  201. /* Zero a page of EPC memory and add it to an initialized enclave. */
  202. static inline int __eaug(struct sgx_pageinfo *pginfo, void *addr)
  203. {
  204. return __encls_2(EAUG, pginfo, addr);
  205. }
  206. #endif /* _X86_ENCLS_H */