1/* Save current context.
2   Copyright (C) 2002-2021 Free Software Foundation, Inc.
3   This file is part of the GNU C Library.
4
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.
9
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.
14
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   <https://www.gnu.org/licenses/>.  */
18
19#include <sysdep.h>
20#include <rtld-global-offsets.h>
21#include <shlib-compat.h>
22
23#define __ASSEMBLY__
24#include <asm/ptrace.h>
25#include <asm/errno.h>
26#include "ucontext_i.h"
27
28
29#if SHLIB_COMPAT (libc, GLIBC_2_3, GLIBC_2_3_4)
30ENTRY(__novec_getcontext)
31	CALL_MCOUNT 1
32  std  r0,(SIGCONTEXT_GP_REGS+(PT_R0*8))(r3)
33  std  r1,(SIGCONTEXT_GP_REGS+(PT_R1*8))(r3)
34  mflr  r0
35  std  r2,(SIGCONTEXT_GP_REGS+(PT_R2*8))(r3)
36  std  r0,FRAME_LR_SAVE(r1)
37  cfi_offset (lr, FRAME_LR_SAVE)
38  std  r0,(SIGCONTEXT_GP_REGS+(PT_LNK*8))(r3)
39  std  r0,(SIGCONTEXT_GP_REGS+(PT_NIP*8))(r3)
40  stdu  r1,-128(r1)
41  cfi_adjust_cfa_offset (128)
42  std  r4,(SIGCONTEXT_GP_REGS+(PT_R4*8))(r3)
43  std  r5,(SIGCONTEXT_GP_REGS+(PT_R5*8))(r3)
44  std  r6,(SIGCONTEXT_GP_REGS+(PT_R6*8))(r3)
45  std  r7,(SIGCONTEXT_GP_REGS+(PT_R7*8))(r3)
46  std  r8,(SIGCONTEXT_GP_REGS+(PT_R8*8))(r3)
47  std  r9,(SIGCONTEXT_GP_REGS+(PT_R9*8))(r3)
48  std  r10,(SIGCONTEXT_GP_REGS+(PT_R10*8))(r3)
49  std  r11,(SIGCONTEXT_GP_REGS+(PT_R11*8))(r3)
50  std  r12,(SIGCONTEXT_GP_REGS+(PT_R12*8))(r3)
51  std  r13,(SIGCONTEXT_GP_REGS+(PT_R13*8))(r3)
52  std  r14,(SIGCONTEXT_GP_REGS+(PT_R14*8))(r3)
53  std  r15,(SIGCONTEXT_GP_REGS+(PT_R15*8))(r3)
54  std  r16,(SIGCONTEXT_GP_REGS+(PT_R16*8))(r3)
55  std  r17,(SIGCONTEXT_GP_REGS+(PT_R17*8))(r3)
56  std  r18,(SIGCONTEXT_GP_REGS+(PT_R18*8))(r3)
57  std  r19,(SIGCONTEXT_GP_REGS+(PT_R19*8))(r3)
58  std  r20,(SIGCONTEXT_GP_REGS+(PT_R20*8))(r3)
59  std  r21,(SIGCONTEXT_GP_REGS+(PT_R21*8))(r3)
60  std  r22,(SIGCONTEXT_GP_REGS+(PT_R22*8))(r3)
61  std  r23,(SIGCONTEXT_GP_REGS+(PT_R23*8))(r3)
62  std  r24,(SIGCONTEXT_GP_REGS+(PT_R24*8))(r3)
63  std  r25,(SIGCONTEXT_GP_REGS+(PT_R25*8))(r3)
64  std  r26,(SIGCONTEXT_GP_REGS+(PT_R26*8))(r3)
65  std  r27,(SIGCONTEXT_GP_REGS+(PT_R27*8))(r3)
66  std  r28,(SIGCONTEXT_GP_REGS+(PT_R28*8))(r3)
67  std  r29,(SIGCONTEXT_GP_REGS+(PT_R29*8))(r3)
68  std  r30,(SIGCONTEXT_GP_REGS+(PT_R30*8))(r3)
69  std  r31,(SIGCONTEXT_GP_REGS+(PT_R31*8))(r3)
70  mfctr  r0
71  std  r0,(SIGCONTEXT_GP_REGS+(PT_CTR*8))(r3)
72  mfxer  r0
73  std  r0,(SIGCONTEXT_GP_REGS+(PT_XER*8))(r3)
74  mfcr  r0
75  std  r0,(SIGCONTEXT_GP_REGS+(PT_CCR*8))(r3)
76
77  /* Set the return value of swapcontext to "success".  R3 is the only
78     register whose value is not preserved in the saved context.  */
79  li   r0,0
80  std  r0,(SIGCONTEXT_GP_REGS+(PT_R3*8))(r3)
81
82  /* Zero fill fields that can't be set in user state or are unused.  */
83  std  r0,(SIGCONTEXT_GP_REGS+(PT_MSR*8))(r3)
84  std  r0,(SIGCONTEXT_GP_REGS+(34*8))(r3)
85  std  r0,(SIGCONTEXT_GP_REGS+(PT_SOFTE*8))(r3)
86  std  r0,(SIGCONTEXT_GP_REGS+(40*8))(r3)
87  std  r0,(SIGCONTEXT_GP_REGS+(41*8))(r3)
88  std  r0,(SIGCONTEXT_GP_REGS+(42*8))(r3)
89  std  r0,(SIGCONTEXT_GP_REGS+(PT_RESULT*8))(r3)
90
91  /* Set the PT_REGS pointer to the address of sigcontext's gp_regs
92     field.  Struct pt_regs and elf_gregset_t are the same thing.
93     We kept the regs field for backwards compatibility with
94     libraries built before we extended sigcontext.  */
95  addi r0,r3,SIGCONTEXT_GP_REGS
96  std  r0,SIGCONTEXT_PT_REGS(r3)
97
98  stfd  fp0,(SIGCONTEXT_FP_REGS+(PT_R0*8))(r3)
99  stfd  fp1,(SIGCONTEXT_FP_REGS+(PT_R1*8))(r3)
100  stfd  fp2,(SIGCONTEXT_FP_REGS+(PT_R2*8))(r3)
101  stfd  fp3,(SIGCONTEXT_FP_REGS+(PT_R3*8))(r3)
102  stfd  fp4,(SIGCONTEXT_FP_REGS+(PT_R4*8))(r3)
103  stfd  fp5,(SIGCONTEXT_FP_REGS+(PT_R5*8))(r3)
104  stfd  fp6,(SIGCONTEXT_FP_REGS+(PT_R6*8))(r3)
105  stfd  fp7,(SIGCONTEXT_FP_REGS+(PT_R7*8))(r3)
106  stfd  fp8,(SIGCONTEXT_FP_REGS+(PT_R8*8))(r3)
107  stfd  fp9,(SIGCONTEXT_FP_REGS+(PT_R9*8))(r3)
108  stfd  fp10,(SIGCONTEXT_FP_REGS+(PT_R10*8))(r3)
109  stfd  fp11,(SIGCONTEXT_FP_REGS+(PT_R11*8))(r3)
110  stfd  fp12,(SIGCONTEXT_FP_REGS+(PT_R12*8))(r3)
111  stfd  fp13,(SIGCONTEXT_FP_REGS+(PT_R13*8))(r3)
112  stfd  fp14,(SIGCONTEXT_FP_REGS+(PT_R14*8))(r3)
113  stfd  fp15,(SIGCONTEXT_FP_REGS+(PT_R15*8))(r3)
114  stfd  fp16,(SIGCONTEXT_FP_REGS+(PT_R16*8))(r3)
115  stfd  fp17,(SIGCONTEXT_FP_REGS+(PT_R17*8))(r3)
116  stfd  fp18,(SIGCONTEXT_FP_REGS+(PT_R18*8))(r3)
117  stfd  fp19,(SIGCONTEXT_FP_REGS+(PT_R19*8))(r3)
118  stfd  fp20,(SIGCONTEXT_FP_REGS+(PT_R20*8))(r3)
119  stfd  fp21,(SIGCONTEXT_FP_REGS+(PT_R21*8))(r3)
120  stfd  fp22,(SIGCONTEXT_FP_REGS+(PT_R22*8))(r3)
121  stfd  fp23,(SIGCONTEXT_FP_REGS+(PT_R23*8))(r3)
122  stfd  fp24,(SIGCONTEXT_FP_REGS+(PT_R24*8))(r3)
123  stfd  fp25,(SIGCONTEXT_FP_REGS+(PT_R25*8))(r3)
124  stfd  fp26,(SIGCONTEXT_FP_REGS+(PT_R26*8))(r3)
125  stfd  fp27,(SIGCONTEXT_FP_REGS+(PT_R27*8))(r3)
126  stfd  fp28,(SIGCONTEXT_FP_REGS+(PT_R28*8))(r3)
127  stfd  fp29,(SIGCONTEXT_FP_REGS+(PT_R29*8))(r3)
128  mffs  fp0
129  stfd  fp30,(SIGCONTEXT_FP_REGS+(PT_R30*8))(r3)
130  stfd  fp31,(SIGCONTEXT_FP_REGS+(PT_R31*8))(r3)
131  stfd  fp0,(SIGCONTEXT_FP_REGS+(32*8))(r3)
132
133  addi  r5,r3,UCONTEXT_SIGMASK
134  li  r4,0
135  li  r3,SIG_BLOCK
136  bl  JUMPTARGET(__sigprocmask)
137  nop
138
139  ld    r0,128+FRAME_LR_SAVE(r1)
140  addi  r1,r1,128
141  mtlr  r0
142  blr
143PSEUDO_END(__novec_getcontext)
144
145compat_symbol (libc, __novec_getcontext, getcontext, GLIBC_2_3)
146
147#endif
148
149	.section	".toc","aw"
150.LC__dl_hwcap:
151#ifdef SHARED
152	.tc _rtld_global_ro[TC],_rtld_global_ro
153#else
154	.tc _dl_hwcap[TC],_dl_hwcap
155#endif
156	.section ".text"
157
158	.machine	"altivec"
159ENTRY(__getcontext)
160	CALL_MCOUNT 1
161  std  r0,(SIGCONTEXT_GP_REGS+(PT_R0*8))(r3)
162  std  r1,(SIGCONTEXT_GP_REGS+(PT_R1*8))(r3)
163  mflr  r0
164  std  r2,(SIGCONTEXT_GP_REGS+(PT_R2*8))(r3)
165  std  r0,FRAME_LR_SAVE(r1)
166  cfi_offset (lr, FRAME_LR_SAVE)
167  std  r0,(SIGCONTEXT_GP_REGS+(PT_LNK*8))(r3)
168  std  r0,(SIGCONTEXT_GP_REGS+(PT_NIP*8))(r3)
169  stdu  r1,-128(r1)
170  cfi_adjust_cfa_offset (128)
171  std  r4,(SIGCONTEXT_GP_REGS+(PT_R4*8))(r3)
172  std  r5,(SIGCONTEXT_GP_REGS+(PT_R5*8))(r3)
173  std  r6,(SIGCONTEXT_GP_REGS+(PT_R6*8))(r3)
174  std  r7,(SIGCONTEXT_GP_REGS+(PT_R7*8))(r3)
175  std  r8,(SIGCONTEXT_GP_REGS+(PT_R8*8))(r3)
176  std  r9,(SIGCONTEXT_GP_REGS+(PT_R9*8))(r3)
177  std  r10,(SIGCONTEXT_GP_REGS+(PT_R10*8))(r3)
178  std  r11,(SIGCONTEXT_GP_REGS+(PT_R11*8))(r3)
179  std  r12,(SIGCONTEXT_GP_REGS+(PT_R12*8))(r3)
180  std  r13,(SIGCONTEXT_GP_REGS+(PT_R13*8))(r3)
181  std  r14,(SIGCONTEXT_GP_REGS+(PT_R14*8))(r3)
182  std  r15,(SIGCONTEXT_GP_REGS+(PT_R15*8))(r3)
183  std  r16,(SIGCONTEXT_GP_REGS+(PT_R16*8))(r3)
184  std  r17,(SIGCONTEXT_GP_REGS+(PT_R17*8))(r3)
185  std  r18,(SIGCONTEXT_GP_REGS+(PT_R18*8))(r3)
186  std  r19,(SIGCONTEXT_GP_REGS+(PT_R19*8))(r3)
187  std  r20,(SIGCONTEXT_GP_REGS+(PT_R20*8))(r3)
188  std  r21,(SIGCONTEXT_GP_REGS+(PT_R21*8))(r3)
189  std  r22,(SIGCONTEXT_GP_REGS+(PT_R22*8))(r3)
190  std  r23,(SIGCONTEXT_GP_REGS+(PT_R23*8))(r3)
191  std  r24,(SIGCONTEXT_GP_REGS+(PT_R24*8))(r3)
192  std  r25,(SIGCONTEXT_GP_REGS+(PT_R25*8))(r3)
193  std  r26,(SIGCONTEXT_GP_REGS+(PT_R26*8))(r3)
194  std  r27,(SIGCONTEXT_GP_REGS+(PT_R27*8))(r3)
195  std  r28,(SIGCONTEXT_GP_REGS+(PT_R28*8))(r3)
196  std  r29,(SIGCONTEXT_GP_REGS+(PT_R29*8))(r3)
197  std  r30,(SIGCONTEXT_GP_REGS+(PT_R30*8))(r3)
198  std  r31,(SIGCONTEXT_GP_REGS+(PT_R31*8))(r3)
199  mfctr  r0
200  std  r0,(SIGCONTEXT_GP_REGS+(PT_CTR*8))(r3)
201  mfxer  r0
202  std  r0,(SIGCONTEXT_GP_REGS+(PT_XER*8))(r3)
203  mfcr  r0
204  std  r0,(SIGCONTEXT_GP_REGS+(PT_CCR*8))(r3)
205
206  /* Set the return value of swapcontext to "success".  R3 is the only
207     register whose value is not preserved in the saved context.  */
208  li   r0,0
209  std  r0,(SIGCONTEXT_GP_REGS+(PT_R3*8))(r3)
210
211  /* Zero fill fields that can't be set in user state or are unused.  */
212  std  r0,(SIGCONTEXT_GP_REGS+(PT_MSR*8))(r3)
213  std  r0,(SIGCONTEXT_GP_REGS+(34*8))(r3)
214  std  r0,(SIGCONTEXT_GP_REGS+(PT_SOFTE*8))(r3)
215  std  r0,(SIGCONTEXT_GP_REGS+(40*8))(r3)
216  std  r0,(SIGCONTEXT_GP_REGS+(41*8))(r3)
217  std  r0,(SIGCONTEXT_GP_REGS+(42*8))(r3)
218  std  r0,(SIGCONTEXT_GP_REGS+(PT_RESULT*8))(r3)
219
220  /* Set the PT_REGS pointer to the address of sigcontext's gp_regs
221     field.  Struct pt_regs and elf_gregset_t are the same thing.
222     We kept the regs field for backwards compatibility with
223     libraries built before we extended sigcontext.  */
224  addi r0,r3,SIGCONTEXT_GP_REGS
225  std  r0,SIGCONTEXT_PT_REGS(r3)
226
227  stfd  fp0,(SIGCONTEXT_FP_REGS+(PT_R0*8))(r3)
228  stfd  fp1,(SIGCONTEXT_FP_REGS+(PT_R1*8))(r3)
229  stfd  fp2,(SIGCONTEXT_FP_REGS+(PT_R2*8))(r3)
230  stfd  fp3,(SIGCONTEXT_FP_REGS+(PT_R3*8))(r3)
231  stfd  fp4,(SIGCONTEXT_FP_REGS+(PT_R4*8))(r3)
232  stfd  fp5,(SIGCONTEXT_FP_REGS+(PT_R5*8))(r3)
233  stfd  fp6,(SIGCONTEXT_FP_REGS+(PT_R6*8))(r3)
234  stfd  fp7,(SIGCONTEXT_FP_REGS+(PT_R7*8))(r3)
235  stfd  fp8,(SIGCONTEXT_FP_REGS+(PT_R8*8))(r3)
236  stfd  fp9,(SIGCONTEXT_FP_REGS+(PT_R9*8))(r3)
237  stfd  fp10,(SIGCONTEXT_FP_REGS+(PT_R10*8))(r3)
238  stfd  fp11,(SIGCONTEXT_FP_REGS+(PT_R11*8))(r3)
239  stfd  fp12,(SIGCONTEXT_FP_REGS+(PT_R12*8))(r3)
240  stfd  fp13,(SIGCONTEXT_FP_REGS+(PT_R13*8))(r3)
241  stfd  fp14,(SIGCONTEXT_FP_REGS+(PT_R14*8))(r3)
242  stfd  fp15,(SIGCONTEXT_FP_REGS+(PT_R15*8))(r3)
243  stfd  fp16,(SIGCONTEXT_FP_REGS+(PT_R16*8))(r3)
244  stfd  fp17,(SIGCONTEXT_FP_REGS+(PT_R17*8))(r3)
245  stfd  fp18,(SIGCONTEXT_FP_REGS+(PT_R18*8))(r3)
246  stfd  fp19,(SIGCONTEXT_FP_REGS+(PT_R19*8))(r3)
247  stfd  fp20,(SIGCONTEXT_FP_REGS+(PT_R20*8))(r3)
248  stfd  fp21,(SIGCONTEXT_FP_REGS+(PT_R21*8))(r3)
249  stfd  fp22,(SIGCONTEXT_FP_REGS+(PT_R22*8))(r3)
250  stfd  fp23,(SIGCONTEXT_FP_REGS+(PT_R23*8))(r3)
251  stfd  fp24,(SIGCONTEXT_FP_REGS+(PT_R24*8))(r3)
252  stfd  fp25,(SIGCONTEXT_FP_REGS+(PT_R25*8))(r3)
253  stfd  fp26,(SIGCONTEXT_FP_REGS+(PT_R26*8))(r3)
254  stfd  fp27,(SIGCONTEXT_FP_REGS+(PT_R27*8))(r3)
255  stfd  fp28,(SIGCONTEXT_FP_REGS+(PT_R28*8))(r3)
256  stfd  fp29,(SIGCONTEXT_FP_REGS+(PT_R29*8))(r3)
257  mffs  fp0
258  stfd  fp30,(SIGCONTEXT_FP_REGS+(PT_R30*8))(r3)
259  stfd  fp31,(SIGCONTEXT_FP_REGS+(PT_R31*8))(r3)
260  stfd  fp0,(SIGCONTEXT_FP_REGS+(32*8))(r3)
261
262  ld    r5,.LC__dl_hwcap@toc(r2)
263# ifdef SHARED
264/* Load _rtld-global._dl_hwcap.  */
265  ld    r5,RTLD_GLOBAL_RO_DL_HWCAP_OFFSET(r5)
266# else
267  ld    r5,0(r5) /* Load extern _dl_hwcap.  */
268# endif
269  la    r10,(SIGCONTEXT_V_RESERVE+8)(r3)
270  la    r9,(SIGCONTEXT_V_RESERVE+24)(r3)
271
272  andis.  r5,r5,(PPC_FEATURE_HAS_ALTIVEC >> 16)
273
274  clrrdi  r10,r10,4
275  beq   L(has_no_vec)
276  clrrdi  r9,r9,4
277  mr    r5,r10	/* Capture *v_regs value in r5.  */
278
279  stvx  v0,0,r10
280  stvx  v1,0,r9
281  addi  r10,r10,32
282  addi  r9,r9,32
283
284  stvx  v2,0,r10
285  stvx  v3,0,r9
286  addi  r10,r10,32
287  addi  r9,r9,32
288
289  stvx  v4,0,r10
290  stvx  v5,0,r9
291  addi  r10,r10,32
292  addi  r9,r9,32
293
294  stvx  v6,0,r10
295  stvx  v7,0,r9
296  addi  r10,r10,32
297  addi  r9,r9,32
298
299  stvx  v8,0,r10
300  stvx  v9,0,r9
301  addi  r10,r10,32
302  addi  r9,r9,32
303
304  stvx  v10,0,r10
305  stvx  v11,0,r9
306  addi  r10,r10,32
307  addi  r9,r9,32
308
309  stvx  v12,0,r10
310  stvx  v13,0,r9
311  addi  r10,r10,32
312  addi  r9,r9,32
313
314  stvx  v14,0,r10
315  stvx  v15,0,r9
316  addi  r10,r10,32
317  addi  r9,r9,32
318
319  stvx  v16,0,r10
320  stvx  v17,0,r9
321  addi  r10,r10,32
322  addi  r9,r9,32
323
324  stvx  v18,0,r10
325  stvx  v19,0,r9
326  addi  r10,r10,32
327  addi  r9,r9,32
328
329  stvx  v20,0,r10
330  stvx  v21,0,r9
331  addi  r10,r10,32
332  addi  r9,r9,32
333
334  stvx  v22,0,r10
335  stvx  v23,0,r9
336  addi  r10,r10,32
337  addi  r9,r9,32
338
339  stvx  v24,0,r10
340  stvx  v25,0,r9
341  addi  r10,r10,32
342  addi  r9,r9,32
343
344  stvx  v26,0,r10
345  stvx  v27,0,r9
346  addi  r10,r10,32
347  addi  r9,r9,32
348
349  stvx  v28,0,r10
350  stvx  v29,0,r9
351  addi  r10,r10,32
352  addi  r9,r9,32
353
354  stvx  v30,0,r10
355  stvx  v31,0,r9
356  addi  r10,r10,32
357  addi  r9,r9,32
358
359  mfvscr  v0
360  mfspr r0,VRSAVE
361  stvx  v0,0,r10
362  stw   r0,0(9)
363
364L(has_no_vec):
365/*
366   Store either a NULL or a quadword aligned pointer to the Vector register
367   array into *v_regs.
368*/
369  std   r5,(SIGCONTEXT_V_REGS_PTR)(r3)
370
371  addi  r5,r3,UCONTEXT_SIGMASK
372  li  r4,0
373  li  r3,SIG_BLOCK
374  bl  JUMPTARGET(__sigprocmask)
375  nop
376
377  ld    r0,128+FRAME_LR_SAVE(r1)
378  addi  r1,r1,128
379  mtlr  r0
380  blr
381PSEUDO_END(__getcontext)
382
383versioned_symbol (libc, __getcontext, getcontext, GLIBC_2_3_4)
384