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
36 std r0,FRAME_LR_SAVE(r1)
37 cfi_offset (lr, FRAME_LR_SAVE)
39 cfi_adjust_cfa_offset (128)
43 * If this ucontext refers to the point where we were interrupted
44 * by a signal, we have to use the rt_sigreturn system call to
45 * return to the context so we get both LR and CTR restored.
47 * Otherwise, the context we are restoring is either just after
48 * a procedure call (getcontext/swapcontext) or at the beginning
49 * of a procedure call (makecontext), so we don't need to restore
50 * msr and ctr. We don't restore r13 since it will be used as
52 ld r0,(SIGCONTEXT_GP_REGS+(PT_MSR*8))(r31)
57 addi r4,r3,UCONTEXT_SIGMASK
59 bl JUMPTARGET(__sigprocmask)
64 lfd fp0,(SIGCONTEXT_FP_REGS+(32*8))(r31)
65 lfd fp31,(SIGCONTEXT_FP_REGS+(PT_R31*8))(r31)
66 lfd fp30,(SIGCONTEXT_FP_REGS+(PT_R30*8))(r31)
68 lfd fp29,(SIGCONTEXT_FP_REGS+(PT_R29*8))(r31)
69 lfd fp28,(SIGCONTEXT_FP_REGS+(PT_R28*8))(r31)
70 lfd fp27,(SIGCONTEXT_FP_REGS+(PT_R27*8))(r31)
71 lfd fp26,(SIGCONTEXT_FP_REGS+(PT_R26*8))(r31)
72 lfd fp25,(SIGCONTEXT_FP_REGS+(PT_R25*8))(r31)
73 lfd fp24,(SIGCONTEXT_FP_REGS+(PT_R24*8))(r31)
74 lfd fp23,(SIGCONTEXT_FP_REGS+(PT_R23*8))(r31)
75 lfd fp22,(SIGCONTEXT_FP_REGS+(PT_R22*8))(r31)
76 lfd fp21,(SIGCONTEXT_FP_REGS+(PT_R21*8))(r31)
77 lfd fp20,(SIGCONTEXT_FP_REGS+(PT_R20*8))(r31)
78 lfd fp19,(SIGCONTEXT_FP_REGS+(PT_R19*8))(r31)
79 lfd fp18,(SIGCONTEXT_FP_REGS+(PT_R18*8))(r31)
80 lfd fp17,(SIGCONTEXT_FP_REGS+(PT_R17*8))(r31)
81 lfd fp16,(SIGCONTEXT_FP_REGS+(PT_R16*8))(r31)
82 lfd fp15,(SIGCONTEXT_FP_REGS+(PT_R15*8))(r31)
83 lfd fp14,(SIGCONTEXT_FP_REGS+(PT_R14*8))(r31)
84 lfd fp13,(SIGCONTEXT_FP_REGS+(PT_R13*8))(r31)
85 lfd fp12,(SIGCONTEXT_FP_REGS+(PT_R12*8))(r31)
86 lfd fp11,(SIGCONTEXT_FP_REGS+(PT_R11*8))(r31)
87 lfd fp10,(SIGCONTEXT_FP_REGS+(PT_R10*8))(r31)
88 lfd fp9,(SIGCONTEXT_FP_REGS+(PT_R9*8))(r31)
89 lfd fp8,(SIGCONTEXT_FP_REGS+(PT_R8*8))(r31)
90 lfd fp7,(SIGCONTEXT_FP_REGS+(PT_R7*8))(r31)
91 lfd fp6,(SIGCONTEXT_FP_REGS+(PT_R6*8))(r31)
92 lfd fp5,(SIGCONTEXT_FP_REGS+(PT_R5*8))(r31)
93 lfd fp4,(SIGCONTEXT_FP_REGS+(PT_R4*8))(r31)
94 lfd fp3,(SIGCONTEXT_FP_REGS+(PT_R3*8))(r31)
95 lfd fp2,(SIGCONTEXT_FP_REGS+(PT_R2*8))(r31)
96 lfd fp1,(SIGCONTEXT_FP_REGS+(PT_R1*8))(r31)
97 lfd fp0,(SIGCONTEXT_FP_REGS+(PT_R0*8))(r31)
99 ld r0,(SIGCONTEXT_GP_REGS+(PT_LNK*8))(r31)
100 ld r1,(SIGCONTEXT_GP_REGS+(PT_R1*8))(r31)
102 ld r2,(SIGCONTEXT_GP_REGS+(PT_R2*8))(r31)
103 ld r0,(SIGCONTEXT_GP_REGS+(PT_XER*8))(r31)
104 ld r3,(SIGCONTEXT_GP_REGS+(PT_R3*8))(r31)
106 ld r4,(SIGCONTEXT_GP_REGS+(PT_R4*8))(r31)
107 ld r0,(SIGCONTEXT_GP_REGS+(PT_CCR*8))(r31)
108 ld r5,(SIGCONTEXT_GP_REGS+(PT_R5*8))(r31)
110 ld r6,(SIGCONTEXT_GP_REGS+(PT_R6*8))(r31)
111 ld r7,(SIGCONTEXT_GP_REGS+(PT_R7*8))(r31)
112 ld r8,(SIGCONTEXT_GP_REGS+(PT_R8*8))(r31)
113 ld r9,(SIGCONTEXT_GP_REGS+(PT_R9*8))(r31)
114 ld r10,(SIGCONTEXT_GP_REGS+(PT_R10*8))(r31)
115 ld r11,(SIGCONTEXT_GP_REGS+(PT_R11*8))(r31)
116 ld r12,(SIGCONTEXT_GP_REGS+(PT_R12*8))(r31)
117 /* Don't reload the thread ID or TLS pointer (r13). */
118 ld r14,(SIGCONTEXT_GP_REGS+(PT_R14*8))(r31)
119 ld r15,(SIGCONTEXT_GP_REGS+(PT_R15*8))(r31)
120 ld r16,(SIGCONTEXT_GP_REGS+(PT_R16*8))(r31)
121 ld r17,(SIGCONTEXT_GP_REGS+(PT_R17*8))(r31)
122 ld r18,(SIGCONTEXT_GP_REGS+(PT_R18*8))(r31)
123 ld r19,(SIGCONTEXT_GP_REGS+(PT_R19*8))(r31)
124 ld r20,(SIGCONTEXT_GP_REGS+(PT_R20*8))(r31)
125 ld r21,(SIGCONTEXT_GP_REGS+(PT_R21*8))(r31)
126 ld r22,(SIGCONTEXT_GP_REGS+(PT_R22*8))(r31)
127 ld r23,(SIGCONTEXT_GP_REGS+(PT_R23*8))(r31)
128 ld r24,(SIGCONTEXT_GP_REGS+(PT_R24*8))(r31)
129 ld r25,(SIGCONTEXT_GP_REGS+(PT_R25*8))(r31)
130 ld r26,(SIGCONTEXT_GP_REGS+(PT_R26*8))(r31)
131 ld r27,(SIGCONTEXT_GP_REGS+(PT_R27*8))(r31)
132 ld r28,(SIGCONTEXT_GP_REGS+(PT_R28*8))(r31)
133 ld r29,(SIGCONTEXT_GP_REGS+(PT_R29*8))(r31)
134 ld r30,(SIGCONTEXT_GP_REGS+(PT_R30*8))(r31)
136 /* Now we branch to the "Next Instruction Pointer" from the saved
137 context. With the powerpc64 instruction set there is no good way to
138 do this (from user state) without clobbering either the LR or CTR.
139 The makecontext and swapcontext functions depend on the callers
140 LR being preserved so we use the CTR. */
141 ld r0,(SIGCONTEXT_GP_REGS+(PT_NIP*8))(r31)
143 ld r0,(SIGCONTEXT_GP_REGS+(PT_R0*8))(r31)
144 ld r31,(SIGCONTEXT_GP_REGS+(PT_R31*8))(r31)
148 ld r0,128+FRAME_LR_SAVE(r1)
154 /* At this point we assume that the ucontext was created by a
155 rt_signal and we should use rt_sigreturn to restore the original
156 state. As of the 2.4.21 kernel the ucontext is the first thing
157 (offset 0) in the rt_signal frame and rt_sigreturn expects the
158 ucontext address in R1. Normally the rt-signal trampoline handles
159 this by popping dummy frame before the rt_signal syscall. In our
160 case the stack may not be in its original (signal handler return with
161 R1 pointing at the dummy frame) state. We do have the ucontext
162 address in R3, so simply copy R3 to R1 before the syscall. */
165 li r0,SYS_ify(rt_sigreturn)
169 /* If the kernel is not at least 2.4.21 then generate a ENOSYS stub. */
171 std r0,FRAME_LR_SAVE(r1)
174 bl JUMPTARGET(__syscall_error)
177 ld r0,128+FRAME_LR_SAVE(r1)
183 PSEUDO_END(__novec_setcontext)
185 compat_symbol (libc, __novec_setcontext, setcontext, GLIBC_2_3)
192 .tc _rtld_global_ro[TC],_rtld_global_ro
194 .tc _dl_hwcap[TC],_dl_hwcap
201 #ifdef __ASSUME_NEW_RT_SIGRETURN_SYSCALL
204 std r0,FRAME_LR_SAVE(r1)
205 cfi_offset (lr, FRAME_LR_SAVE)
207 cfi_adjust_cfa_offset (128)
211 * If this ucontext refers to the point where we were interrupted
212 * by a signal, we have to use the rt_sigreturn system call to
213 * return to the context so we get both LR and CTR restored.
215 * Otherwise, the context we are restoring is either just after
216 * a procedure call (getcontext/swapcontext) or at the beginning
217 * of a procedure call (makecontext), so we don't need to restore
218 * msr and ctr. We don't restore r13 since it will be used as
219 * the TLS pointer. */
220 ld r0,(SIGCONTEXT_GP_REGS+(PT_MSR*8))(r31)
225 addi r4,r3,UCONTEXT_SIGMASK
227 bl JUMPTARGET(__sigprocmask)
232 ld r5,.LC__dl_hwcap@toc(r2)
233 ld r10,(SIGCONTEXT_V_REGS_PTR)(r31)
235 /* Load _rtld-global._dl_hwcap. */
236 ld r5,RTLD_GLOBAL_RO_DL_HWCAP_OFFSET(r5)
238 ld r5,0(r5) /* Load extern _dl_hwcap. */
240 andis. r5,r5,(PPC_FEATURE_HAS_ALTIVEC >> 16)
342 lfd fp0,(SIGCONTEXT_FP_REGS+(32*8))(r31)
343 lfd fp31,(SIGCONTEXT_FP_REGS+(PT_R31*8))(r31)
344 lfd fp30,(SIGCONTEXT_FP_REGS+(PT_R30*8))(r31)
346 lfd fp29,(SIGCONTEXT_FP_REGS+(PT_R29*8))(r31)
347 lfd fp28,(SIGCONTEXT_FP_REGS+(PT_R28*8))(r31)
348 lfd fp27,(SIGCONTEXT_FP_REGS+(PT_R27*8))(r31)
349 lfd fp26,(SIGCONTEXT_FP_REGS+(PT_R26*8))(r31)
350 lfd fp25,(SIGCONTEXT_FP_REGS+(PT_R25*8))(r31)
351 lfd fp24,(SIGCONTEXT_FP_REGS+(PT_R24*8))(r31)
352 lfd fp23,(SIGCONTEXT_FP_REGS+(PT_R23*8))(r31)
353 lfd fp22,(SIGCONTEXT_FP_REGS+(PT_R22*8))(r31)
354 lfd fp21,(SIGCONTEXT_FP_REGS+(PT_R21*8))(r31)
355 lfd fp20,(SIGCONTEXT_FP_REGS+(PT_R20*8))(r31)
356 lfd fp19,(SIGCONTEXT_FP_REGS+(PT_R19*8))(r31)
357 lfd fp18,(SIGCONTEXT_FP_REGS+(PT_R18*8))(r31)
358 lfd fp17,(SIGCONTEXT_FP_REGS+(PT_R17*8))(r31)
359 lfd fp16,(SIGCONTEXT_FP_REGS+(PT_R16*8))(r31)
360 lfd fp15,(SIGCONTEXT_FP_REGS+(PT_R15*8))(r31)
361 lfd fp14,(SIGCONTEXT_FP_REGS+(PT_R14*8))(r31)
362 lfd fp13,(SIGCONTEXT_FP_REGS+(PT_R13*8))(r31)
363 lfd fp12,(SIGCONTEXT_FP_REGS+(PT_R12*8))(r31)
364 lfd fp11,(SIGCONTEXT_FP_REGS+(PT_R11*8))(r31)
365 lfd fp10,(SIGCONTEXT_FP_REGS+(PT_R10*8))(r31)
366 lfd fp9,(SIGCONTEXT_FP_REGS+(PT_R9*8))(r31)
367 lfd fp8,(SIGCONTEXT_FP_REGS+(PT_R8*8))(r31)
368 lfd fp7,(SIGCONTEXT_FP_REGS+(PT_R7*8))(r31)
369 lfd fp6,(SIGCONTEXT_FP_REGS+(PT_R6*8))(r31)
370 lfd fp5,(SIGCONTEXT_FP_REGS+(PT_R5*8))(r31)
371 lfd fp4,(SIGCONTEXT_FP_REGS+(PT_R4*8))(r31)
372 lfd fp3,(SIGCONTEXT_FP_REGS+(PT_R3*8))(r31)
373 lfd fp2,(SIGCONTEXT_FP_REGS+(PT_R2*8))(r31)
374 lfd fp1,(SIGCONTEXT_FP_REGS+(PT_R1*8))(r31)
375 lfd fp0,(SIGCONTEXT_FP_REGS+(PT_R0*8))(r31)
377 ld r0,(SIGCONTEXT_GP_REGS+(PT_LNK*8))(r31)
378 ld r1,(SIGCONTEXT_GP_REGS+(PT_R1*8))(r31)
380 ld r2,(SIGCONTEXT_GP_REGS+(PT_R2*8))(r31)
381 ld r0,(SIGCONTEXT_GP_REGS+(PT_XER*8))(r31)
382 ld r3,(SIGCONTEXT_GP_REGS+(PT_R3*8))(r31)
384 ld r4,(SIGCONTEXT_GP_REGS+(PT_R4*8))(r31)
385 ld r0,(SIGCONTEXT_GP_REGS+(PT_CCR*8))(r31)
386 ld r5,(SIGCONTEXT_GP_REGS+(PT_R5*8))(r31)
387 ld r6,(SIGCONTEXT_GP_REGS+(PT_R6*8))(r31)
388 ld r7,(SIGCONTEXT_GP_REGS+(PT_R7*8))(r31)
389 ld r8,(SIGCONTEXT_GP_REGS+(PT_R8*8))(r31)
390 ld r9,(SIGCONTEXT_GP_REGS+(PT_R9*8))(r31)
392 ld r10,(SIGCONTEXT_GP_REGS+(PT_R10*8))(r31)
393 ld r11,(SIGCONTEXT_GP_REGS+(PT_R11*8))(r31)
394 ld r12,(SIGCONTEXT_GP_REGS+(PT_R12*8))(r31)
395 /* Don't reload the thread ID or TLS pointer (r13). */
396 ld r14,(SIGCONTEXT_GP_REGS+(PT_R14*8))(r31)
397 ld r15,(SIGCONTEXT_GP_REGS+(PT_R15*8))(r31)
398 ld r16,(SIGCONTEXT_GP_REGS+(PT_R16*8))(r31)
399 ld r17,(SIGCONTEXT_GP_REGS+(PT_R17*8))(r31)
400 ld r18,(SIGCONTEXT_GP_REGS+(PT_R18*8))(r31)
401 ld r19,(SIGCONTEXT_GP_REGS+(PT_R19*8))(r31)
402 ld r20,(SIGCONTEXT_GP_REGS+(PT_R20*8))(r31)
403 ld r21,(SIGCONTEXT_GP_REGS+(PT_R21*8))(r31)
404 ld r22,(SIGCONTEXT_GP_REGS+(PT_R22*8))(r31)
405 ld r23,(SIGCONTEXT_GP_REGS+(PT_R23*8))(r31)
406 ld r24,(SIGCONTEXT_GP_REGS+(PT_R24*8))(r31)
407 ld r25,(SIGCONTEXT_GP_REGS+(PT_R25*8))(r31)
408 ld r26,(SIGCONTEXT_GP_REGS+(PT_R26*8))(r31)
409 ld r27,(SIGCONTEXT_GP_REGS+(PT_R27*8))(r31)
410 ld r28,(SIGCONTEXT_GP_REGS+(PT_R28*8))(r31)
411 ld r29,(SIGCONTEXT_GP_REGS+(PT_R29*8))(r31)
412 ld r30,(SIGCONTEXT_GP_REGS+(PT_R30*8))(r31)
414 /* Now we branch to the "Next Instruction Pointer" from the saved
415 context. With the powerpc64 instruction set there is no good way to
416 do this (from user state) without clobbering either the LR or CTR.
417 The makecontext and swapcontext functions depend on the callers
418 LR being preserved so we use the CTR. */
419 ld r0,(SIGCONTEXT_GP_REGS+(PT_NIP*8))(r31)
421 ld r0,(SIGCONTEXT_GP_REGS+(PT_R0*8))(r31)
422 ld r31,(SIGCONTEXT_GP_REGS+(PT_R31*8))(r31)
426 ld r0,128+FRAME_LR_SAVE(r1)
432 /* At this point we assume that the ucontext was created by a
433 rt_signal and we should use rt_sigreturn to restore the original
434 state. As of the 2.4.21 kernel the ucontext is the first thing
435 (offset 0) in the rt_signal frame and rt_sigreturn expects the
436 ucontext address in R1. Normally the rt-signal trampoline handles
437 this by popping dummy frame before the rt_signal syscall. In our
438 case the stack may not be in its original (signal handler return with
439 R1 pointing at the dummy frame) state. We do have the ucontext
440 address in R3, so simply copy R3 to R1 before the syscall. */
443 li r0,SYS_ify(rt_sigreturn)
447 /* If the kernel is not at least 2.4.21 then generate a ENOSYS stub. */
449 std r0,FRAME_LR_SAVE(r1)
450 cfi_offset (lr, FRAME_LR_SAVE)
452 cfi_adjust_cfa_offset (128)
454 bl JUMPTARGET(__syscall_error)
457 ld r0,128+FRAME_LR_SAVE(r1)
463 PSEUDO_END(__setcontext)
465 versioned_symbol (libc, __setcontext, setcontext, GLIBC_2_3_4)