]> Git Repo - J-linux.git/blob - tools/testing/selftests/powerpc/utils.c
Merge tag 'vfs-6.13-rc7.fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs
[J-linux.git] / tools / testing / selftests / powerpc / utils.c
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * Copyright 2013-2015, Michael Ellerman, IBM Corp.
4  */
5
6 #define _GNU_SOURCE     /* For CPU_ZERO etc. */
7
8 #include <elf.h>
9 #include <errno.h>
10 #include <fcntl.h>
11 #include <inttypes.h>
12 #include <limits.h>
13 #include <link.h>
14 #include <sched.h>
15 #include <stdio.h>
16 #include <stdlib.h>
17 #include <string.h>
18 #include <sys/ioctl.h>
19 #include <sys/stat.h>
20 #include <sys/sysinfo.h>
21 #include <sys/types.h>
22 #include <sys/utsname.h>
23 #include <unistd.h>
24 #include <asm/unistd.h>
25 #include <linux/limits.h>
26
27 #include "utils.h"
28
29 static char auxv[4096];
30
31 int read_file(const char *path, char *buf, size_t count, size_t *len)
32 {
33         ssize_t rc;
34         int fd;
35         int err;
36         char eof;
37
38         fd = open(path, O_RDONLY);
39         if (fd < 0)
40                 return -errno;
41
42         rc = read(fd, buf, count);
43         if (rc < 0) {
44                 err = -errno;
45                 goto out;
46         }
47
48         if (len)
49                 *len = rc;
50
51         /* Overflow if there are still more bytes after filling the buffer */
52         if (rc == count) {
53                 rc = read(fd, &eof, 1);
54                 if (rc != 0) {
55                         err = -EOVERFLOW;
56                         goto out;
57                 }
58         }
59
60         err = 0;
61
62 out:
63         close(fd);
64         errno = -err;
65         return err;
66 }
67
68 int read_file_alloc(const char *path, char **buf, size_t *len)
69 {
70         size_t read_offset = 0;
71         size_t buffer_len = 0;
72         char *buffer = NULL;
73         int err;
74         int fd;
75
76         fd = open(path, O_RDONLY);
77         if (fd < 0)
78                 return -errno;
79
80         /*
81          * We don't use stat & preallocate st_size because some non-files
82          * report 0 file size. Instead just dynamically grow the buffer
83          * as needed.
84          */
85         while (1) {
86                 ssize_t rc;
87
88                 if (read_offset >= buffer_len / 2) {
89                         char *next_buffer;
90
91                         buffer_len = buffer_len ? buffer_len * 2 : 4096;
92                         next_buffer = realloc(buffer, buffer_len);
93                         if (!next_buffer) {
94                                 err = -errno;
95                                 goto out;
96                         }
97                         buffer = next_buffer;
98                 }
99
100                 rc = read(fd, buffer + read_offset, buffer_len - read_offset);
101                 if (rc < 0) {
102                         err = -errno;
103                         goto out;
104                 }
105
106                 if (rc == 0)
107                         break;
108
109                 read_offset += rc;
110         }
111
112         *buf = buffer;
113         if (len)
114                 *len = read_offset;
115
116         err = 0;
117
118 out:
119         close(fd);
120         if (err)
121                 free(buffer);
122         errno = -err;
123         return err;
124 }
125
126 int write_file(const char *path, const char *buf, size_t count)
127 {
128         int fd;
129         int err;
130         ssize_t rc;
131
132         fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, 0644);
133         if (fd < 0)
134                 return -errno;
135
136         rc = write(fd, buf, count);
137         if (rc < 0) {
138                 err = -errno;
139                 goto out;
140         }
141
142         if (rc != count) {
143                 err = -EOVERFLOW;
144                 goto out;
145         }
146
147         err = 0;
148
149 out:
150         close(fd);
151         errno = -err;
152         return err;
153 }
154
155 int read_auxv(char *buf, ssize_t buf_size)
156 {
157         int err;
158
159         err = read_file("/proc/self/auxv", buf, buf_size, NULL);
160         if (err) {
161                 perror("Error reading /proc/self/auxv");
162                 return err;
163         }
164
165         return 0;
166 }
167
168 int read_debugfs_file(const char *subpath, char *buf, size_t count)
169 {
170         char path[PATH_MAX] = "/sys/kernel/debug/";
171
172         strncat(path, subpath, sizeof(path) - strlen(path) - 1);
173
174         return read_file(path, buf, count, NULL);
175 }
176
177 int write_debugfs_file(const char *subpath, const char *buf, size_t count)
178 {
179         char path[PATH_MAX] = "/sys/kernel/debug/";
180
181         strncat(path, subpath, sizeof(path) - strlen(path) - 1);
182
183         return write_file(path, buf, count);
184 }
185
186 static int validate_int_parse(const char *buffer, size_t count, char *end)
187 {
188         int err = 0;
189
190         /* Require at least one digit */
191         if (end == buffer) {
192                 err = -EINVAL;
193                 goto out;
194         }
195
196         /* Require all remaining characters be whitespace-ish */
197         for (; end < buffer + count; end++) {
198                 if (*end == '\0')
199                         break;
200
201                 if (*end != ' ' && *end != '\n') {
202                         err = -EINVAL;
203                         goto out;
204                 }
205         }
206
207 out:
208         errno = -err;
209         return err;
210 }
211
212 static int parse_bounded_int(const char *buffer, size_t count, intmax_t *result,
213                              int base, intmax_t min, intmax_t max)
214 {
215         int err;
216         char *end;
217
218         errno = 0;
219         *result = strtoimax(buffer, &end, base);
220
221         if (errno)
222                 return -errno;
223
224         err = validate_int_parse(buffer, count, end);
225         if (err)
226                 goto out;
227
228         if (*result < min || *result > max)
229                 err = -EOVERFLOW;
230
231 out:
232         errno = -err;
233         return err;
234 }
235
236 static int parse_bounded_uint(const char *buffer, size_t count, uintmax_t *result,
237                               int base, uintmax_t max)
238 {
239         int err = 0;
240         char *end;
241
242         errno = 0;
243         *result = strtoumax(buffer, &end, base);
244
245         if (errno)
246                 return -errno;
247
248         err = validate_int_parse(buffer, count, end);
249         if (err)
250                 goto out;
251
252         if (*result > max)
253                 err = -EOVERFLOW;
254
255 out:
256         errno = -err;
257         return err;
258 }
259
260 int parse_intmax(const char *buffer, size_t count, intmax_t *result, int base)
261 {
262         return parse_bounded_int(buffer, count, result, base, INTMAX_MIN, INTMAX_MAX);
263 }
264
265 int parse_uintmax(const char *buffer, size_t count, uintmax_t *result, int base)
266 {
267         return parse_bounded_uint(buffer, count, result, base, UINTMAX_MAX);
268 }
269
270 int parse_int(const char *buffer, size_t count, int *result, int base)
271 {
272         intmax_t parsed;
273         int err = parse_bounded_int(buffer, count, &parsed, base, INT_MIN, INT_MAX);
274
275         *result = parsed;
276         return err;
277 }
278
279 int parse_uint(const char *buffer, size_t count, unsigned int *result, int base)
280 {
281         uintmax_t parsed;
282         int err = parse_bounded_uint(buffer, count, &parsed, base, UINT_MAX);
283
284         *result = parsed;
285         return err;
286 }
287
288 int parse_long(const char *buffer, size_t count, long *result, int base)
289 {
290         intmax_t parsed;
291         int err = parse_bounded_int(buffer, count, &parsed, base, LONG_MIN, LONG_MAX);
292
293         *result = parsed;
294         return err;
295 }
296
297 int parse_ulong(const char *buffer, size_t count, unsigned long *result, int base)
298 {
299         uintmax_t parsed;
300         int err = parse_bounded_uint(buffer, count, &parsed, base, ULONG_MAX);
301
302         *result = parsed;
303         return err;
304 }
305
306 int read_long(const char *path, long *result, int base)
307 {
308         int err;
309         char buffer[32] = {0};
310
311         err = read_file(path, buffer, sizeof(buffer) - 1, NULL);
312         if (err)
313                 return err;
314
315         return parse_long(buffer, sizeof(buffer), result, base);
316 }
317
318 int read_ulong(const char *path, unsigned long *result, int base)
319 {
320         int err;
321         char buffer[32] = {0};
322
323         err = read_file(path, buffer, sizeof(buffer) - 1, NULL);
324         if (err)
325                 return err;
326
327         return parse_ulong(buffer, sizeof(buffer), result, base);
328 }
329
330 int write_long(const char *path, long result, int base)
331 {
332         int err;
333         int len;
334         char buffer[32];
335
336         /* Decimal only for now: no format specifier for signed hex values */
337         if (base != 10) {
338                 err = -EINVAL;
339                 goto out;
340         }
341
342         len = snprintf(buffer, sizeof(buffer), "%ld", result);
343         if (len < 0 || len >= sizeof(buffer)) {
344                 err = -EOVERFLOW;
345                 goto out;
346         }
347
348         err = write_file(path, buffer, len);
349
350 out:
351         errno = -err;
352         return err;
353 }
354
355 int write_ulong(const char *path, unsigned long result, int base)
356 {
357         int err;
358         int len;
359         char buffer[32];
360         char *fmt;
361
362         switch (base) {
363         case 10:
364                 fmt = "%lu";
365                 break;
366         case 16:
367                 fmt = "%lx";
368                 break;
369         default:
370                 err = -EINVAL;
371                 goto out;
372         }
373
374         len = snprintf(buffer, sizeof(buffer), fmt, result);
375         if (len < 0 || len >= sizeof(buffer)) {
376                 err = -errno;
377                 goto out;
378         }
379
380         err = write_file(path, buffer, len);
381
382 out:
383         errno = -err;
384         return err;
385 }
386
387 void *find_auxv_entry(int type, char *auxv)
388 {
389         ElfW(auxv_t) *p;
390
391         p = (ElfW(auxv_t) *)auxv;
392
393         while (p->a_type != AT_NULL) {
394                 if (p->a_type == type)
395                         return p;
396
397                 p++;
398         }
399
400         return NULL;
401 }
402
403 void *get_auxv_entry(int type)
404 {
405         ElfW(auxv_t) *p;
406
407         if (read_auxv(auxv, sizeof(auxv)))
408                 return NULL;
409
410         p = find_auxv_entry(type, auxv);
411         if (p)
412                 return (void *)p->a_un.a_val;
413
414         return NULL;
415 }
416
417 int pick_online_cpu(void)
418 {
419         int ncpus, cpu = -1;
420         cpu_set_t *mask;
421         size_t size;
422
423         ncpus = get_nprocs_conf();
424         size = CPU_ALLOC_SIZE(ncpus);
425         mask = CPU_ALLOC(ncpus);
426         if (!mask) {
427                 perror("malloc");
428                 return -1;
429         }
430
431         CPU_ZERO_S(size, mask);
432
433         if (sched_getaffinity(0, size, mask)) {
434                 perror("sched_getaffinity");
435                 goto done;
436         }
437
438         /* We prefer a primary thread, but skip 0 */
439         for (cpu = 8; cpu < ncpus; cpu += 8)
440                 if (CPU_ISSET_S(cpu, size, mask))
441                         goto done;
442
443         /* Search for anything, but in reverse */
444         for (cpu = ncpus - 1; cpu >= 0; cpu--)
445                 if (CPU_ISSET_S(cpu, size, mask))
446                         goto done;
447
448         printf("No cpus in affinity mask?!\n");
449
450 done:
451         CPU_FREE(mask);
452         return cpu;
453 }
454
455 int bind_to_cpu(int cpu)
456 {
457         cpu_set_t mask;
458         int err;
459
460         if (cpu == BIND_CPU_ANY) {
461                 cpu = pick_online_cpu();
462                 if (cpu < 0)
463                         return cpu;
464         }
465
466         printf("Binding to cpu %d\n", cpu);
467
468         CPU_ZERO(&mask);
469         CPU_SET(cpu, &mask);
470
471         err = sched_setaffinity(0, sizeof(mask), &mask);
472         if (err)
473                 return err;
474
475         return cpu;
476 }
477
478 bool is_ppc64le(void)
479 {
480         struct utsname uts;
481         int rc;
482
483         errno = 0;
484         rc = uname(&uts);
485         if (rc) {
486                 perror("uname");
487                 return false;
488         }
489
490         return strcmp(uts.machine, "ppc64le") == 0;
491 }
492
493 int read_sysfs_file(char *fpath, char *result, size_t result_size)
494 {
495         char path[PATH_MAX] = "/sys/";
496
497         strncat(path, fpath, PATH_MAX - strlen(path) - 1);
498
499         return read_file(path, result, result_size, NULL);
500 }
501
502 int read_debugfs_int(const char *debugfs_file, int *result)
503 {
504         int err;
505         char value[16] = {0};
506
507         err = read_debugfs_file(debugfs_file, value, sizeof(value) - 1);
508         if (err)
509                 return err;
510
511         return parse_int(value, sizeof(value), result, 10);
512 }
513
514 int write_debugfs_int(const char *debugfs_file, int result)
515 {
516         char value[16];
517
518         snprintf(value, 16, "%d", result);
519
520         return write_debugfs_file(debugfs_file, value, strlen(value));
521 }
522
523 static long perf_event_open(struct perf_event_attr *hw_event, pid_t pid,
524                 int cpu, int group_fd, unsigned long flags)
525 {
526         return syscall(__NR_perf_event_open, hw_event, pid, cpu,
527                       group_fd, flags);
528 }
529
530 static void perf_event_attr_init(struct perf_event_attr *event_attr,
531                                         unsigned int type,
532                                         unsigned long config)
533 {
534         memset(event_attr, 0, sizeof(*event_attr));
535
536         event_attr->type = type;
537         event_attr->size = sizeof(struct perf_event_attr);
538         event_attr->config = config;
539         event_attr->read_format = PERF_FORMAT_GROUP;
540         event_attr->disabled = 1;
541         event_attr->exclude_kernel = 1;
542         event_attr->exclude_hv = 1;
543         event_attr->exclude_guest = 1;
544 }
545
546 int perf_event_open_counter(unsigned int type,
547                             unsigned long config, int group_fd)
548 {
549         int fd;
550         struct perf_event_attr event_attr;
551
552         perf_event_attr_init(&event_attr, type, config);
553
554         fd = perf_event_open(&event_attr, 0, -1, group_fd, 0);
555
556         if (fd < 0)
557                 perror("perf_event_open() failed");
558
559         return fd;
560 }
561
562 int perf_event_enable(int fd)
563 {
564         if (ioctl(fd, PERF_EVENT_IOC_ENABLE, PERF_IOC_FLAG_GROUP) == -1) {
565                 perror("error while enabling perf events");
566                 return -1;
567         }
568
569         return 0;
570 }
571
572 int perf_event_disable(int fd)
573 {
574         if (ioctl(fd, PERF_EVENT_IOC_DISABLE, PERF_IOC_FLAG_GROUP) == -1) {
575                 perror("error disabling perf events");
576                 return -1;
577         }
578
579         return 0;
580 }
581
582 int perf_event_reset(int fd)
583 {
584         if (ioctl(fd, PERF_EVENT_IOC_RESET, PERF_IOC_FLAG_GROUP) == -1) {
585                 perror("error resetting perf events");
586                 return -1;
587         }
588
589         return 0;
590 }
591
592 int using_hash_mmu(bool *using_hash)
593 {
594         char line[128];
595         FILE *f;
596         int rc;
597
598         f = fopen("/proc/cpuinfo", "r");
599         FAIL_IF(!f);
600
601         rc = 0;
602         while (fgets(line, sizeof(line), f) != NULL) {
603                 if (!strcmp(line, "MMU          : Hash\n") ||
604                     !strcmp(line, "platform     : Cell\n") ||
605                     !strcmp(line, "platform     : PowerMac\n")) {
606                         *using_hash = true;
607                         goto out;
608                 }
609
610                 if (strcmp(line, "MMU           : Radix\n") == 0) {
611                         *using_hash = false;
612                         goto out;
613                 }
614         }
615
616         rc = -1;
617 out:
618         fclose(f);
619         return rc;
620 }
621
622 struct sigaction push_signal_handler(int sig, void (*fn)(int, siginfo_t *, void *))
623 {
624         struct sigaction sa;
625         struct sigaction old_handler;
626
627         sa.sa_sigaction = fn;
628         sigemptyset(&sa.sa_mask);
629         sa.sa_flags = SA_SIGINFO;
630         FAIL_IF_EXIT_MSG(sigaction(sig, &sa, &old_handler),
631                          "failed to push signal handler");
632
633         return old_handler;
634 }
635
636 struct sigaction pop_signal_handler(int sig, struct sigaction old_handler)
637 {
638         struct sigaction popped;
639
640         FAIL_IF_EXIT_MSG(sigaction(sig, &old_handler, &popped),
641                          "failed to pop signal handler");
642
643         return popped;
644 }
This page took 0.061972 seconds and 4 git commands to generate.