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)
32 #ifdef __ASSUME_NEW_RT_SIGRETURN_SYSCALL
35 std r0,FRAME_LR_SAVE(r1)
40 * If this ucontext refers to the point where we were interrupted
41 * by a signal, we have to use the rt_sigreturn system call to
42 * return to the context so we get both LR and CTR restored.
44 * Otherwise, the context we are restoring is either just after
45 * a procedure call (getcontext/swapcontext) or at the beginning
46 * of a procedure call (makecontext), so we don't need to restore
47 * msr and ctr. We don't restore r13 since it will be used as
49 lwz r0,(SIGCONTEXT_GP_REGS+(PT_MSR*8))(r31)
54 addi r4,r3,UCONTEXT_SIGMASK
56 bl JUMPTARGET(sigprocmask)
61 lfd fp0,(SIGCONTEXT_FP_REGS+(32*8))(r31)
62 lfd fp31,(SIGCONTEXT_FP_REGS+(PT_R31*8))(r31)
63 lfd fp30,(SIGCONTEXT_FP_REGS+(PT_R30*8))(r31)
65 lfd fp29,(SIGCONTEXT_FP_REGS+(PT_R29*8))(r31)
66 lfd fp28,(SIGCONTEXT_FP_REGS+(PT_R28*8))(r31)
67 lfd fp27,(SIGCONTEXT_FP_REGS+(PT_R27*8))(r31)
68 lfd fp26,(SIGCONTEXT_FP_REGS+(PT_R26*8))(r31)
69 lfd fp25,(SIGCONTEXT_FP_REGS+(PT_R25*8))(r31)
70 lfd fp24,(SIGCONTEXT_FP_REGS+(PT_R24*8))(r31)
71 lfd fp23,(SIGCONTEXT_FP_REGS+(PT_R23*8))(r31)
72 lfd fp22,(SIGCONTEXT_FP_REGS+(PT_R22*8))(r31)
73 lfd fp21,(SIGCONTEXT_FP_REGS+(PT_R21*8))(r31)
74 lfd fp20,(SIGCONTEXT_FP_REGS+(PT_R20*8))(r31)
75 lfd fp19,(SIGCONTEXT_FP_REGS+(PT_R19*8))(r31)
76 lfd fp18,(SIGCONTEXT_FP_REGS+(PT_R18*8))(r31)
77 lfd fp17,(SIGCONTEXT_FP_REGS+(PT_R17*8))(r31)
78 lfd fp16,(SIGCONTEXT_FP_REGS+(PT_R16*8))(r31)
79 lfd fp15,(SIGCONTEXT_FP_REGS+(PT_R15*8))(r31)
80 lfd fp14,(SIGCONTEXT_FP_REGS+(PT_R14*8))(r31)
81 lfd fp13,(SIGCONTEXT_FP_REGS+(PT_R13*8))(r31)
82 lfd fp12,(SIGCONTEXT_FP_REGS+(PT_R12*8))(r31)
83 lfd fp11,(SIGCONTEXT_FP_REGS+(PT_R11*8))(r31)
84 lfd fp10,(SIGCONTEXT_FP_REGS+(PT_R10*8))(r31)
85 lfd fp9,(SIGCONTEXT_FP_REGS+(PT_R9*8))(r31)
86 lfd fp8,(SIGCONTEXT_FP_REGS+(PT_R8*8))(r31)
87 lfd fp7,(SIGCONTEXT_FP_REGS+(PT_R7*8))(r31)
88 lfd fp6,(SIGCONTEXT_FP_REGS+(PT_R6*8))(r31)
89 lfd fp5,(SIGCONTEXT_FP_REGS+(PT_R5*8))(r31)
90 lfd fp4,(SIGCONTEXT_FP_REGS+(PT_R4*8))(r31)
91 lfd fp3,(SIGCONTEXT_FP_REGS+(PT_R3*8))(r31)
92 lfd fp2,(SIGCONTEXT_FP_REGS+(PT_R2*8))(r31)
93 lfd fp1,(SIGCONTEXT_FP_REGS+(PT_R1*8))(r31)
94 lfd fp0,(SIGCONTEXT_FP_REGS+(PT_R0*8))(r31)
96 ld r0,(SIGCONTEXT_GP_REGS+(PT_LNK*8))(r31)
97 ld r1,(SIGCONTEXT_GP_REGS+(PT_R1*8))(r31)
99 ld r2,(SIGCONTEXT_GP_REGS+(PT_R2*8))(r31)
100 ld r0,(SIGCONTEXT_GP_REGS+(PT_XER*8))(r31)
101 ld r3,(SIGCONTEXT_GP_REGS+(PT_R3*8))(r31)
103 ld r4,(SIGCONTEXT_GP_REGS+(PT_R4*8))(r31)
104 ld r0,(SIGCONTEXT_GP_REGS+(PT_CCR*8))(r31)
105 ld r5,(SIGCONTEXT_GP_REGS+(PT_R5*8))(r31)
107 ld r6,(SIGCONTEXT_GP_REGS+(PT_R6*8))(r31)
108 ld r7,(SIGCONTEXT_GP_REGS+(PT_R7*8))(r31)
109 ld r8,(SIGCONTEXT_GP_REGS+(PT_R8*8))(r31)
110 ld r9,(SIGCONTEXT_GP_REGS+(PT_R9*8))(r31)
111 ld r10,(SIGCONTEXT_GP_REGS+(PT_R10*8))(r31)
112 ld r11,(SIGCONTEXT_GP_REGS+(PT_R11*8))(r31)
113 ld r12,(SIGCONTEXT_GP_REGS+(PT_R12*8))(r31)
114 /* Don't reload the thread ID or TLS pointer (r13). */
115 ld r14,(SIGCONTEXT_GP_REGS+(PT_R14*8))(r31)
116 ld r15,(SIGCONTEXT_GP_REGS+(PT_R15*8))(r31)
117 ld r16,(SIGCONTEXT_GP_REGS+(PT_R16*8))(r31)
118 ld r17,(SIGCONTEXT_GP_REGS+(PT_R17*8))(r31)
119 ld r18,(SIGCONTEXT_GP_REGS+(PT_R18*8))(r31)
120 ld r19,(SIGCONTEXT_GP_REGS+(PT_R19*8))(r31)
121 ld r20,(SIGCONTEXT_GP_REGS+(PT_R20*8))(r31)
122 ld r21,(SIGCONTEXT_GP_REGS+(PT_R21*8))(r31)
123 ld r22,(SIGCONTEXT_GP_REGS+(PT_R22*8))(r31)
124 ld r23,(SIGCONTEXT_GP_REGS+(PT_R23*8))(r31)
125 ld r24,(SIGCONTEXT_GP_REGS+(PT_R24*8))(r31)
126 ld r25,(SIGCONTEXT_GP_REGS+(PT_R25*8))(r31)
127 ld r26,(SIGCONTEXT_GP_REGS+(PT_R26*8))(r31)
128 ld r27,(SIGCONTEXT_GP_REGS+(PT_R27*8))(r31)
129 ld r28,(SIGCONTEXT_GP_REGS+(PT_R28*8))(r31)
130 ld r29,(SIGCONTEXT_GP_REGS+(PT_R29*8))(r31)
131 ld r30,(SIGCONTEXT_GP_REGS+(PT_R30*8))(r31)
133 /* Now we branch to the "Next Instruction Pointer" from the saved
134 context. With the powerpc64 instruction set there is no good way to
135 do this (from user state) without clobbering either the LR or CTR.
136 The makecontext and swapcontext functions depend on the callers
137 LR being preserved so we use the CTR. */
138 ld r0,(SIGCONTEXT_GP_REGS+(PT_NIP*8))(r31)
140 ld r0,(SIGCONTEXT_GP_REGS+(PT_R0*8))(r31)
141 ld r31,(SIGCONTEXT_GP_REGS+(PT_R31*8))(r31)
145 ld r0,128+FRAME_LR_SAVE(r1)
151 /* At this point we assume that the ucontext was created by a
152 rt_signal and we should use rt_sigreturn to restore the original
153 state. As of the 2.4.21 kernel the ucontext is the first thing
154 (offset 0) in the rt_signal frame and rt_sigreturn expects the
155 ucontext address in R1. Normally the rt-signal trampoline handles
156 this by popping dummy frame before the rt_signal syscall. In our
157 case the stack may not be in its original (signal handler return with
158 R1 pointing at the dummy frame) state. We do have the ucontext
159 address in R3, so simply copy R3 to R1 before the syscall. */
162 li r0,SYS_ify(rt_sigreturn)
166 /* If the kernel is not at least 2.4.21 then generate a ENOSYS stub. */
168 std r0,FRAME_LR_SAVE(r1)
171 bl JUMPTARGET(__syscall_error)
174 ld r0,128+FRAME_LR_SAVE(r1)
180 PSEUDO_END(__novec_setcontext)
182 compat_symbol (libc, __novec_setcontext, setcontext, GLIBC_2_3)
189 .tc _rtld_global[TC],_rtld_global
191 .tc _dl_hwcap[TC],_dl_hwcap
196 #ifdef __ASSUME_NEW_RT_SIGRETURN_SYSCALL
199 std r0,FRAME_LR_SAVE(r1)
204 * If this ucontext refers to the point where we were interrupted
205 * by a signal, we have to use the rt_sigreturn system call to
206 * return to the context so we get both LR and CTR restored.
208 * Otherwise, the context we are restoring is either just after
209 * a procedure call (getcontext/swapcontext) or at the beginning
210 * of a procedure call (makecontext), so we don't need to restore
211 * msr and ctr. We don't restore r13 since it will be used as
212 * the TLS pointer. */
213 lwz r0,(SIGCONTEXT_GP_REGS+(PT_MSR*8))(r31)
218 addi r4,r3,UCONTEXT_SIGMASK
220 bl JUMPTARGET(sigprocmask)
225 ld r5,.LC__dl_hwcap@toc(r2)
226 ld r10,(SIGCONTEXT_V_REGS_PTR)(r31)
228 /* Load _rtld-global._dl_hwcap. */
229 ld r5,RTLD_GLOBAL_DL_HWCAP_OFFSET(r5)
231 ld r5,0(r5) /* Load extern _dl_hwcap. */
233 andis. r5,r5,(PPC_FEATURE_HAS_ALTIVEC >> 16)
335 lfd fp0,(SIGCONTEXT_FP_REGS+(32*8))(r31)
336 lfd fp31,(SIGCONTEXT_FP_REGS+(PT_R31*8))(r31)
337 lfd fp30,(SIGCONTEXT_FP_REGS+(PT_R30*8))(r31)
339 lfd fp29,(SIGCONTEXT_FP_REGS+(PT_R29*8))(r31)
340 lfd fp28,(SIGCONTEXT_FP_REGS+(PT_R28*8))(r31)
341 lfd fp27,(SIGCONTEXT_FP_REGS+(PT_R27*8))(r31)
342 lfd fp26,(SIGCONTEXT_FP_REGS+(PT_R26*8))(r31)
343 lfd fp25,(SIGCONTEXT_FP_REGS+(PT_R25*8))(r31)
344 lfd fp24,(SIGCONTEXT_FP_REGS+(PT_R24*8))(r31)
345 lfd fp23,(SIGCONTEXT_FP_REGS+(PT_R23*8))(r31)
346 lfd fp22,(SIGCONTEXT_FP_REGS+(PT_R22*8))(r31)
347 lfd fp21,(SIGCONTEXT_FP_REGS+(PT_R21*8))(r31)
348 lfd fp20,(SIGCONTEXT_FP_REGS+(PT_R20*8))(r31)
349 lfd fp19,(SIGCONTEXT_FP_REGS+(PT_R19*8))(r31)
350 lfd fp18,(SIGCONTEXT_FP_REGS+(PT_R18*8))(r31)
351 lfd fp17,(SIGCONTEXT_FP_REGS+(PT_R17*8))(r31)
352 lfd fp16,(SIGCONTEXT_FP_REGS+(PT_R16*8))(r31)
353 lfd fp15,(SIGCONTEXT_FP_REGS+(PT_R15*8))(r31)
354 lfd fp14,(SIGCONTEXT_FP_REGS+(PT_R14*8))(r31)
355 lfd fp13,(SIGCONTEXT_FP_REGS+(PT_R13*8))(r31)
356 lfd fp12,(SIGCONTEXT_FP_REGS+(PT_R12*8))(r31)
357 lfd fp11,(SIGCONTEXT_FP_REGS+(PT_R11*8))(r31)
358 lfd fp10,(SIGCONTEXT_FP_REGS+(PT_R10*8))(r31)
359 lfd fp9,(SIGCONTEXT_FP_REGS+(PT_R9*8))(r31)
360 lfd fp8,(SIGCONTEXT_FP_REGS+(PT_R8*8))(r31)
361 lfd fp7,(SIGCONTEXT_FP_REGS+(PT_R7*8))(r31)
362 lfd fp6,(SIGCONTEXT_FP_REGS+(PT_R6*8))(r31)
363 lfd fp5,(SIGCONTEXT_FP_REGS+(PT_R5*8))(r31)
364 lfd fp4,(SIGCONTEXT_FP_REGS+(PT_R4*8))(r31)
365 lfd fp3,(SIGCONTEXT_FP_REGS+(PT_R3*8))(r31)
366 lfd fp2,(SIGCONTEXT_FP_REGS+(PT_R2*8))(r31)
367 lfd fp1,(SIGCONTEXT_FP_REGS+(PT_R1*8))(r31)
368 lfd fp0,(SIGCONTEXT_FP_REGS+(PT_R0*8))(r31)
370 ld r0,(SIGCONTEXT_GP_REGS+(PT_LNK*8))(r31)
371 ld r1,(SIGCONTEXT_GP_REGS+(PT_R1*8))(r31)
373 ld r2,(SIGCONTEXT_GP_REGS+(PT_R2*8))(r31)
374 ld r0,(SIGCONTEXT_GP_REGS+(PT_XER*8))(r31)
375 ld r3,(SIGCONTEXT_GP_REGS+(PT_R3*8))(r31)
377 ld r4,(SIGCONTEXT_GP_REGS+(PT_R4*8))(r31)
378 ld r0,(SIGCONTEXT_GP_REGS+(PT_CCR*8))(r31)
379 ld r5,(SIGCONTEXT_GP_REGS+(PT_R5*8))(r31)
381 ld r6,(SIGCONTEXT_GP_REGS+(PT_R6*8))(r31)
382 ld r7,(SIGCONTEXT_GP_REGS+(PT_R7*8))(r31)
383 ld r8,(SIGCONTEXT_GP_REGS+(PT_R8*8))(r31)
384 ld r9,(SIGCONTEXT_GP_REGS+(PT_R9*8))(r31)
385 ld r10,(SIGCONTEXT_GP_REGS+(PT_R10*8))(r31)
386 ld r11,(SIGCONTEXT_GP_REGS+(PT_R11*8))(r31)
387 ld r12,(SIGCONTEXT_GP_REGS+(PT_R12*8))(r31)
388 /* Don't reload the thread ID or TLS pointer (r13). */
389 ld r14,(SIGCONTEXT_GP_REGS+(PT_R14*8))(r31)
390 ld r15,(SIGCONTEXT_GP_REGS+(PT_R15*8))(r31)
391 ld r16,(SIGCONTEXT_GP_REGS+(PT_R16*8))(r31)
392 ld r17,(SIGCONTEXT_GP_REGS+(PT_R17*8))(r31)
393 ld r18,(SIGCONTEXT_GP_REGS+(PT_R18*8))(r31)
394 ld r19,(SIGCONTEXT_GP_REGS+(PT_R19*8))(r31)
395 ld r20,(SIGCONTEXT_GP_REGS+(PT_R20*8))(r31)
396 ld r21,(SIGCONTEXT_GP_REGS+(PT_R21*8))(r31)
397 ld r22,(SIGCONTEXT_GP_REGS+(PT_R22*8))(r31)
398 ld r23,(SIGCONTEXT_GP_REGS+(PT_R23*8))(r31)
399 ld r24,(SIGCONTEXT_GP_REGS+(PT_R24*8))(r31)
400 ld r25,(SIGCONTEXT_GP_REGS+(PT_R25*8))(r31)
401 ld r26,(SIGCONTEXT_GP_REGS+(PT_R26*8))(r31)
402 ld r27,(SIGCONTEXT_GP_REGS+(PT_R27*8))(r31)
403 ld r28,(SIGCONTEXT_GP_REGS+(PT_R28*8))(r31)
404 ld r29,(SIGCONTEXT_GP_REGS+(PT_R29*8))(r31)
405 ld r30,(SIGCONTEXT_GP_REGS+(PT_R30*8))(r31)
407 /* Now we branch to the "Next Instruction Pointer" from the saved
408 context. With the powerpc64 instruction set there is no good way to
409 do this (from user state) without clobbering either the LR or CTR.
410 The makecontext and swapcontext functions depend on the callers
411 LR being preserved so we use the CTR. */
412 ld r0,(SIGCONTEXT_GP_REGS+(PT_NIP*8))(r31)
414 ld r0,(SIGCONTEXT_GP_REGS+(PT_R0*8))(r31)
415 ld r31,(SIGCONTEXT_GP_REGS+(PT_R31*8))(r31)
419 ld r0,128+FRAME_LR_SAVE(r1)
425 /* At this point we assume that the ucontext was created by a
426 rt_signal and we should use rt_sigreturn to restore the original
427 state. As of the 2.4.21 kernel the ucontext is the first thing
428 (offset 0) in the rt_signal frame and rt_sigreturn expects the
429 ucontext address in R1. Normally the rt-signal trampoline handles
430 this by popping dummy frame before the rt_signal syscall. In our
431 case the stack may not be in its original (signal handler return with
432 R1 pointing at the dummy frame) state. We do have the ucontext
433 address in R3, so simply copy R3 to R1 before the syscall. */
436 li r0,SYS_ify(rt_sigreturn)
440 /* If the kernel is not at least 2.4.21 then generate a ENOSYS stub. */
442 std r0,FRAME_LR_SAVE(r1)
445 bl JUMPTARGET(__syscall_error)
448 ld r0,128+FRAME_LR_SAVE(r1)
454 PSEUDO_END(__setcontext)
456 versioned_symbol (libc, __setcontext, setcontext, GLIBC_2_3_4)