trts_pic.S 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522
  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. DECLARE_GLOBAL_FUNC force_exit_enclave
  172. READ_TD_DATA last_sp
  173. sub $(2*SE_WORDSIZE), %xax
  174. mov %xax, %xbp
  175. mov $SGX_ERROR_ENCLAVE_CRASHED, %xbx
  176. jmp .Lexit_enclave
  177. /*
  178. * -------------------------------------------------------------------------
  179. * sgx_status_t do_ocall(unsigned int index, void *ms);
  180. *
  181. * Function: do_ocall
  182. * The entry point of the enclave
  183. * Parameters:
  184. * func_addr - target function address
  185. * ms - marshalling structure
  186. *
  187. * Stack: (same as do_oret)
  188. * bottom of stack ->
  189. * -----------------
  190. * | ECALL/OCALL |
  191. * previous TD.last_sp -> | frames |
  192. * -----------------
  193. * | ECALL frame |
  194. * | do_ocall param 2| 21
  195. * | do_ocall param 1| 20
  196. * |do_ocall ret_addr| 19
  197. * | ocall_depth | 18
  198. * | reserved | 17
  199. * | reserved | 16
  200. * | reserved | 15
  201. * | rbx | 14
  202. * | rsi | 13
  203. * | rdi | 12
  204. * | rbp | 11
  205. * | r12 | 10
  206. * | r13 | 9
  207. * | r14 | 8
  208. * | r15 | 7
  209. * | prev TD.last_sp | 6
  210. * | ocall_index | 5
  211. * | OCALL FLAG | 4
  212. * | shadow | 3
  213. * | shadow | 2
  214. * | shadow | 1
  215. * TD.last_sp -> | shadow | 0
  216. * -----------------
  217. * -------------------------------------------------------------------------
  218. */
  219. DECLARE_LOCAL_FUNC do_ocall
  220. /*
  221. * 8 for GPR, 1 for TD.last_sp, 1 for ocall_index
  222. * 1 for OCALL_FLAG, 4 for shadow space.
  223. * Stack Pointer is 16-byte aligned under x86_64.
  224. */
  225. sub $(19*SE_WORDSIZE), %xsp
  226. /* save non-volatile registers, except xsp */
  227. mov %xbx, SE_WORDSIZE*14(%xsp)
  228. mov %xsi, SE_WORDSIZE*13(%xsp)
  229. mov %xdi, SE_WORDSIZE*12(%xsp)
  230. mov %xbp, SE_WORDSIZE*11(%xsp)
  231. #ifdef LINUX64
  232. mov %r12, SE_WORDSIZE*10(%rsp)
  233. mov %r13, SE_WORDSIZE* 9(%rsp)
  234. mov %r14, SE_WORDSIZE* 8(%rsp)
  235. mov %r15, SE_WORDSIZE* 7(%rsp)
  236. #endif
  237. /* set xdi and xsi using the input parameters */
  238. #ifdef LINUX64
  239. mov %edi, %edi /* it should clear the high 32bit word of RDI */
  240. /*
  241. * rdi - param 1 (index), rsi - param 2 (ms)
  242. * only use lower 32bit of rdi, rsi remains unchanged.
  243. */
  244. #endif
  245. #ifdef LINUX32
  246. mov SE_WORDSIZE*20(%esp), %edi
  247. mov SE_WORDSIZE*21(%esp), %esi
  248. #endif
  249. /* save ocall index to the stack */
  250. mov $OCALL_FLAG, %xax
  251. mov %xax, SE_WORDSIZE*4(%xsp) /* save OCALL_FLAG */
  252. mov %xdi, SE_WORDSIZE*5(%xsp) /* save ocall_index */
  253. /*
  254. * save the inside stack context
  255. * push TD.last_sp
  256. * set TD.last_sp = xsp
  257. */
  258. READ_TD_DATA self_addr
  259. mov %xax, %xbx
  260. /* call update_ocall_lastsp */
  261. #ifdef LINUX32
  262. mov %xsp, (%xsp)
  263. #else
  264. mov %xsp, %xdi
  265. #endif
  266. call update_ocall_lastsp /* xax: td.last_sp */
  267. #ifdef LINUX64
  268. mov SE_WORDSIZE*12(%xsp), %xdi /* restore xdi */
  269. mov SE_WORDSIZE*13(%xsp), %xsi /* restore xdi */
  270. #endif
  271. /* restore outside stack context */
  272. mov first_ssa_gpr(%xbx), %xdx
  273. mov ssa_bp_u(%xdx), %xbp
  274. mov ssa_sp_u(%xdx), %xsp
  275. /*
  276. * set EEXIT registers
  277. * return address can be read from the ECALL frame:
  278. * TD.last_sp ->
  279. * -------------
  280. * | ret_addr |
  281. * | xbp_u |
  282. * | xsp_u |
  283. * | ... |
  284. */
  285. mov -1*SE_WORDSIZE(%xax), %xbx /* return address */
  286. mov $SE_EEXIT, %xax /* EEXIT leaf */
  287. /* Clear all GPRs, except xax, xbx, xdi, and xsi*/
  288. xor %xcx, %xcx
  289. xor %xdx, %xdx
  290. #ifdef LINUX64
  291. xor %r8, %r8
  292. xor %r9, %r9
  293. xor %r10, %r10
  294. xor %r11, %r11
  295. xor %r12, %r12
  296. xor %r13, %r13
  297. xor %r14, %r14
  298. xor %r15, %r15
  299. #endif
  300. /* Set status flags to pre-defined values */
  301. add %xdx, %xdx /* OF = SF = AF = CF = 0; ZF = PF = 1 */
  302. ENCLU
  303. /*
  304. * ------------------------------------------------------------------
  305. * this function is the wrapper of do_ocall, which is used to
  306. * stick ocall bridge and proxy frame together
  307. * ------------------------------------------------------------------
  308. */
  309. DECLARE_LOCAL_FUNC __morestack
  310. .cfi_startproc
  311. push %xbp
  312. .cfi_def_cfa_offset 2*SE_WORDSIZE
  313. .cfi_offset xbp,-2*SE_WORDSIZE
  314. mov %xsp, %xbp
  315. .cfi_def_cfa_register xbp
  316. sub $(4*SE_WORDSIZE), %xsp
  317. #ifdef LINUX32
  318. /* save the 2 parameters */
  319. mov (2*SE_WORDSIZE)(%xbp), %xax
  320. mov %xax, (0*SE_WORDSIZE)(%xsp)
  321. mov (3*SE_WORDSIZE)(%xbp), %xax
  322. mov %xax, (1*SE_WORDSIZE)(%xsp)
  323. #endif
  324. call do_ocall
  325. leave
  326. ret
  327. .cfi_endproc
  328. DECLARE_GLOBAL_FUNC asm_oret
  329. #ifdef LINUX32
  330. mov SE_WORDSIZE(%xsp), %xdi
  331. mov 2*SE_WORDSIZE(%xsp), %xsi
  332. #endif
  333. mov %xdi, %xsp /* restore thread_data.last_sp */
  334. mov %xsi, %xax /* ocall return value */
  335. #ifdef LINUX64
  336. mov 7*SE_WORDSIZE(%xsp), %r15
  337. mov 8*SE_WORDSIZE(%xsp), %r14
  338. mov 9*SE_WORDSIZE(%xsp), %r13
  339. mov 10*SE_WORDSIZE(%xsp), %r12
  340. #endif
  341. mov 11*SE_WORDSIZE(%xsp), %xbp
  342. mov 12*SE_WORDSIZE(%xsp), %xdi
  343. mov 13*SE_WORDSIZE(%xsp), %xsi
  344. mov 14*SE_WORDSIZE(%xsp), %xbx
  345. add $(19*SE_WORDSIZE), %xsp
  346. ret
  347. /* should not come here */
  348. ud2
  349. /*
  350. * ------------------------------------------------------------------------
  351. * extern "C" int do_egetkey(key_request_t *key_request, key_128bit_t *key)
  352. * return value:
  353. * 0 - success
  354. * none-zeor - EGETKEY error code
  355. * EGETKEY: rbx - the address of KEYREQUEST structure
  356. * rcx - the address where the key is outputted
  357. * ------------------------------------------------------------------------
  358. */
  359. DECLARE_LOCAL_FUNC do_egetkey
  360. SE_PROLOG
  361. mov $SE_EGETKEY, %xax /* EGETKEY leaf */
  362. ENCLU
  363. #ifdef SE_SIM
  364. cmp $SGX_SUCCESS, %xax /* In simulation mode, ZF flag will not be set */
  365. jnz .Legetkey_done /* because the stack clean operation will always clean ZF flag */
  366. #else
  367. jz .Legetkey_done /* if EGETKEY error, ZF flag is set and error code is set to xax */
  368. #endif
  369. xor %xax, %xax
  370. .Legetkey_done:
  371. SE_EPILOG
  372. ret
  373. /*
  374. * -------------------------------------------------------------------------
  375. * extern "C" void do_ereport(sgx_target_info_t *target_info, sgx_report_data_t *report_data, sgx_report_t *report);
  376. * EREPORT: rbx - the address of TARGETINFO;
  377. * rcx - the address of REPORTDATA;
  378. * rdx - the address where REPORT is outputted
  379. * -------------------------------------------------------------------------
  380. */
  381. DECLARE_LOCAL_FUNC do_ereport
  382. SE_PROLOG
  383. mov $SE_EREPORT, %xax /* EREPORT leaf */
  384. ENCLU
  385. SE_EPILOG
  386. ret
  387. #define _RDRAND_RETRY_TIMES 10
  388. /*
  389. * -------------------------------------
  390. * extern "C" uint32_t do_rdrand(uint32_t *rand);
  391. * return value:
  392. * non-zero: rdrand succeeded
  393. * zero: rdrand failed
  394. * -------------------------------------
  395. */
  396. DECLARE_LOCAL_FUNC do_rdrand
  397. mov $_RDRAND_RETRY_TIMES, %ecx
  398. .Lrdrand_retry:
  399. .byte 0x0F, 0xC7, 0xF0 /* rdrand %eax */
  400. jc .Lrdrand_return
  401. dec %ecx
  402. jnz .Lrdrand_retry
  403. xor %xax, %xax
  404. ret
  405. .Lrdrand_return:
  406. #ifdef LINUX32
  407. mov SE_WORDSIZE(%esp), %ecx
  408. #else
  409. mov %rdi, %rcx
  410. #endif
  411. movl %eax, (%xcx)
  412. mov $1, %xax
  413. ret
  414. /*
  415. * -------------------------------------------------------------------------
  416. * extern "C" void abort(void) __attribute__(__noreturn__);
  417. * -------------------------------------------------------------------------
  418. */
  419. DECLARE_LOCAL_FUNC abort
  420. lea_pic g_enclave_state, %xax
  421. movl $ENCLAVE_CRASHED, (%xax)
  422. ud2
  423. /*
  424. * -------------------------------------------------------------------------
  425. * extern "C" __attribute__((regparm(1))) void continue_execution(sgx_exception_info_t *info);
  426. * -------------------------------------------------------------------------
  427. */
  428. DECLARE_LOCAL_FUNC continue_execution
  429. #ifdef LINUX32
  430. mov %xax, %xcx
  431. #else
  432. mov %xdi, %xcx
  433. #endif
  434. mov SE_WORDSIZE*0(%xcx), %xax
  435. push %xax # push xax
  436. mov SE_WORDSIZE*1(%xcx), %xax
  437. push %xax # push xcx
  438. mov SE_WORDSIZE*4(%xcx), %xax
  439. sub $(SE_WORDSIZE), %xax # xax: xsp
  440. # restore registers except xax, xcx, xsp
  441. mov SE_WORDSIZE*2(%xcx), %xdx
  442. mov SE_WORDSIZE*3(%xcx), %xbx
  443. mov SE_WORDSIZE*5(%xcx), %xbp
  444. mov SE_WORDSIZE*6(%xcx), %xsi
  445. mov SE_WORDSIZE*7(%xcx), %xdi
  446. #ifdef LINUX64
  447. mov SE_WORDSIZE*8(%xcx), %r8
  448. mov SE_WORDSIZE*9(%xcx), %r9
  449. mov SE_WORDSIZE*10(%xcx), %r10
  450. mov SE_WORDSIZE*11(%xcx), %r11
  451. mov SE_WORDSIZE*12(%xcx), %r12
  452. mov SE_WORDSIZE*13(%xcx), %r13
  453. mov SE_WORDSIZE*14(%xcx), %r14
  454. mov SE_WORDSIZE*15(%xcx), %r15
  455. push SE_WORDSIZE*16(%xcx)
  456. popf # make sure the following instructions do not affect flags
  457. #else
  458. push SE_WORDSIZE*8(%xcx)
  459. popf
  460. #endif
  461. #ifdef LINUX64
  462. mov SE_WORDSIZE*17(%xcx), %xcx
  463. #else
  464. mov SE_WORDSIZE*9(%xcx), %xcx # xcx: xip
  465. #endif
  466. # do not setup the new stack until info is not needed any more
  467. # otherwise, info will be overwritten
  468. mov %xcx, (%xax) # save xip to the new stack
  469. pop %xcx # restore xcx
  470. pop %xsp # xsp: xax
  471. xchg %xax, %xsp
  472. ret