accel/qaic: Add AIC200 support
[drm/drm-misc.git] / tools / testing / selftests / powerpc / utils.c
blobe5f2d8735c649a10a8ce1b1c63afe9e9e3084bb3
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3 * Copyright 2013-2015, Michael Ellerman, IBM Corp.
4 */
6 #define _GNU_SOURCE /* For CPU_ZERO etc. */
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>
27 #include "utils.h"
29 static char auxv[4096];
31 int read_file(const char *path, char *buf, size_t count, size_t *len)
33 ssize_t rc;
34 int fd;
35 int err;
36 char eof;
38 fd = open(path, O_RDONLY);
39 if (fd < 0)
40 return -errno;
42 rc = read(fd, buf, count);
43 if (rc < 0) {
44 err = -errno;
45 goto out;
48 if (len)
49 *len = rc;
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;
60 err = 0;
62 out:
63 close(fd);
64 errno = -err;
65 return err;
68 int read_file_alloc(const char *path, char **buf, size_t *len)
70 size_t read_offset = 0;
71 size_t buffer_len = 0;
72 char *buffer = NULL;
73 int err;
74 int fd;
76 fd = open(path, O_RDONLY);
77 if (fd < 0)
78 return -errno;
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.
85 while (1) {
86 ssize_t rc;
88 if (read_offset >= buffer_len / 2) {
89 char *next_buffer;
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;
97 buffer = next_buffer;
100 rc = read(fd, buffer + read_offset, buffer_len - read_offset);
101 if (rc < 0) {
102 err = -errno;
103 goto out;
106 if (rc == 0)
107 break;
109 read_offset += rc;
112 *buf = buffer;
113 if (len)
114 *len = read_offset;
116 err = 0;
118 out:
119 close(fd);
120 if (err)
121 free(buffer);
122 errno = -err;
123 return err;
126 int write_file(const char *path, const char *buf, size_t count)
128 int fd;
129 int err;
130 ssize_t rc;
132 fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, 0644);
133 if (fd < 0)
134 return -errno;
136 rc = write(fd, buf, count);
137 if (rc < 0) {
138 err = -errno;
139 goto out;
142 if (rc != count) {
143 err = -EOVERFLOW;
144 goto out;
147 err = 0;
149 out:
150 close(fd);
151 errno = -err;
152 return err;
155 int read_auxv(char *buf, ssize_t buf_size)
157 int err;
159 err = read_file("/proc/self/auxv", buf, buf_size, NULL);
160 if (err) {
161 perror("Error reading /proc/self/auxv");
162 return err;
165 return 0;
168 int read_debugfs_file(const char *subpath, char *buf, size_t count)
170 char path[PATH_MAX] = "/sys/kernel/debug/";
172 strncat(path, subpath, sizeof(path) - strlen(path) - 1);
174 return read_file(path, buf, count, NULL);
177 int write_debugfs_file(const char *subpath, const char *buf, size_t count)
179 char path[PATH_MAX] = "/sys/kernel/debug/";
181 strncat(path, subpath, sizeof(path) - strlen(path) - 1);
183 return write_file(path, buf, count);
186 static int validate_int_parse(const char *buffer, size_t count, char *end)
188 int err = 0;
190 /* Require at least one digit */
191 if (end == buffer) {
192 err = -EINVAL;
193 goto out;
196 /* Require all remaining characters be whitespace-ish */
197 for (; end < buffer + count; end++) {
198 if (*end == '\0')
199 break;
201 if (*end != ' ' && *end != '\n') {
202 err = -EINVAL;
203 goto out;
207 out:
208 errno = -err;
209 return err;
212 static int parse_bounded_int(const char *buffer, size_t count, intmax_t *result,
213 int base, intmax_t min, intmax_t max)
215 int err;
216 char *end;
218 errno = 0;
219 *result = strtoimax(buffer, &end, base);
221 if (errno)
222 return -errno;
224 err = validate_int_parse(buffer, count, end);
225 if (err)
226 goto out;
228 if (*result < min || *result > max)
229 err = -EOVERFLOW;
231 out:
232 errno = -err;
233 return err;
236 static int parse_bounded_uint(const char *buffer, size_t count, uintmax_t *result,
237 int base, uintmax_t max)
239 int err = 0;
240 char *end;
242 errno = 0;
243 *result = strtoumax(buffer, &end, base);
245 if (errno)
246 return -errno;
248 err = validate_int_parse(buffer, count, end);
249 if (err)
250 goto out;
252 if (*result > max)
253 err = -EOVERFLOW;
255 out:
256 errno = -err;
257 return err;
260 int parse_intmax(const char *buffer, size_t count, intmax_t *result, int base)
262 return parse_bounded_int(buffer, count, result, base, INTMAX_MIN, INTMAX_MAX);
265 int parse_uintmax(const char *buffer, size_t count, uintmax_t *result, int base)
267 return parse_bounded_uint(buffer, count, result, base, UINTMAX_MAX);
270 int parse_int(const char *buffer, size_t count, int *result, int base)
272 intmax_t parsed;
273 int err = parse_bounded_int(buffer, count, &parsed, base, INT_MIN, INT_MAX);
275 *result = parsed;
276 return err;
279 int parse_uint(const char *buffer, size_t count, unsigned int *result, int base)
281 uintmax_t parsed;
282 int err = parse_bounded_uint(buffer, count, &parsed, base, UINT_MAX);
284 *result = parsed;
285 return err;
288 int parse_long(const char *buffer, size_t count, long *result, int base)
290 intmax_t parsed;
291 int err = parse_bounded_int(buffer, count, &parsed, base, LONG_MIN, LONG_MAX);
293 *result = parsed;
294 return err;
297 int parse_ulong(const char *buffer, size_t count, unsigned long *result, int base)
299 uintmax_t parsed;
300 int err = parse_bounded_uint(buffer, count, &parsed, base, ULONG_MAX);
302 *result = parsed;
303 return err;
306 int read_long(const char *path, long *result, int base)
308 int err;
309 char buffer[32] = {0};
311 err = read_file(path, buffer, sizeof(buffer) - 1, NULL);
312 if (err)
313 return err;
315 return parse_long(buffer, sizeof(buffer), result, base);
318 int read_ulong(const char *path, unsigned long *result, int base)
320 int err;
321 char buffer[32] = {0};
323 err = read_file(path, buffer, sizeof(buffer) - 1, NULL);
324 if (err)
325 return err;
327 return parse_ulong(buffer, sizeof(buffer), result, base);
330 int write_long(const char *path, long result, int base)
332 int err;
333 int len;
334 char buffer[32];
336 /* Decimal only for now: no format specifier for signed hex values */
337 if (base != 10) {
338 err = -EINVAL;
339 goto out;
342 len = snprintf(buffer, sizeof(buffer), "%ld", result);
343 if (len < 0 || len >= sizeof(buffer)) {
344 err = -EOVERFLOW;
345 goto out;
348 err = write_file(path, buffer, len);
350 out:
351 errno = -err;
352 return err;
355 int write_ulong(const char *path, unsigned long result, int base)
357 int err;
358 int len;
359 char buffer[32];
360 char *fmt;
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;
374 len = snprintf(buffer, sizeof(buffer), fmt, result);
375 if (len < 0 || len >= sizeof(buffer)) {
376 err = -errno;
377 goto out;
380 err = write_file(path, buffer, len);
382 out:
383 errno = -err;
384 return err;
387 void *find_auxv_entry(int type, char *auxv)
389 ElfW(auxv_t) *p;
391 p = (ElfW(auxv_t) *)auxv;
393 while (p->a_type != AT_NULL) {
394 if (p->a_type == type)
395 return p;
397 p++;
400 return NULL;
403 void *get_auxv_entry(int type)
405 ElfW(auxv_t) *p;
407 if (read_auxv(auxv, sizeof(auxv)))
408 return NULL;
410 p = find_auxv_entry(type, auxv);
411 if (p)
412 return (void *)p->a_un.a_val;
414 return NULL;
417 int pick_online_cpu(void)
419 int ncpus, cpu = -1;
420 cpu_set_t *mask;
421 size_t size;
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;
431 CPU_ZERO_S(size, mask);
433 if (sched_getaffinity(0, size, mask)) {
434 perror("sched_getaffinity");
435 goto done;
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;
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;
448 printf("No cpus in affinity mask?!\n");
450 done:
451 CPU_FREE(mask);
452 return cpu;
455 int bind_to_cpu(int cpu)
457 cpu_set_t mask;
458 int err;
460 if (cpu == BIND_CPU_ANY) {
461 cpu = pick_online_cpu();
462 if (cpu < 0)
463 return cpu;
466 printf("Binding to cpu %d\n", cpu);
468 CPU_ZERO(&mask);
469 CPU_SET(cpu, &mask);
471 err = sched_setaffinity(0, sizeof(mask), &mask);
472 if (err)
473 return err;
475 return cpu;
478 bool is_ppc64le(void)
480 struct utsname uts;
481 int rc;
483 errno = 0;
484 rc = uname(&uts);
485 if (rc) {
486 perror("uname");
487 return false;
490 return strcmp(uts.machine, "ppc64le") == 0;
493 int read_sysfs_file(char *fpath, char *result, size_t result_size)
495 char path[PATH_MAX] = "/sys/";
497 strncat(path, fpath, PATH_MAX - strlen(path) - 1);
499 return read_file(path, result, result_size, NULL);
502 int read_debugfs_int(const char *debugfs_file, int *result)
504 int err;
505 char value[16] = {0};
507 err = read_debugfs_file(debugfs_file, value, sizeof(value) - 1);
508 if (err)
509 return err;
511 return parse_int(value, sizeof(value), result, 10);
514 int write_debugfs_int(const char *debugfs_file, int result)
516 char value[16];
518 snprintf(value, 16, "%d", result);
520 return write_debugfs_file(debugfs_file, value, strlen(value));
523 static long perf_event_open(struct perf_event_attr *hw_event, pid_t pid,
524 int cpu, int group_fd, unsigned long flags)
526 return syscall(__NR_perf_event_open, hw_event, pid, cpu,
527 group_fd, flags);
530 static void perf_event_attr_init(struct perf_event_attr *event_attr,
531 unsigned int type,
532 unsigned long config)
534 memset(event_attr, 0, sizeof(*event_attr));
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;
546 int perf_event_open_counter(unsigned int type,
547 unsigned long config, int group_fd)
549 int fd;
550 struct perf_event_attr event_attr;
552 perf_event_attr_init(&event_attr, type, config);
554 fd = perf_event_open(&event_attr, 0, -1, group_fd, 0);
556 if (fd < 0)
557 perror("perf_event_open() failed");
559 return fd;
562 int perf_event_enable(int fd)
564 if (ioctl(fd, PERF_EVENT_IOC_ENABLE, PERF_IOC_FLAG_GROUP) == -1) {
565 perror("error while enabling perf events");
566 return -1;
569 return 0;
572 int perf_event_disable(int fd)
574 if (ioctl(fd, PERF_EVENT_IOC_DISABLE, PERF_IOC_FLAG_GROUP) == -1) {
575 perror("error disabling perf events");
576 return -1;
579 return 0;
582 int perf_event_reset(int fd)
584 if (ioctl(fd, PERF_EVENT_IOC_RESET, PERF_IOC_FLAG_GROUP) == -1) {
585 perror("error resetting perf events");
586 return -1;
589 return 0;
592 int using_hash_mmu(bool *using_hash)
594 char line[128];
595 FILE *f;
596 int rc;
598 f = fopen("/proc/cpuinfo", "r");
599 FAIL_IF(!f);
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;
610 if (strcmp(line, "MMU : Radix\n") == 0) {
611 *using_hash = false;
612 goto out;
616 rc = -1;
617 out:
618 fclose(f);
619 return rc;
622 struct sigaction push_signal_handler(int sig, void (*fn)(int, siginfo_t *, void *))
624 struct sigaction sa;
625 struct sigaction old_handler;
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");
633 return old_handler;
636 struct sigaction pop_signal_handler(int sig, struct sigaction old_handler)
638 struct sigaction popped;
640 FAIL_IF_EXIT_MSG(sigaction(sig, &old_handler, &popped),
641 "failed to pop signal handler");
643 return popped;