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
29static char auxv[4096];
30
31int 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
62out:
63	close(fd);
64	errno = -err;
65	return err;
66}
67
68int 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
118out:
119	close(fd);
120	if (err)
121		free(buffer);
122	errno = -err;
123	return err;
124}
125
126int 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
149out:
150	close(fd);
151	errno = -err;
152	return err;
153}
154
155int 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
168int 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
177int 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
186static 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
207out:
208	errno = -err;
209	return err;
210}
211
212static 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
231out:
232	errno = -err;
233	return err;
234}
235
236static 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
255out:
256	errno = -err;
257	return err;
258}
259
260int 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
265int 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
270int 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
279int 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
288int 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
297int 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
306int 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
318int 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
330int 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
350out:
351	errno = -err;
352	return err;
353}
354
355int 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
382out:
383	errno = -err;
384	return err;
385}
386
387void *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
403void *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
417int 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
450done:
451	CPU_FREE(mask);
452	return cpu;
453}
454
455int 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
478bool 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
493int 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
502int 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
514int 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
523static 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
530static 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
546int 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
562int 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
572int 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
582int 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
592int 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;
617out:
618	fclose(f);
619	return rc;
620}
621
622struct 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
636struct 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}
645