xref: /openbmc/linux/tools/testing/selftests/powerpc/utils.c (revision d1301afd71bd38b1610b391e50debf766faa84be)
1fcb45ec0SMichael Ellerman /*
2fcb45ec0SMichael Ellerman  * Copyright 2013-2015, Michael Ellerman, IBM Corp.
3fcb45ec0SMichael Ellerman  * Licensed under GPLv2.
4fcb45ec0SMichael Ellerman  */
5fcb45ec0SMichael Ellerman 
6*d1301afdSMichael Ellerman #define _GNU_SOURCE	/* For CPU_ZERO etc. */
7*d1301afdSMichael Ellerman 
8fcb45ec0SMichael Ellerman #include <elf.h>
9fcb45ec0SMichael Ellerman #include <errno.h>
10fcb45ec0SMichael Ellerman #include <fcntl.h>
11fcb45ec0SMichael Ellerman #include <link.h>
12*d1301afdSMichael Ellerman #include <sched.h>
13fcb45ec0SMichael Ellerman #include <stdio.h>
14fcb45ec0SMichael Ellerman #include <sys/stat.h>
15fcb45ec0SMichael Ellerman #include <sys/types.h>
16fcb45ec0SMichael Ellerman #include <unistd.h>
17fcb45ec0SMichael Ellerman 
18fcb45ec0SMichael Ellerman #include "utils.h"
19fcb45ec0SMichael Ellerman 
20fcb45ec0SMichael Ellerman static char auxv[4096];
21fcb45ec0SMichael Ellerman 
22fcb45ec0SMichael Ellerman void *get_auxv_entry(int type)
23fcb45ec0SMichael Ellerman {
24fcb45ec0SMichael Ellerman 	ElfW(auxv_t) *p;
25fcb45ec0SMichael Ellerman 	void *result;
26fcb45ec0SMichael Ellerman 	ssize_t num;
27fcb45ec0SMichael Ellerman 	int fd;
28fcb45ec0SMichael Ellerman 
29fcb45ec0SMichael Ellerman 	fd = open("/proc/self/auxv", O_RDONLY);
30fcb45ec0SMichael Ellerman 	if (fd == -1) {
31fcb45ec0SMichael Ellerman 		perror("open");
32fcb45ec0SMichael Ellerman 		return NULL;
33fcb45ec0SMichael Ellerman 	}
34fcb45ec0SMichael Ellerman 
35fcb45ec0SMichael Ellerman 	result = NULL;
36fcb45ec0SMichael Ellerman 
37fcb45ec0SMichael Ellerman 	num = read(fd, auxv, sizeof(auxv));
38fcb45ec0SMichael Ellerman 	if (num < 0) {
39fcb45ec0SMichael Ellerman 		perror("read");
40fcb45ec0SMichael Ellerman 		goto out;
41fcb45ec0SMichael Ellerman 	}
42fcb45ec0SMichael Ellerman 
43fcb45ec0SMichael Ellerman 	if (num > sizeof(auxv)) {
44fcb45ec0SMichael Ellerman 		printf("Overflowed auxv buffer\n");
45fcb45ec0SMichael Ellerman 		goto out;
46fcb45ec0SMichael Ellerman 	}
47fcb45ec0SMichael Ellerman 
48fcb45ec0SMichael Ellerman 	p = (ElfW(auxv_t) *)auxv;
49fcb45ec0SMichael Ellerman 
50fcb45ec0SMichael Ellerman 	while (p->a_type != AT_NULL) {
51fcb45ec0SMichael Ellerman 		if (p->a_type == type) {
52fcb45ec0SMichael Ellerman 			result = (void *)p->a_un.a_val;
53fcb45ec0SMichael Ellerman 			break;
54fcb45ec0SMichael Ellerman 		}
55fcb45ec0SMichael Ellerman 
56fcb45ec0SMichael Ellerman 		p++;
57fcb45ec0SMichael Ellerman 	}
58fcb45ec0SMichael Ellerman out:
59fcb45ec0SMichael Ellerman 	close(fd);
60fcb45ec0SMichael Ellerman 	return result;
61fcb45ec0SMichael Ellerman }
62*d1301afdSMichael Ellerman 
63*d1301afdSMichael Ellerman int pick_online_cpu(void)
64*d1301afdSMichael Ellerman {
65*d1301afdSMichael Ellerman 	cpu_set_t mask;
66*d1301afdSMichael Ellerman 	int cpu;
67*d1301afdSMichael Ellerman 
68*d1301afdSMichael Ellerman 	CPU_ZERO(&mask);
69*d1301afdSMichael Ellerman 
70*d1301afdSMichael Ellerman 	if (sched_getaffinity(0, sizeof(mask), &mask)) {
71*d1301afdSMichael Ellerman 		perror("sched_getaffinity");
72*d1301afdSMichael Ellerman 		return -1;
73*d1301afdSMichael Ellerman 	}
74*d1301afdSMichael Ellerman 
75*d1301afdSMichael Ellerman 	/* We prefer a primary thread, but skip 0 */
76*d1301afdSMichael Ellerman 	for (cpu = 8; cpu < CPU_SETSIZE; cpu += 8)
77*d1301afdSMichael Ellerman 		if (CPU_ISSET(cpu, &mask))
78*d1301afdSMichael Ellerman 			return cpu;
79*d1301afdSMichael Ellerman 
80*d1301afdSMichael Ellerman 	/* Search for anything, but in reverse */
81*d1301afdSMichael Ellerman 	for (cpu = CPU_SETSIZE - 1; cpu >= 0; cpu--)
82*d1301afdSMichael Ellerman 		if (CPU_ISSET(cpu, &mask))
83*d1301afdSMichael Ellerman 			return cpu;
84*d1301afdSMichael Ellerman 
85*d1301afdSMichael Ellerman 	printf("No cpus in affinity mask?!\n");
86*d1301afdSMichael Ellerman 	return -1;
87*d1301afdSMichael Ellerman }
88