2 Copyright (C) 2002, 2004, 2005, 2006 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., 51 Franklin Street, Fifth Floor, 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
37 std r0,FRAME_LR_SAVE(r1)
38 cfi_offset (lr, FRAME_LR_SAVE)
40 cfi_adjust_cfa_offset (128)
44 * If this ucontext refers to the point where we were interrupted
45 * by a signal, we have to use the rt_sigreturn system call to
46 * return to the context so we get both LR and CTR restored.
48 * Otherwise, the context we are restoring is either just after
49 * a procedure call (getcontext/swapcontext) or at the beginning
50 * of a procedure call (makecontext), so we don't need to restore
51 * msr and ctr. We don't restore r13 since it will be used as
53 ld r0,(SIGCONTEXT_GP_REGS+(PT_MSR*8))(r31)
58 addi r4,r3,UCONTEXT_SIGMASK
60 bl JUMPTARGET(__sigprocmask)
65 lfd fp0,(SIGCONTEXT_FP_REGS+(32*8))(r31)
66 lfd fp31,(SIGCONTEXT_FP_REGS+(PT_R31*8))(r31)
67 lfd fp30,(SIGCONTEXT_FP_REGS+(PT_R30*8))(r31)
69 lfd fp29,(SIGCONTEXT_FP_REGS+(PT_R29*8))(r31)
70 lfd fp28,(SIGCONTEXT_FP_REGS+(PT_R28*8))(r31)
71 lfd fp27,(SIGCONTEXT_FP_REGS+(PT_R27*8))(r31)
72 lfd fp26,(SIGCONTEXT_FP_REGS+(PT_R26*8))(r31)
73 lfd fp25,(SIGCONTEXT_FP_REGS+(PT_R25*8))(r31)
74 lfd fp24,(SIGCONTEXT_FP_REGS+(PT_R24*8))(r31)
75 lfd fp23,(SIGCONTEXT_FP_REGS+(PT_R23*8))(r31)
76 lfd fp22,(SIGCONTEXT_FP_REGS+(PT_R22*8))(r31)
77 lfd fp21,(SIGCONTEXT_FP_REGS+(PT_R21*8))(r31)
78 lfd fp20,(SIGCONTEXT_FP_REGS+(PT_R20*8))(r31)
79 lfd fp19,(SIGCONTEXT_FP_REGS+(PT_R19*8))(r31)
80 lfd fp18,(SIGCONTEXT_FP_REGS+(PT_R18*8))(r31)
81 lfd fp17,(SIGCONTEXT_FP_REGS+(PT_R17*8))(r31)
82 lfd fp16,(SIGCONTEXT_FP_REGS+(PT_R16*8))(r31)
83 lfd fp15,(SIGCONTEXT_FP_REGS+(PT_R15*8))(r31)
84 lfd fp14,(SIGCONTEXT_FP_REGS+(PT_R14*8))(r31)
85 lfd fp13,(SIGCONTEXT_FP_REGS+(PT_R13*8))(r31)
86 lfd fp12,(SIGCONTEXT_FP_REGS+(PT_R12*8))(r31)
87 lfd fp11,(SIGCONTEXT_FP_REGS+(PT_R11*8))(r31)
88 lfd fp10,(SIGCONTEXT_FP_REGS+(PT_R10*8))(r31)
89 lfd fp9,(SIGCONTEXT_FP_REGS+(PT_R9*8))(r31)
90 lfd fp8,(SIGCONTEXT_FP_REGS+(PT_R8*8))(r31)
91 lfd fp7,(SIGCONTEXT_FP_REGS+(PT_R7*8))(r31)
92 lfd fp6,(SIGCONTEXT_FP_REGS+(PT_R6*8))(r31)
93 lfd fp5,(SIGCONTEXT_FP_REGS+(PT_R5*8))(r31)
94 lfd fp4,(SIGCONTEXT_FP_REGS+(PT_R4*8))(r31)
95 lfd fp3,(SIGCONTEXT_FP_REGS+(PT_R3*8))(r31)
96 lfd fp2,(SIGCONTEXT_FP_REGS+(PT_R2*8))(r31)
97 lfd fp1,(SIGCONTEXT_FP_REGS+(PT_R1*8))(r31)
98 lfd fp0,(SIGCONTEXT_FP_REGS+(PT_R0*8))(r31)
100 ld r0,(SIGCONTEXT_GP_REGS+(PT_LNK*8))(r31)
101 ld r1,(SIGCONTEXT_GP_REGS+(PT_R1*8))(r31)
103 ld r2,(SIGCONTEXT_GP_REGS+(PT_R2*8))(r31)
104 ld r0,(SIGCONTEXT_GP_REGS+(PT_XER*8))(r31)
105 ld r3,(SIGCONTEXT_GP_REGS+(PT_R3*8))(r31)
107 ld r4,(SIGCONTEXT_GP_REGS+(PT_R4*8))(r31)
108 ld r0,(SIGCONTEXT_GP_REGS+(PT_CCR*8))(r31)
109 ld r5,(SIGCONTEXT_GP_REGS+(PT_R5*8))(r31)
111 ld r6,(SIGCONTEXT_GP_REGS+(PT_R6*8))(r31)
112 ld r7,(SIGCONTEXT_GP_REGS+(PT_R7*8))(r31)
113 ld r8,(SIGCONTEXT_GP_REGS+(PT_R8*8))(r31)
114 ld r9,(SIGCONTEXT_GP_REGS+(PT_R9*8))(r31)
115 ld r10,(SIGCONTEXT_GP_REGS+(PT_R10*8))(r31)
116 ld r11,(SIGCONTEXT_GP_REGS+(PT_R11*8))(r31)
117 ld r12,(SIGCONTEXT_GP_REGS+(PT_R12*8))(r31)
118 /* Don't reload the thread ID or TLS pointer (r13). */
119 ld r14,(SIGCONTEXT_GP_REGS+(PT_R14*8))(r31)
120 ld r15,(SIGCONTEXT_GP_REGS+(PT_R15*8))(r31)
121 ld r16,(SIGCONTEXT_GP_REGS+(PT_R16*8))(r31)
122 ld r17,(SIGCONTEXT_GP_REGS+(PT_R17*8))(r31)
123 ld r18,(SIGCONTEXT_GP_REGS+(PT_R18*8))(r31)
124 ld r19,(SIGCONTEXT_GP_REGS+(PT_R19*8))(r31)
125 ld r20,(SIGCONTEXT_GP_REGS+(PT_R20*8))(r31)
126 ld r21,(SIGCONTEXT_GP_REGS+(PT_R21*8))(r31)
127 ld r22,(SIGCONTEXT_GP_REGS+(PT_R22*8))(r31)
128 ld r23,(SIGCONTEXT_GP_REGS+(PT_R23*8))(r31)
129 ld r24,(SIGCONTEXT_GP_REGS+(PT_R24*8))(r31)
130 ld r25,(SIGCONTEXT_GP_REGS+(PT_R25*8))(r31)
131 ld r26,(SIGCONTEXT_GP_REGS+(PT_R26*8))(r31)
132 ld r27,(SIGCONTEXT_GP_REGS+(PT_R27*8))(r31)
133 ld r28,(SIGCONTEXT_GP_REGS+(PT_R28*8))(r31)
134 ld r29,(SIGCONTEXT_GP_REGS+(PT_R29*8))(r31)
135 ld r30,(SIGCONTEXT_GP_REGS+(PT_R30*8))(r31)
137 /* Now we branch to the "Next Instruction Pointer" from the saved
138 context. With the powerpc64 instruction set there is no good way to
139 do this (from user state) without clobbering either the LR or CTR.
140 The makecontext and swapcontext functions depend on the callers
141 LR being preserved so we use the CTR. */
142 ld r0,(SIGCONTEXT_GP_REGS+(PT_NIP*8))(r31)
144 ld r0,(SIGCONTEXT_GP_REGS+(PT_R0*8))(r31)
145 ld r31,(SIGCONTEXT_GP_REGS+(PT_R31*8))(r31)
149 ld r0,128+FRAME_LR_SAVE(r1)
155 /* At this point we assume that the ucontext was created by a
156 rt_signal and we should use rt_sigreturn to restore the original
157 state. As of the 2.4.21 kernel the ucontext is the first thing
158 (offset 0) in the rt_signal frame and rt_sigreturn expects the
159 ucontext address in R1. Normally the rt-signal trampoline handles
160 this by popping dummy frame before the rt_signal syscall. In our
161 case the stack may not be in its original (signal handler return with
162 R1 pointing at the dummy frame) state. We do have the ucontext
163 address in R3, so simply copy R3 to R1 before the syscall. */
166 li r0,SYS_ify(rt_sigreturn)
170 /* If the kernel is not at least 2.4.21 then generate a ENOSYS stub. */
172 std r0,FRAME_LR_SAVE(r1)
173 cfi_offset(lr,FRAME_LR_SAVE)
175 cfi_adjust_cfa_offset(128)
177 bl JUMPTARGET(__syscall_error)
180 ld r0,128+FRAME_LR_SAVE(r1)
186 PSEUDO_END(__novec_setcontext)
188 compat_symbol (libc, __novec_setcontext, setcontext, GLIBC_2_3)
195 .tc _rtld_global_ro[TC],_rtld_global_ro
197 .tc _dl_hwcap[TC],_dl_hwcap
204 #ifdef __ASSUME_NEW_RT_SIGRETURN_SYSCALL
208 std r0,FRAME_LR_SAVE(r1)
209 cfi_offset (lr, FRAME_LR_SAVE)
211 cfi_adjust_cfa_offset (128)
215 * If this ucontext refers to the point where we were interrupted
216 * by a signal, we have to use the rt_sigreturn system call to
217 * return to the context so we get both LR and CTR restored.
219 * Otherwise, the context we are restoring is either just after
220 * a procedure call (getcontext/swapcontext) or at the beginning
221 * of a procedure call (makecontext), so we don't need to restore
222 * msr and ctr. We don't restore r13 since it will be used as
223 * the TLS pointer. */
224 ld r0,(SIGCONTEXT_GP_REGS+(PT_MSR*8))(r31)
229 addi r4,r3,UCONTEXT_SIGMASK
231 bl JUMPTARGET(__sigprocmask)
236 ld r5,.LC__dl_hwcap@toc(r2)
237 ld r10,(SIGCONTEXT_V_REGS_PTR)(r31)
239 /* Load _rtld-global._dl_hwcap. */
240 ld r5,RTLD_GLOBAL_RO_DL_HWCAP_OFFSET(r5)
242 ld r5,0(r5) /* Load extern _dl_hwcap. */
244 andis. r5,r5,(PPC_FEATURE_HAS_ALTIVEC >> 16)
346 lfd fp0,(SIGCONTEXT_FP_REGS+(32*8))(r31)
347 lfd fp31,(SIGCONTEXT_FP_REGS+(PT_R31*8))(r31)
348 lfd fp30,(SIGCONTEXT_FP_REGS+(PT_R30*8))(r31)
350 lfd fp29,(SIGCONTEXT_FP_REGS+(PT_R29*8))(r31)
351 lfd fp28,(SIGCONTEXT_FP_REGS+(PT_R28*8))(r31)
352 lfd fp27,(SIGCONTEXT_FP_REGS+(PT_R27*8))(r31)
353 lfd fp26,(SIGCONTEXT_FP_REGS+(PT_R26*8))(r31)
354 lfd fp25,(SIGCONTEXT_FP_REGS+(PT_R25*8))(r31)
355 lfd fp24,(SIGCONTEXT_FP_REGS+(PT_R24*8))(r31)
356 lfd fp23,(SIGCONTEXT_FP_REGS+(PT_R23*8))(r31)
357 lfd fp22,(SIGCONTEXT_FP_REGS+(PT_R22*8))(r31)
358 lfd fp21,(SIGCONTEXT_FP_REGS+(PT_R21*8))(r31)
359 lfd fp20,(SIGCONTEXT_FP_REGS+(PT_R20*8))(r31)
360 lfd fp19,(SIGCONTEXT_FP_REGS+(PT_R19*8))(r31)
361 lfd fp18,(SIGCONTEXT_FP_REGS+(PT_R18*8))(r31)
362 lfd fp17,(SIGCONTEXT_FP_REGS+(PT_R17*8))(r31)
363 lfd fp16,(SIGCONTEXT_FP_REGS+(PT_R16*8))(r31)
364 lfd fp15,(SIGCONTEXT_FP_REGS+(PT_R15*8))(r31)
365 lfd fp14,(SIGCONTEXT_FP_REGS+(PT_R14*8))(r31)
366 lfd fp13,(SIGCONTEXT_FP_REGS+(PT_R13*8))(r31)
367 lfd fp12,(SIGCONTEXT_FP_REGS+(PT_R12*8))(r31)
368 lfd fp11,(SIGCONTEXT_FP_REGS+(PT_R11*8))(r31)
369 lfd fp10,(SIGCONTEXT_FP_REGS+(PT_R10*8))(r31)
370 lfd fp9,(SIGCONTEXT_FP_REGS+(PT_R9*8))(r31)
371 lfd fp8,(SIGCONTEXT_FP_REGS+(PT_R8*8))(r31)
372 lfd fp7,(SIGCONTEXT_FP_REGS+(PT_R7*8))(r31)
373 lfd fp6,(SIGCONTEXT_FP_REGS+(PT_R6*8))(r31)
374 lfd fp5,(SIGCONTEXT_FP_REGS+(PT_R5*8))(r31)
375 lfd fp4,(SIGCONTEXT_FP_REGS+(PT_R4*8))(r31)
376 lfd fp3,(SIGCONTEXT_FP_REGS+(PT_R3*8))(r31)
377 lfd fp2,(SIGCONTEXT_FP_REGS+(PT_R2*8))(r31)
378 lfd fp1,(SIGCONTEXT_FP_REGS+(PT_R1*8))(r31)
379 lfd fp0,(SIGCONTEXT_FP_REGS+(PT_R0*8))(r31)
381 ld r0,(SIGCONTEXT_GP_REGS+(PT_LNK*8))(r31)
382 ld r1,(SIGCONTEXT_GP_REGS+(PT_R1*8))(r31)
384 ld r2,(SIGCONTEXT_GP_REGS+(PT_R2*8))(r31)
385 ld r0,(SIGCONTEXT_GP_REGS+(PT_XER*8))(r31)
386 ld r3,(SIGCONTEXT_GP_REGS+(PT_R3*8))(r31)
388 ld r4,(SIGCONTEXT_GP_REGS+(PT_R4*8))(r31)
389 ld r0,(SIGCONTEXT_GP_REGS+(PT_CCR*8))(r31)
390 ld r5,(SIGCONTEXT_GP_REGS+(PT_R5*8))(r31)
391 ld r6,(SIGCONTEXT_GP_REGS+(PT_R6*8))(r31)
392 ld r7,(SIGCONTEXT_GP_REGS+(PT_R7*8))(r31)
393 ld r8,(SIGCONTEXT_GP_REGS+(PT_R8*8))(r31)
394 ld r9,(SIGCONTEXT_GP_REGS+(PT_R9*8))(r31)
396 ld r10,(SIGCONTEXT_GP_REGS+(PT_R10*8))(r31)
397 ld r11,(SIGCONTEXT_GP_REGS+(PT_R11*8))(r31)
398 ld r12,(SIGCONTEXT_GP_REGS+(PT_R12*8))(r31)
399 /* Don't reload the thread ID or TLS pointer (r13). */
400 ld r14,(SIGCONTEXT_GP_REGS+(PT_R14*8))(r31)
401 ld r15,(SIGCONTEXT_GP_REGS+(PT_R15*8))(r31)
402 ld r16,(SIGCONTEXT_GP_REGS+(PT_R16*8))(r31)
403 ld r17,(SIGCONTEXT_GP_REGS+(PT_R17*8))(r31)
404 ld r18,(SIGCONTEXT_GP_REGS+(PT_R18*8))(r31)
405 ld r19,(SIGCONTEXT_GP_REGS+(PT_R19*8))(r31)
406 ld r20,(SIGCONTEXT_GP_REGS+(PT_R20*8))(r31)
407 ld r21,(SIGCONTEXT_GP_REGS+(PT_R21*8))(r31)
408 ld r22,(SIGCONTEXT_GP_REGS+(PT_R22*8))(r31)
409 ld r23,(SIGCONTEXT_GP_REGS+(PT_R23*8))(r31)
410 ld r24,(SIGCONTEXT_GP_REGS+(PT_R24*8))(r31)
411 ld r25,(SIGCONTEXT_GP_REGS+(PT_R25*8))(r31)
412 ld r26,(SIGCONTEXT_GP_REGS+(PT_R26*8))(r31)
413 ld r27,(SIGCONTEXT_GP_REGS+(PT_R27*8))(r31)
414 ld r28,(SIGCONTEXT_GP_REGS+(PT_R28*8))(r31)
415 ld r29,(SIGCONTEXT_GP_REGS+(PT_R29*8))(r31)
416 ld r30,(SIGCONTEXT_GP_REGS+(PT_R30*8))(r31)
418 /* Now we branch to the "Next Instruction Pointer" from the saved
419 context. With the powerpc64 instruction set there is no good way to
420 do this (from user state) without clobbering either the LR or CTR.
421 The makecontext and swapcontext functions depend on the callers
422 LR being preserved so we use the CTR. */
423 ld r0,(SIGCONTEXT_GP_REGS+(PT_NIP*8))(r31)
425 ld r0,(SIGCONTEXT_GP_REGS+(PT_R0*8))(r31)
426 ld r31,(SIGCONTEXT_GP_REGS+(PT_R31*8))(r31)
430 ld r0,128+FRAME_LR_SAVE(r1)
436 /* At this point we assume that the ucontext was created by a
437 rt_signal and we should use rt_sigreturn to restore the original
438 state. As of the 2.4.21 kernel the ucontext is the first thing
439 (offset 0) in the rt_signal frame and rt_sigreturn expects the
440 ucontext address in R1. Normally the rt-signal trampoline handles
441 this by popping dummy frame before the rt_signal syscall. In our
442 case the stack may not be in its original (signal handler return with
443 R1 pointing at the dummy frame) state. We do have the ucontext
444 address in R3, so simply copy R3 to R1 before the syscall. */
447 li r0,SYS_ify(rt_sigreturn)
451 /* If the kernel is not at least 2.4.21 then generate a ENOSYS stub. */
453 std r0,FRAME_LR_SAVE(r1)
454 cfi_offset (lr, FRAME_LR_SAVE)
456 cfi_adjust_cfa_offset (128)
458 bl JUMPTARGET(__syscall_error)
461 ld r0,128+FRAME_LR_SAVE(r1)
467 PSEUDO_END(__setcontext)
469 versioned_symbol (libc, __setcontext, setcontext, GLIBC_2_3_4)