trts_pic.S 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504
  1. /*
  2. * Copyright (C) 2011-2017 Intel Corporation. All rights reserved.
  3. *
  4. * Redistribution and use in source and binary forms, with or without
  5. * modification, are permitted provided that the following conditions
  6. * are met:
  7. *
  8. * * Redistributions of source code must retain the above copyright
  9. * notice, this list of conditions and the following disclaimer.
  10. * * Redistributions in binary form must reproduce the above copyright
  11. * notice, this list of conditions and the following disclaimer in
  12. * the documentation and/or other materials provided with the
  13. * distribution.
  14. * * Neither the name of Intel Corporation nor the names of its
  15. * contributors may be used to endorse or promote products derived
  16. * from this software without specific prior written permission.
  17. *
  18. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  19. * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  20. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  21. * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  22. * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  23. * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  24. * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  25. * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  26. * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  27. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  28. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  29. *
  30. */
  31. /*
  32. * Description:
  33. * The file provides `enclave_entry' function to switch code between
  34. * trusted and untrusted envronment.
  35. */
  36. .file "trts_pic.S"
  37. #include "trts_pic.h"
  38. .text
  39. DECLARE_LOCAL_FUNC get_enclave_base
  40. lea_pic __ImageBase, %xax
  41. ret
  42. DECLARE_LOCAL_FUNC get_enclave_state
  43. lea_pic g_enclave_state, %xcx
  44. xor %xax, %xax
  45. movl (%xcx), %eax
  46. ret
  47. DECLARE_LOCAL_FUNC set_enclave_state
  48. lea_pic g_enclave_state, %xax
  49. #ifdef LINUX32
  50. mov SE_WORDSIZE(%esp), %edi
  51. #endif
  52. movl %edi, (%xax)
  53. ret
  54. DECLARE_LOCAL_FUNC lock_enclave
  55. lea_pic g_enclave_state, %xdx
  56. xor %xax, %xax
  57. mov $ENCLAVE_INIT_NOT_STARTED, %eax
  58. xor %xcx, %xcx
  59. mov $ENCLAVE_INIT_IN_PROGRESS, %ecx /* if (g_global_data.enclave_state == ENCLAVE_INIT_NOT_STARTED) */
  60. lock cmpxchgl %ecx, (%xdx) /* g_global_data.enclave_state == ENCLAVE_INIT_IN_PROGRESS */
  61. ret /* xax: the initial value of enclave state */
  62. /*
  63. * ---------------------------------------------------------------------
  64. * Function: thread_data_t* get_thread_data(void);
  65. *
  66. * Get the address of thread_data
  67. * ---------------------------------------------------------------------
  68. */
  69. DECLARE_LOCAL_FUNC get_thread_data
  70. READ_TD_DATA self_addr
  71. ret
  72. /*
  73. * ---------------------------------------------------------------------
  74. * Function: enclave_entry
  75. * The entry point of the enclave.
  76. *
  77. * Registers:
  78. * XAX - TCS.CSSA
  79. * XBX - the address of a TCS
  80. * XCX - the address of the instruction following the EENTER
  81. * XDI - the reason of entering the enclave
  82. * XSI - the pointer to the marshalling structure
  83. */
  84. DECLARE_GLOBAL_FUNC enclave_entry
  85. /*
  86. * ----------------------------------------------------------------------
  87. * Dispatch code according to CSSA and the reason of EENTER
  88. * eax > 0 - exception handler
  89. * edi >= 0 - ecall
  90. * edi == -1 - do_init_enclave
  91. * edi == -2 - oret
  92. * Registers
  93. * No need to use any register during the dipatch
  94. * ----------------------------------------------------------------------
  95. */
  96. .cfi_startproc
  97. cmp $0, %xax
  98. jne .Ldo_handler /* handle exception state */
  99. xor %xdx, %xdx
  100. READ_TD_DATA last_sp
  101. cmp $0, %xax
  102. jne .Lswitch_stack
  103. GET_STACK_BASE %xbx /* if last_sp == 0, set sp to stack base */
  104. sub $STATIC_STACK_SIZE, %xax /* give space for static stack */
  105. .Lswitch_stack:
  106. xchg %xsp, %xax
  107. push %xcx
  108. push %xbp
  109. .cfi_def_cfa_offset 2 * SE_WORDSIZE
  110. .cfi_offset xbp, -2 * SE_WORDSIZE
  111. mov %xsp, %xbp
  112. .cfi_def_cfa_register xbp
  113. /* Save the registers */
  114. sub $(6*SE_WORDSIZE), %xsp
  115. mov %xax, -1*SE_WORDSIZE(%xbp) /* xsp_u */
  116. mov %xdx, -3*SE_WORDSIZE(%xbp) /* cssa */
  117. mov %xbx, -4*SE_WORDSIZE(%xbp) /* TCS */
  118. mov %xsi, -5*SE_WORDSIZE(%xbp) /* XSI */
  119. mov %xdi, -6*SE_WORDSIZE(%xbp) /* XDI */
  120. #ifdef LINUX64
  121. mov %rdx, %rcx
  122. mov %rbx, %rdx
  123. #endif
  124. call enter_enclave
  125. .Lexit_enclave:
  126. mov -1*SE_WORDSIZE(%xbp), %xdx /* xdx: xsp_u */
  127. mov %xbp, %xsp
  128. pop %xbp /* xbp_u */
  129. pop %xbx /* ret_u */
  130. mov %xdx, %xsp /* xsp_u */
  131. mov $OCMD_ERET, %xdi
  132. mov %xax, %xsi
  133. .Lclear_and_exit_enclave:
  134. /* Clear all GPRs, except xax, xbx, xdi and xsi */
  135. xor %xcx, %xcx
  136. xor %xdx, %xdx
  137. #if defined(LINUX64)
  138. xor %r8, %r8
  139. xor %r9, %r9
  140. xor %r10, %r10
  141. xor %r11, %r11
  142. xor %r12, %r12
  143. xor %r13, %r13
  144. xor %r14, %r14
  145. xor %r15, %r15
  146. #endif
  147. /* Set status flags to pre-defined values */
  148. add %xdx, %xdx /* OF = SF = AF = CF = 0; ZF = PF = 1 */
  149. /* EEXIT */
  150. mov $SE_EEXIT, %xax /* EEXIT leaf */
  151. ENCLU
  152. /* Should not come here */
  153. ud2
  154. .Ldo_handler:
  155. mov %xax, %xdx /* XDX: cssa */
  156. GET_STACK_BASE %xbx /* XAX: static stack, set sp to stack base */
  157. jmp .Lswitch_stack
  158. /* Should not come here */
  159. ud2
  160. .cfi_endproc
  161. /*
  162. * -------------------------------------------------------------------------
  163. * sgx_status_t do_ocall(unsigned int index, void *ms);
  164. *
  165. * Function: do_ocall
  166. * The entry point of the enclave
  167. * Parameters:
  168. * func_addr - target function address
  169. * ms - marshalling structure
  170. *
  171. * Stack: (same as do_oret)
  172. * bottom of stack ->
  173. * -----------------
  174. * | ECALL/OCALL |
  175. * previous TD.last_sp -> | frames |
  176. * -----------------
  177. * | ECALL frame |
  178. * | do_ocall param 2| 21
  179. * | do_ocall param 1| 20
  180. * |do_ocall ret_addr| 19
  181. * | ocall_depth | 18
  182. * | reserved | 17
  183. * | reserved | 16
  184. * | reserved | 15
  185. * | rbx | 14
  186. * | rsi | 13
  187. * | rdi | 12
  188. * | rbp | 11
  189. * | r12 | 10
  190. * | r13 | 9
  191. * | r14 | 8
  192. * | r15 | 7
  193. * | prev TD.last_sp | 6
  194. * | ocall_index | 5
  195. * | OCALL FLAG | 4
  196. * | shadow | 3
  197. * | shadow | 2
  198. * | shadow | 1
  199. * TD.last_sp -> | shadow | 0
  200. * -----------------
  201. * -------------------------------------------------------------------------
  202. */
  203. DECLARE_LOCAL_FUNC do_ocall
  204. /*
  205. * 8 for GPR, 1 for TD.last_sp, 1 for ocall_index
  206. * 1 for OCALL_FLAG, 4 for shadow space.
  207. * Stack Pointer is 16-byte aligned under x86_64.
  208. */
  209. sub $(19*SE_WORDSIZE), %xsp
  210. /* save non-volatile registers, except xsp */
  211. mov %xbx, SE_WORDSIZE*14(%xsp)
  212. mov %xsi, SE_WORDSIZE*13(%xsp)
  213. mov %xdi, SE_WORDSIZE*12(%xsp)
  214. mov %xbp, SE_WORDSIZE*11(%xsp)
  215. #ifdef LINUX64
  216. mov %r12, SE_WORDSIZE*10(%rsp)
  217. mov %r13, SE_WORDSIZE* 9(%rsp)
  218. mov %r14, SE_WORDSIZE* 8(%rsp)
  219. mov %r15, SE_WORDSIZE* 7(%rsp)
  220. #endif
  221. /* set xdi and xsi using the input parameters */
  222. #ifdef LINUX64
  223. mov %edi, %edi /* it should clear the high 32bit word of RDI */
  224. /*
  225. * rdi - param 1 (index), rsi - param 2 (ms)
  226. * only use lower 32bit of rdi, rsi remains unchanged.
  227. */
  228. #endif
  229. #ifdef LINUX32
  230. mov SE_WORDSIZE*20(%esp), %edi
  231. mov SE_WORDSIZE*21(%esp), %esi
  232. #endif
  233. /* save ocall index to the stack */
  234. mov $OCALL_FLAG, %xax
  235. mov %xax, SE_WORDSIZE*4(%xsp) /* save OCALL_FLAG */
  236. mov %xdi, SE_WORDSIZE*5(%xsp) /* save ocall_index */
  237. /*
  238. * save the inside stack context
  239. * push TD.last_sp
  240. * set TD.last_sp = xsp
  241. */
  242. READ_TD_DATA self_addr
  243. mov %xax, %xbx
  244. /* call update_ocall_lastsp */
  245. #ifdef LINUX32
  246. mov %xsp, (%xsp)
  247. #else
  248. mov %xsp, %xdi
  249. #endif
  250. call update_ocall_lastsp /* xax: td.last_sp */
  251. #ifdef LINUX64
  252. mov SE_WORDSIZE*12(%xsp), %xdi /* restore xdi */
  253. mov SE_WORDSIZE*13(%xsp), %xsi /* restore xdi */
  254. #endif
  255. /* restore outside stack context */
  256. mov first_ssa_gpr(%xbx), %xdx
  257. mov ssa_bp_u(%xdx), %xbp
  258. mov ssa_sp_u(%xdx), %xsp
  259. /*
  260. * set EEXIT registers
  261. * return address can be read from the ECALL frame:
  262. * TD.last_sp ->
  263. * -------------
  264. * | ret_addr |
  265. * | xbp_u |
  266. * | xsp_u |
  267. * | ... |
  268. */
  269. mov -1*SE_WORDSIZE(%xax), %xbx /* return address */
  270. mov $SE_EEXIT, %xax /* EEXIT leaf */
  271. /* Clear all GPRs, except xax, xbx, xdi, and xsi*/
  272. xor %xcx, %xcx
  273. xor %xdx, %xdx
  274. #ifdef LINUX64
  275. xor %r8, %r8
  276. xor %r9, %r9
  277. xor %r10, %r10
  278. xor %r11, %r11
  279. xor %r12, %r12
  280. xor %r13, %r13
  281. xor %r14, %r14
  282. xor %r15, %r15
  283. #endif
  284. /* Set status flags to pre-defined values */
  285. add %xdx, %xdx /* OF = SF = AF = CF = 0; ZF = PF = 1 */
  286. ENCLU
  287. /*
  288. * ------------------------------------------------------------------
  289. * this function is the wrapper of do_ocall, which is used to
  290. * stick ocall bridge and proxy frame together
  291. * ------------------------------------------------------------------
  292. */
  293. DECLARE_LOCAL_FUNC __morestack
  294. .cfi_startproc
  295. push %xbp
  296. .cfi_def_cfa_offset 2*SE_WORDSIZE
  297. .cfi_offset xbp,-2*SE_WORDSIZE
  298. mov %xsp, %xbp
  299. .cfi_def_cfa_register xbp
  300. sub $(4*SE_WORDSIZE), %xsp
  301. #ifdef LINUX32
  302. /* save the 2 parameters */
  303. mov (2*SE_WORDSIZE)(%xbp), %xax
  304. mov %xax, (0*SE_WORDSIZE)(%xsp)
  305. mov (3*SE_WORDSIZE)(%xbp), %xax
  306. mov %xax, (1*SE_WORDSIZE)(%xsp)
  307. #endif
  308. call do_ocall
  309. leave
  310. ret
  311. .cfi_endproc
  312. DECLARE_GLOBAL_FUNC asm_oret
  313. #ifdef LINUX32
  314. mov SE_WORDSIZE(%xsp), %xdi
  315. mov 2*SE_WORDSIZE(%xsp), %xsi
  316. #endif
  317. mov %xdi, %xsp /* restore thread_data.last_sp */
  318. mov %xsi, %xax /* ocall return value */
  319. #ifdef LINUX64
  320. mov 7*SE_WORDSIZE(%xsp), %r15
  321. mov 8*SE_WORDSIZE(%xsp), %r14
  322. mov 9*SE_WORDSIZE(%xsp), %r13
  323. mov 10*SE_WORDSIZE(%xsp), %r12
  324. #endif
  325. mov 11*SE_WORDSIZE(%xsp), %xbp
  326. mov 12*SE_WORDSIZE(%xsp), %xdi
  327. mov 13*SE_WORDSIZE(%xsp), %xsi
  328. mov 14*SE_WORDSIZE(%xsp), %xbx
  329. add $(19*SE_WORDSIZE), %xsp
  330. ret
  331. /* should not come here */
  332. ud2
  333. /*
  334. * ------------------------------------------------------------------------
  335. * extern "C" int do_egetkey(key_request_t *key_request, key_128bit_t *key)
  336. * return value:
  337. * 0 - success
  338. * none-zeor - EGETKEY error code
  339. * EGETKEY: rbx - the address of KEYREQUEST structure
  340. * rcx - the address where the key is outputted
  341. * ------------------------------------------------------------------------
  342. */
  343. DECLARE_LOCAL_FUNC do_egetkey
  344. SE_PROLOG
  345. mov $SE_EGETKEY, %xax /* EGETKEY leaf */
  346. ENCLU
  347. #ifdef SE_SIM
  348. cmp $SGX_SUCCESS, %xax /* In simulation mode, ZF flag will not be set */
  349. jnz .Legetkey_done /* because the stack clean operation will always clean ZF flag */
  350. #else
  351. jz .Legetkey_done /* if EGETKEY error, ZF flag is set and error code is set to xax */
  352. #endif
  353. xor %xax, %xax
  354. .Legetkey_done:
  355. SE_EPILOG
  356. ret
  357. /*
  358. * -------------------------------------------------------------------------
  359. * extern "C" void do_ereport(sgx_target_info_t *target_info, sgx_report_data_t *report_data, sgx_report_t *report);
  360. * EREPORT: rbx - the address of TARGETINFO;
  361. * rcx - the address of REPORTDATA;
  362. * rdx - the address where REPORT is outputted
  363. * -------------------------------------------------------------------------
  364. */
  365. DECLARE_LOCAL_FUNC do_ereport
  366. SE_PROLOG
  367. mov $SE_EREPORT, %xax /* EREPORT leaf */
  368. ENCLU
  369. SE_EPILOG
  370. ret
  371. #define _RDRAND_RETRY_TIMES 10
  372. /*
  373. * -------------------------------------
  374. * extern "C" uint32_t do_rdrand(uint32_t *rand);
  375. * return value:
  376. * non-zero: rdrand succeeded
  377. * zero: rdrand failed
  378. * -------------------------------------
  379. */
  380. DECLARE_LOCAL_FUNC do_rdrand
  381. mov $_RDRAND_RETRY_TIMES, %ecx
  382. .Lrdrand_retry:
  383. .byte 0x0F, 0xC7, 0xF0 /* rdrand %eax */
  384. jc .Lrdrand_return
  385. dec %ecx
  386. jnz .Lrdrand_retry
  387. xor %xax, %xax
  388. ret
  389. .Lrdrand_return:
  390. #ifdef LINUX32
  391. mov SE_WORDSIZE(%esp), %ecx
  392. #else
  393. mov %rdi, %rcx
  394. #endif
  395. movl %eax, (%xcx)
  396. mov $1, %xax
  397. ret
  398. /*
  399. * -------------------------------------------------------------------------
  400. * extern "C" void abort(void) __attribute__(__noreturn__);
  401. * -------------------------------------------------------------------------
  402. */
  403. DECLARE_LOCAL_FUNC abort
  404. lea_pic g_enclave_state, %xax
  405. movl $ENCLAVE_CRASHED, (%xax)
  406. ud2
  407. /*
  408. * -------------------------------------------------------------------------
  409. * extern "C" __attribute__((regparm(1))) void continue_execution(sgx_exception_info_t *info);
  410. * -------------------------------------------------------------------------
  411. */
  412. DECLARE_LOCAL_FUNC continue_execution
  413. #ifdef LINUX32
  414. mov %xax, %xcx
  415. #else
  416. mov %xdi, %xcx
  417. #endif
  418. mov SE_WORDSIZE*0(%xcx), %xax
  419. push %xax # push xax
  420. mov SE_WORDSIZE*1(%xcx), %xax
  421. push %xax # push xcx
  422. mov SE_WORDSIZE*4(%xcx), %xax
  423. sub $(SE_WORDSIZE), %xax # xax: xsp
  424. # restore registers except xax, xcx, xsp
  425. mov SE_WORDSIZE*2(%xcx), %xdx
  426. mov SE_WORDSIZE*3(%xcx), %xbx
  427. mov SE_WORDSIZE*5(%xcx), %xbp
  428. mov SE_WORDSIZE*6(%xcx), %xsi
  429. mov SE_WORDSIZE*7(%xcx), %xdi
  430. #ifdef LINUX64
  431. mov SE_WORDSIZE*8(%xcx), %r8
  432. mov SE_WORDSIZE*9(%xcx), %r9
  433. mov SE_WORDSIZE*10(%xcx), %r10
  434. mov SE_WORDSIZE*11(%xcx), %r11
  435. mov SE_WORDSIZE*12(%xcx), %r12
  436. mov SE_WORDSIZE*13(%xcx), %r13
  437. mov SE_WORDSIZE*14(%xcx), %r14
  438. mov SE_WORDSIZE*15(%xcx), %r15
  439. push SE_WORDSIZE*16(%xcx)
  440. popf # make sure the following instructions do not affect flags
  441. #else
  442. push SE_WORDSIZE*8(%xcx)
  443. popf
  444. #endif
  445. #ifdef LINUX64
  446. mov SE_WORDSIZE*17(%xcx), %xcx
  447. #else
  448. mov SE_WORDSIZE*9(%xcx), %xcx # xcx: xip
  449. #endif
  450. # do not setup the new stack until info is not needed any more
  451. # otherwise, info will be overwritten
  452. mov %xcx, (%xax) # save xip to the new stack
  453. pop %xcx # restore xcx
  454. pop %xsp # xsp: xax
  455. xchg %xax, %xsp
  456. ret