xref: /aosp_15_r20/external/linux-kselftest/tools/testing/selftests/powerpc/utils.c (revision 053f45be4e351dfd5e965df293cd45b779f579ee)
1*053f45beSAndroid Build Coastguard Worker // SPDX-License-Identifier: GPL-2.0-only
2*053f45beSAndroid Build Coastguard Worker /*
3*053f45beSAndroid Build Coastguard Worker  * Copyright 2013-2015, Michael Ellerman, IBM Corp.
4*053f45beSAndroid Build Coastguard Worker  */
5*053f45beSAndroid Build Coastguard Worker 
6*053f45beSAndroid Build Coastguard Worker #define _GNU_SOURCE	/* For CPU_ZERO etc. */
7*053f45beSAndroid Build Coastguard Worker 
8*053f45beSAndroid Build Coastguard Worker #include <elf.h>
9*053f45beSAndroid Build Coastguard Worker #include <errno.h>
10*053f45beSAndroid Build Coastguard Worker #include <fcntl.h>
11*053f45beSAndroid Build Coastguard Worker #include <link.h>
12*053f45beSAndroid Build Coastguard Worker #include <sched.h>
13*053f45beSAndroid Build Coastguard Worker #include <stdio.h>
14*053f45beSAndroid Build Coastguard Worker #include <stdlib.h>
15*053f45beSAndroid Build Coastguard Worker #include <string.h>
16*053f45beSAndroid Build Coastguard Worker #include <sys/ioctl.h>
17*053f45beSAndroid Build Coastguard Worker #include <sys/stat.h>
18*053f45beSAndroid Build Coastguard Worker #include <sys/sysinfo.h>
19*053f45beSAndroid Build Coastguard Worker #include <sys/types.h>
20*053f45beSAndroid Build Coastguard Worker #include <sys/utsname.h>
21*053f45beSAndroid Build Coastguard Worker #include <unistd.h>
22*053f45beSAndroid Build Coastguard Worker #include <asm/unistd.h>
23*053f45beSAndroid Build Coastguard Worker #include <linux/limits.h>
24*053f45beSAndroid Build Coastguard Worker 
25*053f45beSAndroid Build Coastguard Worker #include "utils.h"
26*053f45beSAndroid Build Coastguard Worker 
27*053f45beSAndroid Build Coastguard Worker static char auxv[4096];
28*053f45beSAndroid Build Coastguard Worker 
read_auxv(char * buf,ssize_t buf_size)29*053f45beSAndroid Build Coastguard Worker int read_auxv(char *buf, ssize_t buf_size)
30*053f45beSAndroid Build Coastguard Worker {
31*053f45beSAndroid Build Coastguard Worker 	ssize_t num;
32*053f45beSAndroid Build Coastguard Worker 	int rc, fd;
33*053f45beSAndroid Build Coastguard Worker 
34*053f45beSAndroid Build Coastguard Worker 	fd = open("/proc/self/auxv", O_RDONLY);
35*053f45beSAndroid Build Coastguard Worker 	if (fd == -1) {
36*053f45beSAndroid Build Coastguard Worker 		perror("open");
37*053f45beSAndroid Build Coastguard Worker 		return -errno;
38*053f45beSAndroid Build Coastguard Worker 	}
39*053f45beSAndroid Build Coastguard Worker 
40*053f45beSAndroid Build Coastguard Worker 	num = read(fd, buf, buf_size);
41*053f45beSAndroid Build Coastguard Worker 	if (num < 0) {
42*053f45beSAndroid Build Coastguard Worker 		perror("read");
43*053f45beSAndroid Build Coastguard Worker 		rc = -EIO;
44*053f45beSAndroid Build Coastguard Worker 		goto out;
45*053f45beSAndroid Build Coastguard Worker 	}
46*053f45beSAndroid Build Coastguard Worker 
47*053f45beSAndroid Build Coastguard Worker 	if (num > buf_size) {
48*053f45beSAndroid Build Coastguard Worker 		printf("overflowed auxv buffer\n");
49*053f45beSAndroid Build Coastguard Worker 		rc = -EOVERFLOW;
50*053f45beSAndroid Build Coastguard Worker 		goto out;
51*053f45beSAndroid Build Coastguard Worker 	}
52*053f45beSAndroid Build Coastguard Worker 
53*053f45beSAndroid Build Coastguard Worker 	rc = 0;
54*053f45beSAndroid Build Coastguard Worker out:
55*053f45beSAndroid Build Coastguard Worker 	close(fd);
56*053f45beSAndroid Build Coastguard Worker 	return rc;
57*053f45beSAndroid Build Coastguard Worker }
58*053f45beSAndroid Build Coastguard Worker 
find_auxv_entry(int type,char * auxv)59*053f45beSAndroid Build Coastguard Worker void *find_auxv_entry(int type, char *auxv)
60*053f45beSAndroid Build Coastguard Worker {
61*053f45beSAndroid Build Coastguard Worker 	ElfW(auxv_t) *p;
62*053f45beSAndroid Build Coastguard Worker 
63*053f45beSAndroid Build Coastguard Worker 	p = (ElfW(auxv_t) *)auxv;
64*053f45beSAndroid Build Coastguard Worker 
65*053f45beSAndroid Build Coastguard Worker 	while (p->a_type != AT_NULL) {
66*053f45beSAndroid Build Coastguard Worker 		if (p->a_type == type)
67*053f45beSAndroid Build Coastguard Worker 			return p;
68*053f45beSAndroid Build Coastguard Worker 
69*053f45beSAndroid Build Coastguard Worker 		p++;
70*053f45beSAndroid Build Coastguard Worker 	}
71*053f45beSAndroid Build Coastguard Worker 
72*053f45beSAndroid Build Coastguard Worker 	return NULL;
73*053f45beSAndroid Build Coastguard Worker }
74*053f45beSAndroid Build Coastguard Worker 
get_auxv_entry(int type)75*053f45beSAndroid Build Coastguard Worker void *get_auxv_entry(int type)
76*053f45beSAndroid Build Coastguard Worker {
77*053f45beSAndroid Build Coastguard Worker 	ElfW(auxv_t) *p;
78*053f45beSAndroid Build Coastguard Worker 
79*053f45beSAndroid Build Coastguard Worker 	if (read_auxv(auxv, sizeof(auxv)))
80*053f45beSAndroid Build Coastguard Worker 		return NULL;
81*053f45beSAndroid Build Coastguard Worker 
82*053f45beSAndroid Build Coastguard Worker 	p = find_auxv_entry(type, auxv);
83*053f45beSAndroid Build Coastguard Worker 	if (p)
84*053f45beSAndroid Build Coastguard Worker 		return (void *)p->a_un.a_val;
85*053f45beSAndroid Build Coastguard Worker 
86*053f45beSAndroid Build Coastguard Worker 	return NULL;
87*053f45beSAndroid Build Coastguard Worker }
88*053f45beSAndroid Build Coastguard Worker 
pick_online_cpu(void)89*053f45beSAndroid Build Coastguard Worker int pick_online_cpu(void)
90*053f45beSAndroid Build Coastguard Worker {
91*053f45beSAndroid Build Coastguard Worker 	int ncpus, cpu = -1;
92*053f45beSAndroid Build Coastguard Worker 	cpu_set_t *mask;
93*053f45beSAndroid Build Coastguard Worker 	size_t size;
94*053f45beSAndroid Build Coastguard Worker 
95*053f45beSAndroid Build Coastguard Worker 	ncpus = get_nprocs_conf();
96*053f45beSAndroid Build Coastguard Worker 	size = CPU_ALLOC_SIZE(ncpus);
97*053f45beSAndroid Build Coastguard Worker 	mask = CPU_ALLOC(ncpus);
98*053f45beSAndroid Build Coastguard Worker 	if (!mask) {
99*053f45beSAndroid Build Coastguard Worker 		perror("malloc");
100*053f45beSAndroid Build Coastguard Worker 		return -1;
101*053f45beSAndroid Build Coastguard Worker 	}
102*053f45beSAndroid Build Coastguard Worker 
103*053f45beSAndroid Build Coastguard Worker 	CPU_ZERO_S(size, mask);
104*053f45beSAndroid Build Coastguard Worker 
105*053f45beSAndroid Build Coastguard Worker 	if (sched_getaffinity(0, size, mask)) {
106*053f45beSAndroid Build Coastguard Worker 		perror("sched_getaffinity");
107*053f45beSAndroid Build Coastguard Worker 		goto done;
108*053f45beSAndroid Build Coastguard Worker 	}
109*053f45beSAndroid Build Coastguard Worker 
110*053f45beSAndroid Build Coastguard Worker 	/* We prefer a primary thread, but skip 0 */
111*053f45beSAndroid Build Coastguard Worker 	for (cpu = 8; cpu < ncpus; cpu += 8)
112*053f45beSAndroid Build Coastguard Worker 		if (CPU_ISSET_S(cpu, size, mask))
113*053f45beSAndroid Build Coastguard Worker 			goto done;
114*053f45beSAndroid Build Coastguard Worker 
115*053f45beSAndroid Build Coastguard Worker 	/* Search for anything, but in reverse */
116*053f45beSAndroid Build Coastguard Worker 	for (cpu = ncpus - 1; cpu >= 0; cpu--)
117*053f45beSAndroid Build Coastguard Worker 		if (CPU_ISSET_S(cpu, size, mask))
118*053f45beSAndroid Build Coastguard Worker 			goto done;
119*053f45beSAndroid Build Coastguard Worker 
120*053f45beSAndroid Build Coastguard Worker 	printf("No cpus in affinity mask?!\n");
121*053f45beSAndroid Build Coastguard Worker 
122*053f45beSAndroid Build Coastguard Worker done:
123*053f45beSAndroid Build Coastguard Worker 	CPU_FREE(mask);
124*053f45beSAndroid Build Coastguard Worker 	return cpu;
125*053f45beSAndroid Build Coastguard Worker }
126*053f45beSAndroid Build Coastguard Worker 
is_ppc64le(void)127*053f45beSAndroid Build Coastguard Worker bool is_ppc64le(void)
128*053f45beSAndroid Build Coastguard Worker {
129*053f45beSAndroid Build Coastguard Worker 	struct utsname uts;
130*053f45beSAndroid Build Coastguard Worker 	int rc;
131*053f45beSAndroid Build Coastguard Worker 
132*053f45beSAndroid Build Coastguard Worker 	errno = 0;
133*053f45beSAndroid Build Coastguard Worker 	rc = uname(&uts);
134*053f45beSAndroid Build Coastguard Worker 	if (rc) {
135*053f45beSAndroid Build Coastguard Worker 		perror("uname");
136*053f45beSAndroid Build Coastguard Worker 		return false;
137*053f45beSAndroid Build Coastguard Worker 	}
138*053f45beSAndroid Build Coastguard Worker 
139*053f45beSAndroid Build Coastguard Worker 	return strcmp(uts.machine, "ppc64le") == 0;
140*053f45beSAndroid Build Coastguard Worker }
141*053f45beSAndroid Build Coastguard Worker 
read_sysfs_file(char * fpath,char * result,size_t result_size)142*053f45beSAndroid Build Coastguard Worker int read_sysfs_file(char *fpath, char *result, size_t result_size)
143*053f45beSAndroid Build Coastguard Worker {
144*053f45beSAndroid Build Coastguard Worker 	char path[PATH_MAX] = "/sys/";
145*053f45beSAndroid Build Coastguard Worker 	int rc = -1, fd;
146*053f45beSAndroid Build Coastguard Worker 
147*053f45beSAndroid Build Coastguard Worker 	strncat(path, fpath, PATH_MAX - strlen(path) - 1);
148*053f45beSAndroid Build Coastguard Worker 
149*053f45beSAndroid Build Coastguard Worker 	if ((fd = open(path, O_RDONLY)) < 0)
150*053f45beSAndroid Build Coastguard Worker 		return rc;
151*053f45beSAndroid Build Coastguard Worker 
152*053f45beSAndroid Build Coastguard Worker 	rc = read(fd, result, result_size);
153*053f45beSAndroid Build Coastguard Worker 
154*053f45beSAndroid Build Coastguard Worker 	close(fd);
155*053f45beSAndroid Build Coastguard Worker 
156*053f45beSAndroid Build Coastguard Worker 	if (rc < 0)
157*053f45beSAndroid Build Coastguard Worker 		return rc;
158*053f45beSAndroid Build Coastguard Worker 
159*053f45beSAndroid Build Coastguard Worker 	return 0;
160*053f45beSAndroid Build Coastguard Worker }
161*053f45beSAndroid Build Coastguard Worker 
read_debugfs_file(char * debugfs_file,int * result)162*053f45beSAndroid Build Coastguard Worker int read_debugfs_file(char *debugfs_file, int *result)
163*053f45beSAndroid Build Coastguard Worker {
164*053f45beSAndroid Build Coastguard Worker 	int rc = -1, fd;
165*053f45beSAndroid Build Coastguard Worker 	char path[PATH_MAX];
166*053f45beSAndroid Build Coastguard Worker 	char value[16];
167*053f45beSAndroid Build Coastguard Worker 
168*053f45beSAndroid Build Coastguard Worker 	strcpy(path, "/sys/kernel/debug/");
169*053f45beSAndroid Build Coastguard Worker 	strncat(path, debugfs_file, PATH_MAX - strlen(path) - 1);
170*053f45beSAndroid Build Coastguard Worker 
171*053f45beSAndroid Build Coastguard Worker 	if ((fd = open(path, O_RDONLY)) < 0)
172*053f45beSAndroid Build Coastguard Worker 		return rc;
173*053f45beSAndroid Build Coastguard Worker 
174*053f45beSAndroid Build Coastguard Worker 	if ((rc = read(fd, value, sizeof(value))) < 0)
175*053f45beSAndroid Build Coastguard Worker 		return rc;
176*053f45beSAndroid Build Coastguard Worker 
177*053f45beSAndroid Build Coastguard Worker 	value[15] = 0;
178*053f45beSAndroid Build Coastguard Worker 	*result = atoi(value);
179*053f45beSAndroid Build Coastguard Worker 	close(fd);
180*053f45beSAndroid Build Coastguard Worker 
181*053f45beSAndroid Build Coastguard Worker 	return 0;
182*053f45beSAndroid Build Coastguard Worker }
183*053f45beSAndroid Build Coastguard Worker 
write_debugfs_file(char * debugfs_file,int result)184*053f45beSAndroid Build Coastguard Worker int write_debugfs_file(char *debugfs_file, int result)
185*053f45beSAndroid Build Coastguard Worker {
186*053f45beSAndroid Build Coastguard Worker 	int rc = -1, fd;
187*053f45beSAndroid Build Coastguard Worker 	char path[PATH_MAX];
188*053f45beSAndroid Build Coastguard Worker 	char value[16];
189*053f45beSAndroid Build Coastguard Worker 
190*053f45beSAndroid Build Coastguard Worker 	strcpy(path, "/sys/kernel/debug/");
191*053f45beSAndroid Build Coastguard Worker 	strncat(path, debugfs_file, PATH_MAX - strlen(path) - 1);
192*053f45beSAndroid Build Coastguard Worker 
193*053f45beSAndroid Build Coastguard Worker 	if ((fd = open(path, O_WRONLY)) < 0)
194*053f45beSAndroid Build Coastguard Worker 		return rc;
195*053f45beSAndroid Build Coastguard Worker 
196*053f45beSAndroid Build Coastguard Worker 	snprintf(value, 16, "%d", result);
197*053f45beSAndroid Build Coastguard Worker 
198*053f45beSAndroid Build Coastguard Worker 	if ((rc = write(fd, value, strlen(value))) < 0)
199*053f45beSAndroid Build Coastguard Worker 		return rc;
200*053f45beSAndroid Build Coastguard Worker 
201*053f45beSAndroid Build Coastguard Worker 	close(fd);
202*053f45beSAndroid Build Coastguard Worker 
203*053f45beSAndroid Build Coastguard Worker 	return 0;
204*053f45beSAndroid Build Coastguard Worker }
205*053f45beSAndroid Build Coastguard Worker 
perf_event_open(struct perf_event_attr * hw_event,pid_t pid,int cpu,int group_fd,unsigned long flags)206*053f45beSAndroid Build Coastguard Worker static long perf_event_open(struct perf_event_attr *hw_event, pid_t pid,
207*053f45beSAndroid Build Coastguard Worker 		int cpu, int group_fd, unsigned long flags)
208*053f45beSAndroid Build Coastguard Worker {
209*053f45beSAndroid Build Coastguard Worker 	return syscall(__NR_perf_event_open, hw_event, pid, cpu,
210*053f45beSAndroid Build Coastguard Worker 		      group_fd, flags);
211*053f45beSAndroid Build Coastguard Worker }
212*053f45beSAndroid Build Coastguard Worker 
perf_event_attr_init(struct perf_event_attr * event_attr,unsigned int type,unsigned long config)213*053f45beSAndroid Build Coastguard Worker static void perf_event_attr_init(struct perf_event_attr *event_attr,
214*053f45beSAndroid Build Coastguard Worker 					unsigned int type,
215*053f45beSAndroid Build Coastguard Worker 					unsigned long config)
216*053f45beSAndroid Build Coastguard Worker {
217*053f45beSAndroid Build Coastguard Worker 	memset(event_attr, 0, sizeof(*event_attr));
218*053f45beSAndroid Build Coastguard Worker 
219*053f45beSAndroid Build Coastguard Worker 	event_attr->type = type;
220*053f45beSAndroid Build Coastguard Worker 	event_attr->size = sizeof(struct perf_event_attr);
221*053f45beSAndroid Build Coastguard Worker 	event_attr->config = config;
222*053f45beSAndroid Build Coastguard Worker 	event_attr->read_format = PERF_FORMAT_GROUP;
223*053f45beSAndroid Build Coastguard Worker 	event_attr->disabled = 1;
224*053f45beSAndroid Build Coastguard Worker 	event_attr->exclude_kernel = 1;
225*053f45beSAndroid Build Coastguard Worker 	event_attr->exclude_hv = 1;
226*053f45beSAndroid Build Coastguard Worker 	event_attr->exclude_guest = 1;
227*053f45beSAndroid Build Coastguard Worker }
228*053f45beSAndroid Build Coastguard Worker 
perf_event_open_counter(unsigned int type,unsigned long config,int group_fd)229*053f45beSAndroid Build Coastguard Worker int perf_event_open_counter(unsigned int type,
230*053f45beSAndroid Build Coastguard Worker 			    unsigned long config, int group_fd)
231*053f45beSAndroid Build Coastguard Worker {
232*053f45beSAndroid Build Coastguard Worker 	int fd;
233*053f45beSAndroid Build Coastguard Worker 	struct perf_event_attr event_attr;
234*053f45beSAndroid Build Coastguard Worker 
235*053f45beSAndroid Build Coastguard Worker 	perf_event_attr_init(&event_attr, type, config);
236*053f45beSAndroid Build Coastguard Worker 
237*053f45beSAndroid Build Coastguard Worker 	fd = perf_event_open(&event_attr, 0, -1, group_fd, 0);
238*053f45beSAndroid Build Coastguard Worker 
239*053f45beSAndroid Build Coastguard Worker 	if (fd < 0)
240*053f45beSAndroid Build Coastguard Worker 		perror("perf_event_open() failed");
241*053f45beSAndroid Build Coastguard Worker 
242*053f45beSAndroid Build Coastguard Worker 	return fd;
243*053f45beSAndroid Build Coastguard Worker }
244*053f45beSAndroid Build Coastguard Worker 
perf_event_enable(int fd)245*053f45beSAndroid Build Coastguard Worker int perf_event_enable(int fd)
246*053f45beSAndroid Build Coastguard Worker {
247*053f45beSAndroid Build Coastguard Worker 	if (ioctl(fd, PERF_EVENT_IOC_ENABLE, PERF_IOC_FLAG_GROUP) == -1) {
248*053f45beSAndroid Build Coastguard Worker 		perror("error while enabling perf events");
249*053f45beSAndroid Build Coastguard Worker 		return -1;
250*053f45beSAndroid Build Coastguard Worker 	}
251*053f45beSAndroid Build Coastguard Worker 
252*053f45beSAndroid Build Coastguard Worker 	return 0;
253*053f45beSAndroid Build Coastguard Worker }
254*053f45beSAndroid Build Coastguard Worker 
perf_event_disable(int fd)255*053f45beSAndroid Build Coastguard Worker int perf_event_disable(int fd)
256*053f45beSAndroid Build Coastguard Worker {
257*053f45beSAndroid Build Coastguard Worker 	if (ioctl(fd, PERF_EVENT_IOC_DISABLE, PERF_IOC_FLAG_GROUP) == -1) {
258*053f45beSAndroid Build Coastguard Worker 		perror("error disabling perf events");
259*053f45beSAndroid Build Coastguard Worker 		return -1;
260*053f45beSAndroid Build Coastguard Worker 	}
261*053f45beSAndroid Build Coastguard Worker 
262*053f45beSAndroid Build Coastguard Worker 	return 0;
263*053f45beSAndroid Build Coastguard Worker }
264*053f45beSAndroid Build Coastguard Worker 
perf_event_reset(int fd)265*053f45beSAndroid Build Coastguard Worker int perf_event_reset(int fd)
266*053f45beSAndroid Build Coastguard Worker {
267*053f45beSAndroid Build Coastguard Worker 	if (ioctl(fd, PERF_EVENT_IOC_RESET, PERF_IOC_FLAG_GROUP) == -1) {
268*053f45beSAndroid Build Coastguard Worker 		perror("error resetting perf events");
269*053f45beSAndroid Build Coastguard Worker 		return -1;
270*053f45beSAndroid Build Coastguard Worker 	}
271*053f45beSAndroid Build Coastguard Worker 
272*053f45beSAndroid Build Coastguard Worker 	return 0;
273*053f45beSAndroid Build Coastguard Worker }
274*053f45beSAndroid Build Coastguard Worker 
using_hash_mmu(bool * using_hash)275*053f45beSAndroid Build Coastguard Worker int using_hash_mmu(bool *using_hash)
276*053f45beSAndroid Build Coastguard Worker {
277*053f45beSAndroid Build Coastguard Worker 	char line[128];
278*053f45beSAndroid Build Coastguard Worker 	FILE *f;
279*053f45beSAndroid Build Coastguard Worker 	int rc;
280*053f45beSAndroid Build Coastguard Worker 
281*053f45beSAndroid Build Coastguard Worker 	f = fopen("/proc/cpuinfo", "r");
282*053f45beSAndroid Build Coastguard Worker 	FAIL_IF(!f);
283*053f45beSAndroid Build Coastguard Worker 
284*053f45beSAndroid Build Coastguard Worker 	rc = 0;
285*053f45beSAndroid Build Coastguard Worker 	while (fgets(line, sizeof(line), f) != NULL) {
286*053f45beSAndroid Build Coastguard Worker 		if (!strcmp(line, "MMU		: Hash\n") ||
287*053f45beSAndroid Build Coastguard Worker 		    !strcmp(line, "platform	: Cell\n") ||
288*053f45beSAndroid Build Coastguard Worker 		    !strcmp(line, "platform	: PowerMac\n")) {
289*053f45beSAndroid Build Coastguard Worker 			*using_hash = true;
290*053f45beSAndroid Build Coastguard Worker 			goto out;
291*053f45beSAndroid Build Coastguard Worker 		}
292*053f45beSAndroid Build Coastguard Worker 
293*053f45beSAndroid Build Coastguard Worker 		if (strcmp(line, "MMU		: Radix\n") == 0) {
294*053f45beSAndroid Build Coastguard Worker 			*using_hash = false;
295*053f45beSAndroid Build Coastguard Worker 			goto out;
296*053f45beSAndroid Build Coastguard Worker 		}
297*053f45beSAndroid Build Coastguard Worker 	}
298*053f45beSAndroid Build Coastguard Worker 
299*053f45beSAndroid Build Coastguard Worker 	rc = -1;
300*053f45beSAndroid Build Coastguard Worker out:
301*053f45beSAndroid Build Coastguard Worker 	fclose(f);
302*053f45beSAndroid Build Coastguard Worker 	return rc;
303*053f45beSAndroid Build Coastguard Worker }
304