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 29 static char auxv[4096]; 30 31 int 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 62 out: 63 close(fd); 64 errno = -err; 65 return err; 66 } 67 68 int 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 118 out: 119 close(fd); 120 if (err) 121 free(buffer); 122 errno = -err; 123 return err; 124 } 125 126 int 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 149 out: 150 close(fd); 151 errno = -err; 152 return err; 153 } 154 155 int 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 168 int 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 177 int 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 186 static 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 207 out: 208 errno = -err; 209 return err; 210 } 211 212 static 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 231 out: 232 errno = -err; 233 return err; 234 } 235 236 static 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 255 out: 256 errno = -err; 257 return err; 258 } 259 260 int 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 265 int 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 270 int 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 279 int 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 288 int 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 297 int 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 306 int 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 318 int 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 330 int 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 350 out: 351 errno = -err; 352 return err; 353 } 354 355 int 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 382 out: 383 errno = -err; 384 return err; 385 } 386 387 void *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 403 void *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 417 int 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 450 done: 451 CPU_FREE(mask); 452 return cpu; 453 } 454 455 bool is_ppc64le(void) 456 { 457 struct utsname uts; 458 int rc; 459 460 errno = 0; 461 rc = uname(&uts); 462 if (rc) { 463 perror("uname"); 464 return false; 465 } 466 467 return strcmp(uts.machine, "ppc64le") == 0; 468 } 469 470 int read_sysfs_file(char *fpath, char *result, size_t result_size) 471 { 472 char path[PATH_MAX] = "/sys/"; 473 474 strncat(path, fpath, PATH_MAX - strlen(path) - 1); 475 476 return read_file(path, result, result_size, NULL); 477 } 478 479 int read_debugfs_int(const char *debugfs_file, int *result) 480 { 481 int err; 482 char value[16] = {0}; 483 484 err = read_debugfs_file(debugfs_file, value, sizeof(value) - 1); 485 if (err) 486 return err; 487 488 return parse_int(value, sizeof(value), result, 10); 489 } 490 491 int write_debugfs_int(const char *debugfs_file, int result) 492 { 493 char value[16]; 494 495 snprintf(value, 16, "%d", result); 496 497 return write_debugfs_file(debugfs_file, value, strlen(value)); 498 } 499 500 static long perf_event_open(struct perf_event_attr *hw_event, pid_t pid, 501 int cpu, int group_fd, unsigned long flags) 502 { 503 return syscall(__NR_perf_event_open, hw_event, pid, cpu, 504 group_fd, flags); 505 } 506 507 static void perf_event_attr_init(struct perf_event_attr *event_attr, 508 unsigned int type, 509 unsigned long config) 510 { 511 memset(event_attr, 0, sizeof(*event_attr)); 512 513 event_attr->type = type; 514 event_attr->size = sizeof(struct perf_event_attr); 515 event_attr->config = config; 516 event_attr->read_format = PERF_FORMAT_GROUP; 517 event_attr->disabled = 1; 518 event_attr->exclude_kernel = 1; 519 event_attr->exclude_hv = 1; 520 event_attr->exclude_guest = 1; 521 } 522 523 int perf_event_open_counter(unsigned int type, 524 unsigned long config, int group_fd) 525 { 526 int fd; 527 struct perf_event_attr event_attr; 528 529 perf_event_attr_init(&event_attr, type, config); 530 531 fd = perf_event_open(&event_attr, 0, -1, group_fd, 0); 532 533 if (fd < 0) 534 perror("perf_event_open() failed"); 535 536 return fd; 537 } 538 539 int perf_event_enable(int fd) 540 { 541 if (ioctl(fd, PERF_EVENT_IOC_ENABLE, PERF_IOC_FLAG_GROUP) == -1) { 542 perror("error while enabling perf events"); 543 return -1; 544 } 545 546 return 0; 547 } 548 549 int perf_event_disable(int fd) 550 { 551 if (ioctl(fd, PERF_EVENT_IOC_DISABLE, PERF_IOC_FLAG_GROUP) == -1) { 552 perror("error disabling perf events"); 553 return -1; 554 } 555 556 return 0; 557 } 558 559 int perf_event_reset(int fd) 560 { 561 if (ioctl(fd, PERF_EVENT_IOC_RESET, PERF_IOC_FLAG_GROUP) == -1) { 562 perror("error resetting perf events"); 563 return -1; 564 } 565 566 return 0; 567 } 568 569 int using_hash_mmu(bool *using_hash) 570 { 571 char line[128]; 572 FILE *f; 573 int rc; 574 575 f = fopen("/proc/cpuinfo", "r"); 576 FAIL_IF(!f); 577 578 rc = 0; 579 while (fgets(line, sizeof(line), f) != NULL) { 580 if (!strcmp(line, "MMU : Hash\n") || 581 !strcmp(line, "platform : Cell\n") || 582 !strcmp(line, "platform : PowerMac\n")) { 583 *using_hash = true; 584 goto out; 585 } 586 587 if (strcmp(line, "MMU : Radix\n") == 0) { 588 *using_hash = false; 589 goto out; 590 } 591 } 592 593 rc = -1; 594 out: 595 fclose(f); 596 return rc; 597 } 598