1 #include "../perf.h" 2 #include "util.h" 3 #include <api/fs/fs.h> 4 #include <sys/mman.h> 5 #ifdef HAVE_BACKTRACE_SUPPORT 6 #include <execinfo.h> 7 #endif 8 #include <stdio.h> 9 #include <stdlib.h> 10 #include <string.h> 11 #include <errno.h> 12 #include <limits.h> 13 #include <byteswap.h> 14 #include <linux/kernel.h> 15 16 /* 17 * XXX We need to find a better place for these things... 18 */ 19 unsigned int page_size; 20 int cacheline_size; 21 22 bool test_attr__enabled; 23 24 bool perf_host = true; 25 bool perf_guest = false; 26 27 char tracing_events_path[PATH_MAX + 1] = "/sys/kernel/debug/tracing/events"; 28 29 void event_attr_init(struct perf_event_attr *attr) 30 { 31 if (!perf_host) 32 attr->exclude_host = 1; 33 if (!perf_guest) 34 attr->exclude_guest = 1; 35 /* to capture ABI version */ 36 attr->size = sizeof(*attr); 37 } 38 39 int mkdir_p(char *path, mode_t mode) 40 { 41 struct stat st; 42 int err; 43 char *d = path; 44 45 if (*d != '/') 46 return -1; 47 48 if (stat(path, &st) == 0) 49 return 0; 50 51 while (*++d == '/'); 52 53 while ((d = strchr(d, '/'))) { 54 *d = '\0'; 55 err = stat(path, &st) && mkdir(path, mode); 56 *d++ = '/'; 57 if (err) 58 return -1; 59 while (*d == '/') 60 ++d; 61 } 62 return (stat(path, &st) && mkdir(path, mode)) ? -1 : 0; 63 } 64 65 static int slow_copyfile(const char *from, const char *to, mode_t mode) 66 { 67 int err = -1; 68 char *line = NULL; 69 size_t n; 70 FILE *from_fp = fopen(from, "r"), *to_fp; 71 mode_t old_umask; 72 73 if (from_fp == NULL) 74 goto out; 75 76 old_umask = umask(mode ^ 0777); 77 to_fp = fopen(to, "w"); 78 umask(old_umask); 79 if (to_fp == NULL) 80 goto out_fclose_from; 81 82 while (getline(&line, &n, from_fp) > 0) 83 if (fputs(line, to_fp) == EOF) 84 goto out_fclose_to; 85 err = 0; 86 out_fclose_to: 87 fclose(to_fp); 88 free(line); 89 out_fclose_from: 90 fclose(from_fp); 91 out: 92 return err; 93 } 94 95 int copyfile_mode(const char *from, const char *to, mode_t mode) 96 { 97 int fromfd, tofd; 98 struct stat st; 99 void *addr; 100 int err = -1; 101 102 if (stat(from, &st)) 103 goto out; 104 105 if (st.st_size == 0) /* /proc? do it slowly... */ 106 return slow_copyfile(from, to, mode); 107 108 fromfd = open(from, O_RDONLY); 109 if (fromfd < 0) 110 goto out; 111 112 tofd = creat(to, mode); 113 if (tofd < 0) 114 goto out_close_from; 115 116 addr = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fromfd, 0); 117 if (addr == MAP_FAILED) 118 goto out_close_to; 119 120 if (write(tofd, addr, st.st_size) == st.st_size) 121 err = 0; 122 123 munmap(addr, st.st_size); 124 out_close_to: 125 close(tofd); 126 if (err) 127 unlink(to); 128 out_close_from: 129 close(fromfd); 130 out: 131 return err; 132 } 133 134 int copyfile(const char *from, const char *to) 135 { 136 return copyfile_mode(from, to, 0755); 137 } 138 139 unsigned long convert_unit(unsigned long value, char *unit) 140 { 141 *unit = ' '; 142 143 if (value > 1000) { 144 value /= 1000; 145 *unit = 'K'; 146 } 147 148 if (value > 1000) { 149 value /= 1000; 150 *unit = 'M'; 151 } 152 153 if (value > 1000) { 154 value /= 1000; 155 *unit = 'G'; 156 } 157 158 return value; 159 } 160 161 static ssize_t ion(bool is_read, int fd, void *buf, size_t n) 162 { 163 void *buf_start = buf; 164 size_t left = n; 165 166 while (left) { 167 ssize_t ret = is_read ? read(fd, buf, left) : 168 write(fd, buf, left); 169 170 if (ret < 0 && errno == EINTR) 171 continue; 172 if (ret <= 0) 173 return ret; 174 175 left -= ret; 176 buf += ret; 177 } 178 179 BUG_ON((size_t)(buf - buf_start) != n); 180 return n; 181 } 182 183 /* 184 * Read exactly 'n' bytes or return an error. 185 */ 186 ssize_t readn(int fd, void *buf, size_t n) 187 { 188 return ion(true, fd, buf, n); 189 } 190 191 /* 192 * Write exactly 'n' bytes or return an error. 193 */ 194 ssize_t writen(int fd, void *buf, size_t n) 195 { 196 return ion(false, fd, buf, n); 197 } 198 199 size_t hex_width(u64 v) 200 { 201 size_t n = 1; 202 203 while ((v >>= 4)) 204 ++n; 205 206 return n; 207 } 208 209 static int hex(char ch) 210 { 211 if ((ch >= '0') && (ch <= '9')) 212 return ch - '0'; 213 if ((ch >= 'a') && (ch <= 'f')) 214 return ch - 'a' + 10; 215 if ((ch >= 'A') && (ch <= 'F')) 216 return ch - 'A' + 10; 217 return -1; 218 } 219 220 /* 221 * While we find nice hex chars, build a long_val. 222 * Return number of chars processed. 223 */ 224 int hex2u64(const char *ptr, u64 *long_val) 225 { 226 const char *p = ptr; 227 *long_val = 0; 228 229 while (*p) { 230 const int hex_val = hex(*p); 231 232 if (hex_val < 0) 233 break; 234 235 *long_val = (*long_val << 4) | hex_val; 236 p++; 237 } 238 239 return p - ptr; 240 } 241 242 /* Obtain a backtrace and print it to stdout. */ 243 #ifdef HAVE_BACKTRACE_SUPPORT 244 void dump_stack(void) 245 { 246 void *array[16]; 247 size_t size = backtrace(array, ARRAY_SIZE(array)); 248 char **strings = backtrace_symbols(array, size); 249 size_t i; 250 251 printf("Obtained %zd stack frames.\n", size); 252 253 for (i = 0; i < size; i++) 254 printf("%s\n", strings[i]); 255 256 free(strings); 257 } 258 #else 259 void dump_stack(void) {} 260 #endif 261 262 void get_term_dimensions(struct winsize *ws) 263 { 264 char *s = getenv("LINES"); 265 266 if (s != NULL) { 267 ws->ws_row = atoi(s); 268 s = getenv("COLUMNS"); 269 if (s != NULL) { 270 ws->ws_col = atoi(s); 271 if (ws->ws_row && ws->ws_col) 272 return; 273 } 274 } 275 #ifdef TIOCGWINSZ 276 if (ioctl(1, TIOCGWINSZ, ws) == 0 && 277 ws->ws_row && ws->ws_col) 278 return; 279 #endif 280 ws->ws_row = 25; 281 ws->ws_col = 80; 282 } 283 284 static void set_tracing_events_path(const char *mountpoint) 285 { 286 snprintf(tracing_events_path, sizeof(tracing_events_path), "%s/%s", 287 mountpoint, "tracing/events"); 288 } 289 290 const char *perf_debugfs_mount(const char *mountpoint) 291 { 292 const char *mnt; 293 294 mnt = debugfs_mount(mountpoint); 295 if (!mnt) 296 return NULL; 297 298 set_tracing_events_path(mnt); 299 300 return mnt; 301 } 302 303 void perf_debugfs_set_path(const char *mntpt) 304 { 305 snprintf(debugfs_mountpoint, strlen(debugfs_mountpoint), "%s", mntpt); 306 set_tracing_events_path(mntpt); 307 } 308 309 static const char *find_debugfs(void) 310 { 311 const char *path = perf_debugfs_mount(NULL); 312 313 if (!path) 314 fprintf(stderr, "Your kernel does not support the debugfs filesystem"); 315 316 return path; 317 } 318 319 /* 320 * Finds the path to the debugfs/tracing 321 * Allocates the string and stores it. 322 */ 323 const char *find_tracing_dir(void) 324 { 325 static char *tracing; 326 static int tracing_found; 327 const char *debugfs; 328 329 if (tracing_found) 330 return tracing; 331 332 debugfs = find_debugfs(); 333 if (!debugfs) 334 return NULL; 335 336 tracing = malloc(strlen(debugfs) + 9); 337 if (!tracing) 338 return NULL; 339 340 sprintf(tracing, "%s/tracing", debugfs); 341 342 tracing_found = 1; 343 return tracing; 344 } 345 346 char *get_tracing_file(const char *name) 347 { 348 const char *tracing; 349 char *file; 350 351 tracing = find_tracing_dir(); 352 if (!tracing) 353 return NULL; 354 355 file = malloc(strlen(tracing) + strlen(name) + 2); 356 if (!file) 357 return NULL; 358 359 sprintf(file, "%s/%s", tracing, name); 360 return file; 361 } 362 363 void put_tracing_file(char *file) 364 { 365 free(file); 366 } 367 368 int parse_nsec_time(const char *str, u64 *ptime) 369 { 370 u64 time_sec, time_nsec; 371 char *end; 372 373 time_sec = strtoul(str, &end, 10); 374 if (*end != '.' && *end != '\0') 375 return -1; 376 377 if (*end == '.') { 378 int i; 379 char nsec_buf[10]; 380 381 if (strlen(++end) > 9) 382 return -1; 383 384 strncpy(nsec_buf, end, 9); 385 nsec_buf[9] = '\0'; 386 387 /* make it nsec precision */ 388 for (i = strlen(nsec_buf); i < 9; i++) 389 nsec_buf[i] = '0'; 390 391 time_nsec = strtoul(nsec_buf, &end, 10); 392 if (*end != '\0') 393 return -1; 394 } else 395 time_nsec = 0; 396 397 *ptime = time_sec * NSEC_PER_SEC + time_nsec; 398 return 0; 399 } 400 401 unsigned long parse_tag_value(const char *str, struct parse_tag *tags) 402 { 403 struct parse_tag *i = tags; 404 405 while (i->tag) { 406 char *s; 407 408 s = strchr(str, i->tag); 409 if (s) { 410 unsigned long int value; 411 char *endptr; 412 413 value = strtoul(str, &endptr, 10); 414 if (s != endptr) 415 break; 416 417 if (value > ULONG_MAX / i->mult) 418 break; 419 value *= i->mult; 420 return value; 421 } 422 i++; 423 } 424 425 return (unsigned long) -1; 426 } 427 428 int filename__read_int(const char *filename, int *value) 429 { 430 char line[64]; 431 int fd = open(filename, O_RDONLY), err = -1; 432 433 if (fd < 0) 434 return -1; 435 436 if (read(fd, line, sizeof(line)) > 0) { 437 *value = atoi(line); 438 err = 0; 439 } 440 441 close(fd); 442 return err; 443 } 444 445 int filename__read_str(const char *filename, char **buf, size_t *sizep) 446 { 447 size_t size = 0, alloc_size = 0; 448 void *bf = NULL, *nbf; 449 int fd, n, err = 0; 450 451 fd = open(filename, O_RDONLY); 452 if (fd < 0) 453 return -errno; 454 455 do { 456 if (size == alloc_size) { 457 alloc_size += BUFSIZ; 458 nbf = realloc(bf, alloc_size); 459 if (!nbf) { 460 err = -ENOMEM; 461 break; 462 } 463 464 bf = nbf; 465 } 466 467 n = read(fd, bf + size, alloc_size - size); 468 if (n < 0) { 469 if (size) { 470 pr_warning("read failed %d: %s\n", 471 errno, strerror(errno)); 472 err = 0; 473 } else 474 err = -errno; 475 476 break; 477 } 478 479 size += n; 480 } while (n > 0); 481 482 if (!err) { 483 *sizep = size; 484 *buf = bf; 485 } else 486 free(bf); 487 488 close(fd); 489 return err; 490 } 491 492 const char *get_filename_for_perf_kvm(void) 493 { 494 const char *filename; 495 496 if (perf_host && !perf_guest) 497 filename = strdup("perf.data.host"); 498 else if (!perf_host && perf_guest) 499 filename = strdup("perf.data.guest"); 500 else 501 filename = strdup("perf.data.kvm"); 502 503 return filename; 504 } 505 506 int perf_event_paranoid(void) 507 { 508 char path[PATH_MAX]; 509 const char *procfs = procfs__mountpoint(); 510 int value; 511 512 if (!procfs) 513 return INT_MAX; 514 515 scnprintf(path, PATH_MAX, "%s/sys/kernel/perf_event_paranoid", procfs); 516 517 if (filename__read_int(path, &value)) 518 return INT_MAX; 519 520 return value; 521 } 522 523 void mem_bswap_32(void *src, int byte_size) 524 { 525 u32 *m = src; 526 while (byte_size > 0) { 527 *m = bswap_32(*m); 528 byte_size -= sizeof(u32); 529 ++m; 530 } 531 } 532 533 void mem_bswap_64(void *src, int byte_size) 534 { 535 u64 *m = src; 536 537 while (byte_size > 0) { 538 *m = bswap_64(*m); 539 byte_size -= sizeof(u64); 540 ++m; 541 } 542 } 543