clk: Drop the rate range on clk_put()
[linux-2.6-microblaze.git] / tools / testing / selftests / arm64 / fp / sve-ptrace.c
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * Copyright (C) 2015-2021 ARM Limited.
4  * Original author: Dave Martin <Dave.Martin@arm.com>
5  */
6 #include <errno.h>
7 #include <stdbool.h>
8 #include <stddef.h>
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <string.h>
12 #include <unistd.h>
13 #include <sys/auxv.h>
14 #include <sys/prctl.h>
15 #include <sys/ptrace.h>
16 #include <sys/types.h>
17 #include <sys/uio.h>
18 #include <sys/wait.h>
19 #include <asm/sigcontext.h>
20 #include <asm/ptrace.h>
21
22 #include "../../kselftest.h"
23
24 #define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]))
25
26 /* <linux/elf.h> and <sys/auxv.h> don't like each other, so: */
27 #ifndef NT_ARM_SVE
28 #define NT_ARM_SVE 0x405
29 #endif
30
31 struct vec_type {
32         const char *name;
33         unsigned long hwcap_type;
34         unsigned long hwcap;
35         int regset;
36         int prctl_set;
37 };
38
39 static const struct vec_type vec_types[] = {
40         {
41                 .name = "SVE",
42                 .hwcap_type = AT_HWCAP,
43                 .hwcap = HWCAP_SVE,
44                 .regset = NT_ARM_SVE,
45                 .prctl_set = PR_SVE_SET_VL,
46         },
47 };
48
49 #define VL_TESTS (((SVE_VQ_MAX - SVE_VQ_MIN) + 1) * 3)
50 #define FLAG_TESTS 2
51 #define FPSIMD_TESTS 3
52
53 #define EXPECTED_TESTS ((VL_TESTS + FLAG_TESTS + FPSIMD_TESTS) * ARRAY_SIZE(vec_types))
54
55 static void fill_buf(char *buf, size_t size)
56 {
57         int i;
58
59         for (i = 0; i < size; i++)
60                 buf[i] = random();
61 }
62
63 static int do_child(void)
64 {
65         if (ptrace(PTRACE_TRACEME, -1, NULL, NULL))
66                 ksft_exit_fail_msg("PTRACE_TRACEME", strerror(errno));
67
68         if (raise(SIGSTOP))
69                 ksft_exit_fail_msg("raise(SIGSTOP)", strerror(errno));
70
71         return EXIT_SUCCESS;
72 }
73
74 static int get_fpsimd(pid_t pid, struct user_fpsimd_state *fpsimd)
75 {
76         struct iovec iov;
77
78         iov.iov_base = fpsimd;
79         iov.iov_len = sizeof(*fpsimd);
80         return ptrace(PTRACE_GETREGSET, pid, NT_PRFPREG, &iov);
81 }
82
83 static struct user_sve_header *get_sve(pid_t pid, const struct vec_type *type,
84                                        void **buf, size_t *size)
85 {
86         struct user_sve_header *sve;
87         void *p;
88         size_t sz = sizeof *sve;
89         struct iovec iov;
90
91         while (1) {
92                 if (*size < sz) {
93                         p = realloc(*buf, sz);
94                         if (!p) {
95                                 errno = ENOMEM;
96                                 goto error;
97                         }
98
99                         *buf = p;
100                         *size = sz;
101                 }
102
103                 iov.iov_base = *buf;
104                 iov.iov_len = sz;
105                 if (ptrace(PTRACE_GETREGSET, pid, type->regset, &iov))
106                         goto error;
107
108                 sve = *buf;
109                 if (sve->size <= sz)
110                         break;
111
112                 sz = sve->size;
113         }
114
115         return sve;
116
117 error:
118         return NULL;
119 }
120
121 static int set_sve(pid_t pid, const struct vec_type *type,
122                    const struct user_sve_header *sve)
123 {
124         struct iovec iov;
125
126         iov.iov_base = (void *)sve;
127         iov.iov_len = sve->size;
128         return ptrace(PTRACE_SETREGSET, pid, type->regset, &iov);
129 }
130
131 /* Validate setting and getting the inherit flag */
132 static void ptrace_set_get_inherit(pid_t child, const struct vec_type *type)
133 {
134         struct user_sve_header sve;
135         struct user_sve_header *new_sve = NULL;
136         size_t new_sve_size = 0;
137         int ret;
138
139         /* First set the flag */
140         memset(&sve, 0, sizeof(sve));
141         sve.size = sizeof(sve);
142         sve.vl = sve_vl_from_vq(SVE_VQ_MIN);
143         sve.flags = SVE_PT_VL_INHERIT;
144         ret = set_sve(child, type, &sve);
145         if (ret != 0) {
146                 ksft_test_result_fail("Failed to set %s SVE_PT_VL_INHERIT\n",
147                                       type->name);
148                 return;
149         }
150
151         /*
152          * Read back the new register state and verify that we have
153          * set the flags we expected.
154          */
155         if (!get_sve(child, type, (void **)&new_sve, &new_sve_size)) {
156                 ksft_test_result_fail("Failed to read %s SVE flags\n",
157                                       type->name);
158                 return;
159         }
160
161         ksft_test_result(new_sve->flags & SVE_PT_VL_INHERIT,
162                          "%s SVE_PT_VL_INHERIT set\n", type->name);
163
164         /* Now clear */
165         sve.flags &= ~SVE_PT_VL_INHERIT;
166         ret = set_sve(child, type, &sve);
167         if (ret != 0) {
168                 ksft_test_result_fail("Failed to clear %s SVE_PT_VL_INHERIT\n",
169                                       type->name);
170                 return;
171         }
172
173         if (!get_sve(child, type, (void **)&new_sve, &new_sve_size)) {
174                 ksft_test_result_fail("Failed to read %s SVE flags\n",
175                                       type->name);
176                 return;
177         }
178
179         ksft_test_result(!(new_sve->flags & SVE_PT_VL_INHERIT),
180                          "%s SVE_PT_VL_INHERIT cleared\n", type->name);
181
182         free(new_sve);
183 }
184
185 /* Validate attempting to set the specfied VL via ptrace */
186 static void ptrace_set_get_vl(pid_t child, const struct vec_type *type,
187                               unsigned int vl, bool *supported)
188 {
189         struct user_sve_header sve;
190         struct user_sve_header *new_sve = NULL;
191         size_t new_sve_size = 0;
192         int ret, prctl_vl;
193
194         *supported = false;
195
196         /* Check if the VL is supported in this process */
197         prctl_vl = prctl(type->prctl_set, vl);
198         if (prctl_vl == -1)
199                 ksft_exit_fail_msg("prctl(PR_%s_SET_VL) failed: %s (%d)\n",
200                                    type->name, strerror(errno), errno);
201
202         /* If the VL is not supported then a supported VL will be returned */
203         *supported = (prctl_vl == vl);
204
205         /* Set the VL by doing a set with no register payload */
206         memset(&sve, 0, sizeof(sve));
207         sve.size = sizeof(sve);
208         sve.vl = vl;
209         ret = set_sve(child, type, &sve);
210         if (ret != 0) {
211                 ksft_test_result_fail("Failed to set %s VL %u\n",
212                                       type->name, vl);
213                 return;
214         }
215
216         /*
217          * Read back the new register state and verify that we have the
218          * same VL that we got from prctl() on ourselves.
219          */
220         if (!get_sve(child, type, (void **)&new_sve, &new_sve_size)) {
221                 ksft_test_result_fail("Failed to read %s VL %u\n",
222                                       type->name, vl);
223                 return;
224         }
225
226         ksft_test_result(new_sve->vl = prctl_vl, "Set %s VL %u\n",
227                          type->name, vl);
228
229         free(new_sve);
230 }
231
232 static void check_u32(unsigned int vl, const char *reg,
233                       uint32_t *in, uint32_t *out, int *errors)
234 {
235         if (*in != *out) {
236                 printf("# VL %d %s wrote %x read %x\n",
237                        vl, reg, *in, *out);
238                 (*errors)++;
239         }
240 }
241
242 /* Access the FPSIMD registers via the SVE regset */
243 static void ptrace_sve_fpsimd(pid_t child, const struct vec_type *type)
244 {
245         void *svebuf = NULL;
246         size_t svebufsz = 0;
247         struct user_sve_header *sve;
248         struct user_fpsimd_state *fpsimd, new_fpsimd;
249         unsigned int i, j;
250         unsigned char *p;
251
252         /* New process should start with FPSIMD registers only */
253         sve = get_sve(child, type, &svebuf, &svebufsz);
254         if (!sve) {
255                 ksft_test_result_fail("get_sve(%s): %s\n",
256                                       type->name, strerror(errno));
257
258                 return;
259         } else {
260                 ksft_test_result_pass("get_sve(%s FPSIMD)\n", type->name);
261         }
262
263         ksft_test_result((sve->flags & SVE_PT_REGS_MASK) == SVE_PT_REGS_FPSIMD,
264                          "Set FPSIMD registers via %s\n", type->name);
265         if ((sve->flags & SVE_PT_REGS_MASK) != SVE_PT_REGS_FPSIMD)
266                 goto out;
267
268         /* Try to set a known FPSIMD state via PT_REGS_SVE */
269         fpsimd = (struct user_fpsimd_state *)((char *)sve +
270                                               SVE_PT_FPSIMD_OFFSET);
271         for (i = 0; i < 32; ++i) {
272                 p = (unsigned char *)&fpsimd->vregs[i];
273
274                 for (j = 0; j < sizeof(fpsimd->vregs[i]); ++j)
275                         p[j] = j;
276         }
277
278         if (set_sve(child, type, sve)) {
279                 ksft_test_result_fail("set_sve(%s FPSIMD): %s\n",
280                                       type->name, strerror(errno));
281
282                 goto out;
283         }
284
285         /* Verify via the FPSIMD regset */
286         if (get_fpsimd(child, &new_fpsimd)) {
287                 ksft_test_result_fail("get_fpsimd(): %s\n",
288                                       strerror(errno));
289                 goto out;
290         }
291         if (memcmp(fpsimd, &new_fpsimd, sizeof(*fpsimd)) == 0)
292                 ksft_test_result_pass("%s get_fpsimd() gave same state\n",
293                                       type->name);
294         else
295                 ksft_test_result_fail("%s get_fpsimd() gave different state\n",
296                                       type->name);
297
298 out:
299         free(svebuf);
300 }
301
302 /* Validate attempting to set SVE data and read SVE data */
303 static void ptrace_set_sve_get_sve_data(pid_t child,
304                                         const struct vec_type *type,
305                                         unsigned int vl)
306 {
307         void *write_buf;
308         void *read_buf = NULL;
309         struct user_sve_header *write_sve;
310         struct user_sve_header *read_sve;
311         size_t read_sve_size = 0;
312         unsigned int vq = sve_vq_from_vl(vl);
313         int ret, i;
314         size_t data_size;
315         int errors = 0;
316
317         data_size = SVE_PT_SVE_OFFSET + SVE_PT_SVE_SIZE(vq, SVE_PT_REGS_SVE);
318         write_buf = malloc(data_size);
319         if (!write_buf) {
320                 ksft_test_result_fail("Error allocating %d byte buffer for %s VL %u\n",
321                                       data_size, type->name, vl);
322                 return;
323         }
324         write_sve = write_buf;
325
326         /* Set up some data and write it out */
327         memset(write_sve, 0, data_size);
328         write_sve->size = data_size;
329         write_sve->vl = vl;
330         write_sve->flags = SVE_PT_REGS_SVE;
331
332         for (i = 0; i < __SVE_NUM_ZREGS; i++)
333                 fill_buf(write_buf + SVE_PT_SVE_ZREG_OFFSET(vq, i),
334                          SVE_PT_SVE_ZREG_SIZE(vq));
335
336         for (i = 0; i < __SVE_NUM_PREGS; i++)
337                 fill_buf(write_buf + SVE_PT_SVE_PREG_OFFSET(vq, i),
338                          SVE_PT_SVE_PREG_SIZE(vq));
339
340         fill_buf(write_buf + SVE_PT_SVE_FPSR_OFFSET(vq), SVE_PT_SVE_FPSR_SIZE);
341         fill_buf(write_buf + SVE_PT_SVE_FPCR_OFFSET(vq), SVE_PT_SVE_FPCR_SIZE);
342
343         /* TODO: Generate a valid FFR pattern */
344
345         ret = set_sve(child, type, write_sve);
346         if (ret != 0) {
347                 ksft_test_result_fail("Failed to set %s VL %u data\n",
348                                       type->name, vl);
349                 goto out;
350         }
351
352         /* Read the data back */
353         if (!get_sve(child, type, (void **)&read_buf, &read_sve_size)) {
354                 ksft_test_result_fail("Failed to read %s VL %u data\n",
355                                       type->name, vl);
356                 goto out;
357         }
358         read_sve = read_buf;
359
360         /* We might read more data if there's extensions we don't know */
361         if (read_sve->size < write_sve->size) {
362                 ksft_test_result_fail("%s wrote %d bytes, only read %d\n",
363                                       type->name, write_sve->size,
364                                       read_sve->size);
365                 goto out_read;
366         }
367
368         for (i = 0; i < __SVE_NUM_ZREGS; i++) {
369                 if (memcmp(write_buf + SVE_PT_SVE_ZREG_OFFSET(vq, i),
370                            read_buf + SVE_PT_SVE_ZREG_OFFSET(vq, i),
371                            SVE_PT_SVE_ZREG_SIZE(vq)) != 0) {
372                         printf("# Mismatch in %u Z%d\n", vl, i);
373                         errors++;
374                 }
375         }
376
377         for (i = 0; i < __SVE_NUM_PREGS; i++) {
378                 if (memcmp(write_buf + SVE_PT_SVE_PREG_OFFSET(vq, i),
379                            read_buf + SVE_PT_SVE_PREG_OFFSET(vq, i),
380                            SVE_PT_SVE_PREG_SIZE(vq)) != 0) {
381                         printf("# Mismatch in %u P%d\n", vl, i);
382                         errors++;
383                 }
384         }
385
386         check_u32(vl, "FPSR", write_buf + SVE_PT_SVE_FPSR_OFFSET(vq),
387                   read_buf + SVE_PT_SVE_FPSR_OFFSET(vq), &errors);
388         check_u32(vl, "FPCR", write_buf + SVE_PT_SVE_FPCR_OFFSET(vq),
389                   read_buf + SVE_PT_SVE_FPCR_OFFSET(vq), &errors);
390
391         ksft_test_result(errors == 0, "Set and get %s data for VL %u\n",
392                          type->name, vl);
393
394 out_read:
395         free(read_buf);
396 out:
397         free(write_buf);
398 }
399
400 /* Validate attempting to set SVE data and read SVE data */
401 static void ptrace_set_sve_get_fpsimd_data(pid_t child,
402                                            const struct vec_type *type,
403                                            unsigned int vl)
404 {
405         void *write_buf;
406         struct user_sve_header *write_sve;
407         unsigned int vq = sve_vq_from_vl(vl);
408         struct user_fpsimd_state fpsimd_state;
409         int ret, i;
410         size_t data_size;
411         int errors = 0;
412
413         if (__BYTE_ORDER == __BIG_ENDIAN) {
414                 ksft_test_result_skip("Big endian not supported\n");
415                 return;
416         }
417
418         data_size = SVE_PT_SVE_OFFSET + SVE_PT_SVE_SIZE(vq, SVE_PT_REGS_SVE);
419         write_buf = malloc(data_size);
420         if (!write_buf) {
421                 ksft_test_result_fail("Error allocating %d byte buffer for %s VL %u\n",
422                                       data_size, type->name, vl);
423                 return;
424         }
425         write_sve = write_buf;
426
427         /* Set up some data and write it out */
428         memset(write_sve, 0, data_size);
429         write_sve->size = data_size;
430         write_sve->vl = vl;
431         write_sve->flags = SVE_PT_REGS_SVE;
432
433         for (i = 0; i < __SVE_NUM_ZREGS; i++)
434                 fill_buf(write_buf + SVE_PT_SVE_ZREG_OFFSET(vq, i),
435                          SVE_PT_SVE_ZREG_SIZE(vq));
436
437         fill_buf(write_buf + SVE_PT_SVE_FPSR_OFFSET(vq), SVE_PT_SVE_FPSR_SIZE);
438         fill_buf(write_buf + SVE_PT_SVE_FPCR_OFFSET(vq), SVE_PT_SVE_FPCR_SIZE);
439
440         ret = set_sve(child, type, write_sve);
441         if (ret != 0) {
442                 ksft_test_result_fail("Failed to set %s VL %u data\n",
443                                       type->name, vl);
444                 goto out;
445         }
446
447         /* Read the data back */
448         if (get_fpsimd(child, &fpsimd_state)) {
449                 ksft_test_result_fail("Failed to read %s VL %u FPSIMD data\n",
450                                       type->name, vl);
451                 goto out;
452         }
453
454         for (i = 0; i < __SVE_NUM_ZREGS; i++) {
455                 __uint128_t tmp = 0;
456
457                 /*
458                  * Z regs are stored endianness invariant, this won't
459                  * work for big endian
460                  */
461                 memcpy(&tmp, write_buf + SVE_PT_SVE_ZREG_OFFSET(vq, i),
462                        sizeof(tmp));
463
464                 if (tmp != fpsimd_state.vregs[i]) {
465                         printf("# Mismatch in FPSIMD for %s VL %u Z%d\n",
466                                type->name, vl, i);
467                         errors++;
468                 }
469         }
470
471         check_u32(vl, "FPSR", write_buf + SVE_PT_SVE_FPSR_OFFSET(vq),
472                   &fpsimd_state.fpsr, &errors);
473         check_u32(vl, "FPCR", write_buf + SVE_PT_SVE_FPCR_OFFSET(vq),
474                   &fpsimd_state.fpcr, &errors);
475
476         ksft_test_result(errors == 0, "Set and get FPSIMD data for %s VL %u\n",
477                          type->name, vl);
478
479 out:
480         free(write_buf);
481 }
482
483 static int do_parent(pid_t child)
484 {
485         int ret = EXIT_FAILURE;
486         pid_t pid;
487         int status, i;
488         siginfo_t si;
489         unsigned int vq, vl;
490         bool vl_supported;
491
492         /* Attach to the child */
493         while (1) {
494                 int sig;
495
496                 pid = wait(&status);
497                 if (pid == -1) {
498                         perror("wait");
499                         goto error;
500                 }
501
502                 /*
503                  * This should never happen but it's hard to flag in
504                  * the framework.
505                  */
506                 if (pid != child)
507                         continue;
508
509                 if (WIFEXITED(status) || WIFSIGNALED(status))
510                         ksft_exit_fail_msg("Child died unexpectedly\n");
511
512                 if (!WIFSTOPPED(status))
513                         goto error;
514
515                 sig = WSTOPSIG(status);
516
517                 if (ptrace(PTRACE_GETSIGINFO, pid, NULL, &si)) {
518                         if (errno == ESRCH)
519                                 goto disappeared;
520
521                         if (errno == EINVAL) {
522                                 sig = 0; /* bust group-stop */
523                                 goto cont;
524                         }
525
526                         ksft_test_result_fail("PTRACE_GETSIGINFO: %s\n",
527                                               strerror(errno));
528                         goto error;
529                 }
530
531                 if (sig == SIGSTOP && si.si_code == SI_TKILL &&
532                     si.si_pid == pid)
533                         break;
534
535         cont:
536                 if (ptrace(PTRACE_CONT, pid, NULL, sig)) {
537                         if (errno == ESRCH)
538                                 goto disappeared;
539
540                         ksft_test_result_fail("PTRACE_CONT: %s\n",
541                                               strerror(errno));
542                         goto error;
543                 }
544         }
545
546         for (i = 0; i < ARRAY_SIZE(vec_types); i++) {
547                 /* FPSIMD via SVE regset */
548                 if (getauxval(vec_types[i].hwcap_type) & vec_types[i].hwcap) {
549                         ptrace_sve_fpsimd(child, &vec_types[i]);
550                 } else {
551                         ksft_test_result_skip("%s FPSIMD get via SVE\n",
552                                               vec_types[i].name);
553                         ksft_test_result_skip("%s FPSIMD set via SVE\n",
554                                               vec_types[i].name);
555                         ksft_test_result_skip("%s set read via FPSIMD\n",
556                                               vec_types[i].name);
557                 }
558
559                 /* prctl() flags */
560                 ptrace_set_get_inherit(child, &vec_types[i]);
561
562                 /* Step through every possible VQ */
563                 for (vq = SVE_VQ_MIN; vq <= SVE_VQ_MAX; vq++) {
564                         vl = sve_vl_from_vq(vq);
565
566                         /* First, try to set this vector length */
567                         if (getauxval(vec_types[i].hwcap_type) &
568                             vec_types[i].hwcap) {
569                                 ptrace_set_get_vl(child, &vec_types[i], vl,
570                                                   &vl_supported);
571                         } else {
572                                 ksft_test_result_skip("%s get/set VL %d\n",
573                                                       vec_types[i].name, vl);
574                                 vl_supported = false;
575                         }
576
577                         /* If the VL is supported validate data set/get */
578                         if (vl_supported) {
579                                 ptrace_set_sve_get_sve_data(child, &vec_types[i], vl);
580                                 ptrace_set_sve_get_fpsimd_data(child, &vec_types[i], vl);
581                         } else {
582                                 ksft_test_result_skip("%s set SVE get SVE for VL %d\n",
583                                                       vec_types[i].name, vl);
584                                 ksft_test_result_skip("%s set SVE get FPSIMD for VL %d\n",
585                                                       vec_types[i].name, vl);
586                         }
587                 }
588         }
589
590         ret = EXIT_SUCCESS;
591
592 error:
593         kill(child, SIGKILL);
594
595 disappeared:
596         return ret;
597 }
598
599 int main(void)
600 {
601         int ret = EXIT_SUCCESS;
602         pid_t child;
603
604         srandom(getpid());
605
606         ksft_print_header();
607         ksft_set_plan(EXPECTED_TESTS);
608
609         if (!(getauxval(AT_HWCAP) & HWCAP_SVE))
610                 ksft_exit_skip("SVE not available\n");
611
612         child = fork();
613         if (!child)
614                 return do_child();
615
616         if (do_parent(child))
617                 ret = EXIT_FAILURE;
618
619         ksft_print_cnts();
620
621         return ret;
622 }