1 // SPDX-License-Identifier: GPL-2.0 2 #include "../perf.h" 3 #include "util.h" 4 #include "debug.h" 5 #include <api/fs/fs.h> 6 #include <sys/mman.h> 7 #include <sys/stat.h> 8 #include <sys/utsname.h> 9 #include <dirent.h> 10 #include <fcntl.h> 11 #include <inttypes.h> 12 #include <signal.h> 13 #include <stdio.h> 14 #include <stdlib.h> 15 #include <string.h> 16 #include <errno.h> 17 #include <limits.h> 18 #include <linux/kernel.h> 19 #include <linux/log2.h> 20 #include <linux/time64.h> 21 #include <unistd.h> 22 #include "strlist.h" 23 24 /* 25 * XXX We need to find a better place for these things... 26 */ 27 28 bool perf_singlethreaded = true; 29 30 void perf_set_singlethreaded(void) 31 { 32 perf_singlethreaded = true; 33 } 34 35 void perf_set_multithreaded(void) 36 { 37 perf_singlethreaded = false; 38 } 39 40 unsigned int page_size; 41 42 #ifdef _SC_LEVEL1_DCACHE_LINESIZE 43 #define cache_line_size(cacheline_sizep) *cacheline_sizep = sysconf(_SC_LEVEL1_DCACHE_LINESIZE) 44 #else 45 static void cache_line_size(int *cacheline_sizep) 46 { 47 if (sysfs__read_int("devices/system/cpu/cpu0/cache/index0/coherency_line_size", cacheline_sizep)) 48 pr_debug("cannot determine cache line size"); 49 } 50 #endif 51 52 int cacheline_size(void) 53 { 54 static int size; 55 56 if (!size) 57 cache_line_size(&size); 58 59 return size; 60 } 61 62 int sysctl_perf_event_max_stack = PERF_MAX_STACK_DEPTH; 63 int sysctl_perf_event_max_contexts_per_stack = PERF_MAX_CONTEXTS_PER_STACK; 64 65 int sysctl__max_stack(void) 66 { 67 int value; 68 69 if (sysctl__read_int("kernel/perf_event_max_stack", &value) == 0) 70 sysctl_perf_event_max_stack = value; 71 72 if (sysctl__read_int("kernel/perf_event_max_contexts_per_stack", &value) == 0) 73 sysctl_perf_event_max_contexts_per_stack = value; 74 75 return sysctl_perf_event_max_stack; 76 } 77 78 bool test_attr__enabled; 79 80 bool perf_host = true; 81 bool perf_guest = false; 82 83 void event_attr_init(struct perf_event_attr *attr) 84 { 85 if (!perf_host) 86 attr->exclude_host = 1; 87 if (!perf_guest) 88 attr->exclude_guest = 1; 89 /* to capture ABI version */ 90 attr->size = sizeof(*attr); 91 } 92 93 int mkdir_p(char *path, mode_t mode) 94 { 95 struct stat st; 96 int err; 97 char *d = path; 98 99 if (*d != '/') 100 return -1; 101 102 if (stat(path, &st) == 0) 103 return 0; 104 105 while (*++d == '/'); 106 107 while ((d = strchr(d, '/'))) { 108 *d = '\0'; 109 err = stat(path, &st) && mkdir(path, mode); 110 *d++ = '/'; 111 if (err) 112 return -1; 113 while (*d == '/') 114 ++d; 115 } 116 return (stat(path, &st) && mkdir(path, mode)) ? -1 : 0; 117 } 118 119 int rm_rf(const char *path) 120 { 121 DIR *dir; 122 int ret = 0; 123 struct dirent *d; 124 char namebuf[PATH_MAX]; 125 126 dir = opendir(path); 127 if (dir == NULL) 128 return 0; 129 130 while ((d = readdir(dir)) != NULL && !ret) { 131 struct stat statbuf; 132 133 if (!strcmp(d->d_name, ".") || !strcmp(d->d_name, "..")) 134 continue; 135 136 scnprintf(namebuf, sizeof(namebuf), "%s/%s", 137 path, d->d_name); 138 139 /* We have to check symbolic link itself */ 140 ret = lstat(namebuf, &statbuf); 141 if (ret < 0) { 142 pr_debug("stat failed: %s\n", namebuf); 143 break; 144 } 145 146 if (S_ISDIR(statbuf.st_mode)) 147 ret = rm_rf(namebuf); 148 else 149 ret = unlink(namebuf); 150 } 151 closedir(dir); 152 153 if (ret < 0) 154 return ret; 155 156 return rmdir(path); 157 } 158 159 /* A filter which removes dot files */ 160 bool lsdir_no_dot_filter(const char *name __maybe_unused, struct dirent *d) 161 { 162 return d->d_name[0] != '.'; 163 } 164 165 /* lsdir reads a directory and store it in strlist */ 166 struct strlist *lsdir(const char *name, 167 bool (*filter)(const char *, struct dirent *)) 168 { 169 struct strlist *list = NULL; 170 DIR *dir; 171 struct dirent *d; 172 173 dir = opendir(name); 174 if (!dir) 175 return NULL; 176 177 list = strlist__new(NULL, NULL); 178 if (!list) { 179 errno = ENOMEM; 180 goto out; 181 } 182 183 while ((d = readdir(dir)) != NULL) { 184 if (!filter || filter(name, d)) 185 strlist__add(list, d->d_name); 186 } 187 188 out: 189 closedir(dir); 190 return list; 191 } 192 193 static int slow_copyfile(const char *from, const char *to, struct nsinfo *nsi) 194 { 195 int err = -1; 196 char *line = NULL; 197 size_t n; 198 FILE *from_fp, *to_fp; 199 struct nscookie nsc; 200 201 nsinfo__mountns_enter(nsi, &nsc); 202 from_fp = fopen(from, "r"); 203 nsinfo__mountns_exit(&nsc); 204 if (from_fp == NULL) 205 goto out; 206 207 to_fp = fopen(to, "w"); 208 if (to_fp == NULL) 209 goto out_fclose_from; 210 211 while (getline(&line, &n, from_fp) > 0) 212 if (fputs(line, to_fp) == EOF) 213 goto out_fclose_to; 214 err = 0; 215 out_fclose_to: 216 fclose(to_fp); 217 free(line); 218 out_fclose_from: 219 fclose(from_fp); 220 out: 221 return err; 222 } 223 224 int copyfile_offset(int ifd, loff_t off_in, int ofd, loff_t off_out, u64 size) 225 { 226 void *ptr; 227 loff_t pgoff; 228 229 pgoff = off_in & ~(page_size - 1); 230 off_in -= pgoff; 231 232 ptr = mmap(NULL, off_in + size, PROT_READ, MAP_PRIVATE, ifd, pgoff); 233 if (ptr == MAP_FAILED) 234 return -1; 235 236 while (size) { 237 ssize_t ret = pwrite(ofd, ptr + off_in, size, off_out); 238 if (ret < 0 && errno == EINTR) 239 continue; 240 if (ret <= 0) 241 break; 242 243 size -= ret; 244 off_in += ret; 245 off_out += ret; 246 } 247 munmap(ptr, off_in + size); 248 249 return size ? -1 : 0; 250 } 251 252 static int copyfile_mode_ns(const char *from, const char *to, mode_t mode, 253 struct nsinfo *nsi) 254 { 255 int fromfd, tofd; 256 struct stat st; 257 int err; 258 char *tmp = NULL, *ptr = NULL; 259 struct nscookie nsc; 260 261 nsinfo__mountns_enter(nsi, &nsc); 262 err = stat(from, &st); 263 nsinfo__mountns_exit(&nsc); 264 if (err) 265 goto out; 266 err = -1; 267 268 /* extra 'x' at the end is to reserve space for '.' */ 269 if (asprintf(&tmp, "%s.XXXXXXx", to) < 0) { 270 tmp = NULL; 271 goto out; 272 } 273 ptr = strrchr(tmp, '/'); 274 if (!ptr) 275 goto out; 276 ptr = memmove(ptr + 1, ptr, strlen(ptr) - 1); 277 *ptr = '.'; 278 279 tofd = mkstemp(tmp); 280 if (tofd < 0) 281 goto out; 282 283 if (fchmod(tofd, mode)) 284 goto out_close_to; 285 286 if (st.st_size == 0) { /* /proc? do it slowly... */ 287 err = slow_copyfile(from, tmp, nsi); 288 goto out_close_to; 289 } 290 291 nsinfo__mountns_enter(nsi, &nsc); 292 fromfd = open(from, O_RDONLY); 293 nsinfo__mountns_exit(&nsc); 294 if (fromfd < 0) 295 goto out_close_to; 296 297 err = copyfile_offset(fromfd, 0, tofd, 0, st.st_size); 298 299 close(fromfd); 300 out_close_to: 301 close(tofd); 302 if (!err) 303 err = link(tmp, to); 304 unlink(tmp); 305 out: 306 free(tmp); 307 return err; 308 } 309 310 int copyfile_ns(const char *from, const char *to, struct nsinfo *nsi) 311 { 312 return copyfile_mode_ns(from, to, 0755, nsi); 313 } 314 315 int copyfile_mode(const char *from, const char *to, mode_t mode) 316 { 317 return copyfile_mode_ns(from, to, mode, NULL); 318 } 319 320 int copyfile(const char *from, const char *to) 321 { 322 return copyfile_mode(from, to, 0755); 323 } 324 325 static ssize_t ion(bool is_read, int fd, void *buf, size_t n) 326 { 327 void *buf_start = buf; 328 size_t left = n; 329 330 while (left) { 331 /* buf must be treated as const if !is_read. */ 332 ssize_t ret = is_read ? read(fd, buf, left) : 333 write(fd, buf, left); 334 335 if (ret < 0 && errno == EINTR) 336 continue; 337 if (ret <= 0) 338 return ret; 339 340 left -= ret; 341 buf += ret; 342 } 343 344 BUG_ON((size_t)(buf - buf_start) != n); 345 return n; 346 } 347 348 /* 349 * Read exactly 'n' bytes or return an error. 350 */ 351 ssize_t readn(int fd, void *buf, size_t n) 352 { 353 return ion(true, fd, buf, n); 354 } 355 356 /* 357 * Write exactly 'n' bytes or return an error. 358 */ 359 ssize_t writen(int fd, const void *buf, size_t n) 360 { 361 /* ion does not modify buf. */ 362 return ion(false, fd, (void *)buf, n); 363 } 364 365 size_t hex_width(u64 v) 366 { 367 size_t n = 1; 368 369 while ((v >>= 4)) 370 ++n; 371 372 return n; 373 } 374 375 /* 376 * While we find nice hex chars, build a long_val. 377 * Return number of chars processed. 378 */ 379 int hex2u64(const char *ptr, u64 *long_val) 380 { 381 char *p; 382 383 *long_val = strtoull(ptr, &p, 16); 384 385 return p - ptr; 386 } 387 388 int perf_event_paranoid(void) 389 { 390 int value; 391 392 if (sysctl__read_int("kernel/perf_event_paranoid", &value)) 393 return INT_MAX; 394 395 return value; 396 } 397 static int 398 fetch_ubuntu_kernel_version(unsigned int *puint) 399 { 400 ssize_t len; 401 size_t line_len = 0; 402 char *ptr, *line = NULL; 403 int version, patchlevel, sublevel, err; 404 FILE *vsig; 405 406 if (!puint) 407 return 0; 408 409 vsig = fopen("/proc/version_signature", "r"); 410 if (!vsig) { 411 pr_debug("Open /proc/version_signature failed: %s\n", 412 strerror(errno)); 413 return -1; 414 } 415 416 len = getline(&line, &line_len, vsig); 417 fclose(vsig); 418 err = -1; 419 if (len <= 0) { 420 pr_debug("Reading from /proc/version_signature failed: %s\n", 421 strerror(errno)); 422 goto errout; 423 } 424 425 ptr = strrchr(line, ' '); 426 if (!ptr) { 427 pr_debug("Parsing /proc/version_signature failed: %s\n", line); 428 goto errout; 429 } 430 431 err = sscanf(ptr + 1, "%d.%d.%d", 432 &version, &patchlevel, &sublevel); 433 if (err != 3) { 434 pr_debug("Unable to get kernel version from /proc/version_signature '%s'\n", 435 line); 436 goto errout; 437 } 438 439 *puint = (version << 16) + (patchlevel << 8) + sublevel; 440 err = 0; 441 errout: 442 free(line); 443 return err; 444 } 445 446 int 447 fetch_kernel_version(unsigned int *puint, char *str, 448 size_t str_size) 449 { 450 struct utsname utsname; 451 int version, patchlevel, sublevel, err; 452 bool int_ver_ready = false; 453 454 if (access("/proc/version_signature", R_OK) == 0) 455 if (!fetch_ubuntu_kernel_version(puint)) 456 int_ver_ready = true; 457 458 if (uname(&utsname)) 459 return -1; 460 461 if (str && str_size) { 462 strncpy(str, utsname.release, str_size); 463 str[str_size - 1] = '\0'; 464 } 465 466 if (!puint || int_ver_ready) 467 return 0; 468 469 err = sscanf(utsname.release, "%d.%d.%d", 470 &version, &patchlevel, &sublevel); 471 472 if (err != 3) { 473 pr_debug("Unable to get kernel version from uname '%s'\n", 474 utsname.release); 475 return -1; 476 } 477 478 *puint = (version << 16) + (patchlevel << 8) + sublevel; 479 return 0; 480 } 481 482 const char *perf_tip(const char *dirpath) 483 { 484 struct strlist *tips; 485 struct str_node *node; 486 char *tip = NULL; 487 struct strlist_config conf = { 488 .dirname = dirpath, 489 .file_only = true, 490 }; 491 492 tips = strlist__new("tips.txt", &conf); 493 if (tips == NULL) 494 return errno == ENOENT ? NULL : 495 "Tip: check path of tips.txt or get more memory! ;-p"; 496 497 if (strlist__nr_entries(tips) == 0) 498 goto out; 499 500 node = strlist__entry(tips, random() % strlist__nr_entries(tips)); 501 if (asprintf(&tip, "Tip: %s", node->s) < 0) 502 tip = (char *)"Tip: get more memory! ;-)"; 503 504 out: 505 strlist__delete(tips); 506 507 return tip; 508 } 509