trts_pic.S 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611
  1. /*
  2. * Copyright (C) 2011-2018 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. .section .nipx,"ax",@progbits
  40. DECLARE_LOCAL_FUNC get_enclave_base
  41. lea_pic __ImageBase, %xax
  42. ret
  43. DECLARE_LOCAL_FUNC get_enclave_state
  44. lea_pic g_enclave_state, %xcx
  45. xor %xax, %xax
  46. movl (%xcx), %eax
  47. ret
  48. DECLARE_LOCAL_FUNC set_enclave_state
  49. lea_pic g_enclave_state, %xax
  50. #ifdef LINUX32
  51. mov SE_WORDSIZE(%esp), %edi
  52. #endif
  53. movl %edi, (%xax)
  54. ret
  55. DECLARE_LOCAL_FUNC lock_enclave
  56. lea_pic g_enclave_state, %xdx
  57. xor %xax, %xax
  58. mov $ENCLAVE_INIT_NOT_STARTED, %eax
  59. xor %xcx, %xcx
  60. mov $ENCLAVE_INIT_IN_PROGRESS, %ecx /* if (g_global_data.enclave_state == ENCLAVE_INIT_NOT_STARTED) */
  61. lock cmpxchgl %ecx, (%xdx) /* g_global_data.enclave_state == ENCLAVE_INIT_IN_PROGRESS */
  62. ret /* xax: the initial value of enclave state */
  63. /*
  64. * ---------------------------------------------------------------------
  65. * Function: thread_data_t* get_thread_data(void);
  66. *
  67. * Get the address of thread_data
  68. * ---------------------------------------------------------------------
  69. */
  70. DECLARE_LOCAL_FUNC get_thread_data
  71. READ_TD_DATA self_addr
  72. ret
  73. /*
  74. * ---------------------------------------------------------------------
  75. * Function: sys_word_t get_stack_guard(void);
  76. *
  77. * Get the value of stack_guard
  78. * ---------------------------------------------------------------------
  79. */
  80. DECLARE_LOCAL_FUNC get_stack_guard
  81. READ_TD_DATA stack_guard
  82. ret
  83. /*
  84. * ---------------------------------------------------------------------
  85. * Function: enclave_entry
  86. * The entry point of the enclave.
  87. *
  88. * Registers:
  89. * XAX - TCS.CSSA
  90. * XBX - the address of a TCS
  91. * XCX - the address of the instruction following the EENTER
  92. * XDI - the reason of entering the enclave
  93. * XSI - the pointer to the marshalling structure
  94. */
  95. DECLARE_GLOBAL_FUNC enclave_entry
  96. /*
  97. * ----------------------------------------------------------------------
  98. * Dispatch code according to CSSA and the reason of EENTER
  99. * eax > 0 - exception handler
  100. * edi >= 0 - ecall
  101. * edi == -1 - do_init_enclave
  102. * edi == -2 - oret
  103. * Registers
  104. * No need to use any register during the dipatch
  105. * ----------------------------------------------------------------------
  106. */
  107. .cfi_startproc
  108. /* Clear unused general registers */
  109. xor %xdx, %xdx
  110. add %xdx, %xdx /* OF = SF = AF = CF = 0; ZF = PF = 1 */
  111. #if defined(LINUX64)
  112. xor %r8, %r8
  113. xor %r9, %r9
  114. xor %r10, %r10
  115. xor %r11, %r11
  116. xor %r12, %r12
  117. xor %r13, %r13
  118. xor %r14, %r14
  119. xor %r15, %r15
  120. #endif
  121. /* switch to trusted stack */
  122. cmp $0, %xax
  123. jne .Ldo_handler /* handle exception state */
  124. /* xor %xdx, %xdx xdx is cssa, make sure it is 0 */
  125. READ_TD_DATA last_sp
  126. cmp $0, %xax
  127. jne .Lswitch_stack
  128. GET_STACK_BASE %xbx /* if last_sp == 0, set sp to stack base */
  129. sub $STATIC_STACK_SIZE, %xax /* give space for static stack */
  130. .Lswitch_stack:
  131. xchg %xsp, %xax
  132. push %xcx
  133. push %xbp
  134. .cfi_def_cfa_offset 2 * SE_WORDSIZE
  135. .cfi_offset xbp, -2 * SE_WORDSIZE
  136. mov %xsp, %xbp
  137. .cfi_def_cfa_register xbp
  138. /* Save the registers */
  139. sub $(6*SE_WORDSIZE), %xsp
  140. mov %xax, -1*SE_WORDSIZE(%xbp) /* xsp_u */
  141. mov %xdx, -3*SE_WORDSIZE(%xbp) /* cssa */
  142. mov %xbx, -4*SE_WORDSIZE(%xbp) /* TCS */
  143. mov %xsi, -5*SE_WORDSIZE(%xbp) /* XSI */
  144. mov %xdi, -6*SE_WORDSIZE(%xbp) /* XDI */
  145. #ifdef LINUX64
  146. mov %rdx, %rcx
  147. mov %rbx, %rdx
  148. #endif
  149. call enter_enclave
  150. mov %xax, %xbx
  151. .Lexit_enclave:
  152. /* clean extended feature registers */
  153. lea_pic SYNTHETIC_STATE, %xdi
  154. #ifdef LINUX32
  155. mov %xdi, (%xsp)
  156. #endif
  157. call restore_xregs
  158. /* set xdi and xsi */
  159. mov $OCMD_ERET, %xdi
  160. mov %xbx, %xsi
  161. /* restore stack */
  162. mov -1*SE_WORDSIZE(%xbp), %xdx /* xdx: xsp_u */
  163. mov %xbp, %xsp
  164. pop %xbp /* xbp_u */
  165. pop %xbx /* ret_u */
  166. mov %xdx, %xsp /* xsp_u */
  167. .Lclear_and_exit_enclave:
  168. /* Clear all GPRs, except xax, xbx, xdi and xsi */
  169. xor %xcx, %xcx
  170. xor %xdx, %xdx
  171. #if defined(LINUX64)
  172. xor %r8, %r8
  173. xor %r9, %r9
  174. xor %r10, %r10
  175. xor %r11, %r11
  176. xor %r12, %r12
  177. xor %r13, %r13
  178. xor %r14, %r14
  179. xor %r15, %r15
  180. #endif
  181. /* Set status flags to pre-defined values */
  182. add %xdx, %xdx /* OF = SF = AF = CF = 0; ZF = PF = 1 */
  183. /* EEXIT */
  184. mov $SE_EEXIT, %xax /* EEXIT leaf */
  185. ENCLU
  186. /* Should not come here */
  187. ud2
  188. .Ldo_handler:
  189. mov %xax, %xdx /* XDX: cssa */
  190. GET_STACK_BASE %xbx /* XAX: static stack, set sp to stack base */
  191. jmp .Lswitch_stack
  192. /* Should not come here */
  193. ud2
  194. .cfi_endproc
  195. /*
  196. * -------------------------------------------------------------------------
  197. * sgx_status_t do_ocall(unsigned int index, void *ms);
  198. *
  199. * Function: do_ocall
  200. * The entry point of the enclave
  201. * Parameters:
  202. * func_addr - target function address
  203. * ms - marshalling structure
  204. *
  205. * Stack: (same as do_oret)
  206. * bottom of stack ->
  207. * -----------------
  208. * | ECALL/OCALL |
  209. * previous TD.last_sp -> | frames |
  210. * -----------------
  211. * | ECALL frame |
  212. * | do_ocall param 2| 3
  213. * | do_ocall param 1| 2
  214. * |do_ocall ret_addr| 1
  215. * | xbp | 0 + xbp
  216. * | .... |
  217. * | xsave buffer |
  218. * | .... |
  219. * | xsave pointer | 19
  220. * | ocall_depth | 18
  221. * | reserved | 17
  222. * | reserved | 16
  223. * | reserved | 15
  224. * | rbx | 14
  225. * | rsi | 13
  226. * | rdi | 12
  227. * | rbp | 11
  228. * | r12 | 10
  229. * | r13 | 9
  230. * | r14 | 8
  231. * | r15 | 7
  232. * | prev TD.last_sp | 6
  233. * | ocall_index | 5
  234. * | OCALL FLAG | 4
  235. * | shadow | 3
  236. * | shadow | 2
  237. * | shadow | 1
  238. * TD.last_sp -> | shadow | 0 + xsp
  239. * -----------------
  240. * -------------------------------------------------------------------------
  241. */
  242. DECLARE_LOCAL_FUNC do_ocall
  243. /*
  244. * 8 for GPR, 1 for TD.last_sp, 1 for ocall_index
  245. * 1 for OCALL_FLAG, 4 for shadow space.
  246. * Stack Pointer is 16-byte aligned under x86_64.
  247. */
  248. push %xbp
  249. mov %xsp, %xbp
  250. /* save parameters in stack */
  251. #ifdef LINUX64
  252. mov %xdi, 2*SE_WORDSIZE(%xbp)
  253. mov %xsi, 3*SE_WORDSIZE(%xbp)
  254. #endif
  255. /* save and clean extended feature registers */
  256. READ_TD_DATA xsave_size
  257. sub %xax, %xsp /* allocate buffer to save xregs */
  258. mov $0x3f, %xax
  259. not %xax
  260. and %xax, %xsp /* xsave requires 64 byte aligned */
  261. mov %xsp, %xcx # xsave pointer
  262. sub $(20*SE_WORDSIZE), %xsp /* 20 slots for GPRs and other info */
  263. mov %xcx, SE_WORDSIZE*19(%xsp) /* addr for xsave */
  264. /* save non-volatile registers, except xsp */
  265. mov %xbx, SE_WORDSIZE*14(%xsp)
  266. mov %xsi, SE_WORDSIZE*13(%xsp)
  267. mov %xdi, SE_WORDSIZE*12(%xsp)
  268. mov %xbp, SE_WORDSIZE*11(%xsp)
  269. #ifdef LINUX64
  270. mov %r12, SE_WORDSIZE*10(%rsp)
  271. mov %r13, SE_WORDSIZE* 9(%rsp)
  272. mov %r14, SE_WORDSIZE* 8(%rsp)
  273. mov %r15, SE_WORDSIZE* 7(%rsp)
  274. #endif
  275. /* save and clean extended feature registers */
  276. mov SE_WORDSIZE*19(%xsp), %xdi /* xsave pointer */
  277. READ_TD_DATA xsave_size
  278. mov %xax, %xcx
  279. shr $2, %xcx /* xsave size in dword */
  280. xor %xax, %xax
  281. cld
  282. rep stos %eax, %es:(%xdi)
  283. mov SE_WORDSIZE*19(%xsp), %xdi # xsave pointer
  284. mov %xdi, (%xsp)
  285. call save_xregs
  286. lea_pic SYNTHETIC_STATE, %xdi
  287. mov %xdi, (%xsp)
  288. call restore_xregs
  289. /* set xdi and xsi using the input parameters */
  290. #ifdef LINUX64
  291. mov SE_WORDSIZE*12(%xsp), %xdi
  292. mov SE_WORDSIZE*13(%xsp), %xsi
  293. #else
  294. mov SE_WORDSIZE*2(%ebp), %edi
  295. mov SE_WORDSIZE*3(%ebp), %esi
  296. #endif
  297. /* save ocall index to the stack */
  298. mov $OCALL_FLAG, %xax
  299. mov %xax, SE_WORDSIZE*4(%xsp) /* save OCALL_FLAG */
  300. mov %xdi, SE_WORDSIZE*5(%xsp) /* save ocall_index */
  301. /*
  302. * save the inside stack context
  303. * push TD.last_sp
  304. * set TD.last_sp = xsp
  305. */
  306. READ_TD_DATA self_addr
  307. mov %xax, %xbx
  308. /* call update_ocall_lastsp */
  309. #ifdef LINUX32
  310. mov %xsp, (%xsp)
  311. #else
  312. mov %xsp, %xdi
  313. #endif
  314. call update_ocall_lastsp /* xax: td.last_sp */
  315. #ifdef LINUX64
  316. mov SE_WORDSIZE*12(%xsp), %xdi /* restore xdi */
  317. mov SE_WORDSIZE*13(%xsp), %xsi /* restore xdi */
  318. #endif
  319. /* restore outside stack context */
  320. mov first_ssa_gpr(%xbx), %xdx
  321. mov ssa_bp_u(%xdx), %xbp
  322. mov ssa_sp_u(%xdx), %xsp
  323. /*
  324. * set EEXIT registers
  325. * return address can be read from the ECALL frame:
  326. * TD.last_sp ->
  327. * -------------
  328. * | ret_addr |
  329. * | xbp_u |
  330. * | xsp_u |
  331. * | ... |
  332. */
  333. mov -1*SE_WORDSIZE(%xax), %xbx /* return address */
  334. mov $SE_EEXIT, %xax /* EEXIT leaf */
  335. /* Clear all GPRs, except xax, xbx, xdi, and xsi*/
  336. xor %xcx, %xcx
  337. xor %xdx, %xdx
  338. #ifdef LINUX64
  339. xor %r8, %r8
  340. xor %r9, %r9
  341. xor %r10, %r10
  342. xor %r11, %r11
  343. xor %r12, %r12
  344. xor %r13, %r13
  345. xor %r14, %r14
  346. xor %r15, %r15
  347. #endif
  348. /* Set status flags to pre-defined values */
  349. add %xdx, %xdx /* OF = SF = AF = CF = 0; ZF = PF = 1 */
  350. ENCLU
  351. /*
  352. * ------------------------------------------------------------------
  353. * this function is the wrapper of do_ocall, which is used to
  354. * stick ocall bridge and proxy frame together
  355. * ------------------------------------------------------------------
  356. */
  357. DECLARE_LOCAL_FUNC __morestack
  358. .cfi_startproc
  359. push %xbp
  360. .cfi_def_cfa_offset 2*SE_WORDSIZE
  361. .cfi_offset xbp,-2*SE_WORDSIZE
  362. mov %xsp, %xbp
  363. .cfi_def_cfa_register xbp
  364. sub $(4*SE_WORDSIZE), %xsp
  365. #ifdef LINUX32
  366. /* save the 2 parameters */
  367. mov (2*SE_WORDSIZE)(%xbp), %xax
  368. mov %xax, (0*SE_WORDSIZE)(%xsp)
  369. mov (3*SE_WORDSIZE)(%xbp), %xax
  370. mov %xax, (1*SE_WORDSIZE)(%xsp)
  371. #endif
  372. call do_ocall
  373. leave
  374. ret
  375. .cfi_endproc
  376. DECLARE_GLOBAL_FUNC asm_oret
  377. mov %xsp, %xbx
  378. #ifdef LINUX64
  379. mov %xdi, SE_WORDSIZE(%xsp)
  380. mov %xsi, 2*SE_WORDSIZE(%xsp)
  381. #endif
  382. mov SE_WORDSIZE(%xbx), %xsp /* restore thread_data.last_sp */
  383. /* restore extended feature registers */
  384. mov 19*SE_WORDSIZE(%xsp), %xdi
  385. #ifdef LINUX32
  386. mov %xdi, (%xsp)
  387. #endif
  388. call restore_xregs
  389. /* memset_s */
  390. xor %xax, %xax
  391. mov 11*SE_WORDSIZE(%xsp), %xcx
  392. sub %xdi, %xcx
  393. sub $SE_WORDSIZE, %xcx
  394. shr $2, %xcx
  395. cld
  396. rep stos %eax,%es:(%xdi)
  397. mov 2*SE_WORDSIZE(%xbx), %xax /* ocall return value */
  398. #ifdef LINUX64
  399. mov 7*SE_WORDSIZE(%xsp), %r15
  400. mov 8*SE_WORDSIZE(%xsp), %r14
  401. mov 9*SE_WORDSIZE(%xsp), %r13
  402. mov 10*SE_WORDSIZE(%xsp), %r12
  403. #endif
  404. mov 11*SE_WORDSIZE(%xsp), %xbp
  405. mov 12*SE_WORDSIZE(%xsp), %xdi
  406. mov 13*SE_WORDSIZE(%xsp), %xsi
  407. mov 14*SE_WORDSIZE(%xsp), %xbx
  408. mov %xbp, %xsp
  409. pop %xbp
  410. ret
  411. /* should not come here */
  412. ud2
  413. /*
  414. * ------------------------------------------------------------------------
  415. * extern "C" int do_egetkey(key_request_t *key_request, key_128bit_t *key)
  416. * return value:
  417. * 0 - success
  418. * none-zeor - EGETKEY error code
  419. * EGETKEY: rbx - the address of KEYREQUEST structure
  420. * rcx - the address where the key is outputted
  421. * ------------------------------------------------------------------------
  422. */
  423. DECLARE_LOCAL_FUNC do_egetkey
  424. SE_PROLOG
  425. mov $SE_EGETKEY, %xax /* EGETKEY leaf */
  426. ENCLU
  427. #ifdef SE_SIM
  428. cmp $SGX_SUCCESS, %xax /* In simulation mode, ZF flag will not be set */
  429. jnz .Legetkey_done /* because the stack clean operation will always clean ZF flag */
  430. #else
  431. jz .Legetkey_done /* if EGETKEY error, ZF flag is set and error code is set to xax */
  432. #endif
  433. xor %xax, %xax
  434. .Legetkey_done:
  435. SE_EPILOG
  436. /*
  437. * -------------------------------------------------------------------------
  438. * extern "C" void do_ereport(sgx_target_info_t *target_info, sgx_report_data_t *report_data, sgx_report_t *report);
  439. * EREPORT: rbx - the address of TARGETINFO;
  440. * rcx - the address of REPORTDATA;
  441. * rdx - the address where REPORT is outputted
  442. * -------------------------------------------------------------------------
  443. */
  444. DECLARE_LOCAL_FUNC do_ereport
  445. SE_PROLOG
  446. mov $SE_EREPORT, %xax /* EREPORT leaf */
  447. ENCLU
  448. SE_EPILOG
  449. DECLARE_GLOBAL_FUNC do_eaccept
  450. SE_PROLOG
  451. mov $SE_EACCEPT, %eax
  452. ENCLU
  453. cmp $SGX_SUCCESS, %eax
  454. jnz abort
  455. SE_EPILOG
  456. DECLARE_GLOBAL_FUNC do_emodpe
  457. SE_PROLOG
  458. mov $SE_EMODPE, %eax
  459. ENCLU
  460. SE_EPILOG
  461. #define _RDRAND_RETRY_TIMES 10
  462. /*
  463. * -------------------------------------
  464. * extern "C" uint32_t do_rdrand(uint32_t *rand);
  465. * return value:
  466. * non-zero: rdrand succeeded
  467. * zero: rdrand failed
  468. * -------------------------------------
  469. */
  470. DECLARE_LOCAL_FUNC do_rdrand
  471. mov $_RDRAND_RETRY_TIMES, %ecx
  472. .Lrdrand_retry:
  473. .byte 0x0F, 0xC7, 0xF0 /* rdrand %eax */
  474. jc .Lrdrand_return
  475. dec %ecx
  476. jnz .Lrdrand_retry
  477. xor %xax, %xax
  478. ret
  479. .Lrdrand_return:
  480. #ifdef LINUX32
  481. mov SE_WORDSIZE(%esp), %ecx
  482. #else
  483. mov %rdi, %rcx
  484. #endif
  485. movl %eax, (%xcx)
  486. mov $1, %xax
  487. ret
  488. /*
  489. * -------------------------------------------------------------------------
  490. * extern "C" void abort(void) __attribute__(__noreturn__);
  491. * -------------------------------------------------------------------------
  492. */
  493. DECLARE_LOCAL_FUNC abort
  494. lea_pic g_enclave_state, %xax
  495. movl $ENCLAVE_CRASHED, (%xax)
  496. ud2
  497. /*
  498. * -------------------------------------------------------------------------
  499. * extern "C" __attribute__((regparm(1))) void continue_execution(sgx_exception_info_t *info);
  500. * -------------------------------------------------------------------------
  501. */
  502. DECLARE_LOCAL_FUNC continue_execution
  503. #ifdef LINUX32
  504. mov %xax, %xcx
  505. #else
  506. mov %xdi, %xcx
  507. #endif
  508. mov SE_WORDSIZE*0(%xcx), %xax
  509. push %xax /* push xax */
  510. mov SE_WORDSIZE*1(%xcx), %xax
  511. push %xax /* push xcx */
  512. mov SE_WORDSIZE*4(%xcx), %xax /* xax: xsp */
  513. /* x86_64 requires a 128-bytes red zone. We need to allocate buffer to avoid touching the red zone. */
  514. sub $(SE_WORDSIZE + RED_ZONE_SIZE), %xax /* allocate buffer to skip red zone and save xip */
  515. /* restore registers except xax, xcx, xsp */
  516. mov SE_WORDSIZE*2(%xcx), %xdx
  517. mov SE_WORDSIZE*3(%xcx), %xbx
  518. mov SE_WORDSIZE*5(%xcx), %xbp
  519. mov SE_WORDSIZE*6(%xcx), %xsi
  520. mov SE_WORDSIZE*7(%xcx), %xdi
  521. #ifdef LINUX64
  522. mov SE_WORDSIZE*8(%xcx), %r8
  523. mov SE_WORDSIZE*9(%xcx), %r9
  524. mov SE_WORDSIZE*10(%xcx), %r10
  525. mov SE_WORDSIZE*11(%xcx), %r11
  526. mov SE_WORDSIZE*12(%xcx), %r12
  527. mov SE_WORDSIZE*13(%xcx), %r13
  528. mov SE_WORDSIZE*14(%xcx), %r14
  529. mov SE_WORDSIZE*15(%xcx), %r15
  530. push SE_WORDSIZE*16(%xcx)
  531. popf /* make sure the following instructions do not affect flags */
  532. #else
  533. push SE_WORDSIZE*8(%xcx)
  534. popf
  535. #endif
  536. #ifdef LINUX64
  537. mov SE_WORDSIZE*17(%xcx), %xcx
  538. #else
  539. mov SE_WORDSIZE*9(%xcx), %xcx /* xcx: xip */
  540. #endif
  541. /* do not setup the new stack until info is not needed any more
  542. * otherwise, info will be overwritten
  543. */
  544. mov %xcx, (%xax) /* save xip to the new stack */
  545. pop %xcx /* restore xcx */
  546. pop %xsp /* xsp: xax */
  547. xchg %xax, %xsp
  548. ret $(RED_ZONE_SIZE) /* pop xip and red zone (if any) */