diff options
author | Zhang, Yanmin <yanmin_zhang@linux.intel.com> | 2010-04-19 01:32:50 -0400 |
---|---|---|
committer | Avi Kivity <avi@redhat.com> | 2010-04-19 05:37:24 -0400 |
commit | a1645ce12adb6c9cc9e19d7695466204e3f017fe (patch) | |
tree | 5d31aaaf534997e6e9cebc07f38eca35f76986cf /tools/perf/util/map.c | |
parent | ff9d07a0e7ce756a183e7c2e483aec452ee6b574 (diff) |
perf: 'perf kvm' tool for monitoring guest performance from host
Here is the patch of userspace perf tool.
Signed-off-by: Zhang Yanmin <yanmin_zhang@linux.intel.com>
Signed-off-by: Avi Kivity <avi@redhat.com>
Diffstat (limited to 'tools/perf/util/map.c')
-rw-r--r-- | tools/perf/util/map.c | 139 |
1 files changed, 137 insertions, 2 deletions
diff --git a/tools/perf/util/map.c b/tools/perf/util/map.c index 37913b241bdf..7facd016ec97 100644 --- a/tools/perf/util/map.c +++ b/tools/perf/util/map.c | |||
@@ -4,6 +4,7 @@ | |||
4 | #include <stdlib.h> | 4 | #include <stdlib.h> |
5 | #include <string.h> | 5 | #include <string.h> |
6 | #include <stdio.h> | 6 | #include <stdio.h> |
7 | #include <unistd.h> | ||
7 | #include "map.h" | 8 | #include "map.h" |
8 | 9 | ||
9 | const char *map_type__name[MAP__NR_TYPES] = { | 10 | const char *map_type__name[MAP__NR_TYPES] = { |
@@ -37,9 +38,11 @@ void map__init(struct map *self, enum map_type type, | |||
37 | self->map_ip = map__map_ip; | 38 | self->map_ip = map__map_ip; |
38 | self->unmap_ip = map__unmap_ip; | 39 | self->unmap_ip = map__unmap_ip; |
39 | RB_CLEAR_NODE(&self->rb_node); | 40 | RB_CLEAR_NODE(&self->rb_node); |
41 | self->groups = NULL; | ||
40 | } | 42 | } |
41 | 43 | ||
42 | struct map *map__new(u64 start, u64 len, u64 pgoff, u32 pid, char *filename, | 44 | struct map *map__new(struct list_head *dsos__list, u64 start, u64 len, |
45 | u64 pgoff, u32 pid, char *filename, | ||
43 | enum map_type type, char *cwd, int cwdlen) | 46 | enum map_type type, char *cwd, int cwdlen) |
44 | { | 47 | { |
45 | struct map *self = malloc(sizeof(*self)); | 48 | struct map *self = malloc(sizeof(*self)); |
@@ -66,7 +69,7 @@ struct map *map__new(u64 start, u64 len, u64 pgoff, u32 pid, char *filename, | |||
66 | filename = newfilename; | 69 | filename = newfilename; |
67 | } | 70 | } |
68 | 71 | ||
69 | dso = dsos__findnew(filename); | 72 | dso = __dsos__findnew(dsos__list, filename); |
70 | if (dso == NULL) | 73 | if (dso == NULL) |
71 | goto out_delete; | 74 | goto out_delete; |
72 | 75 | ||
@@ -242,6 +245,7 @@ void map_groups__init(struct map_groups *self) | |||
242 | self->maps[i] = RB_ROOT; | 245 | self->maps[i] = RB_ROOT; |
243 | INIT_LIST_HEAD(&self->removed_maps[i]); | 246 | INIT_LIST_HEAD(&self->removed_maps[i]); |
244 | } | 247 | } |
248 | self->this_kerninfo = NULL; | ||
245 | } | 249 | } |
246 | 250 | ||
247 | void map_groups__flush(struct map_groups *self) | 251 | void map_groups__flush(struct map_groups *self) |
@@ -508,3 +512,134 @@ struct map *maps__find(struct rb_root *maps, u64 ip) | |||
508 | 512 | ||
509 | return NULL; | 513 | return NULL; |
510 | } | 514 | } |
515 | |||
516 | struct kernel_info *add_new_kernel_info(struct rb_root *kerninfo_root, | ||
517 | pid_t pid, const char *root_dir) | ||
518 | { | ||
519 | struct rb_node **p = &kerninfo_root->rb_node; | ||
520 | struct rb_node *parent = NULL; | ||
521 | struct kernel_info *kerninfo, *pos; | ||
522 | |||
523 | kerninfo = malloc(sizeof(struct kernel_info)); | ||
524 | if (!kerninfo) | ||
525 | return NULL; | ||
526 | |||
527 | kerninfo->pid = pid; | ||
528 | map_groups__init(&kerninfo->kmaps); | ||
529 | kerninfo->root_dir = strdup(root_dir); | ||
530 | RB_CLEAR_NODE(&kerninfo->rb_node); | ||
531 | INIT_LIST_HEAD(&kerninfo->dsos__user); | ||
532 | INIT_LIST_HEAD(&kerninfo->dsos__kernel); | ||
533 | kerninfo->kmaps.this_kerninfo = kerninfo; | ||
534 | |||
535 | while (*p != NULL) { | ||
536 | parent = *p; | ||
537 | pos = rb_entry(parent, struct kernel_info, rb_node); | ||
538 | if (pid < pos->pid) | ||
539 | p = &(*p)->rb_left; | ||
540 | else | ||
541 | p = &(*p)->rb_right; | ||
542 | } | ||
543 | |||
544 | rb_link_node(&kerninfo->rb_node, parent, p); | ||
545 | rb_insert_color(&kerninfo->rb_node, kerninfo_root); | ||
546 | |||
547 | return kerninfo; | ||
548 | } | ||
549 | |||
550 | struct kernel_info *kerninfo__find(struct rb_root *kerninfo_root, pid_t pid) | ||
551 | { | ||
552 | struct rb_node **p = &kerninfo_root->rb_node; | ||
553 | struct rb_node *parent = NULL; | ||
554 | struct kernel_info *kerninfo; | ||
555 | struct kernel_info *default_kerninfo = NULL; | ||
556 | |||
557 | while (*p != NULL) { | ||
558 | parent = *p; | ||
559 | kerninfo = rb_entry(parent, struct kernel_info, rb_node); | ||
560 | if (pid < kerninfo->pid) | ||
561 | p = &(*p)->rb_left; | ||
562 | else if (pid > kerninfo->pid) | ||
563 | p = &(*p)->rb_right; | ||
564 | else | ||
565 | return kerninfo; | ||
566 | if (!kerninfo->pid) | ||
567 | default_kerninfo = kerninfo; | ||
568 | } | ||
569 | |||
570 | return default_kerninfo; | ||
571 | } | ||
572 | |||
573 | struct kernel_info *kerninfo__findhost(struct rb_root *kerninfo_root) | ||
574 | { | ||
575 | struct rb_node **p = &kerninfo_root->rb_node; | ||
576 | struct rb_node *parent = NULL; | ||
577 | struct kernel_info *kerninfo; | ||
578 | pid_t pid = HOST_KERNEL_ID; | ||
579 | |||
580 | while (*p != NULL) { | ||
581 | parent = *p; | ||
582 | kerninfo = rb_entry(parent, struct kernel_info, rb_node); | ||
583 | if (pid < kerninfo->pid) | ||
584 | p = &(*p)->rb_left; | ||
585 | else if (pid > kerninfo->pid) | ||
586 | p = &(*p)->rb_right; | ||
587 | else | ||
588 | return kerninfo; | ||
589 | } | ||
590 | |||
591 | return NULL; | ||
592 | } | ||
593 | |||
594 | struct kernel_info *kerninfo__findnew(struct rb_root *kerninfo_root, pid_t pid) | ||
595 | { | ||
596 | char path[PATH_MAX]; | ||
597 | const char *root_dir; | ||
598 | int ret; | ||
599 | struct kernel_info *kerninfo = kerninfo__find(kerninfo_root, pid); | ||
600 | |||
601 | if (!kerninfo || kerninfo->pid != pid) { | ||
602 | if (pid == HOST_KERNEL_ID || pid == DEFAULT_GUEST_KERNEL_ID) | ||
603 | root_dir = ""; | ||
604 | else { | ||
605 | if (!symbol_conf.guestmount) | ||
606 | goto out; | ||
607 | sprintf(path, "%s/%d", symbol_conf.guestmount, pid); | ||
608 | ret = access(path, R_OK); | ||
609 | if (ret) { | ||
610 | pr_err("Can't access file %s\n", path); | ||
611 | goto out; | ||
612 | } | ||
613 | root_dir = path; | ||
614 | } | ||
615 | kerninfo = add_new_kernel_info(kerninfo_root, pid, root_dir); | ||
616 | } | ||
617 | |||
618 | out: | ||
619 | return kerninfo; | ||
620 | } | ||
621 | |||
622 | void kerninfo__process_allkernels(struct rb_root *kerninfo_root, | ||
623 | process_kernel_info process, | ||
624 | void *data) | ||
625 | { | ||
626 | struct rb_node *nd; | ||
627 | |||
628 | for (nd = rb_first(kerninfo_root); nd; nd = rb_next(nd)) { | ||
629 | struct kernel_info *pos = rb_entry(nd, struct kernel_info, | ||
630 | rb_node); | ||
631 | process(pos, data); | ||
632 | } | ||
633 | } | ||
634 | |||
635 | char *kern_mmap_name(struct kernel_info *kerninfo, char *buff) | ||
636 | { | ||
637 | if (is_host_kernel(kerninfo)) | ||
638 | sprintf(buff, "[%s]", "kernel.kallsyms"); | ||
639 | else if (is_default_guest(kerninfo)) | ||
640 | sprintf(buff, "[%s]", "guest.kernel.kallsyms"); | ||
641 | else | ||
642 | sprintf(buff, "[%s.%d]", "guest.kernel.kallsyms", kerninfo->pid); | ||
643 | |||
644 | return buff; | ||
645 | } | ||