setcontext.S 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131
  1. /* Install given context.
  2. Copyright (C) 2008-2016 Free Software Foundation, Inc.
  3. This file is part of the GNU C Library.
  4. Contributed by David S. Miller <davem@davemloft.net>, 2008.
  5. The GNU C Library is free software; you can redistribute it and/or
  6. modify it under the terms of the GNU Lesser General Public
  7. License as published by the Free Software Foundation; either
  8. version 2.1 of the License, or (at your option) any later version.
  9. The GNU C Library is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  12. Lesser General Public License for more details.
  13. You should have received a copy of the GNU Lesser General Public
  14. License along with the GNU C Library; if not, see
  15. <http://www.gnu.org/licenses/>. */
  16. #include <sysdep.h>
  17. #include "ucontext_i.h"
  18. #define ST_FLUSH_WINDOWS 3
  19. /* int __setcontext (const ucontext_t *ucp)
  20. Restores the machine context in UCP and thereby resumes execution
  21. in that context.
  22. This implementation is intended to be used for *synchronous* context
  23. switches only. Therefore, it does not have to restore anything
  24. other than the PRESERVED state. */
  25. ENTRY(__setcontext)
  26. save %sp, -112, %sp
  27. mov SIG_SETMASK, %o0
  28. add %i0, UC_SIGMASK, %o1
  29. clr %o2
  30. mov 8, %o3
  31. mov __NR_rt_sigprocmask, %g1
  32. ta 0x10
  33. /* This is a bit on the expensive side, and we could optimize
  34. the unwind similar to how the 32-bit sparc longjmp code
  35. does if performance of this routine really matters. */
  36. ta ST_FLUSH_WINDOWS
  37. ldub [%i0 + UC_MCONTEXT + MC_FPREGS + FPU_EN], %g1
  38. cmp %g1, 0
  39. be 1f
  40. nop
  41. ld [%i0 + UC_MCONTEXT + MC_FPREGS + FPU_FSR], %fsr
  42. ldd [%i0 + UC_MCONTEXT + MC_FPREGS + FPU_D0], %f0
  43. ldd [%i0 + UC_MCONTEXT + MC_FPREGS + FPU_D2], %f2
  44. ldd [%i0 + UC_MCONTEXT + MC_FPREGS + FPU_D4], %f4
  45. ldd [%i0 + UC_MCONTEXT + MC_FPREGS + FPU_D6], %f6
  46. ldd [%i0 + UC_MCONTEXT + MC_FPREGS + FPU_D8], %f8
  47. ldd [%i0 + UC_MCONTEXT + MC_FPREGS + FPU_D10], %f10
  48. ldd [%i0 + UC_MCONTEXT + MC_FPREGS + FPU_D12], %f12
  49. ldd [%i0 + UC_MCONTEXT + MC_FPREGS + FPU_D14], %f14
  50. ldd [%i0 + UC_MCONTEXT + MC_FPREGS + FPU_D16], %f16
  51. ldd [%i0 + UC_MCONTEXT + MC_FPREGS + FPU_D18], %f18
  52. ldd [%i0 + UC_MCONTEXT + MC_FPREGS + FPU_D20], %f20
  53. ldd [%i0 + UC_MCONTEXT + MC_FPREGS + FPU_D22], %f22
  54. ldd [%i0 + UC_MCONTEXT + MC_FPREGS + FPU_D24], %f24
  55. ldd [%i0 + UC_MCONTEXT + MC_FPREGS + FPU_D26], %f26
  56. ldd [%i0 + UC_MCONTEXT + MC_FPREGS + FPU_D28], %f28
  57. ldd [%i0 + UC_MCONTEXT + MC_FPREGS + FPU_D30], %f30
  58. 1:
  59. ld [%i0 + UC_MCONTEXT + MC_GREGS + GREG_Y], %g1
  60. wr %g1, 0x0, %y
  61. /* We specifically do not restore %g1 since we need it here as
  62. a temporary. */
  63. ld [%i0 + UC_MCONTEXT + MC_GREGS + GREG_G2], %g2
  64. ld [%i0 + UC_MCONTEXT + MC_GREGS + GREG_G3], %g3
  65. ld [%i0 + UC_MCONTEXT + MC_GREGS + GREG_G4], %g4
  66. ld [%i0 + UC_MCONTEXT + MC_GREGS + GREG_G5], %g5
  67. ld [%i0 + UC_MCONTEXT + MC_GREGS + GREG_G6], %g6
  68. ld [%i0 + UC_MCONTEXT + MC_GREGS + GREG_G7], %g7
  69. ld [%i0 + UC_MCONTEXT + MC_GREGS + GREG_O1], %i1
  70. ld [%i0 + UC_MCONTEXT + MC_GREGS + GREG_O2], %i2
  71. ld [%i0 + UC_MCONTEXT + MC_GREGS + GREG_O3], %i3
  72. ld [%i0 + UC_MCONTEXT + MC_GREGS + GREG_O4], %i4
  73. ld [%i0 + UC_MCONTEXT + MC_GREGS + GREG_O5], %i5
  74. ld [%i0 + UC_MCONTEXT + MC_GREGS + GREG_O6], %i6
  75. restore
  76. ld [%o0 + UC_MCONTEXT + MC_GREGS + GREG_O7], %o7
  77. ld [%o0 + UC_MCONTEXT + MC_GREGS + GREG_PC], %g1
  78. jmpl %g1, %g0
  79. ld [%o0 + UC_MCONTEXT + MC_GREGS + GREG_O0], %o0
  80. END(__setcontext)
  81. weak_alias (__setcontext, setcontext)
  82. /* We add an NOP here to separate between __setcontext/__startcontext. The
  83. wanted behavior that happens is: when unwinding from a function called
  84. inside a makecontext() context, FDE lookup will use '&__startcontext - 1',
  85. then returns NULL for no FDE found, and immediately ends the unwind, in
  86. a normal fashion.
  87. If this NOP word does not exist, FDE lookup just repeatedly finds
  88. __setcontext's FDE in an infinite loop, due to the convention of using
  89. 'address - 1' for FDE lookup. Modifiying/deleting the below
  90. __startcontext's FDE has no help on this. */
  91. nop
  92. /* This is the helper code which gets called if a function which is
  93. registered with 'makecontext' returns. In this case we have to
  94. install the context listed in the uc_link element of the context
  95. 'makecontext' manipulated at the time of the 'makecontext' call.
  96. If the pointer is NULL the process must terminate. */
  97. ENTRY(__start_context)
  98. ld [%sp + (16 * 4)], %g1
  99. cmp %g1, 0
  100. be,a 1f
  101. clr %o0
  102. call __setcontext
  103. mov %g1, %o0
  104. /* If this returns (which can happen if the syscall fails) we'll
  105. exit the program with the return error value (-1). */
  106. 1: call HIDDEN_JUMPTARGET(exit)
  107. nop
  108. /* The 'exit' call should never return. In case it does cause
  109. the process to terminate. */
  110. unimp
  111. END(__start_context)