makecontext.c 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  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. ucp->uc_mcontext.sc_pc = (unsigned long) __start_context;
  68. ucp->uc_mcontext.sc_a[1] = sp;
  69. ucp->uc_mcontext.sc_a[12] = (unsigned long) func;
  70. ucp->uc_mcontext.sc_a[13] = (unsigned long) ucp->uc_link;
  71. ucp->uc_mcontext.sc_a[14] = argc;
  72. if (argc)
  73. {
  74. va_list ap;
  75. va_start (ap, argc);
  76. for (i = 0; i < argc; ++i)
  77. ((int *) sp)[i + 2] = va_arg (ap, int);
  78. va_end (ap);
  79. }
  80. }
  81. #elif defined(__XTENSA_WINDOWED_ABI__)
  82. /*
  83. * makecontext sets up new stack like this:
  84. *
  85. * +------------------ stack top (uc_stack.ss_sp + uc_stack.ss_size)
  86. * | optional alignment
  87. * +------------------ CFA of __start_context
  88. * 16 | Outermost caller spill area
  89. * +------------------
  90. * 16 | __start_context overflow area
  91. * +------------------ initial sp points here
  92. * | optional padding
  93. * +------------------ Optional arguments 6..argc - 1
  94. * | func arg argc - 1
  95. * | func arg argc - 2
  96. * | ...
  97. * | func arg 6
  98. * +------------------ Optional arguments 3..5
  99. * | func arg 5
  100. * 16 | func arg 4
  101. * | func arg 3
  102. * | padding
  103. * +------------------ CFA of pseudo getcontext
  104. * 16 | __start_context caller spill area
  105. * +------------------
  106. * |
  107. * +------------------ stack bottom (uc_stack.ss_sp)
  108. *
  109. * When argc < 4 both arguments areas are not allocated,
  110. * when 4 <= argc < 7 only area for arguments 3..5 is allocated,
  111. * when argc >= 7 both arguments areas are allocated.
  112. * Arguments 3..5 area is deallocated by the __start_context after
  113. * arguments are loaded into registers.
  114. * uc_mcontext registers are set as if __start_context made call8
  115. * to getcontext, sp points to that pseudo getcontext CFA, spill
  116. * area under that sp has a1 pointing to the __start_context CFA
  117. * at the top of the stack. setcontext/swapcontext will arrange for
  118. * restoring regiters a0..a7 of __start_context.
  119. */
  120. void
  121. __makecontext (ucontext_t *ucp, void (*func) (void), int argc, ...)
  122. {
  123. unsigned long sp = ((unsigned long) ucp->uc_stack.ss_sp
  124. + ucp->uc_stack.ss_size - 32) & -16;
  125. unsigned long spill0[4] =
  126. {
  127. 0, sp + 32, 0, 0,
  128. };
  129. int i;
  130. memset ((void *) sp, 0, 32);
  131. if (argc > 2)
  132. sp -= 4 * (argc - 2);
  133. sp &= -16;
  134. ucp->uc_mcontext.sc_pc =
  135. ((unsigned long) __start_context & 0x3fffffff) + 0x80000000;
  136. ucp->uc_mcontext.sc_a[0] = 0;
  137. ucp->uc_mcontext.sc_a[1] = sp;
  138. ucp->uc_mcontext.sc_a[2] = (unsigned long) func;
  139. ucp->uc_mcontext.sc_a[3] = (unsigned long) ucp->uc_link;
  140. ucp->uc_mcontext.sc_a[4] = argc;
  141. if (argc)
  142. {
  143. va_list ap;
  144. va_start (ap, argc);
  145. for (i = 0; i < argc; ++i)
  146. {
  147. if (i < 3)
  148. ucp->uc_mcontext.sc_a[5 + i] = va_arg (ap, int);
  149. else
  150. ((int *) sp)[i - 2] = va_arg (ap, int);
  151. }
  152. va_end (ap);
  153. }
  154. sp -= 16;
  155. memcpy ((void *) sp, spill0, sizeof (spill0));
  156. }
  157. #else
  158. #error Unsupported Xtensa ABI
  159. #endif
  160. weak_alias (__makecontext, makecontext)