makecontext.c 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184
  1. /* Copyright (C) 2018 - 2022 Free Software Foundation, Inc.
  2. This file is part of the GNU C Library.
  3. The GNU C Library is free software; you can redistribute it and/or
  4. modify it under the terms of the GNU Lesser General Public
  5. License as published by the Free Software Foundation; either
  6. version 2.1 of the License, or (at your option) any later version.
  7. The GNU C Library is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  10. Lesser General Public License for more details.
  11. You should have received a copy of the GNU Lesser General Public
  12. License along with the GNU C Library; if not, see
  13. <http://www.gnu.org/licenses/>. */
  14. #include <sysdep.h>
  15. #include <stdarg.h>
  16. #include <stdint.h>
  17. #include <string.h>
  18. #include <ucontext.h>
  19. extern void __start_context (void);
  20. #if defined(__XTENSA_CALL0_ABI__)
  21. /*
  22. * makecontext sets up new stack like this:
  23. *
  24. * +------------------ stack top (uc_stack.ss_sp + uc_stack.ss_size)
  25. * | optional alignment
  26. * +------------------ CFA of __start_context, initial sp points here
  27. * | optional padding
  28. * +------------------ Optional arguments 6..argc - 1
  29. * | func arg argc - 1
  30. * | func arg argc - 2
  31. * | ...
  32. * | func arg 6
  33. * +------------------ Optional arguments 2..5
  34. * | func arg 5
  35. * 16 | func arg 4
  36. * | func arg 3
  37. * | func arg 2
  38. * +------------------ Optional arguments 0..1
  39. * | func arg 1
  40. * 16 | func arg 0
  41. * | padding
  42. * | padding
  43. * +------------------ CFA of pseudo getcontext
  44. * |
  45. * +------------------ stack bottom (uc_stack.ss_sp)
  46. *
  47. * When argc is 0 arguments areas are not allocated,
  48. * when 1 <= argc < 3 only area for arguments 0..1 is allocated,
  49. * when 3 <= argc < 7 areas for arguments 0..1 and 2..5 is allocated,
  50. * when argc >= 7 all three arguments areas are allocated.
  51. * Arguments 0..5 area is deallocated by the __start_context after
  52. * arguments are loaded into registers.
  53. * uc_mcontext registers are set as if __start_context made call0
  54. * to getcontext, sp points to that pseudo getcontext CFA.
  55. * setcontext/swapcontext will arrange for restoring regiters
  56. * a1, a12..a15 of __start_context.
  57. */
  58. void
  59. __makecontext (ucontext_t *ucp, void (*func) (void), int argc, ...)
  60. {
  61. unsigned long sp = ((unsigned long) ucp->uc_stack.ss_sp
  62. + ucp->uc_stack.ss_size) & -16;
  63. int i;
  64. if (argc > 0)
  65. sp -= 4 * (argc + 2);
  66. sp &= -16;
  67. #ifdef __FDPIC__
  68. ucp->uc_mcontext.sc_pc = ((unsigned long *) __start_context)[0];
  69. ucp->uc_mcontext.sc_a[15] = ((unsigned long *) __start_context)[1];
  70. #else
  71. ucp->uc_mcontext.sc_pc = (unsigned long) __start_context;
  72. #endif
  73. ucp->uc_mcontext.sc_a[1] = sp;
  74. ucp->uc_mcontext.sc_a[12] = (unsigned long) func;
  75. ucp->uc_mcontext.sc_a[13] = (unsigned long) ucp->uc_link;
  76. ucp->uc_mcontext.sc_a[14] = argc;
  77. if (argc)
  78. {
  79. va_list ap;
  80. va_start (ap, argc);
  81. for (i = 0; i < argc; ++i)
  82. ((int *) sp)[i + 2] = va_arg (ap, int);
  83. va_end (ap);
  84. }
  85. }
  86. #elif defined(__XTENSA_WINDOWED_ABI__)
  87. /*
  88. * makecontext sets up new stack like this:
  89. *
  90. * +------------------ stack top (uc_stack.ss_sp + uc_stack.ss_size)
  91. * | optional alignment
  92. * +------------------ CFA of __start_context
  93. * 16 | Outermost caller spill area
  94. * +------------------
  95. * 16 | __start_context overflow area
  96. * +------------------ initial sp points here
  97. * | optional padding
  98. * +------------------ Optional arguments 6..argc - 1
  99. * | func arg argc - 1
  100. * | func arg argc - 2
  101. * | ...
  102. * | func arg 6
  103. * +------------------ Optional arguments 3..5
  104. * | func arg 5
  105. * 16 | func arg 4
  106. * | func arg 3
  107. * | padding
  108. * +------------------ CFA of pseudo getcontext
  109. * 16 | __start_context caller spill area
  110. * +------------------
  111. * |
  112. * +------------------ stack bottom (uc_stack.ss_sp)
  113. *
  114. * When argc < 4 both arguments areas are not allocated,
  115. * when 4 <= argc < 7 only area for arguments 3..5 is allocated,
  116. * when argc >= 7 both arguments areas are allocated.
  117. * Arguments 3..5 area is deallocated by the __start_context after
  118. * arguments are loaded into registers.
  119. * uc_mcontext registers are set as if __start_context made call8
  120. * to getcontext, sp points to that pseudo getcontext CFA, spill
  121. * area under that sp has a1 pointing to the __start_context CFA
  122. * at the top of the stack. setcontext/swapcontext will arrange for
  123. * restoring regiters a0..a7 of __start_context.
  124. */
  125. void
  126. __makecontext (ucontext_t *ucp, void (*func) (void), int argc, ...)
  127. {
  128. unsigned long sp = ((unsigned long) ucp->uc_stack.ss_sp
  129. + ucp->uc_stack.ss_size - 32) & -16;
  130. unsigned long spill0[4] =
  131. {
  132. 0, sp + 32, 0, 0,
  133. };
  134. int i;
  135. memset ((void *) sp, 0, 32);
  136. if (argc > 2)
  137. sp -= 4 * (argc - 2);
  138. sp &= -16;
  139. ucp->uc_mcontext.sc_pc =
  140. ((unsigned long) __start_context & 0x3fffffff) + 0x80000000;
  141. ucp->uc_mcontext.sc_a[0] = 0;
  142. ucp->uc_mcontext.sc_a[1] = sp;
  143. ucp->uc_mcontext.sc_a[2] = (unsigned long) func;
  144. ucp->uc_mcontext.sc_a[3] = (unsigned long) ucp->uc_link;
  145. ucp->uc_mcontext.sc_a[4] = argc;
  146. if (argc)
  147. {
  148. va_list ap;
  149. va_start (ap, argc);
  150. for (i = 0; i < argc; ++i)
  151. {
  152. if (i < 3)
  153. ucp->uc_mcontext.sc_a[5 + i] = va_arg (ap, int);
  154. else
  155. ((int *) sp)[i - 2] = va_arg (ap, int);
  156. }
  157. va_end (ap);
  158. }
  159. sp -= 16;
  160. memcpy ((void *) sp, spill0, sizeof (spill0));
  161. }
  162. #else
  163. #error Unsupported Xtensa ABI
  164. #endif
  165. weak_alias (__makecontext, makecontext)