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/header.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/header.c')
-rw-r--r-- | tools/perf/util/header.c | 213 |
1 files changed, 173 insertions, 40 deletions
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c index 628173ba689e..75d016768021 100644 --- a/tools/perf/util/header.c +++ b/tools/perf/util/header.c | |||
@@ -190,7 +190,8 @@ static int write_padded(int fd, const void *bf, size_t count, | |||
190 | continue; \ | 190 | continue; \ |
191 | else | 191 | else |
192 | 192 | ||
193 | static int __dsos__write_buildid_table(struct list_head *head, u16 misc, int fd) | 193 | static int __dsos__write_buildid_table(struct list_head *head, pid_t pid, |
194 | u16 misc, int fd) | ||
194 | { | 195 | { |
195 | struct dso *pos; | 196 | struct dso *pos; |
196 | 197 | ||
@@ -205,6 +206,7 @@ static int __dsos__write_buildid_table(struct list_head *head, u16 misc, int fd) | |||
205 | len = ALIGN(len, NAME_ALIGN); | 206 | len = ALIGN(len, NAME_ALIGN); |
206 | memset(&b, 0, sizeof(b)); | 207 | memset(&b, 0, sizeof(b)); |
207 | memcpy(&b.build_id, pos->build_id, sizeof(pos->build_id)); | 208 | memcpy(&b.build_id, pos->build_id, sizeof(pos->build_id)); |
209 | b.pid = pid; | ||
208 | b.header.misc = misc; | 210 | b.header.misc = misc; |
209 | b.header.size = sizeof(b) + len; | 211 | b.header.size = sizeof(b) + len; |
210 | err = do_write(fd, &b, sizeof(b)); | 212 | err = do_write(fd, &b, sizeof(b)); |
@@ -219,13 +221,33 @@ static int __dsos__write_buildid_table(struct list_head *head, u16 misc, int fd) | |||
219 | return 0; | 221 | return 0; |
220 | } | 222 | } |
221 | 223 | ||
222 | static int dsos__write_buildid_table(int fd) | 224 | static int dsos__write_buildid_table(struct perf_header *header, int fd) |
223 | { | 225 | { |
224 | int err = __dsos__write_buildid_table(&dsos__kernel, | 226 | struct perf_session *session = container_of(header, |
225 | PERF_RECORD_MISC_KERNEL, fd); | 227 | struct perf_session, header); |
226 | if (err == 0) | 228 | struct rb_node *nd; |
227 | err = __dsos__write_buildid_table(&dsos__user, | 229 | int err = 0; |
228 | PERF_RECORD_MISC_USER, fd); | 230 | u16 kmisc, umisc; |
231 | |||
232 | for (nd = rb_first(&session->kerninfo_root); nd; nd = rb_next(nd)) { | ||
233 | struct kernel_info *pos = rb_entry(nd, struct kernel_info, | ||
234 | rb_node); | ||
235 | if (is_host_kernel(pos)) { | ||
236 | kmisc = PERF_RECORD_MISC_KERNEL; | ||
237 | umisc = PERF_RECORD_MISC_USER; | ||
238 | } else { | ||
239 | kmisc = PERF_RECORD_MISC_GUEST_KERNEL; | ||
240 | umisc = PERF_RECORD_MISC_GUEST_USER; | ||
241 | } | ||
242 | |||
243 | err = __dsos__write_buildid_table(&pos->dsos__kernel, pos->pid, | ||
244 | kmisc, fd); | ||
245 | if (err == 0) | ||
246 | err = __dsos__write_buildid_table(&pos->dsos__user, | ||
247 | pos->pid, umisc, fd); | ||
248 | if (err) | ||
249 | break; | ||
250 | } | ||
229 | return err; | 251 | return err; |
230 | } | 252 | } |
231 | 253 | ||
@@ -342,9 +364,12 @@ static int __dsos__cache_build_ids(struct list_head *head, const char *debugdir) | |||
342 | return err; | 364 | return err; |
343 | } | 365 | } |
344 | 366 | ||
345 | static int dsos__cache_build_ids(void) | 367 | static int dsos__cache_build_ids(struct perf_header *self) |
346 | { | 368 | { |
347 | int err_kernel, err_user; | 369 | struct perf_session *session = container_of(self, |
370 | struct perf_session, header); | ||
371 | struct rb_node *nd; | ||
372 | int ret = 0; | ||
348 | char debugdir[PATH_MAX]; | 373 | char debugdir[PATH_MAX]; |
349 | 374 | ||
350 | snprintf(debugdir, sizeof(debugdir), "%s/%s", getenv("HOME"), | 375 | snprintf(debugdir, sizeof(debugdir), "%s/%s", getenv("HOME"), |
@@ -353,9 +378,30 @@ static int dsos__cache_build_ids(void) | |||
353 | if (mkdir(debugdir, 0755) != 0 && errno != EEXIST) | 378 | if (mkdir(debugdir, 0755) != 0 && errno != EEXIST) |
354 | return -1; | 379 | return -1; |
355 | 380 | ||
356 | err_kernel = __dsos__cache_build_ids(&dsos__kernel, debugdir); | 381 | for (nd = rb_first(&session->kerninfo_root); nd; nd = rb_next(nd)) { |
357 | err_user = __dsos__cache_build_ids(&dsos__user, debugdir); | 382 | struct kernel_info *pos = rb_entry(nd, struct kernel_info, |
358 | return err_kernel || err_user ? -1 : 0; | 383 | rb_node); |
384 | ret |= __dsos__cache_build_ids(&pos->dsos__kernel, debugdir); | ||
385 | ret |= __dsos__cache_build_ids(&pos->dsos__user, debugdir); | ||
386 | } | ||
387 | return ret ? -1 : 0; | ||
388 | } | ||
389 | |||
390 | static bool dsos__read_build_ids(struct perf_header *self, bool with_hits) | ||
391 | { | ||
392 | bool ret = false; | ||
393 | struct perf_session *session = container_of(self, | ||
394 | struct perf_session, header); | ||
395 | struct rb_node *nd; | ||
396 | |||
397 | for (nd = rb_first(&session->kerninfo_root); nd; nd = rb_next(nd)) { | ||
398 | struct kernel_info *pos = rb_entry(nd, struct kernel_info, | ||
399 | rb_node); | ||
400 | ret |= __dsos__read_build_ids(&pos->dsos__kernel, with_hits); | ||
401 | ret |= __dsos__read_build_ids(&pos->dsos__user, with_hits); | ||
402 | } | ||
403 | |||
404 | return ret; | ||
359 | } | 405 | } |
360 | 406 | ||
361 | static int perf_header__adds_write(struct perf_header *self, int fd) | 407 | static int perf_header__adds_write(struct perf_header *self, int fd) |
@@ -366,7 +412,7 @@ static int perf_header__adds_write(struct perf_header *self, int fd) | |||
366 | u64 sec_start; | 412 | u64 sec_start; |
367 | int idx = 0, err; | 413 | int idx = 0, err; |
368 | 414 | ||
369 | if (dsos__read_build_ids(true)) | 415 | if (dsos__read_build_ids(self, true)) |
370 | perf_header__set_feat(self, HEADER_BUILD_ID); | 416 | perf_header__set_feat(self, HEADER_BUILD_ID); |
371 | 417 | ||
372 | nr_sections = bitmap_weight(self->adds_features, HEADER_FEAT_BITS); | 418 | nr_sections = bitmap_weight(self->adds_features, HEADER_FEAT_BITS); |
@@ -401,14 +447,14 @@ static int perf_header__adds_write(struct perf_header *self, int fd) | |||
401 | 447 | ||
402 | /* Write build-ids */ | 448 | /* Write build-ids */ |
403 | buildid_sec->offset = lseek(fd, 0, SEEK_CUR); | 449 | buildid_sec->offset = lseek(fd, 0, SEEK_CUR); |
404 | err = dsos__write_buildid_table(fd); | 450 | err = dsos__write_buildid_table(self, fd); |
405 | if (err < 0) { | 451 | if (err < 0) { |
406 | pr_debug("failed to write buildid table\n"); | 452 | pr_debug("failed to write buildid table\n"); |
407 | goto out_free; | 453 | goto out_free; |
408 | } | 454 | } |
409 | buildid_sec->size = lseek(fd, 0, SEEK_CUR) - | 455 | buildid_sec->size = lseek(fd, 0, SEEK_CUR) - |
410 | buildid_sec->offset; | 456 | buildid_sec->offset; |
411 | dsos__cache_build_ids(); | 457 | dsos__cache_build_ids(self); |
412 | } | 458 | } |
413 | 459 | ||
414 | lseek(fd, sec_start, SEEK_SET); | 460 | lseek(fd, sec_start, SEEK_SET); |
@@ -633,6 +679,85 @@ int perf_file_header__read(struct perf_file_header *self, | |||
633 | return 0; | 679 | return 0; |
634 | } | 680 | } |
635 | 681 | ||
682 | static int __event_process_build_id(struct build_id_event *bev, | ||
683 | char *filename, | ||
684 | struct perf_session *session) | ||
685 | { | ||
686 | int err = -1; | ||
687 | struct list_head *head; | ||
688 | struct kernel_info *kerninfo; | ||
689 | u16 misc; | ||
690 | struct dso *dso; | ||
691 | enum dso_kernel_type dso_type; | ||
692 | |||
693 | kerninfo = kerninfo__findnew(&session->kerninfo_root, bev->pid); | ||
694 | if (!kerninfo) | ||
695 | goto out; | ||
696 | |||
697 | misc = bev->header.misc & PERF_RECORD_MISC_CPUMODE_MASK; | ||
698 | |||
699 | switch (misc) { | ||
700 | case PERF_RECORD_MISC_KERNEL: | ||
701 | dso_type = DSO_TYPE_KERNEL; | ||
702 | head = &kerninfo->dsos__kernel; | ||
703 | break; | ||
704 | case PERF_RECORD_MISC_GUEST_KERNEL: | ||
705 | dso_type = DSO_TYPE_GUEST_KERNEL; | ||
706 | head = &kerninfo->dsos__kernel; | ||
707 | break; | ||
708 | case PERF_RECORD_MISC_USER: | ||
709 | case PERF_RECORD_MISC_GUEST_USER: | ||
710 | dso_type = DSO_TYPE_USER; | ||
711 | head = &kerninfo->dsos__user; | ||
712 | break; | ||
713 | default: | ||
714 | goto out; | ||
715 | } | ||
716 | |||
717 | dso = __dsos__findnew(head, filename); | ||
718 | if (dso != NULL) { | ||
719 | dso__set_build_id(dso, &bev->build_id); | ||
720 | if (filename[0] == '[') | ||
721 | dso->kernel = dso_type; | ||
722 | } | ||
723 | |||
724 | err = 0; | ||
725 | out: | ||
726 | return err; | ||
727 | } | ||
728 | |||
729 | static int perf_header__read_build_ids(struct perf_header *self, | ||
730 | int input, u64 offset, u64 size) | ||
731 | { | ||
732 | struct perf_session *session = container_of(self, | ||
733 | struct perf_session, header); | ||
734 | struct build_id_event bev; | ||
735 | char filename[PATH_MAX]; | ||
736 | u64 limit = offset + size; | ||
737 | int err = -1; | ||
738 | |||
739 | while (offset < limit) { | ||
740 | ssize_t len; | ||
741 | |||
742 | if (read(input, &bev, sizeof(bev)) != sizeof(bev)) | ||
743 | goto out; | ||
744 | |||
745 | if (self->needs_swap) | ||
746 | perf_event_header__bswap(&bev.header); | ||
747 | |||
748 | len = bev.header.size - sizeof(bev); | ||
749 | if (read(input, filename, len) != len) | ||
750 | goto out; | ||
751 | |||
752 | __event_process_build_id(&bev, filename, session); | ||
753 | |||
754 | offset += bev.header.size; | ||
755 | } | ||
756 | err = 0; | ||
757 | out: | ||
758 | return err; | ||
759 | } | ||
760 | |||
636 | static int perf_file_section__process(struct perf_file_section *self, | 761 | static int perf_file_section__process(struct perf_file_section *self, |
637 | struct perf_header *ph, | 762 | struct perf_header *ph, |
638 | int feat, int fd) | 763 | int feat, int fd) |
@@ -989,6 +1114,7 @@ int event__process_tracing_data(event_t *self, | |||
989 | 1114 | ||
990 | int event__synthesize_build_id(struct dso *pos, u16 misc, | 1115 | int event__synthesize_build_id(struct dso *pos, u16 misc, |
991 | event__handler_t process, | 1116 | event__handler_t process, |
1117 | struct kernel_info *kerninfo, | ||
992 | struct perf_session *session) | 1118 | struct perf_session *session) |
993 | { | 1119 | { |
994 | event_t ev; | 1120 | event_t ev; |
@@ -1005,6 +1131,7 @@ int event__synthesize_build_id(struct dso *pos, u16 misc, | |||
1005 | memcpy(&ev.build_id.build_id, pos->build_id, sizeof(pos->build_id)); | 1131 | memcpy(&ev.build_id.build_id, pos->build_id, sizeof(pos->build_id)); |
1006 | ev.build_id.header.type = PERF_RECORD_HEADER_BUILD_ID; | 1132 | ev.build_id.header.type = PERF_RECORD_HEADER_BUILD_ID; |
1007 | ev.build_id.header.misc = misc; | 1133 | ev.build_id.header.misc = misc; |
1134 | ev.build_id.pid = kerninfo->pid; | ||
1008 | ev.build_id.header.size = sizeof(ev.build_id) + len; | 1135 | ev.build_id.header.size = sizeof(ev.build_id) + len; |
1009 | memcpy(&ev.build_id.filename, pos->long_name, pos->long_name_len); | 1136 | memcpy(&ev.build_id.filename, pos->long_name, pos->long_name_len); |
1010 | 1137 | ||
@@ -1015,6 +1142,7 @@ int event__synthesize_build_id(struct dso *pos, u16 misc, | |||
1015 | 1142 | ||
1016 | static int __event_synthesize_build_ids(struct list_head *head, u16 misc, | 1143 | static int __event_synthesize_build_ids(struct list_head *head, u16 misc, |
1017 | event__handler_t process, | 1144 | event__handler_t process, |
1145 | struct kernel_info *kerninfo, | ||
1018 | struct perf_session *session) | 1146 | struct perf_session *session) |
1019 | { | 1147 | { |
1020 | struct dso *pos; | 1148 | struct dso *pos; |
@@ -1024,7 +1152,8 @@ static int __event_synthesize_build_ids(struct list_head *head, u16 misc, | |||
1024 | if (!pos->hit) | 1152 | if (!pos->hit) |
1025 | continue; | 1153 | continue; |
1026 | 1154 | ||
1027 | err = event__synthesize_build_id(pos, misc, process, session); | 1155 | err = event__synthesize_build_id(pos, misc, process, |
1156 | kerninfo, session); | ||
1028 | if (err < 0) | 1157 | if (err < 0) |
1029 | return err; | 1158 | return err; |
1030 | } | 1159 | } |
@@ -1035,44 +1164,48 @@ static int __event_synthesize_build_ids(struct list_head *head, u16 misc, | |||
1035 | int event__synthesize_build_ids(event__handler_t process, | 1164 | int event__synthesize_build_ids(event__handler_t process, |
1036 | struct perf_session *session) | 1165 | struct perf_session *session) |
1037 | { | 1166 | { |
1038 | int err; | 1167 | int err = 0; |
1168 | u16 kmisc, umisc; | ||
1169 | struct kernel_info *pos; | ||
1170 | struct rb_node *nd; | ||
1039 | 1171 | ||
1040 | if (!dsos__read_build_ids(true)) | 1172 | if (!dsos__read_build_ids(&session->header, true)) |
1041 | return 0; | 1173 | return 0; |
1042 | 1174 | ||
1043 | err = __event_synthesize_build_ids(&dsos__kernel, | 1175 | for (nd = rb_first(&session->kerninfo_root); nd; nd = rb_next(nd)) { |
1044 | PERF_RECORD_MISC_KERNEL, | 1176 | pos = rb_entry(nd, struct kernel_info, rb_node); |
1045 | process, session); | 1177 | if (is_host_kernel(pos)) { |
1046 | if (err == 0) | 1178 | kmisc = PERF_RECORD_MISC_KERNEL; |
1047 | err = __event_synthesize_build_ids(&dsos__user, | 1179 | umisc = PERF_RECORD_MISC_USER; |
1048 | PERF_RECORD_MISC_USER, | 1180 | } else { |
1049 | process, session); | 1181 | kmisc = PERF_RECORD_MISC_GUEST_KERNEL; |
1182 | umisc = PERF_RECORD_MISC_GUEST_USER; | ||
1183 | } | ||
1184 | |||
1185 | err = __event_synthesize_build_ids(&pos->dsos__kernel, | ||
1186 | kmisc, process, pos, session); | ||
1187 | if (err == 0) | ||
1188 | err = __event_synthesize_build_ids(&pos->dsos__user, | ||
1189 | umisc, process, pos, session); | ||
1190 | if (err) | ||
1191 | break; | ||
1192 | } | ||
1050 | 1193 | ||
1051 | if (err < 0) { | 1194 | if (err < 0) { |
1052 | pr_debug("failed to synthesize build ids\n"); | 1195 | pr_debug("failed to synthesize build ids\n"); |
1053 | return err; | 1196 | return err; |
1054 | } | 1197 | } |
1055 | 1198 | ||
1056 | dsos__cache_build_ids(); | 1199 | dsos__cache_build_ids(&session->header); |
1057 | 1200 | ||
1058 | return 0; | 1201 | return 0; |
1059 | } | 1202 | } |
1060 | 1203 | ||
1061 | int event__process_build_id(event_t *self, | 1204 | int event__process_build_id(event_t *self, |
1062 | struct perf_session *session __unused) | 1205 | struct perf_session *session) |
1063 | { | 1206 | { |
1064 | struct list_head *head = &dsos__user; | 1207 | __event_process_build_id(&self->build_id, |
1065 | struct dso *dso; | 1208 | self->build_id.filename, |
1066 | 1209 | session); | |
1067 | if (self->build_id.header.misc & PERF_RECORD_MISC_KERNEL) | ||
1068 | head = &dsos__kernel; | ||
1069 | |||
1070 | dso = __dsos__findnew(head, self->build_id.filename); | ||
1071 | if (dso != NULL) { | ||
1072 | dso__set_build_id(dso, &self->build_id.build_id); | ||
1073 | if (head == &dsos__kernel && self->build_id.filename[0] == '[') | ||
1074 | dso->kernel = 1; | ||
1075 | } | ||
1076 | |||
1077 | return 0; | 1210 | return 0; |
1078 | } | 1211 | } |