1/* Copyright (C) 2012-2022 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
3
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.
8
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.
13
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/>. */
17
18/* Verify that changing AVX512 registers in audit library won't affect
19 function parameter passing/return. */
20
21#include <dlfcn.h>
22#include <link.h>
23#include <stddef.h>
24#include <stdint.h>
25#include <stdio.h>
26#include <stdlib.h>
27#include <string.h>
28#include <unistd.h>
29#include <bits/wordsize.h>
30#include <gnu/lib-names.h>
31
32unsigned int
33la_version (unsigned int v)
34{
35 setlinebuf (stdout);
36
37 printf (format: "version: %u\n", v);
38
39 char buf[20];
40 sprintf (buf, "%u", v);
41
42 return v;
43}
44
45void
46la_activity (uintptr_t *cookie, unsigned int flag)
47{
48 if (flag == LA_ACT_CONSISTENT)
49 printf (format: "activity: consistent\n");
50 else if (flag == LA_ACT_ADD)
51 printf (format: "activity: add\n");
52 else if (flag == LA_ACT_DELETE)
53 printf (format: "activity: delete\n");
54 else
55 printf (format: "activity: unknown activity %u\n", flag);
56}
57
58char *
59la_objsearch (const char *name, uintptr_t *cookie, unsigned int flag)
60{
61 char buf[100];
62 const char *flagstr;
63 if (flag == LA_SER_ORIG)
64 flagstr = "LA_SET_ORIG";
65 else if (flag == LA_SER_LIBPATH)
66 flagstr = "LA_SER_LIBPATH";
67 else if (flag == LA_SER_RUNPATH)
68 flagstr = "LA_SER_RUNPATH";
69 else if (flag == LA_SER_CONFIG)
70 flagstr = "LA_SER_CONFIG";
71 else if (flag == LA_SER_DEFAULT)
72 flagstr = "LA_SER_DEFAULT";
73 else if (flag == LA_SER_SECURE)
74 flagstr = "LA_SER_SECURE";
75 else
76 {
77 sprintf (buf, "unknown flag %d", flag);
78 flagstr = buf;
79 }
80 printf (format: "objsearch: %s, %s\n", name, flagstr);
81
82 return (char *) name;
83}
84
85unsigned int
86la_objopen (struct link_map *l, Lmid_t lmid, uintptr_t *cookie)
87{
88 printf (format: "objopen: %ld, %s\n", lmid, l->l_name);
89
90 return 3;
91}
92
93void
94la_preinit (uintptr_t *cookie)
95{
96 printf (format: "preinit\n");
97}
98
99unsigned int
100la_objclose (uintptr_t *cookie)
101{
102 printf (format: "objclose\n");
103 return 0;
104}
105
106uintptr_t
107la_symbind32 (Elf32_Sym *sym, unsigned int ndx, uintptr_t *refcook,
108 uintptr_t *defcook, unsigned int *flags, const char *symname)
109{
110 printf (format: "symbind32: symname=%s, st_value=%#lx, ndx=%u, flags=%u\n",
111 symname, (long int) sym->st_value, ndx, *flags);
112
113 return sym->st_value;
114}
115
116uintptr_t
117la_symbind64 (Elf64_Sym *sym, unsigned int ndx, uintptr_t *refcook,
118 uintptr_t *defcook, unsigned int *flags, const char *symname)
119{
120 printf (format: "symbind64: symname=%s, st_value=%#lx, ndx=%u, flags=%u\n",
121 symname, (long int) sym->st_value, ndx, *flags);
122
123 return sym->st_value;
124}
125
126#include <tst-audit.h>
127
128#ifdef __AVX512F__
129#include <immintrin.h>
130#include <cpuid.h>
131
132static int
133check_avx512 (void)
134{
135 unsigned int eax, ebx, ecx, edx;
136
137 if (__get_cpuid (1, &eax, &ebx, &ecx, &edx) == 0
138 || (ecx & (bit_AVX | bit_OSXSAVE)) != (bit_AVX | bit_OSXSAVE))
139 return 0;
140
141 __cpuid_count (7, 0, eax, ebx, ecx, edx);
142 if (!(ebx & bit_AVX512F))
143 return 0;
144
145 asm ("xgetbv" : "=a" (eax), "=d" (edx) : "c" (0));
146
147 /* Verify that ZMM, YMM and XMM states are enabled. */
148 return (eax & 0xe6) == 0xe6;
149}
150
151#else
152#include <emmintrin.h>
153#endif
154
155ElfW(Addr)
156pltenter (ElfW(Sym) *sym, unsigned int ndx, uintptr_t *refcook,
157 uintptr_t *defcook, La_regs *regs, unsigned int *flags,
158 const char *symname, long int *framesizep)
159{
160 printf (format: "pltenter: symname=%s, st_value=%#lx, ndx=%u, flags=%u\n",
161 symname, (long int) sym->st_value, ndx, *flags);
162
163#ifdef __AVX512F__
164 if (check_avx512 () && strcmp (symname, "audit_test") == 0)
165 {
166 __m512i zero = _mm512_setzero_si512 ();
167 if (memcmp (&regs->lr_vector[0], &zero, sizeof (zero))
168 || memcmp (&regs->lr_vector[1], &zero, sizeof (zero))
169 || memcmp (&regs->lr_vector[2], &zero, sizeof (zero))
170 || memcmp (&regs->lr_vector[3], &zero, sizeof (zero))
171 || memcmp (&regs->lr_vector[4], &zero, sizeof (zero))
172 || memcmp (&regs->lr_vector[5], &zero, sizeof (zero))
173 || memcmp (&regs->lr_vector[6], &zero, sizeof (zero))
174 || memcmp (&regs->lr_vector[7], &zero, sizeof (zero)))
175 abort ();
176
177 for (int i = 0; i < 8; i++)
178 regs->lr_vector[i].zmm[0]
179 = (La_x86_64_zmm) _mm512_set1_epi64 (i + 1);
180
181 __m512i zmm = _mm512_set1_epi64 (-1);
182 asm volatile ("vmovdqa64 %0, %%zmm0" : : "x" (zmm) : "xmm0" );
183 asm volatile ("vmovdqa64 %0, %%zmm1" : : "x" (zmm) : "xmm1" );
184 asm volatile ("vmovdqa64 %0, %%zmm2" : : "x" (zmm) : "xmm2" );
185 asm volatile ("vmovdqa64 %0, %%zmm3" : : "x" (zmm) : "xmm3" );
186 asm volatile ("vmovdqa64 %0, %%zmm4" : : "x" (zmm) : "xmm4" );
187 asm volatile ("vmovdqa64 %0, %%zmm5" : : "x" (zmm) : "xmm5" );
188 asm volatile ("vmovdqa64 %0, %%zmm6" : : "x" (zmm) : "xmm6" );
189 asm volatile ("vmovdqa64 %0, %%zmm7" : : "x" (zmm) : "xmm7" );
190
191 *framesizep = 1024;
192 }
193#endif
194
195 return sym->st_value;
196}
197
198unsigned int
199pltexit (ElfW(Sym) *sym, unsigned int ndx, uintptr_t *refcook,
200 uintptr_t *defcook, const La_regs *inregs, La_retval *outregs,
201 const char *symname)
202{
203 printf (format: "pltexit: symname=%s, st_value=%#lx, ndx=%u, retval=%tu\n",
204 symname, (long int) sym->st_value, ndx,
205 (ptrdiff_t) outregs->int_retval);
206
207#ifdef __AVX512F__
208 if (check_avx512 () && strcmp (symname, "audit_test") == 0)
209 {
210 __m512i zero = _mm512_setzero_si512 ();
211 if (memcmp (&outregs->lrv_vector0, &zero, sizeof (zero)))
212 abort ();
213
214 for (int i = 0; i < 8; i++)
215 {
216 __m512i zmm = _mm512_set1_epi64 (i + 1);
217 if (memcmp (&inregs->lr_vector[i], &zmm, sizeof (zmm)) != 0)
218 abort ();
219 }
220
221 outregs->lrv_vector0.zmm[0]
222 = (La_x86_64_zmm) _mm512_set1_epi64 (0x12349876);
223
224 __m512i zmm = _mm512_set1_epi64 (-1);
225 asm volatile ("vmovdqa64 %0, %%zmm0" : : "x" (zmm) : "xmm0" );
226 asm volatile ("vmovdqa64 %0, %%zmm1" : : "x" (zmm) : "xmm1" );
227 }
228#endif
229
230 return 0;
231}
232

source code of glibc/sysdeps/x86_64/tst-auditmod10b.c