]>
Commit | Line | Data |
---|---|---|
609b4783 | 1 | /* Create new context. |
6d7e8eda | 2 | Copyright (C) 2002-2023 Free Software Foundation, Inc. |
609b4783 UD |
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 | |
59ba27a6 | 16 | License along with the GNU C Library; if not, see |
5a82c748 | 17 | <https://www.gnu.org/licenses/>. */ |
609b4783 UD |
18 | |
19 | #include <sysdep.h> | |
20 | ||
21 | #define __ASSEMBLY__ | |
22 | #include <asm/ptrace.h> | |
23 | #include "ucontext_i.h" | |
38e68573 | 24 | #include <asm/errno.h> |
609b4783 | 25 | |
fb499eb0 | 26 | ENTRY (__makecontext) |
865d953f | 27 | CALL_MCOUNT 3 |
609b4783 | 28 | /* Save parameters into the parameter save area of callers frame. */ |
fb499eb0 AM |
29 | std r3,FRAME_PARM_SAVE+0(r1) /* ucontext_t *ucp */ |
30 | std r4,FRAME_PARM_SAVE+8(r1) /* void (*func)(void) */ | |
31 | std r5,FRAME_PARM_SAVE+16(r1) /* int argc */ | |
32 | std r6,FRAME_PARM_SAVE+24(r1) /* ... */ | |
33 | std r7,FRAME_PARM_SAVE+32(r1) | |
34 | std r8,FRAME_PARM_SAVE+40(r1) | |
35 | std r9,FRAME_PARM_SAVE+48(r1) | |
36 | std r10,FRAME_PARM_SAVE+56(r1) | |
609b4783 UD |
37 | mflr r0 |
38 | /* Get the address of the target functions first parameter. */ | |
fb499eb0 | 39 | addi r6,r1,FRAME_PARM_SAVE+24 |
609b4783 | 40 | std r0,FRAME_LR_SAVE(r1) |
a7e91561 | 41 | cfi_offset (lr, FRAME_LR_SAVE) |
609b4783 | 42 | stdu r1,-128(r1) |
a7e91561 | 43 | cfi_adjust_cfa_offset (128) |
a99a3055 | 44 | |
609b4783 | 45 | /* Get the ucontexts stack pointer and size. Compute the top of stack |
a99a3055 | 46 | and round down to a quadword boundary. Then stack a dummy frame |
609b4783 | 47 | with a null back chain. We store the context pointer in the frames |
a99a3055 UD |
48 | "compiler double word" field so we can recover if is the function |
49 | returns. Finally save the callers link register and TOC pointer | |
609b4783 UD |
50 | into this frame so the debugger can display a backtrace. |
51 | */ | |
52 | ld r7,UCONTEXT_STACK_SP(r3) | |
53 | ld r0,UCONTEXT_STACK_SIZE(r3) | |
54 | add r7,r7,r0 | |
55 | clrrdi r7,r7,4 | |
56 | li r0,0 | |
5ef6ae4b | 57 | stdu r0,-64(r7) |
fb499eb0 | 58 | std r3,FRAME_PARM_SAVE(r7) /* Store context in dummy parm1. */ |
609b4783 UD |
59 | mflr r0 |
60 | std r2,FRAME_TOC_SAVE(r7) /* Store the TOC pointer for later. */ | |
61 | std r0,FRAME_LR_SAVE(r7) | |
a99a3055 | 62 | |
609b4783 | 63 | /* Now we need to stack another frame to hold the parameter save area |
a99a3055 UD |
64 | for the function. We need to allocate a frame with the minimum 48 |
65 | byte header and 8 parameter register. However if there are more | |
609b4783 | 66 | than 8 parameters addition space is need to hold all the parameters. |
a99a3055 | 67 | The total size it rounded up to a quadword multiple then a frame is |
609b4783 | 68 | stacked. This address is stored in the ucontext as GPR 1. */ |
a99a3055 UD |
69 | |
70 | cmpdi cr1,r5,8 | |
609b4783 UD |
71 | sldi r8,r5,3 |
72 | bgt cr1,L(gt8) | |
73 | li r8,64 | |
74 | L(gt8): | |
75 | addi r8,r8,FRAME_PARM_SAVE+8 /* Add header plus rounding factor. */ | |
76 | clrrdi r8,r8,4 /* Round down to quadword. */ | |
a99a3055 | 77 | |
609b4783 UD |
78 | subf r8,r8,r7 |
79 | std r7,0(r8) /* Stack the frame. */ | |
80 | std r8,(SIGCONTEXT_GP_REGS+(PT_R1*8))(r3) | |
a99a3055 UD |
81 | |
82 | /* Now we need to copy the target functions parameters. The functions | |
609b4783 | 83 | parameters are saved in the parameter save area. We skip over the |
a99a3055 UD |
84 | first three parameters and copy up to 8 double word into the |
85 | SIGCONTEXT_GP_REGS starting with R3. If there are more than 8 | |
609b4783 | 86 | parameters then doublewords 8-N are copied into the parameter |
a99a3055 | 87 | save area of the context frame. */ |
609b4783 UD |
88 | cmpdi r5,0 |
89 | beq L(noparms) | |
90 | mr r0,r5 | |
91 | ble cr1,L(le8) | |
92 | li r0,8 | |
a99a3055 | 93 | L(le8): |
609b4783 UD |
94 | mtctr r0 |
95 | addi r7,r6,-8 | |
96 | addi r9,r3,(SIGCONTEXT_GP_REGS+(PT_R3*8)-8) | |
97 | L(parmloop2): | |
98 | ldu r0,8(r7) | |
99 | stdu r0,8(r9) | |
100 | bdnz L(parmloop2) | |
a99a3055 UD |
101 | |
102 | addi r0,r5,-8 | |
103 | ble cr1,L(noparms) | |
609b4783 | 104 | mtctr r0 |
fb499eb0 | 105 | addi r9,r8,FRAME_PARM_SAVE+64-8 |
609b4783 UD |
106 | L(parmloop): |
107 | ldu r0,8(r7) | |
108 | stdu r0,8(r9) | |
109 | bdnz L(parmloop) | |
a99a3055 | 110 | |
609b4783 | 111 | L(noparms): |
a99a3055 | 112 | |
696caf1d | 113 | #if _CALL_ELF != 2 |
609b4783 | 114 | /* Load the function address and TOC from the function descriptor |
a99a3055 | 115 | and store them in the ucontext as NIP and r2. Store the 3rd |
609b4783 UD |
116 | field of the function descriptor into the ucontext as r11 in case |
117 | the calling language needs the "environment pointer". */ | |
118 | ld r0,0(r4) | |
119 | ld r10,8(r4); | |
a99a3055 UD |
120 | ld r9,16(r4); |
121 | std r0,(SIGCONTEXT_GP_REGS+(PT_NIP*8))(r3) | |
122 | std r10,(SIGCONTEXT_GP_REGS+(PT_R2*8))(r3) | |
609b4783 | 123 | std r9,(SIGCONTEXT_GP_REGS+(PT_R11*8))(r3) |
696caf1d UW |
124 | #else |
125 | /* In the ELFv2 ABI, the function pointer is already the address. | |
126 | Store it as NIP and r12 as required by the ABI. */ | |
127 | std r4,(SIGCONTEXT_GP_REGS+(PT_NIP*8))(r3) | |
128 | std r4,(SIGCONTEXT_GP_REGS+(PT_R12*8))(r3) | |
129 | #endif | |
a99a3055 | 130 | |
609b4783 UD |
131 | /* If the target function returns we need to do some cleanup. We use a |
132 | code trick to get the address of our cleanup function into the link | |
0b2c2ace AM |
133 | register. Do not add any code between here and L(exitcode). |
134 | Use this conditional form of branch and link to avoid destroying | |
135 | the cpu link stack used to predict blr return addresses. */ | |
136 | bcl 20,31,L(gotexitcodeaddr); | |
609b4783 | 137 | |
5162e7dd UW |
138 | /* End FDE now, because while executing on the context's stack |
139 | the unwind info would be wrong otherwise. */ | |
140 | cfi_endproc | |
141 | ||
609b4783 UD |
142 | /* This is the helper code which gets called if a function which |
143 | is registered with 'makecontext' returns. In this case we | |
144 | have to install the context listed in the uc_link element of | |
145 | the context 'makecontext' manipulated at the time of the | |
146 | 'makecontext' call. If the pointer is NULL the process must | |
147 | terminate. */ | |
148 | L(exitcode): | |
d6cffd3e AS |
149 | /* Recover the ucontext and TOC from the dummy frame. */ |
150 | ld r1,FRAME_BACKCHAIN(r1) /* Unstack the parameter save area frame. */ | |
fb499eb0 | 151 | ld r3,FRAME_PARM_SAVE(r1) |
d6cffd3e AS |
152 | ld r2,FRAME_TOC_SAVE(r1) |
153 | ld r3,UCONTEXT_LINK(r3) /* Load the resume context. */ | |
154 | cmpdi r3,0 | |
155 | beq L(do_exit) | |
609b4783 UD |
156 | bl JUMPTARGET(__setcontext) |
157 | nop | |
d6cffd3e AS |
158 | /* If setcontext returns (which can happen if the syscall fails) we will |
159 | exit the program with error status (-1). */ | |
160 | li r3,-1 | |
161 | L(do_exit): | |
a99a3055 | 162 | #ifdef SHARED |
7c7bcf36 | 163 | b JUMPTARGET (NOTOC (__GI_exit)); |
a99a3055 | 164 | #else |
d6cffd3e AS |
165 | b JUMPTARGET(exit); |
166 | nop | |
a99a3055 | 167 | #endif |
d6cffd3e | 168 | b L(do_exit) |
a99a3055 | 169 | |
5162e7dd UW |
170 | /* Re-establish FDE for the rest of the actual makecontext routine. */ |
171 | cfi_startproc | |
172 | cfi_offset (lr, FRAME_LR_SAVE) | |
173 | cfi_adjust_cfa_offset (128) | |
174 | ||
609b4783 | 175 | /* The address of the exit code is in the link register. Store the lr |
a99a3055 | 176 | in the ucontext as LNK so the target function will return to our |
609b4783 UD |
177 | exit code. */ |
178 | L(gotexitcodeaddr): | |
179 | mflr r0 | |
180 | std r0,(SIGCONTEXT_GP_REGS+(PT_LNK*8))(r3) | |
a99a3055 | 181 | ld r0,128+FRAME_LR_SAVE(r1) |
609b4783 UD |
182 | addi r1,r1,128 |
183 | mtlr r0 | |
184 | blr | |
185 | END(__makecontext) | |
186 | ||
1ab18a5b | 187 | weak_alias (__makecontext, makecontext) |