2 Copyright (C) 2002, 2004 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
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.
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.
15 You should have received a copy of the GNU Lesser General Public
16 License along with the GNU C Library; if not, write to the Free
17 Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
21 #include <rtld-global-offsets.h>
22 #include <shlib-compat.h>
23 #include "kernel-features.h"
26 #include <asm/ptrace.h>
27 #include "ucontext_i.h"
28 #include <asm/errno.h>
30 #if SHLIB_COMPAT (libc, GLIBC_2_3, GLIBC_2_3_4)
31 ENTRY(__novec_setcontext)
33 #ifdef __ASSUME_NEW_RT_SIGRETURN_SYSCALL
36 std r0,FRAME_LR_SAVE(r1)
41 * If this ucontext refers to the point where we were interrupted
42 * by a signal, we have to use the rt_sigreturn system call to
43 * return to the context so we get both LR and CTR restored.
45 * Otherwise, the context we are restoring is either just after
46 * a procedure call (getcontext/swapcontext) or at the beginning
47 * of a procedure call (makecontext), so we don't need to restore
48 * msr and ctr. We don't restore r13 since it will be used as
50 lwz r0,(SIGCONTEXT_GP_REGS+(PT_MSR*8))(r31)
55 addi r4,r3,UCONTEXT_SIGMASK
57 bl JUMPTARGET(__sigprocmask)
62 lfd fp0,(SIGCONTEXT_FP_REGS+(32*8))(r31)
63 lfd fp31,(SIGCONTEXT_FP_REGS+(PT_R31*8))(r31)
64 lfd fp30,(SIGCONTEXT_FP_REGS+(PT_R30*8))(r31)
66 lfd fp29,(SIGCONTEXT_FP_REGS+(PT_R29*8))(r31)
67 lfd fp28,(SIGCONTEXT_FP_REGS+(PT_R28*8))(r31)
68 lfd fp27,(SIGCONTEXT_FP_REGS+(PT_R27*8))(r31)
69 lfd fp26,(SIGCONTEXT_FP_REGS+(PT_R26*8))(r31)
70 lfd fp25,(SIGCONTEXT_FP_REGS+(PT_R25*8))(r31)
71 lfd fp24,(SIGCONTEXT_FP_REGS+(PT_R24*8))(r31)
72 lfd fp23,(SIGCONTEXT_FP_REGS+(PT_R23*8))(r31)
73 lfd fp22,(SIGCONTEXT_FP_REGS+(PT_R22*8))(r31)
74 lfd fp21,(SIGCONTEXT_FP_REGS+(PT_R21*8))(r31)
75 lfd fp20,(SIGCONTEXT_FP_REGS+(PT_R20*8))(r31)
76 lfd fp19,(SIGCONTEXT_FP_REGS+(PT_R19*8))(r31)
77 lfd fp18,(SIGCONTEXT_FP_REGS+(PT_R18*8))(r31)
78 lfd fp17,(SIGCONTEXT_FP_REGS+(PT_R17*8))(r31)
79 lfd fp16,(SIGCONTEXT_FP_REGS+(PT_R16*8))(r31)
80 lfd fp15,(SIGCONTEXT_FP_REGS+(PT_R15*8))(r31)
81 lfd fp14,(SIGCONTEXT_FP_REGS+(PT_R14*8))(r31)
82 lfd fp13,(SIGCONTEXT_FP_REGS+(PT_R13*8))(r31)
83 lfd fp12,(SIGCONTEXT_FP_REGS+(PT_R12*8))(r31)
84 lfd fp11,(SIGCONTEXT_FP_REGS+(PT_R11*8))(r31)
85 lfd fp10,(SIGCONTEXT_FP_REGS+(PT_R10*8))(r31)
86 lfd fp9,(SIGCONTEXT_FP_REGS+(PT_R9*8))(r31)
87 lfd fp8,(SIGCONTEXT_FP_REGS+(PT_R8*8))(r31)
88 lfd fp7,(SIGCONTEXT_FP_REGS+(PT_R7*8))(r31)
89 lfd fp6,(SIGCONTEXT_FP_REGS+(PT_R6*8))(r31)
90 lfd fp5,(SIGCONTEXT_FP_REGS+(PT_R5*8))(r31)
91 lfd fp4,(SIGCONTEXT_FP_REGS+(PT_R4*8))(r31)
92 lfd fp3,(SIGCONTEXT_FP_REGS+(PT_R3*8))(r31)
93 lfd fp2,(SIGCONTEXT_FP_REGS+(PT_R2*8))(r31)
94 lfd fp1,(SIGCONTEXT_FP_REGS+(PT_R1*8))(r31)
95 lfd fp0,(SIGCONTEXT_FP_REGS+(PT_R0*8))(r31)
97 ld r0,(SIGCONTEXT_GP_REGS+(PT_LNK*8))(r31)
98 ld r1,(SIGCONTEXT_GP_REGS+(PT_R1*8))(r31)
100 ld r2,(SIGCONTEXT_GP_REGS+(PT_R2*8))(r31)
101 ld r0,(SIGCONTEXT_GP_REGS+(PT_XER*8))(r31)
102 ld r3,(SIGCONTEXT_GP_REGS+(PT_R3*8))(r31)
104 ld r4,(SIGCONTEXT_GP_REGS+(PT_R4*8))(r31)
105 ld r0,(SIGCONTEXT_GP_REGS+(PT_CCR*8))(r31)
106 ld r5,(SIGCONTEXT_GP_REGS+(PT_R5*8))(r31)
108 ld r6,(SIGCONTEXT_GP_REGS+(PT_R6*8))(r31)
109 ld r7,(SIGCONTEXT_GP_REGS+(PT_R7*8))(r31)
110 ld r8,(SIGCONTEXT_GP_REGS+(PT_R8*8))(r31)
111 ld r9,(SIGCONTEXT_GP_REGS+(PT_R9*8))(r31)
112 ld r10,(SIGCONTEXT_GP_REGS+(PT_R10*8))(r31)
113 ld r11,(SIGCONTEXT_GP_REGS+(PT_R11*8))(r31)
114 ld r12,(SIGCONTEXT_GP_REGS+(PT_R12*8))(r31)
115 /* Don't reload the thread ID or TLS pointer (r13). */
116 ld r14,(SIGCONTEXT_GP_REGS+(PT_R14*8))(r31)
117 ld r15,(SIGCONTEXT_GP_REGS+(PT_R15*8))(r31)
118 ld r16,(SIGCONTEXT_GP_REGS+(PT_R16*8))(r31)
119 ld r17,(SIGCONTEXT_GP_REGS+(PT_R17*8))(r31)
120 ld r18,(SIGCONTEXT_GP_REGS+(PT_R18*8))(r31)
121 ld r19,(SIGCONTEXT_GP_REGS+(PT_R19*8))(r31)
122 ld r20,(SIGCONTEXT_GP_REGS+(PT_R20*8))(r31)
123 ld r21,(SIGCONTEXT_GP_REGS+(PT_R21*8))(r31)
124 ld r22,(SIGCONTEXT_GP_REGS+(PT_R22*8))(r31)
125 ld r23,(SIGCONTEXT_GP_REGS+(PT_R23*8))(r31)
126 ld r24,(SIGCONTEXT_GP_REGS+(PT_R24*8))(r31)
127 ld r25,(SIGCONTEXT_GP_REGS+(PT_R25*8))(r31)
128 ld r26,(SIGCONTEXT_GP_REGS+(PT_R26*8))(r31)
129 ld r27,(SIGCONTEXT_GP_REGS+(PT_R27*8))(r31)
130 ld r28,(SIGCONTEXT_GP_REGS+(PT_R28*8))(r31)
131 ld r29,(SIGCONTEXT_GP_REGS+(PT_R29*8))(r31)
132 ld r30,(SIGCONTEXT_GP_REGS+(PT_R30*8))(r31)
134 /* Now we branch to the "Next Instruction Pointer" from the saved
135 context. With the powerpc64 instruction set there is no good way to
136 do this (from user state) without clobbering either the LR or CTR.
137 The makecontext and swapcontext functions depend on the callers
138 LR being preserved so we use the CTR. */
139 ld r0,(SIGCONTEXT_GP_REGS+(PT_NIP*8))(r31)
141 ld r0,(SIGCONTEXT_GP_REGS+(PT_R0*8))(r31)
142 ld r31,(SIGCONTEXT_GP_REGS+(PT_R31*8))(r31)
146 ld r0,128+FRAME_LR_SAVE(r1)
152 /* At this point we assume that the ucontext was created by a
153 rt_signal and we should use rt_sigreturn to restore the original
154 state. As of the 2.4.21 kernel the ucontext is the first thing
155 (offset 0) in the rt_signal frame and rt_sigreturn expects the
156 ucontext address in R1. Normally the rt-signal trampoline handles
157 this by popping dummy frame before the rt_signal syscall. In our
158 case the stack may not be in its original (signal handler return with
159 R1 pointing at the dummy frame) state. We do have the ucontext
160 address in R3, so simply copy R3 to R1 before the syscall. */
163 li r0,SYS_ify(rt_sigreturn)
167 /* If the kernel is not at least 2.4.21 then generate a ENOSYS stub. */
169 std r0,FRAME_LR_SAVE(r1)
172 bl JUMPTARGET(__syscall_error)
175 ld r0,128+FRAME_LR_SAVE(r1)
181 PSEUDO_END(__novec_setcontext)
183 compat_symbol (libc, __novec_setcontext, setcontext, GLIBC_2_3)
190 .tc _rtld_global_ro[TC],_rtld_global_ro
192 .tc _dl_hwcap[TC],_dl_hwcap
199 #ifdef __ASSUME_NEW_RT_SIGRETURN_SYSCALL
202 std r0,FRAME_LR_SAVE(r1)
207 * If this ucontext refers to the point where we were interrupted
208 * by a signal, we have to use the rt_sigreturn system call to
209 * return to the context so we get both LR and CTR restored.
211 * Otherwise, the context we are restoring is either just after
212 * a procedure call (getcontext/swapcontext) or at the beginning
213 * of a procedure call (makecontext), so we don't need to restore
214 * msr and ctr. We don't restore r13 since it will be used as
215 * the TLS pointer. */
216 lwz r0,(SIGCONTEXT_GP_REGS+(PT_MSR*8))(r31)
221 addi r4,r3,UCONTEXT_SIGMASK
223 bl JUMPTARGET(__sigprocmask)
228 ld r5,.LC__dl_hwcap@toc(r2)
229 ld r10,(SIGCONTEXT_V_REGS_PTR)(r31)
231 /* Load _rtld-global._dl_hwcap. */
232 ld r5,RTLD_GLOBAL_RO_DL_HWCAP_OFFSET(r5)
234 ld r5,0(r5) /* Load extern _dl_hwcap. */
236 andis. r5,r5,(PPC_FEATURE_HAS_ALTIVEC >> 16)
338 lfd fp0,(SIGCONTEXT_FP_REGS+(32*8))(r31)
339 lfd fp31,(SIGCONTEXT_FP_REGS+(PT_R31*8))(r31)
340 lfd fp30,(SIGCONTEXT_FP_REGS+(PT_R30*8))(r31)
342 lfd fp29,(SIGCONTEXT_FP_REGS+(PT_R29*8))(r31)
343 lfd fp28,(SIGCONTEXT_FP_REGS+(PT_R28*8))(r31)
344 lfd fp27,(SIGCONTEXT_FP_REGS+(PT_R27*8))(r31)
345 lfd fp26,(SIGCONTEXT_FP_REGS+(PT_R26*8))(r31)
346 lfd fp25,(SIGCONTEXT_FP_REGS+(PT_R25*8))(r31)
347 lfd fp24,(SIGCONTEXT_FP_REGS+(PT_R24*8))(r31)
348 lfd fp23,(SIGCONTEXT_FP_REGS+(PT_R23*8))(r31)
349 lfd fp22,(SIGCONTEXT_FP_REGS+(PT_R22*8))(r31)
350 lfd fp21,(SIGCONTEXT_FP_REGS+(PT_R21*8))(r31)
351 lfd fp20,(SIGCONTEXT_FP_REGS+(PT_R20*8))(r31)
352 lfd fp19,(SIGCONTEXT_FP_REGS+(PT_R19*8))(r31)
353 lfd fp18,(SIGCONTEXT_FP_REGS+(PT_R18*8))(r31)
354 lfd fp17,(SIGCONTEXT_FP_REGS+(PT_R17*8))(r31)
355 lfd fp16,(SIGCONTEXT_FP_REGS+(PT_R16*8))(r31)
356 lfd fp15,(SIGCONTEXT_FP_REGS+(PT_R15*8))(r31)
357 lfd fp14,(SIGCONTEXT_FP_REGS+(PT_R14*8))(r31)
358 lfd fp13,(SIGCONTEXT_FP_REGS+(PT_R13*8))(r31)
359 lfd fp12,(SIGCONTEXT_FP_REGS+(PT_R12*8))(r31)
360 lfd fp11,(SIGCONTEXT_FP_REGS+(PT_R11*8))(r31)
361 lfd fp10,(SIGCONTEXT_FP_REGS+(PT_R10*8))(r31)
362 lfd fp9,(SIGCONTEXT_FP_REGS+(PT_R9*8))(r31)
363 lfd fp8,(SIGCONTEXT_FP_REGS+(PT_R8*8))(r31)
364 lfd fp7,(SIGCONTEXT_FP_REGS+(PT_R7*8))(r31)
365 lfd fp6,(SIGCONTEXT_FP_REGS+(PT_R6*8))(r31)
366 lfd fp5,(SIGCONTEXT_FP_REGS+(PT_R5*8))(r31)
367 lfd fp4,(SIGCONTEXT_FP_REGS+(PT_R4*8))(r31)
368 lfd fp3,(SIGCONTEXT_FP_REGS+(PT_R3*8))(r31)
369 lfd fp2,(SIGCONTEXT_FP_REGS+(PT_R2*8))(r31)
370 lfd fp1,(SIGCONTEXT_FP_REGS+(PT_R1*8))(r31)
371 lfd fp0,(SIGCONTEXT_FP_REGS+(PT_R0*8))(r31)
373 ld r0,(SIGCONTEXT_GP_REGS+(PT_LNK*8))(r31)
374 ld r1,(SIGCONTEXT_GP_REGS+(PT_R1*8))(r31)
376 ld r2,(SIGCONTEXT_GP_REGS+(PT_R2*8))(r31)
377 ld r0,(SIGCONTEXT_GP_REGS+(PT_XER*8))(r31)
378 ld r3,(SIGCONTEXT_GP_REGS+(PT_R3*8))(r31)
380 ld r4,(SIGCONTEXT_GP_REGS+(PT_R4*8))(r31)
381 ld r0,(SIGCONTEXT_GP_REGS+(PT_CCR*8))(r31)
382 ld r5,(SIGCONTEXT_GP_REGS+(PT_R5*8))(r31)
384 ld r6,(SIGCONTEXT_GP_REGS+(PT_R6*8))(r31)
385 ld r7,(SIGCONTEXT_GP_REGS+(PT_R7*8))(r31)
386 ld r8,(SIGCONTEXT_GP_REGS+(PT_R8*8))(r31)
387 ld r9,(SIGCONTEXT_GP_REGS+(PT_R9*8))(r31)
388 ld r10,(SIGCONTEXT_GP_REGS+(PT_R10*8))(r31)
389 ld r11,(SIGCONTEXT_GP_REGS+(PT_R11*8))(r31)
390 ld r12,(SIGCONTEXT_GP_REGS+(PT_R12*8))(r31)
391 /* Don't reload the thread ID or TLS pointer (r13). */
392 ld r14,(SIGCONTEXT_GP_REGS+(PT_R14*8))(r31)
393 ld r15,(SIGCONTEXT_GP_REGS+(PT_R15*8))(r31)
394 ld r16,(SIGCONTEXT_GP_REGS+(PT_R16*8))(r31)
395 ld r17,(SIGCONTEXT_GP_REGS+(PT_R17*8))(r31)
396 ld r18,(SIGCONTEXT_GP_REGS+(PT_R18*8))(r31)
397 ld r19,(SIGCONTEXT_GP_REGS+(PT_R19*8))(r31)
398 ld r20,(SIGCONTEXT_GP_REGS+(PT_R20*8))(r31)
399 ld r21,(SIGCONTEXT_GP_REGS+(PT_R21*8))(r31)
400 ld r22,(SIGCONTEXT_GP_REGS+(PT_R22*8))(r31)
401 ld r23,(SIGCONTEXT_GP_REGS+(PT_R23*8))(r31)
402 ld r24,(SIGCONTEXT_GP_REGS+(PT_R24*8))(r31)
403 ld r25,(SIGCONTEXT_GP_REGS+(PT_R25*8))(r31)
404 ld r26,(SIGCONTEXT_GP_REGS+(PT_R26*8))(r31)
405 ld r27,(SIGCONTEXT_GP_REGS+(PT_R27*8))(r31)
406 ld r28,(SIGCONTEXT_GP_REGS+(PT_R28*8))(r31)
407 ld r29,(SIGCONTEXT_GP_REGS+(PT_R29*8))(r31)
408 ld r30,(SIGCONTEXT_GP_REGS+(PT_R30*8))(r31)
410 /* Now we branch to the "Next Instruction Pointer" from the saved
411 context. With the powerpc64 instruction set there is no good way to
412 do this (from user state) without clobbering either the LR or CTR.
413 The makecontext and swapcontext functions depend on the callers
414 LR being preserved so we use the CTR. */
415 ld r0,(SIGCONTEXT_GP_REGS+(PT_NIP*8))(r31)
417 ld r0,(SIGCONTEXT_GP_REGS+(PT_R0*8))(r31)
418 ld r31,(SIGCONTEXT_GP_REGS+(PT_R31*8))(r31)
422 ld r0,128+FRAME_LR_SAVE(r1)
428 /* At this point we assume that the ucontext was created by a
429 rt_signal and we should use rt_sigreturn to restore the original
430 state. As of the 2.4.21 kernel the ucontext is the first thing
431 (offset 0) in the rt_signal frame and rt_sigreturn expects the
432 ucontext address in R1. Normally the rt-signal trampoline handles
433 this by popping dummy frame before the rt_signal syscall. In our
434 case the stack may not be in its original (signal handler return with
435 R1 pointing at the dummy frame) state. We do have the ucontext
436 address in R3, so simply copy R3 to R1 before the syscall. */
439 li r0,SYS_ify(rt_sigreturn)
443 /* If the kernel is not at least 2.4.21 then generate a ENOSYS stub. */
445 std r0,FRAME_LR_SAVE(r1)
448 bl JUMPTARGET(__syscall_error)
451 ld r0,128+FRAME_LR_SAVE(r1)
457 PSEUDO_END(__setcontext)
459 versioned_symbol (libc, __setcontext, setcontext, GLIBC_2_3_4)