]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blob - gdb/testsuite/gdb.arch/aarch64-sme-core.c
Update copyright year range in header of all files managed by GDB
[thirdparty/binutils-gdb.git] / gdb / testsuite / gdb.arch / aarch64-sme-core.c
1 /* This testcase is part of GDB, the GNU debugger.
2
3 Copyright 2023-2024 Free Software Foundation, Inc.
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 3 of the License, or
8 (at your option) any later version.
9
10 This program 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
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>. */
17
18 /* Exercise AArch64's Scalable Vector/Matrix Extension core file generation
19 for GDB. This includes reading Linux Kernel-generated core files and
20 writing GDB core files via the gcore command and making sure the contents
21 are sane. */
22
23 #include <stdio.h>
24 #include <sys/auxv.h>
25 #include <sys/prctl.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include <unistd.h>
29
30 #ifndef HWCAP_SVE
31 #define HWCAP_SVE (1 << 22)
32 #endif
33
34 #ifndef HWCAP2_SME
35 #define HWCAP2_SME (1 << 23)
36 #endif
37
38 #ifndef HWCAP2_SME2
39 #define HWCAP2_SME2 (1UL << 37)
40 #define HWCAP2_SME2P1 (1UL << 38)
41 #endif
42
43 #ifndef PR_SVE_SET_VL
44 #define PR_SVE_SET_VL 50
45 #define PR_SVE_GET_VL 51
46 #define PR_SVE_VL_LEN_MASK 0xffff
47 #endif
48
49 #ifndef PR_SME_SET_VL
50 #define PR_SME_SET_VL 63
51 #define PR_SME_GET_VL 64
52 #define PR_SME_VL_LEN_MASK 0xffff
53 #endif
54
55 static void
56 enable_za ()
57 {
58 /* smstart za */
59 __asm __volatile (".word 0xD503457F");
60 }
61
62 static void
63 disable_za ()
64 {
65 /* smstop za */
66 __asm __volatile (".word 0xD503447F");
67 }
68
69 static void
70 enable_sm ()
71 {
72 /* smstart sm */
73 __asm __volatile (".word 0xD503437F");
74 }
75
76 static void
77 disable_sm ()
78 {
79 /* smstop sm */
80 __asm __volatile (".word 0xD503427F");
81 }
82
83 static void
84 initialize_fpsimd_state ()
85 {
86 char buffer[16];
87
88 for (int i = 0; i < 16; i++)
89 buffer[i] = 0x55;
90
91 __asm __volatile ("mov x0, %0\n\t" \
92 : : "r" (buffer));
93
94 __asm __volatile ("ldr q0, [x0]");
95 __asm __volatile ("ldr q1, [x0]");
96 __asm __volatile ("ldr q2, [x0]");
97 __asm __volatile ("ldr q3, [x0]");
98 __asm __volatile ("ldr q4, [x0]");
99 __asm __volatile ("ldr q5, [x0]");
100 __asm __volatile ("ldr q6, [x0]");
101 __asm __volatile ("ldr q7, [x0]");
102 __asm __volatile ("ldr q8, [x0]");
103 __asm __volatile ("ldr q9, [x0]");
104 __asm __volatile ("ldr q10, [x0]");
105 __asm __volatile ("ldr q11, [x0]");
106 __asm __volatile ("ldr q12, [x0]");
107 __asm __volatile ("ldr q13, [x0]");
108 __asm __volatile ("ldr q14, [x0]");
109 __asm __volatile ("ldr q15, [x0]");
110 __asm __volatile ("ldr q16, [x0]");
111 __asm __volatile ("ldr q17, [x0]");
112 __asm __volatile ("ldr q18, [x0]");
113 __asm __volatile ("ldr q19, [x0]");
114 __asm __volatile ("ldr q20, [x0]");
115 __asm __volatile ("ldr q21, [x0]");
116 __asm __volatile ("ldr q22, [x0]");
117 __asm __volatile ("ldr q23, [x0]");
118 __asm __volatile ("ldr q24, [x0]");
119 __asm __volatile ("ldr q25, [x0]");
120 __asm __volatile ("ldr q26, [x0]");
121 __asm __volatile ("ldr q27, [x0]");
122 __asm __volatile ("ldr q28, [x0]");
123 __asm __volatile ("ldr q29, [x0]");
124 __asm __volatile ("ldr q30, [x0]");
125 __asm __volatile ("ldr q31, [x0]");
126 }
127
128 static void
129 initialize_za_state ()
130 {
131 /* zero za */
132 __asm __volatile (".word 0xC00800FF");
133
134 char buffer[256];
135
136 for (int i = 0; i < 256; i++)
137 buffer[i] = 0xaa;
138
139 __asm __volatile ("mov x0, %0\n\t" \
140 : : "r" (buffer));
141
142 /* Initialize loop boundaries. */
143 __asm __volatile ("mov w12, 0");
144 __asm __volatile ("mov w17, 256");
145
146 /* loop: ldr za[w12, 0], [x0] */
147 __asm __volatile ("loop: .word 0xe1000000");
148 __asm __volatile ("add w12, w12, 1");
149 __asm __volatile ("cmp w12, w17");
150 __asm __volatile ("bne loop");
151 }
152
153 static void
154 initialize_zt_state ()
155 {
156 unsigned long hwcap2 = getauxval (AT_HWCAP2);
157
158 if (!(hwcap2 & HWCAP2_SME2) && !(hwcap2 & HWCAP2_SME2P1))
159 return;
160
161 char buffer[64];
162
163 for (int i = 0; i < 64; i++)
164 buffer[i] = 0xff;
165
166 __asm __volatile ("mov x0, %0\n\t" \
167 : : "r" (buffer));
168
169 /* Initialize ZT0. */
170 /* ldr zt0, x0 */
171 __asm __volatile (".word 0xe11f8000");
172 }
173
174 static void
175 initialize_tpidr2 ()
176 {
177 __asm __volatile ("mov x0, #0xffffffffffffffff");
178
179 /* Write x0 to tpidr2. */
180 __asm __volatile (".word 0xd51bd0a0");
181 }
182
183 static void
184 initialize_sve_state ()
185 {
186 __asm __volatile ("dup z0.b, -1");
187 __asm __volatile ("dup z1.b, -1");
188 __asm __volatile ("dup z2.b, -1");
189 __asm __volatile ("dup z3.b, -1");
190 __asm __volatile ("dup z4.b, -1");
191 __asm __volatile ("dup z5.b, -1");
192 __asm __volatile ("dup z6.b, -1");
193 __asm __volatile ("dup z7.b, -1");
194 __asm __volatile ("dup z8.b, -1");
195 __asm __volatile ("dup z9.b, -1");
196 __asm __volatile ("dup z10.b, -1");
197 __asm __volatile ("dup z11.b, -1");
198 __asm __volatile ("dup z12.b, -1");
199 __asm __volatile ("dup z13.b, -1");
200 __asm __volatile ("dup z14.b, -1");
201 __asm __volatile ("dup z15.b, -1");
202 __asm __volatile ("dup z16.b, -1");
203 __asm __volatile ("dup z17.b, -1");
204 __asm __volatile ("dup z18.b, -1");
205 __asm __volatile ("dup z19.b, -1");
206 __asm __volatile ("dup z20.b, -1");
207 __asm __volatile ("dup z21.b, -1");
208 __asm __volatile ("dup z22.b, -1");
209 __asm __volatile ("dup z23.b, -1");
210 __asm __volatile ("dup z24.b, -1");
211 __asm __volatile ("dup z25.b, -1");
212 __asm __volatile ("dup z26.b, -1");
213 __asm __volatile ("dup z27.b, -1");
214 __asm __volatile ("dup z28.b, -1");
215 __asm __volatile ("dup z29.b, -1");
216 __asm __volatile ("dup z30.b, -1");
217 __asm __volatile ("dup z31.b, -1");
218 __asm __volatile ("ptrue p0.b");
219 __asm __volatile ("ptrue p1.b");
220 __asm __volatile ("ptrue p2.b");
221 __asm __volatile ("ptrue p3.b");
222 __asm __volatile ("ptrue p4.b");
223 __asm __volatile ("ptrue p5.b");
224 __asm __volatile ("ptrue p6.b");
225 __asm __volatile ("ptrue p7.b");
226 __asm __volatile ("ptrue p8.b");
227 __asm __volatile ("ptrue p9.b");
228 __asm __volatile ("ptrue p10.b");
229 __asm __volatile ("ptrue p11.b");
230 __asm __volatile ("ptrue p12.b");
231 __asm __volatile ("ptrue p13.b");
232 __asm __volatile ("ptrue p14.b");
233 __asm __volatile ("ptrue p15.b");
234 __asm __volatile ("setffr");
235 }
236
237 static int get_vl_size ()
238 {
239 int res = prctl (PR_SVE_GET_VL, 0, 0, 0, 0);
240 if (res < 0)
241 {
242 printf ("FAILED to PR_SVE_GET_VL (%d)", res);
243 return -1;
244 }
245 return (res & PR_SVE_VL_LEN_MASK);
246 }
247
248 static int get_svl_size ()
249 {
250 int res = prctl (PR_SME_GET_VL, 0, 0, 0, 0);
251 if (res < 0)
252 {
253 printf ("FAILED to PR_SME_GET_VL (%d)\n", res);
254 return -1;
255 }
256 return (res & PR_SVE_VL_LEN_MASK);
257 }
258
259 static int set_vl_size (int new_vl)
260 {
261 int res = prctl (PR_SVE_SET_VL, new_vl, 0, 0, 0, 0);
262 if (res < 0)
263 {
264 printf ("FAILED to PR_SVE_SET_VL (%d)\n", res);
265 return -1;
266 }
267
268 res = get_vl_size ();
269 if (res != new_vl)
270 {
271 printf ("Unexpected VL value (%d)\n", res);
272 return -1;
273 }
274
275 return res;
276 }
277
278 static int set_svl_size (int new_svl)
279 {
280 int res = prctl (PR_SME_SET_VL, new_svl, 0, 0, 0, 0);
281 if (res < 0)
282 {
283 printf ("FAILED to PR_SME_SET_VL (%d)\n", res);
284 return -1;
285 }
286
287 res = get_svl_size ();
288 if (res != new_svl)
289 {
290 printf ("Unexpected SVL value (%d)\n", res);
291 return -1;
292 }
293
294 return res;
295 }
296
297 /* Enable register states based on STATE.
298
299 0 - FPSIMD
300 1 - SVE
301 2 - SSVE
302 3 - ZA (+ SME2 ZT0)
303 4 - ZA and SSVE (+ SME2 ZT0). */
304
305 void enable_states (int state)
306 {
307 disable_za ();
308 disable_sm ();
309 initialize_fpsimd_state ();
310
311 if (state == 1)
312 {
313 initialize_sve_state ();
314 }
315 else if (state == 2)
316 {
317 enable_sm ();
318 initialize_sve_state ();
319 }
320 else if (state == 3)
321 {
322 enable_za ();
323 initialize_za_state ();
324 initialize_zt_state ();
325 }
326 else if (state == 4)
327 {
328 enable_za ();
329 enable_sm ();
330 initialize_sve_state ();
331 initialize_za_state ();
332 initialize_zt_state ();
333 }
334
335 return;
336 }
337
338 static int
339 test_id_to_state (int id)
340 {
341 return id / 25;
342 }
343
344 static int
345 test_id_to_vl (int id)
346 {
347 return 16 << ((id / 5) % 5);
348 }
349
350 static int
351 test_id_to_svl (int id)
352 {
353 return 16 << (id % 5);
354 }
355
356 static void
357 dummy ()
358 {
359 }
360
361 int
362 main (int argc, char **argv)
363 {
364 if (argc > 2)
365 printf ("Incorrect number of arguments passed to test.\n");
366
367 if (getauxval (AT_HWCAP) & HWCAP_SVE && getauxval (AT_HWCAP2) & HWCAP2_SME)
368 {
369 long test_id = 0;
370
371 /* If we have a test id passed as argument, read it now. */
372 if (argc == 2)
373 test_id = strtol (argv[1], NULL, 0);
374
375 dummy (); /* stop to initialize test_id */
376
377 int state = test_id_to_state (test_id);
378 int vl = test_id_to_vl (test_id);
379 int svl = test_id_to_svl (test_id);
380
381 if (set_vl_size (vl) == -1 || set_svl_size (svl) == -1)
382 return -1;
383
384 enable_states (state);
385
386 /* Also set the TPIDR2 register so we can test dumping its contents
387 to a core file. */
388 initialize_tpidr2 ();
389
390 char *p = 0x0;
391 *p = 0xff; /* crash point */
392 }
393 else
394 {
395 printf ("SKIP: no HWCAP_SVE or HWCAP2_SME on this system\n");
396 return -1;
397 }
398
399 return 0;
400 }