elf: Ignore LD_LIBRARY_PATH and debug env var for setuid for static
[glibc.git] / sysdeps / powerpc / fpu / tst-setcontext-fpscr.c
blob2eba5f26726dbb7c4ffa0adab5e851c15b261033
1 /* Copyright (C) 2001-2023 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
4 The GNU C Library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Lesser General Public
6 License as published by the Free Software Foundation; either
7 version 2.1 of the License, or (at your option) any later version.
9 The GNU C Library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Lesser General Public License for more details.
14 You should have received a copy of the GNU Lesser General Public
15 License along with the GNU C Library; if not, see
16 <https://www.gnu.org/licenses/>. */
18 #include <errno.h>
19 #include <stdio.h>
20 #include <stdlib.h>
21 #include <string.h>
22 #include <ucontext.h>
23 #include <unistd.h>
24 #include <link.h>
25 #include <elf.h>
26 #include <fpu_control.h>
27 #include <sys/auxv.h>
28 #include <support/support.h>
30 #include <support/xstdio.h>
32 static ucontext_t ctx[3];
35 volatile int global;
38 static int back_in_main;
41 volatile static ElfW(auxv_t) *auxv = NULL;
43 ElfW(Addr) query_auxv(int type)
45 FILE *auxv_f;
46 ElfW(auxv_t) auxv_struct;
47 ElfW(auxv_t) *auxv_temp;
48 int i = 0;
50 /* if the /proc/self/auxv file has not been manually copied into the heap
51 yet, then do it */
53 if(auxv == NULL)
55 auxv_f = fopen("/proc/self/auxv", "r");
57 if(auxv_f == 0)
59 perror("Error opening file for reading");
60 return 0;
62 auxv = xmalloc (getpagesize ());
66 xfread (&auxv_struct, sizeof (ElfW(auxv_t)), 1, auxv_f);
67 auxv[i] = auxv_struct;
68 i++;
69 } while(auxv_struct.a_type != AT_NULL);
72 auxv_temp = (ElfW(auxv_t) *)auxv;
73 i = 0;
76 if(auxv_temp[i].a_type == type)
78 return auxv_temp[i].a_un.a_val;
80 i++;
81 } while (auxv_temp[i].a_type != AT_NULL);
83 return 0;
86 typedef unsigned int di_fpscr_t __attribute__ ((__mode__ (__DI__)));
87 typedef unsigned int si_fpscr_t __attribute__ ((__mode__ (__SI__)));
89 #define _FPSCR_RESERVED 0xfffffff8ffffff04ULL
91 #define _FPSCR_TEST0_DRN 0x0000000400000000ULL
92 #define _FPSCR_TEST0_RN 0x0000000000000003ULL
94 #define _FPSCR_TEST1_DRN 0x0000000300000000ULL
95 #define _FPSCR_TEST1_RN 0x0000000000000002ULL
97 /* Macros for accessing the hardware control word on Power6[x]. */
98 #define _GET_DI_FPSCR(__fpscr) \
99 ({union { double d; di_fpscr_t fpscr; } u; \
100 u.d = __builtin_mffs (); \
101 (__fpscr) = u.fpscr; \
102 u.fpscr; \
105 /* We make sure to zero fp after we use it in order to prevent stale data
106 in an fp register from making a test-case pass erroneously. */
107 # define _SET_DI_FPSCR(__fpscr) \
108 { union { double d; di_fpscr_t fpscr; } u; \
109 register double fr; \
110 u.fpscr = __fpscr; \
111 fr = u.d; \
112 /* Set the entire 64-bit FPSCR. */ \
113 __asm__ (".machine push; " \
114 ".machine \"power6\"; " \
115 "mtfsf 255,%0,1,0; " \
116 ".machine pop" : : "f" (fr)); \
117 fr = 0.0; \
120 # define _GET_SI_FPSCR(__fpscr) \
121 ({union { double d; di_fpscr_t fpscr; } u; \
122 u.d = __builtin_mffs (); \
123 (__fpscr) = (si_fpscr_t) u.fpscr; \
124 (si_fpscr_t) u.fpscr; \
127 /* We make sure to zero fp after we use it in order to prevent stale data
128 in an fp register from making a test-case pass erroneously. */
129 # define _SET_SI_FPSCR(__fpscr) \
130 { union { double d; di_fpscr_t fpscr; } u; \
131 register double fr; \
132 /* More-or-less arbitrary; this is a QNaN. */ \
133 u.fpscr = 0xfff80000ULL << 32; \
134 u.fpscr |= __fpscr & 0xffffffffULL; \
135 fr = u.d; \
136 __builtin_mtfsf (255, fr); \
137 fr = 0.0; \
140 void prime_special_regs(int which)
142 ElfW(Addr) a_val;
144 di_fpscr_t di_fpscr __attribute__ ((__aligned__(8)));
146 a_val = query_auxv(AT_HWCAP);
147 if(a_val == -1)
149 puts ("querying the auxv for the hwcap failed");
150 _exit (1);
153 /* Indicates a 64-bit FPSCR. */
154 if (a_val & PPC_FEATURE_HAS_DFP)
156 _GET_DI_FPSCR(di_fpscr);
158 /* Overwrite the existing DRN and RN if there is one. */
159 if (which == 0)
160 di_fpscr = ((di_fpscr & _FPSCR_RESERVED) | (_FPSCR_TEST0_DRN | _FPSCR_TEST0_RN));
161 else
162 di_fpscr = ((di_fpscr & _FPSCR_RESERVED) | (_FPSCR_TEST1_DRN | _FPSCR_TEST1_RN));
163 puts ("Priming 64-bit FPSCR with:");
164 printf("0x%.16llx\n",(unsigned long long int)di_fpscr);
166 _SET_DI_FPSCR(di_fpscr);
168 else
170 puts ("32-bit FPSCR found and will be tested.");
171 _GET_SI_FPSCR(di_fpscr);
173 /* Overwrite the existing RN if there is one. */
174 if (which == 0)
175 di_fpscr = ((di_fpscr & _FPSCR_RESERVED) | (_FPSCR_TEST0_RN));
176 else
177 di_fpscr = ((di_fpscr & _FPSCR_RESERVED) | (_FPSCR_TEST1_RN));
178 puts ("Priming 32-bit FPSCR with:");
179 printf("0x%.8lx\n",(unsigned long int) di_fpscr);
181 _SET_SI_FPSCR(di_fpscr);
185 void clear_special_regs(void)
187 ElfW(Addr) a_val;
189 di_fpscr_t di_fpscr __attribute__ ((__aligned__(8)));
191 union {
192 double d;
193 unsigned long long int lli;
194 unsigned int li[2];
195 } dlli;
197 a_val = query_auxv(AT_HWCAP);
198 if(a_val == -1)
200 puts ("querying the auxv for the hwcap failed");
201 _exit (1);
204 #if __WORDSIZE == 32
205 dlli.d = ctx[0].uc_mcontext.uc_regs->fpregs.fpscr;
206 #else
207 dlli.d = ctx[0].uc_mcontext.fp_regs[32];
208 #endif
210 puts("The FPSCR value saved in the ucontext_t is:");
212 /* Indicates a 64-bit FPSCR. */
213 if (a_val & PPC_FEATURE_HAS_DFP)
215 printf("0x%.16llx\n",dlli.lli);
216 di_fpscr = 0x0;
217 puts ("Clearing the 64-bit FPSCR to:");
218 printf("0x%.16llx\n",(unsigned long long int) di_fpscr);
220 _SET_DI_FPSCR(di_fpscr);
222 else
224 printf("0x%.8x\n",(unsigned int) dlli.li[1]);
225 di_fpscr = 0x0;
226 puts ("Clearing the 32-bit FPSCR to:");
227 printf("0x%.8lx\n",(unsigned long int) di_fpscr);
229 _SET_SI_FPSCR(di_fpscr);
233 void test_special_regs(int which)
235 ElfW(Addr) a_val;
236 unsigned long long int test;
238 di_fpscr_t di_fpscr __attribute__ ((__aligned__(8)));
240 a_val = query_auxv(AT_HWCAP);
241 if(a_val == -1)
243 puts ("querying the auxv for the hwcap failed");
244 _exit (2);
247 /* Indicates a 64-bit FPSCR. */
248 if (a_val & PPC_FEATURE_HAS_DFP)
250 _GET_DI_FPSCR(di_fpscr);
252 if (which == 0)
253 puts ("After setcontext the 64-bit FPSCR contains:");
254 else
255 puts ("After swapcontext the 64-bit FPSCR contains:");
257 printf("0x%.16llx\n",(unsigned long long int) di_fpscr);
258 test = (_FPSCR_TEST0_DRN | _FPSCR_TEST0_RN);
259 if((di_fpscr & (test)) != (test))
261 printf ("%s: DRN and RN bits set before getcontext were not preserved across [set|swap]context call: %m",__FUNCTION__);
262 _exit (3);
265 else
267 _GET_SI_FPSCR(di_fpscr);
268 if (which == 0)
269 puts ("After setcontext the 32-bit FPSCR contains:");
270 else
271 puts ("After swapcontext the 32-bit FPSCR contains:");
273 printf("0x%.8lx\n",(unsigned long int) di_fpscr);
274 test = _FPSCR_TEST0_RN;
275 if((di_fpscr & test) != test)
277 printf ("%s: RN bit set before getcontext was not preserved across [set|swap]context call: %m",__FUNCTION__);
278 _exit (4);
284 static void
285 check_called (void)
287 if (back_in_main == 0)
289 puts ("program did not reach main again");
290 _exit (5);
296 main (void)
298 atexit (check_called);
300 puts ("priming the FPSCR with a marker");
301 prime_special_regs (0);
303 puts ("making contexts");
304 if (getcontext (&ctx[0]) != 0)
306 if (errno == ENOSYS)
308 back_in_main = 1;
309 exit (0);
312 printf ("%s: getcontext: %m\n", __FUNCTION__);
313 exit (6);
316 /* Play some tricks with this context. */
317 if (++global == 1)
319 clear_special_regs ( );
320 if (setcontext (&ctx[0]) != 0)
322 printf ("%s: setcontext: %m\n", __FUNCTION__);
323 exit (7);
326 if (global != 2)
328 printf ("%s: 'global' not incremented twice\n", __FUNCTION__);
329 exit (8);
332 test_special_regs (0);
334 global = 0;
335 if (getcontext (&ctx[0]) != 0)
337 printf ("%s: getcontext: %m\n", __FUNCTION__);
338 exit (9);
341 if (++global == 1)
343 puts ("priming the FPSCR with a marker");
344 prime_special_regs (1);
346 puts ("swapping contexts");
347 if (swapcontext (&ctx[1], &ctx[0]) != 0)
349 printf ("%s: swapcontext: %m\n", __FUNCTION__);
350 exit (9);
353 if (global != 2)
355 printf ("%s: 'global' not incremented twice\n", __FUNCTION__);
356 exit (10);
359 test_special_regs (1);
361 puts ("back at main program");
362 back_in_main = 1;
364 puts ("test succeeded");
365 return 0;