irqchip: Fix dependencies for archs w/o HAS_IOMEM
[linux/fpc-iii.git] / tools / testing / selftests / powerpc / pmu / lib.c
bloba07104c2afe69229fb74577c6af48c76ff40cadb
1 /*
2 * Copyright 2014, Michael Ellerman, IBM Corp.
3 * Licensed under GPLv2.
4 */
6 #define _GNU_SOURCE /* For CPU_ZERO etc. */
8 #include <errno.h>
9 #include <sched.h>
10 #include <setjmp.h>
11 #include <stdlib.h>
12 #include <sys/wait.h>
14 #include "utils.h"
15 #include "lib.h"
18 int pick_online_cpu(void)
20 cpu_set_t mask;
21 int cpu;
23 CPU_ZERO(&mask);
25 if (sched_getaffinity(0, sizeof(mask), &mask)) {
26 perror("sched_getaffinity");
27 return -1;
30 /* We prefer a primary thread, but skip 0 */
31 for (cpu = 8; cpu < CPU_SETSIZE; cpu += 8)
32 if (CPU_ISSET(cpu, &mask))
33 return cpu;
35 /* Search for anything, but in reverse */
36 for (cpu = CPU_SETSIZE - 1; cpu >= 0; cpu--)
37 if (CPU_ISSET(cpu, &mask))
38 return cpu;
40 printf("No cpus in affinity mask?!\n");
41 return -1;
44 int bind_to_cpu(int cpu)
46 cpu_set_t mask;
48 printf("Binding to cpu %d\n", cpu);
50 CPU_ZERO(&mask);
51 CPU_SET(cpu, &mask);
53 return sched_setaffinity(0, sizeof(mask), &mask);
56 #define PARENT_TOKEN 0xAA
57 #define CHILD_TOKEN 0x55
59 int sync_with_child(union pipe read_pipe, union pipe write_pipe)
61 char c = PARENT_TOKEN;
63 FAIL_IF(write(write_pipe.write_fd, &c, 1) != 1);
64 FAIL_IF(read(read_pipe.read_fd, &c, 1) != 1);
65 if (c != CHILD_TOKEN) /* sometimes expected */
66 return 1;
68 return 0;
71 int wait_for_parent(union pipe read_pipe)
73 char c;
75 FAIL_IF(read(read_pipe.read_fd, &c, 1) != 1);
76 FAIL_IF(c != PARENT_TOKEN);
78 return 0;
81 int notify_parent(union pipe write_pipe)
83 char c = CHILD_TOKEN;
85 FAIL_IF(write(write_pipe.write_fd, &c, 1) != 1);
87 return 0;
90 int notify_parent_of_error(union pipe write_pipe)
92 char c = ~CHILD_TOKEN;
94 FAIL_IF(write(write_pipe.write_fd, &c, 1) != 1);
96 return 0;
99 int wait_for_child(pid_t child_pid)
101 int rc;
103 if (waitpid(child_pid, &rc, 0) == -1) {
104 perror("waitpid");
105 return 1;
108 if (WIFEXITED(rc))
109 rc = WEXITSTATUS(rc);
110 else
111 rc = 1; /* Signal or other */
113 return rc;
116 int kill_child_and_wait(pid_t child_pid)
118 kill(child_pid, SIGTERM);
120 return wait_for_child(child_pid);
123 static int eat_cpu_child(union pipe read_pipe, union pipe write_pipe)
125 volatile int i = 0;
128 * We are just here to eat cpu and die. So make sure we can be killed,
129 * and also don't do any custom SIGTERM handling.
131 signal(SIGTERM, SIG_DFL);
133 notify_parent(write_pipe);
134 wait_for_parent(read_pipe);
136 /* Soak up cpu forever */
137 while (1) i++;
139 return 0;
142 pid_t eat_cpu(int (test_function)(void))
144 union pipe read_pipe, write_pipe;
145 int cpu, rc;
146 pid_t pid;
148 cpu = pick_online_cpu();
149 FAIL_IF(cpu < 0);
150 FAIL_IF(bind_to_cpu(cpu));
152 if (pipe(read_pipe.fds) == -1)
153 return -1;
155 if (pipe(write_pipe.fds) == -1)
156 return -1;
158 pid = fork();
159 if (pid == 0)
160 exit(eat_cpu_child(write_pipe, read_pipe));
162 if (sync_with_child(read_pipe, write_pipe)) {
163 rc = -1;
164 goto out;
167 printf("main test running as pid %d\n", getpid());
169 rc = test_function();
170 out:
171 kill(pid, SIGKILL);
173 return rc;
176 struct addr_range libc, vdso;
178 int parse_proc_maps(void)
180 unsigned long start, end;
181 char execute, name[128];
182 FILE *f;
183 int rc;
185 f = fopen("/proc/self/maps", "r");
186 if (!f) {
187 perror("fopen");
188 return -1;
191 do {
192 /* This skips line with no executable which is what we want */
193 rc = fscanf(f, "%lx-%lx %*c%*c%c%*c %*x %*d:%*d %*d %127s\n",
194 &start, &end, &execute, name);
195 if (rc <= 0)
196 break;
198 if (execute != 'x')
199 continue;
201 if (strstr(name, "libc")) {
202 libc.first = start;
203 libc.last = end - 1;
204 } else if (strstr(name, "[vdso]")) {
205 vdso.first = start;
206 vdso.last = end - 1;
208 } while(1);
210 fclose(f);
212 return 0;
215 #define PARANOID_PATH "/proc/sys/kernel/perf_event_paranoid"
217 bool require_paranoia_below(int level)
219 unsigned long current;
220 char *end, buf[16];
221 FILE *f;
222 int rc;
224 rc = -1;
226 f = fopen(PARANOID_PATH, "r");
227 if (!f) {
228 perror("fopen");
229 goto out;
232 if (!fgets(buf, sizeof(buf), f)) {
233 printf("Couldn't read " PARANOID_PATH "?\n");
234 goto out_close;
237 current = strtoul(buf, &end, 10);
239 if (end == buf) {
240 printf("Couldn't parse " PARANOID_PATH "?\n");
241 goto out_close;
244 if (current >= level)
245 goto out;
247 rc = 0;
248 out_close:
249 fclose(f);
250 out:
251 return rc;