utils.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * Copyright 2013-2015, Michael Ellerman, IBM Corp.
  4. */
  5. #define _GNU_SOURCE /* For CPU_ZERO etc. */
  6. #include <elf.h>
  7. #include <errno.h>
  8. #include <fcntl.h>
  9. #include <inttypes.h>
  10. #include <limits.h>
  11. #include <link.h>
  12. #include <sched.h>
  13. #include <stdio.h>
  14. #include <stdlib.h>
  15. #include <string.h>
  16. #include <sys/ioctl.h>
  17. #include <sys/stat.h>
  18. #include <sys/sysinfo.h>
  19. #include <sys/types.h>
  20. #include <sys/utsname.h>
  21. #include <unistd.h>
  22. #include <asm/unistd.h>
  23. #include <linux/limits.h>
  24. #include "utils.h"
  25. static char auxv[4096];
  26. int read_file(const char *path, char *buf, size_t count, size_t *len)
  27. {
  28. ssize_t rc;
  29. int fd;
  30. int err;
  31. char eof;
  32. fd = open(path, O_RDONLY);
  33. if (fd < 0)
  34. return -errno;
  35. rc = read(fd, buf, count);
  36. if (rc < 0) {
  37. err = -errno;
  38. goto out;
  39. }
  40. if (len)
  41. *len = rc;
  42. /* Overflow if there are still more bytes after filling the buffer */
  43. if (rc == count) {
  44. rc = read(fd, &eof, 1);
  45. if (rc != 0) {
  46. err = -EOVERFLOW;
  47. goto out;
  48. }
  49. }
  50. err = 0;
  51. out:
  52. close(fd);
  53. errno = -err;
  54. return err;
  55. }
  56. int read_file_alloc(const char *path, char **buf, size_t *len)
  57. {
  58. size_t read_offset = 0;
  59. size_t buffer_len = 0;
  60. char *buffer = NULL;
  61. int err;
  62. int fd;
  63. fd = open(path, O_RDONLY);
  64. if (fd < 0)
  65. return -errno;
  66. /*
  67. * We don't use stat & preallocate st_size because some non-files
  68. * report 0 file size. Instead just dynamically grow the buffer
  69. * as needed.
  70. */
  71. while (1) {
  72. ssize_t rc;
  73. if (read_offset >= buffer_len / 2) {
  74. char *next_buffer;
  75. buffer_len = buffer_len ? buffer_len * 2 : 4096;
  76. next_buffer = realloc(buffer, buffer_len);
  77. if (!next_buffer) {
  78. err = -errno;
  79. goto out;
  80. }
  81. buffer = next_buffer;
  82. }
  83. rc = read(fd, buffer + read_offset, buffer_len - read_offset);
  84. if (rc < 0) {
  85. err = -errno;
  86. goto out;
  87. }
  88. if (rc == 0)
  89. break;
  90. read_offset += rc;
  91. }
  92. *buf = buffer;
  93. if (len)
  94. *len = read_offset;
  95. err = 0;
  96. out:
  97. close(fd);
  98. if (err)
  99. free(buffer);
  100. errno = -err;
  101. return err;
  102. }
  103. int write_file(const char *path, const char *buf, size_t count)
  104. {
  105. int fd;
  106. int err;
  107. ssize_t rc;
  108. fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, 0644);
  109. if (fd < 0)
  110. return -errno;
  111. rc = write(fd, buf, count);
  112. if (rc < 0) {
  113. err = -errno;
  114. goto out;
  115. }
  116. if (rc != count) {
  117. err = -EOVERFLOW;
  118. goto out;
  119. }
  120. err = 0;
  121. out:
  122. close(fd);
  123. errno = -err;
  124. return err;
  125. }
  126. int read_auxv(char *buf, ssize_t buf_size)
  127. {
  128. int err;
  129. err = read_file("/proc/self/auxv", buf, buf_size, NULL);
  130. if (err) {
  131. perror("Error reading /proc/self/auxv");
  132. return err;
  133. }
  134. return 0;
  135. }
  136. int read_debugfs_file(const char *subpath, char *buf, size_t count)
  137. {
  138. char path[PATH_MAX] = "/sys/kernel/debug/";
  139. strncat(path, subpath, sizeof(path) - strlen(path) - 1);
  140. return read_file(path, buf, count, NULL);
  141. }
  142. int write_debugfs_file(const char *subpath, const char *buf, size_t count)
  143. {
  144. char path[PATH_MAX] = "/sys/kernel/debug/";
  145. strncat(path, subpath, sizeof(path) - strlen(path) - 1);
  146. return write_file(path, buf, count);
  147. }
  148. static int validate_int_parse(const char *buffer, size_t count, char *end)
  149. {
  150. int err = 0;
  151. /* Require at least one digit */
  152. if (end == buffer) {
  153. err = -EINVAL;
  154. goto out;
  155. }
  156. /* Require all remaining characters be whitespace-ish */
  157. for (; end < buffer + count; end++) {
  158. if (*end == '\0')
  159. break;
  160. if (*end != ' ' && *end != '\n') {
  161. err = -EINVAL;
  162. goto out;
  163. }
  164. }
  165. out:
  166. errno = -err;
  167. return err;
  168. }
  169. static int parse_bounded_int(const char *buffer, size_t count, intmax_t *result,
  170. int base, intmax_t min, intmax_t max)
  171. {
  172. int err;
  173. char *end;
  174. errno = 0;
  175. *result = strtoimax(buffer, &end, base);
  176. if (errno)
  177. return -errno;
  178. err = validate_int_parse(buffer, count, end);
  179. if (err)
  180. goto out;
  181. if (*result < min || *result > max)
  182. err = -EOVERFLOW;
  183. out:
  184. errno = -err;
  185. return err;
  186. }
  187. static int parse_bounded_uint(const char *buffer, size_t count, uintmax_t *result,
  188. int base, uintmax_t max)
  189. {
  190. int err = 0;
  191. char *end;
  192. errno = 0;
  193. *result = strtoumax(buffer, &end, base);
  194. if (errno)
  195. return -errno;
  196. err = validate_int_parse(buffer, count, end);
  197. if (err)
  198. goto out;
  199. if (*result > max)
  200. err = -EOVERFLOW;
  201. out:
  202. errno = -err;
  203. return err;
  204. }
  205. int parse_intmax(const char *buffer, size_t count, intmax_t *result, int base)
  206. {
  207. return parse_bounded_int(buffer, count, result, base, INTMAX_MIN, INTMAX_MAX);
  208. }
  209. int parse_uintmax(const char *buffer, size_t count, uintmax_t *result, int base)
  210. {
  211. return parse_bounded_uint(buffer, count, result, base, UINTMAX_MAX);
  212. }
  213. int parse_int(const char *buffer, size_t count, int *result, int base)
  214. {
  215. intmax_t parsed;
  216. int err = parse_bounded_int(buffer, count, &parsed, base, INT_MIN, INT_MAX);
  217. *result = parsed;
  218. return err;
  219. }
  220. int parse_uint(const char *buffer, size_t count, unsigned int *result, int base)
  221. {
  222. uintmax_t parsed;
  223. int err = parse_bounded_uint(buffer, count, &parsed, base, UINT_MAX);
  224. *result = parsed;
  225. return err;
  226. }
  227. int parse_long(const char *buffer, size_t count, long *result, int base)
  228. {
  229. intmax_t parsed;
  230. int err = parse_bounded_int(buffer, count, &parsed, base, LONG_MIN, LONG_MAX);
  231. *result = parsed;
  232. return err;
  233. }
  234. int parse_ulong(const char *buffer, size_t count, unsigned long *result, int base)
  235. {
  236. uintmax_t parsed;
  237. int err = parse_bounded_uint(buffer, count, &parsed, base, ULONG_MAX);
  238. *result = parsed;
  239. return err;
  240. }
  241. int read_long(const char *path, long *result, int base)
  242. {
  243. int err;
  244. char buffer[32] = {0};
  245. err = read_file(path, buffer, sizeof(buffer) - 1, NULL);
  246. if (err)
  247. return err;
  248. return parse_long(buffer, sizeof(buffer), result, base);
  249. }
  250. int read_ulong(const char *path, unsigned long *result, int base)
  251. {
  252. int err;
  253. char buffer[32] = {0};
  254. err = read_file(path, buffer, sizeof(buffer) - 1, NULL);
  255. if (err)
  256. return err;
  257. return parse_ulong(buffer, sizeof(buffer), result, base);
  258. }
  259. int write_long(const char *path, long result, int base)
  260. {
  261. int err;
  262. int len;
  263. char buffer[32];
  264. /* Decimal only for now: no format specifier for signed hex values */
  265. if (base != 10) {
  266. err = -EINVAL;
  267. goto out;
  268. }
  269. len = snprintf(buffer, sizeof(buffer), "%ld", result);
  270. if (len < 0 || len >= sizeof(buffer)) {
  271. err = -EOVERFLOW;
  272. goto out;
  273. }
  274. err = write_file(path, buffer, len);
  275. out:
  276. errno = -err;
  277. return err;
  278. }
  279. int write_ulong(const char *path, unsigned long result, int base)
  280. {
  281. int err;
  282. int len;
  283. char buffer[32];
  284. char *fmt;
  285. switch (base) {
  286. case 10:
  287. fmt = "%lu";
  288. break;
  289. case 16:
  290. fmt = "%lx";
  291. break;
  292. default:
  293. err = -EINVAL;
  294. goto out;
  295. }
  296. len = snprintf(buffer, sizeof(buffer), fmt, result);
  297. if (len < 0 || len >= sizeof(buffer)) {
  298. err = -errno;
  299. goto out;
  300. }
  301. err = write_file(path, buffer, len);
  302. out:
  303. errno = -err;
  304. return err;
  305. }
  306. void *find_auxv_entry(int type, char *auxv)
  307. {
  308. ElfW(auxv_t) *p;
  309. p = (ElfW(auxv_t) *)auxv;
  310. while (p->a_type != AT_NULL) {
  311. if (p->a_type == type)
  312. return p;
  313. p++;
  314. }
  315. return NULL;
  316. }
  317. void *get_auxv_entry(int type)
  318. {
  319. ElfW(auxv_t) *p;
  320. if (read_auxv(auxv, sizeof(auxv)))
  321. return NULL;
  322. p = find_auxv_entry(type, auxv);
  323. if (p)
  324. return (void *)p->a_un.a_val;
  325. return NULL;
  326. }
  327. int pick_online_cpu(void)
  328. {
  329. int ncpus, cpu = -1;
  330. cpu_set_t *mask;
  331. size_t size;
  332. ncpus = get_nprocs_conf();
  333. size = CPU_ALLOC_SIZE(ncpus);
  334. mask = CPU_ALLOC(ncpus);
  335. if (!mask) {
  336. perror("malloc");
  337. return -1;
  338. }
  339. CPU_ZERO_S(size, mask);
  340. if (sched_getaffinity(0, size, mask)) {
  341. perror("sched_getaffinity");
  342. goto done;
  343. }
  344. /* We prefer a primary thread, but skip 0 */
  345. for (cpu = 8; cpu < ncpus; cpu += 8)
  346. if (CPU_ISSET_S(cpu, size, mask))
  347. goto done;
  348. /* Search for anything, but in reverse */
  349. for (cpu = ncpus - 1; cpu >= 0; cpu--)
  350. if (CPU_ISSET_S(cpu, size, mask))
  351. goto done;
  352. printf("No cpus in affinity mask?!\n");
  353. done:
  354. CPU_FREE(mask);
  355. return cpu;
  356. }
  357. int bind_to_cpu(int cpu)
  358. {
  359. cpu_set_t mask;
  360. int err;
  361. if (cpu == BIND_CPU_ANY) {
  362. cpu = pick_online_cpu();
  363. if (cpu < 0)
  364. return cpu;
  365. }
  366. printf("Binding to cpu %d\n", cpu);
  367. CPU_ZERO(&mask);
  368. CPU_SET(cpu, &mask);
  369. err = sched_setaffinity(0, sizeof(mask), &mask);
  370. if (err)
  371. return err;
  372. return cpu;
  373. }
  374. bool is_ppc64le(void)
  375. {
  376. struct utsname uts;
  377. int rc;
  378. errno = 0;
  379. rc = uname(&uts);
  380. if (rc) {
  381. perror("uname");
  382. return false;
  383. }
  384. return strcmp(uts.machine, "ppc64le") == 0;
  385. }
  386. int read_sysfs_file(char *fpath, char *result, size_t result_size)
  387. {
  388. char path[PATH_MAX] = "/sys/";
  389. strncat(path, fpath, PATH_MAX - strlen(path) - 1);
  390. return read_file(path, result, result_size, NULL);
  391. }
  392. int read_debugfs_int(const char *debugfs_file, int *result)
  393. {
  394. int err;
  395. char value[16] = {0};
  396. err = read_debugfs_file(debugfs_file, value, sizeof(value) - 1);
  397. if (err)
  398. return err;
  399. return parse_int(value, sizeof(value), result, 10);
  400. }
  401. int write_debugfs_int(const char *debugfs_file, int result)
  402. {
  403. char value[16];
  404. snprintf(value, 16, "%d", result);
  405. return write_debugfs_file(debugfs_file, value, strlen(value));
  406. }
  407. static long perf_event_open(struct perf_event_attr *hw_event, pid_t pid,
  408. int cpu, int group_fd, unsigned long flags)
  409. {
  410. return syscall(__NR_perf_event_open, hw_event, pid, cpu,
  411. group_fd, flags);
  412. }
  413. static void perf_event_attr_init(struct perf_event_attr *event_attr,
  414. unsigned int type,
  415. unsigned long config)
  416. {
  417. memset(event_attr, 0, sizeof(*event_attr));
  418. event_attr->type = type;
  419. event_attr->size = sizeof(struct perf_event_attr);
  420. event_attr->config = config;
  421. event_attr->read_format = PERF_FORMAT_GROUP;
  422. event_attr->disabled = 1;
  423. event_attr->exclude_kernel = 1;
  424. event_attr->exclude_hv = 1;
  425. event_attr->exclude_guest = 1;
  426. }
  427. int perf_event_open_counter(unsigned int type,
  428. unsigned long config, int group_fd)
  429. {
  430. int fd;
  431. struct perf_event_attr event_attr;
  432. perf_event_attr_init(&event_attr, type, config);
  433. fd = perf_event_open(&event_attr, 0, -1, group_fd, 0);
  434. if (fd < 0)
  435. perror("perf_event_open() failed");
  436. return fd;
  437. }
  438. int perf_event_enable(int fd)
  439. {
  440. if (ioctl(fd, PERF_EVENT_IOC_ENABLE, PERF_IOC_FLAG_GROUP) == -1) {
  441. perror("error while enabling perf events");
  442. return -1;
  443. }
  444. return 0;
  445. }
  446. int perf_event_disable(int fd)
  447. {
  448. if (ioctl(fd, PERF_EVENT_IOC_DISABLE, PERF_IOC_FLAG_GROUP) == -1) {
  449. perror("error disabling perf events");
  450. return -1;
  451. }
  452. return 0;
  453. }
  454. int perf_event_reset(int fd)
  455. {
  456. if (ioctl(fd, PERF_EVENT_IOC_RESET, PERF_IOC_FLAG_GROUP) == -1) {
  457. perror("error resetting perf events");
  458. return -1;
  459. }
  460. return 0;
  461. }
  462. int using_hash_mmu(bool *using_hash)
  463. {
  464. char line[128];
  465. FILE *f;
  466. int rc;
  467. f = fopen("/proc/cpuinfo", "r");
  468. FAIL_IF(!f);
  469. rc = 0;
  470. while (fgets(line, sizeof(line), f) != NULL) {
  471. if (!strcmp(line, "MMU : Hash\n") ||
  472. !strcmp(line, "platform : Cell\n") ||
  473. !strcmp(line, "platform : PowerMac\n")) {
  474. *using_hash = true;
  475. goto out;
  476. }
  477. if (strcmp(line, "MMU : Radix\n") == 0) {
  478. *using_hash = false;
  479. goto out;
  480. }
  481. }
  482. rc = -1;
  483. out:
  484. fclose(f);
  485. return rc;
  486. }
  487. struct sigaction push_signal_handler(int sig, void (*fn)(int, siginfo_t *, void *))
  488. {
  489. struct sigaction sa;
  490. struct sigaction old_handler;
  491. sa.sa_sigaction = fn;
  492. sigemptyset(&sa.sa_mask);
  493. sa.sa_flags = SA_SIGINFO;
  494. FAIL_IF_EXIT_MSG(sigaction(sig, &sa, &old_handler),
  495. "failed to push signal handler");
  496. return old_handler;
  497. }
  498. struct sigaction pop_signal_handler(int sig, struct sigaction old_handler)
  499. {
  500. struct sigaction popped;
  501. FAIL_IF_EXIT_MSG(sigaction(sig, &old_handler, &popped),
  502. "failed to pop signal handler");
  503. return popped;
  504. }