2 Copyright (C) 2002-2014 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, see
17 <http://www.gnu.org/licenses/>. */
20 #include <rtld-global-offsets.h>
21 #include <shlib-compat.h>
22 #include <kernel-features.h>
25 #include <asm/ptrace.h>
26 #include "ucontext_i.h"
27 #include <asm/errno.h>
32 .tc _rtld_global_ro[TC],_rtld_global_ro
34 .tc _dl_hwcap[TC],_dl_hwcap
38 #if SHLIB_COMPAT (libc, GLIBC_2_3, GLIBC_2_3_4)
39 ENTRY(__novec_setcontext)
44 std r0,FRAME_LR_SAVE(r1)
45 cfi_offset (lr, FRAME_LR_SAVE)
47 cfi_adjust_cfa_offset (128)
51 * If this ucontext refers to the point where we were interrupted
52 * by a signal, we have to use the rt_sigreturn system call to
53 * return to the context so we get both LR and CTR restored.
55 * Otherwise, the context we are restoring is either just after
56 * a procedure call (getcontext/swapcontext) or at the beginning
57 * of a procedure call (makecontext), so we don't need to restore
58 * msr and ctr. We don't restore r13 since it will be used as
60 ld r0,(SIGCONTEXT_GP_REGS+(PT_MSR*8))(r31)
65 addi r4,r3,UCONTEXT_SIGMASK
67 bl JUMPTARGET(__sigprocmask)
73 /* Load _rtld-global._dl_hwcap. */
74 ld r5,RTLD_GLOBAL_RO_DL_HWCAP_OFFSET(r5)
76 ld r5,0(r5) /* Load extern _dl_hwcap. */
79 lfd fp0,(SIGCONTEXT_FP_REGS+(32*8))(r31)
80 lfd fp31,(SIGCONTEXT_FP_REGS+(PT_R31*8))(r31)
81 lfd fp30,(SIGCONTEXT_FP_REGS+(PT_R30*8))(r31)
84 /* Use the extended four-operand version of the mtfsf insn. */
89 /* Availability of DFP indicates a 64-bit FPSCR. */
90 andi. r6,r5,PPC_FEATURE_HAS_DFP
92 /* Use the extended four-operand version of the mtfsf insn. */
95 /* Continue to operate on the FPSCR as if it were 32-bits. */
100 # endif /* _ARCH_PWR6 */
101 lfd fp29,(SIGCONTEXT_FP_REGS+(PT_R29*8))(r31)
102 lfd fp28,(SIGCONTEXT_FP_REGS+(PT_R28*8))(r31)
103 lfd fp27,(SIGCONTEXT_FP_REGS+(PT_R27*8))(r31)
104 lfd fp26,(SIGCONTEXT_FP_REGS+(PT_R26*8))(r31)
105 lfd fp25,(SIGCONTEXT_FP_REGS+(PT_R25*8))(r31)
106 lfd fp24,(SIGCONTEXT_FP_REGS+(PT_R24*8))(r31)
107 lfd fp23,(SIGCONTEXT_FP_REGS+(PT_R23*8))(r31)
108 lfd fp22,(SIGCONTEXT_FP_REGS+(PT_R22*8))(r31)
109 lfd fp21,(SIGCONTEXT_FP_REGS+(PT_R21*8))(r31)
110 lfd fp20,(SIGCONTEXT_FP_REGS+(PT_R20*8))(r31)
111 lfd fp19,(SIGCONTEXT_FP_REGS+(PT_R19*8))(r31)
112 lfd fp18,(SIGCONTEXT_FP_REGS+(PT_R18*8))(r31)
113 lfd fp17,(SIGCONTEXT_FP_REGS+(PT_R17*8))(r31)
114 lfd fp16,(SIGCONTEXT_FP_REGS+(PT_R16*8))(r31)
115 lfd fp15,(SIGCONTEXT_FP_REGS+(PT_R15*8))(r31)
116 lfd fp14,(SIGCONTEXT_FP_REGS+(PT_R14*8))(r31)
117 lfd fp13,(SIGCONTEXT_FP_REGS+(PT_R13*8))(r31)
118 lfd fp12,(SIGCONTEXT_FP_REGS+(PT_R12*8))(r31)
119 lfd fp11,(SIGCONTEXT_FP_REGS+(PT_R11*8))(r31)
120 lfd fp10,(SIGCONTEXT_FP_REGS+(PT_R10*8))(r31)
121 lfd fp9,(SIGCONTEXT_FP_REGS+(PT_R9*8))(r31)
122 lfd fp8,(SIGCONTEXT_FP_REGS+(PT_R8*8))(r31)
123 lfd fp7,(SIGCONTEXT_FP_REGS+(PT_R7*8))(r31)
124 lfd fp6,(SIGCONTEXT_FP_REGS+(PT_R6*8))(r31)
125 lfd fp5,(SIGCONTEXT_FP_REGS+(PT_R5*8))(r31)
126 lfd fp4,(SIGCONTEXT_FP_REGS+(PT_R4*8))(r31)
127 lfd fp3,(SIGCONTEXT_FP_REGS+(PT_R3*8))(r31)
128 lfd fp2,(SIGCONTEXT_FP_REGS+(PT_R2*8))(r31)
129 lfd fp1,(SIGCONTEXT_FP_REGS+(PT_R1*8))(r31)
130 lfd fp0,(SIGCONTEXT_FP_REGS+(PT_R0*8))(r31)
132 /* End FDE now, because the unwind info would be wrong while
133 we're reloading registers to switch to the new context. */
136 ld r0,(SIGCONTEXT_GP_REGS+(PT_LNK*8))(r31)
137 ld r1,(SIGCONTEXT_GP_REGS+(PT_R1*8))(r31)
139 ld r2,(SIGCONTEXT_GP_REGS+(PT_R2*8))(r31)
140 ld r0,(SIGCONTEXT_GP_REGS+(PT_XER*8))(r31)
141 ld r3,(SIGCONTEXT_GP_REGS+(PT_R3*8))(r31)
143 ld r4,(SIGCONTEXT_GP_REGS+(PT_R4*8))(r31)
144 ld r0,(SIGCONTEXT_GP_REGS+(PT_CCR*8))(r31)
145 ld r5,(SIGCONTEXT_GP_REGS+(PT_R5*8))(r31)
147 ld r6,(SIGCONTEXT_GP_REGS+(PT_R6*8))(r31)
148 ld r7,(SIGCONTEXT_GP_REGS+(PT_R7*8))(r31)
149 ld r8,(SIGCONTEXT_GP_REGS+(PT_R8*8))(r31)
150 ld r9,(SIGCONTEXT_GP_REGS+(PT_R9*8))(r31)
151 ld r10,(SIGCONTEXT_GP_REGS+(PT_R10*8))(r31)
152 ld r11,(SIGCONTEXT_GP_REGS+(PT_R11*8))(r31)
153 ld r12,(SIGCONTEXT_GP_REGS+(PT_R12*8))(r31)
154 /* Don't reload the thread ID or TLS pointer (r13). */
155 ld r14,(SIGCONTEXT_GP_REGS+(PT_R14*8))(r31)
156 ld r15,(SIGCONTEXT_GP_REGS+(PT_R15*8))(r31)
157 ld r16,(SIGCONTEXT_GP_REGS+(PT_R16*8))(r31)
158 ld r17,(SIGCONTEXT_GP_REGS+(PT_R17*8))(r31)
159 ld r18,(SIGCONTEXT_GP_REGS+(PT_R18*8))(r31)
160 ld r19,(SIGCONTEXT_GP_REGS+(PT_R19*8))(r31)
161 ld r20,(SIGCONTEXT_GP_REGS+(PT_R20*8))(r31)
162 ld r21,(SIGCONTEXT_GP_REGS+(PT_R21*8))(r31)
163 ld r22,(SIGCONTEXT_GP_REGS+(PT_R22*8))(r31)
164 ld r23,(SIGCONTEXT_GP_REGS+(PT_R23*8))(r31)
165 ld r24,(SIGCONTEXT_GP_REGS+(PT_R24*8))(r31)
166 ld r25,(SIGCONTEXT_GP_REGS+(PT_R25*8))(r31)
167 ld r26,(SIGCONTEXT_GP_REGS+(PT_R26*8))(r31)
168 ld r27,(SIGCONTEXT_GP_REGS+(PT_R27*8))(r31)
169 ld r28,(SIGCONTEXT_GP_REGS+(PT_R28*8))(r31)
170 ld r29,(SIGCONTEXT_GP_REGS+(PT_R29*8))(r31)
171 ld r30,(SIGCONTEXT_GP_REGS+(PT_R30*8))(r31)
173 /* Now we branch to the "Next Instruction Pointer" from the saved
174 context. With the powerpc64 instruction set there is no good way to
175 do this (from user state) without clobbering either the LR or CTR.
176 The makecontext and swapcontext functions depend on the callers
177 LR being preserved so we use the CTR. */
178 ld r0,(SIGCONTEXT_GP_REGS+(PT_NIP*8))(r31)
180 ld r0,(SIGCONTEXT_GP_REGS+(PT_R0*8))(r31)
181 ld r31,(SIGCONTEXT_GP_REGS+(PT_R31*8))(r31)
184 /* Re-establish FDE for the rest of the actual setcontext routine. */
186 cfi_offset (lr, FRAME_LR_SAVE)
187 cfi_adjust_cfa_offset (128)
190 ld r0,128+FRAME_LR_SAVE(r1)
196 /* At this point we assume that the ucontext was created by a
197 rt_signal and we should use rt_sigreturn to restore the original
198 state. As of the 2.4.21 kernel the ucontext is the first thing
199 (offset 0) in the rt_signal frame and rt_sigreturn expects the
200 ucontext address in R1. Normally the rt-signal trampoline handles
201 this by popping dummy frame before the rt_signal syscall. In our
202 case the stack may not be in its original (signal handler return with
203 R1 pointing at the dummy frame) state. We do have the ucontext
204 address in R3, so simply copy R3 to R1 before the syscall. */
207 li r0,SYS_ify(rt_sigreturn)
211 PSEUDO_END(__novec_setcontext)
213 compat_symbol (libc, __novec_setcontext, setcontext, GLIBC_2_3)
224 std r0,FRAME_LR_SAVE(r1)
225 cfi_offset (lr, FRAME_LR_SAVE)
227 cfi_adjust_cfa_offset (128)
231 * If this ucontext refers to the point where we were interrupted
232 * by a signal, we have to use the rt_sigreturn system call to
233 * return to the context so we get both LR and CTR restored.
235 * Otherwise, the context we are restoring is either just after
236 * a procedure call (getcontext/swapcontext) or at the beginning
237 * of a procedure call (makecontext), so we don't need to restore
238 * msr and ctr. We don't restore r13 since it will be used as
239 * the TLS pointer. */
240 ld r0,(SIGCONTEXT_GP_REGS+(PT_MSR*8))(r31)
245 addi r4,r3,UCONTEXT_SIGMASK
247 bl JUMPTARGET(__sigprocmask)
252 ld r5,.LC__dl_hwcap@toc(r2)
253 ld r10,(SIGCONTEXT_V_REGS_PTR)(r31)
255 /* Load _rtld-global._dl_hwcap. */
256 ld r5,RTLD_GLOBAL_RO_DL_HWCAP_OFFSET(r5)
258 ld r5,0(r5) /* Load extern _dl_hwcap. */
260 andis. r6,r5,(PPC_FEATURE_HAS_ALTIVEC >> 16)
362 lfd fp0,(SIGCONTEXT_FP_REGS+(32*8))(r31)
363 lfd fp31,(SIGCONTEXT_FP_REGS+(PT_R31*8))(r31)
364 lfd fp30,(SIGCONTEXT_FP_REGS+(PT_R30*8))(r31)
367 /* Use the extended four-operand version of the mtfsf insn. */
372 /* Availability of DFP indicates a 64-bit FPSCR. */
373 andi. r6,r5,PPC_FEATURE_HAS_DFP
375 /* Use the extended four-operand version of the mtfsf insn. */
378 /* Continue to operate on the FPSCR as if it were 32-bits. */
383 # endif /* _ARCH_PWR6 */
384 lfd fp29,(SIGCONTEXT_FP_REGS+(PT_R29*8))(r31)
385 lfd fp28,(SIGCONTEXT_FP_REGS+(PT_R28*8))(r31)
386 lfd fp27,(SIGCONTEXT_FP_REGS+(PT_R27*8))(r31)
387 lfd fp26,(SIGCONTEXT_FP_REGS+(PT_R26*8))(r31)
388 lfd fp25,(SIGCONTEXT_FP_REGS+(PT_R25*8))(r31)
389 lfd fp24,(SIGCONTEXT_FP_REGS+(PT_R24*8))(r31)
390 lfd fp23,(SIGCONTEXT_FP_REGS+(PT_R23*8))(r31)
391 lfd fp22,(SIGCONTEXT_FP_REGS+(PT_R22*8))(r31)
392 lfd fp21,(SIGCONTEXT_FP_REGS+(PT_R21*8))(r31)
393 lfd fp20,(SIGCONTEXT_FP_REGS+(PT_R20*8))(r31)
394 lfd fp19,(SIGCONTEXT_FP_REGS+(PT_R19*8))(r31)
395 lfd fp18,(SIGCONTEXT_FP_REGS+(PT_R18*8))(r31)
396 lfd fp17,(SIGCONTEXT_FP_REGS+(PT_R17*8))(r31)
397 lfd fp16,(SIGCONTEXT_FP_REGS+(PT_R16*8))(r31)
398 lfd fp15,(SIGCONTEXT_FP_REGS+(PT_R15*8))(r31)
399 lfd fp14,(SIGCONTEXT_FP_REGS+(PT_R14*8))(r31)
400 lfd fp13,(SIGCONTEXT_FP_REGS+(PT_R13*8))(r31)
401 lfd fp12,(SIGCONTEXT_FP_REGS+(PT_R12*8))(r31)
402 lfd fp11,(SIGCONTEXT_FP_REGS+(PT_R11*8))(r31)
403 lfd fp10,(SIGCONTEXT_FP_REGS+(PT_R10*8))(r31)
404 lfd fp9,(SIGCONTEXT_FP_REGS+(PT_R9*8))(r31)
405 lfd fp8,(SIGCONTEXT_FP_REGS+(PT_R8*8))(r31)
406 lfd fp7,(SIGCONTEXT_FP_REGS+(PT_R7*8))(r31)
407 lfd fp6,(SIGCONTEXT_FP_REGS+(PT_R6*8))(r31)
408 lfd fp5,(SIGCONTEXT_FP_REGS+(PT_R5*8))(r31)
409 lfd fp4,(SIGCONTEXT_FP_REGS+(PT_R4*8))(r31)
410 lfd fp3,(SIGCONTEXT_FP_REGS+(PT_R3*8))(r31)
411 lfd fp2,(SIGCONTEXT_FP_REGS+(PT_R2*8))(r31)
412 lfd fp1,(SIGCONTEXT_FP_REGS+(PT_R1*8))(r31)
413 lfd fp0,(SIGCONTEXT_FP_REGS+(PT_R0*8))(r31)
415 /* End FDE now, because the unwind info would be wrong while
416 we're reloading registers to switch to the new context. */
419 ld r0,(SIGCONTEXT_GP_REGS+(PT_LNK*8))(r31)
420 ld r1,(SIGCONTEXT_GP_REGS+(PT_R1*8))(r31)
422 ld r2,(SIGCONTEXT_GP_REGS+(PT_R2*8))(r31)
423 ld r0,(SIGCONTEXT_GP_REGS+(PT_XER*8))(r31)
424 ld r3,(SIGCONTEXT_GP_REGS+(PT_R3*8))(r31)
426 ld r4,(SIGCONTEXT_GP_REGS+(PT_R4*8))(r31)
427 ld r0,(SIGCONTEXT_GP_REGS+(PT_CCR*8))(r31)
428 ld r5,(SIGCONTEXT_GP_REGS+(PT_R5*8))(r31)
429 ld r6,(SIGCONTEXT_GP_REGS+(PT_R6*8))(r31)
430 ld r7,(SIGCONTEXT_GP_REGS+(PT_R7*8))(r31)
431 ld r8,(SIGCONTEXT_GP_REGS+(PT_R8*8))(r31)
432 ld r9,(SIGCONTEXT_GP_REGS+(PT_R9*8))(r31)
434 ld r10,(SIGCONTEXT_GP_REGS+(PT_R10*8))(r31)
435 ld r11,(SIGCONTEXT_GP_REGS+(PT_R11*8))(r31)
436 ld r12,(SIGCONTEXT_GP_REGS+(PT_R12*8))(r31)
437 /* Don't reload the thread ID or TLS pointer (r13). */
438 ld r14,(SIGCONTEXT_GP_REGS+(PT_R14*8))(r31)
439 ld r15,(SIGCONTEXT_GP_REGS+(PT_R15*8))(r31)
440 ld r16,(SIGCONTEXT_GP_REGS+(PT_R16*8))(r31)
441 ld r17,(SIGCONTEXT_GP_REGS+(PT_R17*8))(r31)
442 ld r18,(SIGCONTEXT_GP_REGS+(PT_R18*8))(r31)
443 ld r19,(SIGCONTEXT_GP_REGS+(PT_R19*8))(r31)
444 ld r20,(SIGCONTEXT_GP_REGS+(PT_R20*8))(r31)
445 ld r21,(SIGCONTEXT_GP_REGS+(PT_R21*8))(r31)
446 ld r22,(SIGCONTEXT_GP_REGS+(PT_R22*8))(r31)
447 ld r23,(SIGCONTEXT_GP_REGS+(PT_R23*8))(r31)
448 ld r24,(SIGCONTEXT_GP_REGS+(PT_R24*8))(r31)
449 ld r25,(SIGCONTEXT_GP_REGS+(PT_R25*8))(r31)
450 ld r26,(SIGCONTEXT_GP_REGS+(PT_R26*8))(r31)
451 ld r27,(SIGCONTEXT_GP_REGS+(PT_R27*8))(r31)
452 ld r28,(SIGCONTEXT_GP_REGS+(PT_R28*8))(r31)
453 ld r29,(SIGCONTEXT_GP_REGS+(PT_R29*8))(r31)
454 ld r30,(SIGCONTEXT_GP_REGS+(PT_R30*8))(r31)
456 /* Now we branch to the "Next Instruction Pointer" from the saved
457 context. With the powerpc64 instruction set there is no good way to
458 do this (from user state) without clobbering either the LR or CTR.
459 The makecontext and swapcontext functions depend on the callers
460 LR being preserved so we use the CTR. */
461 ld r0,(SIGCONTEXT_GP_REGS+(PT_NIP*8))(r31)
463 ld r0,(SIGCONTEXT_GP_REGS+(PT_R0*8))(r31)
464 ld r31,(SIGCONTEXT_GP_REGS+(PT_R31*8))(r31)
467 /* Re-establish FDE for the rest of the actual setcontext routine. */
469 cfi_offset (lr, FRAME_LR_SAVE)
470 cfi_adjust_cfa_offset (128)
473 ld r0,128+FRAME_LR_SAVE(r1)
479 /* At this point we assume that the ucontext was created by a
480 rt_signal and we should use rt_sigreturn to restore the original
481 state. As of the 2.4.21 kernel the ucontext is the first thing
482 (offset 0) in the rt_signal frame and rt_sigreturn expects the
483 ucontext address in R1. Normally the rt-signal trampoline handles
484 this by popping dummy frame before the rt_signal syscall. In our
485 case the stack may not be in its original (signal handler return with
486 R1 pointing at the dummy frame) state. We do have the ucontext
487 address in R3, so simply copy R3 to R1 before the syscall. */
490 li r0,SYS_ify(rt_sigreturn)
494 PSEUDO_END(__setcontext)
496 versioned_symbol (libc, __setcontext, setcontext, GLIBC_2_3_4)