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