trts_pic.S 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515
  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: sys_word_t get_stack_guard(void);
  75. *
  76. * Get the value of stack_guard
  77. * ---------------------------------------------------------------------
  78. */
  79. DECLARE_LOCAL_FUNC get_stack_guard
  80. READ_TD_DATA stack_guard
  81. ret
  82. /*
  83. * ---------------------------------------------------------------------
  84. * Function: enclave_entry
  85. * The entry point of the enclave.
  86. *
  87. * Registers:
  88. * XAX - TCS.CSSA
  89. * XBX - the address of a TCS
  90. * XCX - the address of the instruction following the EENTER
  91. * XDI - the reason of entering the enclave
  92. * XSI - the pointer to the marshalling structure
  93. */
  94. DECLARE_GLOBAL_FUNC enclave_entry
  95. /*
  96. * ----------------------------------------------------------------------
  97. * Dispatch code according to CSSA and the reason of EENTER
  98. * eax > 0 - exception handler
  99. * edi >= 0 - ecall
  100. * edi == -1 - do_init_enclave
  101. * edi == -2 - oret
  102. * Registers
  103. * No need to use any register during the dipatch
  104. * ----------------------------------------------------------------------
  105. */
  106. .cfi_startproc
  107. cmp $0, %xax
  108. jne .Ldo_handler /* handle exception state */
  109. xor %xdx, %xdx
  110. READ_TD_DATA last_sp
  111. cmp $0, %xax
  112. jne .Lswitch_stack
  113. GET_STACK_BASE %xbx /* if last_sp == 0, set sp to stack base */
  114. sub $STATIC_STACK_SIZE, %xax /* give space for static stack */
  115. .Lswitch_stack:
  116. xchg %xsp, %xax
  117. push %xcx
  118. push %xbp
  119. .cfi_def_cfa_offset 2 * SE_WORDSIZE
  120. .cfi_offset xbp, -2 * SE_WORDSIZE
  121. mov %xsp, %xbp
  122. .cfi_def_cfa_register xbp
  123. /* Save the registers */
  124. sub $(6*SE_WORDSIZE), %xsp
  125. mov %xax, -1*SE_WORDSIZE(%xbp) /* xsp_u */
  126. mov %xdx, -3*SE_WORDSIZE(%xbp) /* cssa */
  127. mov %xbx, -4*SE_WORDSIZE(%xbp) /* TCS */
  128. mov %xsi, -5*SE_WORDSIZE(%xbp) /* XSI */
  129. mov %xdi, -6*SE_WORDSIZE(%xbp) /* XDI */
  130. #ifdef LINUX64
  131. mov %rdx, %rcx
  132. mov %rbx, %rdx
  133. #endif
  134. call enter_enclave
  135. .Lexit_enclave:
  136. mov -1*SE_WORDSIZE(%xbp), %xdx /* xdx: xsp_u */
  137. mov %xbp, %xsp
  138. pop %xbp /* xbp_u */
  139. pop %xbx /* ret_u */
  140. mov %xdx, %xsp /* xsp_u */
  141. mov $OCMD_ERET, %xdi
  142. mov %xax, %xsi
  143. .Lclear_and_exit_enclave:
  144. /* Clear all GPRs, except xax, xbx, xdi and xsi */
  145. xor %xcx, %xcx
  146. xor %xdx, %xdx
  147. #if defined(LINUX64)
  148. xor %r8, %r8
  149. xor %r9, %r9
  150. xor %r10, %r10
  151. xor %r11, %r11
  152. xor %r12, %r12
  153. xor %r13, %r13
  154. xor %r14, %r14
  155. xor %r15, %r15
  156. #endif
  157. /* Set status flags to pre-defined values */
  158. add %xdx, %xdx /* OF = SF = AF = CF = 0; ZF = PF = 1 */
  159. /* EEXIT */
  160. mov $SE_EEXIT, %xax /* EEXIT leaf */
  161. ENCLU
  162. /* Should not come here */
  163. ud2
  164. .Ldo_handler:
  165. mov %xax, %xdx /* XDX: cssa */
  166. GET_STACK_BASE %xbx /* XAX: static stack, set sp to stack base */
  167. jmp .Lswitch_stack
  168. /* Should not come here */
  169. ud2
  170. .cfi_endproc
  171. /*
  172. * -------------------------------------------------------------------------
  173. * sgx_status_t do_ocall(unsigned int index, void *ms);
  174. *
  175. * Function: do_ocall
  176. * The entry point of the enclave
  177. * Parameters:
  178. * func_addr - target function address
  179. * ms - marshalling structure
  180. *
  181. * Stack: (same as do_oret)
  182. * bottom of stack ->
  183. * -----------------
  184. * | ECALL/OCALL |
  185. * previous TD.last_sp -> | frames |
  186. * -----------------
  187. * | ECALL frame |
  188. * | do_ocall param 2| 21
  189. * | do_ocall param 1| 20
  190. * |do_ocall ret_addr| 19
  191. * | ocall_depth | 18
  192. * | reserved | 17
  193. * | reserved | 16
  194. * | reserved | 15
  195. * | rbx | 14
  196. * | rsi | 13
  197. * | rdi | 12
  198. * | rbp | 11
  199. * | r12 | 10
  200. * | r13 | 9
  201. * | r14 | 8
  202. * | r15 | 7
  203. * | prev TD.last_sp | 6
  204. * | ocall_index | 5
  205. * | OCALL FLAG | 4
  206. * | shadow | 3
  207. * | shadow | 2
  208. * | shadow | 1
  209. * TD.last_sp -> | shadow | 0
  210. * -----------------
  211. * -------------------------------------------------------------------------
  212. */
  213. DECLARE_LOCAL_FUNC do_ocall
  214. /*
  215. * 8 for GPR, 1 for TD.last_sp, 1 for ocall_index
  216. * 1 for OCALL_FLAG, 4 for shadow space.
  217. * Stack Pointer is 16-byte aligned under x86_64.
  218. */
  219. sub $(19*SE_WORDSIZE), %xsp
  220. /* save non-volatile registers, except xsp */
  221. mov %xbx, SE_WORDSIZE*14(%xsp)
  222. mov %xsi, SE_WORDSIZE*13(%xsp)
  223. mov %xdi, SE_WORDSIZE*12(%xsp)
  224. mov %xbp, SE_WORDSIZE*11(%xsp)
  225. #ifdef LINUX64
  226. mov %r12, SE_WORDSIZE*10(%rsp)
  227. mov %r13, SE_WORDSIZE* 9(%rsp)
  228. mov %r14, SE_WORDSIZE* 8(%rsp)
  229. mov %r15, SE_WORDSIZE* 7(%rsp)
  230. #endif
  231. /* set xdi and xsi using the input parameters */
  232. #ifdef LINUX64
  233. mov %edi, %edi /* it should clear the high 32bit word of RDI */
  234. /*
  235. * rdi - param 1 (index), rsi - param 2 (ms)
  236. * only use lower 32bit of rdi, rsi remains unchanged.
  237. */
  238. #endif
  239. #ifdef LINUX32
  240. mov SE_WORDSIZE*20(%esp), %edi
  241. mov SE_WORDSIZE*21(%esp), %esi
  242. #endif
  243. /* save ocall index to the stack */
  244. mov $OCALL_FLAG, %xax
  245. mov %xax, SE_WORDSIZE*4(%xsp) /* save OCALL_FLAG */
  246. mov %xdi, SE_WORDSIZE*5(%xsp) /* save ocall_index */
  247. /*
  248. * save the inside stack context
  249. * push TD.last_sp
  250. * set TD.last_sp = xsp
  251. */
  252. READ_TD_DATA self_addr
  253. mov %xax, %xbx
  254. /* call update_ocall_lastsp */
  255. #ifdef LINUX32
  256. mov %xsp, (%xsp)
  257. #else
  258. mov %xsp, %xdi
  259. #endif
  260. call update_ocall_lastsp /* xax: td.last_sp */
  261. #ifdef LINUX64
  262. mov SE_WORDSIZE*12(%xsp), %xdi /* restore xdi */
  263. mov SE_WORDSIZE*13(%xsp), %xsi /* restore xdi */
  264. #endif
  265. /* restore outside stack context */
  266. mov first_ssa_gpr(%xbx), %xdx
  267. mov ssa_bp_u(%xdx), %xbp
  268. mov ssa_sp_u(%xdx), %xsp
  269. /*
  270. * set EEXIT registers
  271. * return address can be read from the ECALL frame:
  272. * TD.last_sp ->
  273. * -------------
  274. * | ret_addr |
  275. * | xbp_u |
  276. * | xsp_u |
  277. * | ... |
  278. */
  279. mov -1*SE_WORDSIZE(%xax), %xbx /* return address */
  280. mov $SE_EEXIT, %xax /* EEXIT leaf */
  281. /* Clear all GPRs, except xax, xbx, xdi, and xsi*/
  282. xor %xcx, %xcx
  283. xor %xdx, %xdx
  284. #ifdef LINUX64
  285. xor %r8, %r8
  286. xor %r9, %r9
  287. xor %r10, %r10
  288. xor %r11, %r11
  289. xor %r12, %r12
  290. xor %r13, %r13
  291. xor %r14, %r14
  292. xor %r15, %r15
  293. #endif
  294. /* Set status flags to pre-defined values */
  295. add %xdx, %xdx /* OF = SF = AF = CF = 0; ZF = PF = 1 */
  296. ENCLU
  297. /*
  298. * ------------------------------------------------------------------
  299. * this function is the wrapper of do_ocall, which is used to
  300. * stick ocall bridge and proxy frame together
  301. * ------------------------------------------------------------------
  302. */
  303. DECLARE_LOCAL_FUNC __morestack
  304. .cfi_startproc
  305. push %xbp
  306. .cfi_def_cfa_offset 2*SE_WORDSIZE
  307. .cfi_offset xbp,-2*SE_WORDSIZE
  308. mov %xsp, %xbp
  309. .cfi_def_cfa_register xbp
  310. sub $(4*SE_WORDSIZE), %xsp
  311. #ifdef LINUX32
  312. /* save the 2 parameters */
  313. mov (2*SE_WORDSIZE)(%xbp), %xax
  314. mov %xax, (0*SE_WORDSIZE)(%xsp)
  315. mov (3*SE_WORDSIZE)(%xbp), %xax
  316. mov %xax, (1*SE_WORDSIZE)(%xsp)
  317. #endif
  318. call do_ocall
  319. leave
  320. ret
  321. .cfi_endproc
  322. DECLARE_GLOBAL_FUNC asm_oret
  323. #ifdef LINUX32
  324. mov SE_WORDSIZE(%xsp), %xdi
  325. mov 2*SE_WORDSIZE(%xsp), %xsi
  326. #endif
  327. mov %xdi, %xsp /* restore thread_data.last_sp */
  328. mov %xsi, %xax /* ocall return value */
  329. #ifdef LINUX64
  330. mov 7*SE_WORDSIZE(%xsp), %r15
  331. mov 8*SE_WORDSIZE(%xsp), %r14
  332. mov 9*SE_WORDSIZE(%xsp), %r13
  333. mov 10*SE_WORDSIZE(%xsp), %r12
  334. #endif
  335. mov 11*SE_WORDSIZE(%xsp), %xbp
  336. mov 12*SE_WORDSIZE(%xsp), %xdi
  337. mov 13*SE_WORDSIZE(%xsp), %xsi
  338. mov 14*SE_WORDSIZE(%xsp), %xbx
  339. add $(19*SE_WORDSIZE), %xsp
  340. ret
  341. /* should not come here */
  342. ud2
  343. /*
  344. * ------------------------------------------------------------------------
  345. * extern "C" int do_egetkey(key_request_t *key_request, key_128bit_t *key)
  346. * return value:
  347. * 0 - success
  348. * none-zeor - EGETKEY error code
  349. * EGETKEY: rbx - the address of KEYREQUEST structure
  350. * rcx - the address where the key is outputted
  351. * ------------------------------------------------------------------------
  352. */
  353. DECLARE_LOCAL_FUNC do_egetkey
  354. SE_PROLOG
  355. mov $SE_EGETKEY, %xax /* EGETKEY leaf */
  356. ENCLU
  357. #ifdef SE_SIM
  358. cmp $SGX_SUCCESS, %xax /* In simulation mode, ZF flag will not be set */
  359. jnz .Legetkey_done /* because the stack clean operation will always clean ZF flag */
  360. #else
  361. jz .Legetkey_done /* if EGETKEY error, ZF flag is set and error code is set to xax */
  362. #endif
  363. xor %xax, %xax
  364. .Legetkey_done:
  365. SE_EPILOG
  366. ret
  367. /*
  368. * -------------------------------------------------------------------------
  369. * extern "C" void do_ereport(sgx_target_info_t *target_info, sgx_report_data_t *report_data, sgx_report_t *report);
  370. * EREPORT: rbx - the address of TARGETINFO;
  371. * rcx - the address of REPORTDATA;
  372. * rdx - the address where REPORT is outputted
  373. * -------------------------------------------------------------------------
  374. */
  375. DECLARE_LOCAL_FUNC do_ereport
  376. SE_PROLOG
  377. mov $SE_EREPORT, %xax /* EREPORT leaf */
  378. ENCLU
  379. SE_EPILOG
  380. ret
  381. #define _RDRAND_RETRY_TIMES 10
  382. /*
  383. * -------------------------------------
  384. * extern "C" uint32_t do_rdrand(uint32_t *rand);
  385. * return value:
  386. * non-zero: rdrand succeeded
  387. * zero: rdrand failed
  388. * -------------------------------------
  389. */
  390. DECLARE_LOCAL_FUNC do_rdrand
  391. mov $_RDRAND_RETRY_TIMES, %ecx
  392. .Lrdrand_retry:
  393. .byte 0x0F, 0xC7, 0xF0 /* rdrand %eax */
  394. jc .Lrdrand_return
  395. dec %ecx
  396. jnz .Lrdrand_retry
  397. xor %xax, %xax
  398. ret
  399. .Lrdrand_return:
  400. #ifdef LINUX32
  401. mov SE_WORDSIZE(%esp), %ecx
  402. #else
  403. mov %rdi, %rcx
  404. #endif
  405. movl %eax, (%xcx)
  406. mov $1, %xax
  407. ret
  408. /*
  409. * -------------------------------------------------------------------------
  410. * extern "C" void abort(void) __attribute__(__noreturn__);
  411. * -------------------------------------------------------------------------
  412. */
  413. DECLARE_LOCAL_FUNC abort
  414. lea_pic g_enclave_state, %xax
  415. movl $ENCLAVE_CRASHED, (%xax)
  416. ud2
  417. /*
  418. * -------------------------------------------------------------------------
  419. * extern "C" __attribute__((regparm(1))) void continue_execution(sgx_exception_info_t *info);
  420. * -------------------------------------------------------------------------
  421. */
  422. DECLARE_LOCAL_FUNC continue_execution
  423. #ifdef LINUX32
  424. mov %xax, %xcx
  425. #else
  426. mov %xdi, %xcx
  427. #endif
  428. mov SE_WORDSIZE*0(%xcx), %xax
  429. push %xax # push xax
  430. mov SE_WORDSIZE*1(%xcx), %xax
  431. push %xax # push xcx
  432. mov SE_WORDSIZE*4(%xcx), %xax
  433. sub $(SE_WORDSIZE), %xax # xax: xsp
  434. # restore registers except xax, xcx, xsp
  435. mov SE_WORDSIZE*2(%xcx), %xdx
  436. mov SE_WORDSIZE*3(%xcx), %xbx
  437. mov SE_WORDSIZE*5(%xcx), %xbp
  438. mov SE_WORDSIZE*6(%xcx), %xsi
  439. mov SE_WORDSIZE*7(%xcx), %xdi
  440. #ifdef LINUX64
  441. mov SE_WORDSIZE*8(%xcx), %r8
  442. mov SE_WORDSIZE*9(%xcx), %r9
  443. mov SE_WORDSIZE*10(%xcx), %r10
  444. mov SE_WORDSIZE*11(%xcx), %r11
  445. mov SE_WORDSIZE*12(%xcx), %r12
  446. mov SE_WORDSIZE*13(%xcx), %r13
  447. mov SE_WORDSIZE*14(%xcx), %r14
  448. mov SE_WORDSIZE*15(%xcx), %r15
  449. push SE_WORDSIZE*16(%xcx)
  450. popf # make sure the following instructions do not affect flags
  451. #else
  452. push SE_WORDSIZE*8(%xcx)
  453. popf
  454. #endif
  455. #ifdef LINUX64
  456. mov SE_WORDSIZE*17(%xcx), %xcx
  457. #else
  458. mov SE_WORDSIZE*9(%xcx), %xcx # xcx: xip
  459. #endif
  460. # do not setup the new stack until info is not needed any more
  461. # otherwise, info will be overwritten
  462. mov %xcx, (%xax) # save xip to the new stack
  463. pop %xcx # restore xcx
  464. pop %xsp # xsp: xax
  465. xchg %xax, %xsp
  466. ret