aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf/util/header.c
diff options
context:
space:
mode:
authorZhang, Yanmin <yanmin_zhang@linux.intel.com>2010-04-19 01:32:50 -0400
committerAvi Kivity <avi@redhat.com>2010-04-19 05:37:24 -0400
commita1645ce12adb6c9cc9e19d7695466204e3f017fe (patch)
tree5d31aaaf534997e6e9cebc07f38eca35f76986cf /tools/perf/util/header.c
parentff9d07a0e7ce756a183e7c2e483aec452ee6b574 (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.c213
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
193static int __dsos__write_buildid_table(struct list_head *head, u16 misc, int fd) 193static 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
222static int dsos__write_buildid_table(int fd) 224static 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
345static int dsos__cache_build_ids(void) 367static 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
390static 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
361static int perf_header__adds_write(struct perf_header *self, int fd) 407static 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
682static 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;
725out:
726 return err;
727}
728
729static 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;
757out:
758 return err;
759}
760
636static int perf_file_section__process(struct perf_file_section *self, 761static 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
990int event__synthesize_build_id(struct dso *pos, u16 misc, 1115int 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
1016static int __event_synthesize_build_ids(struct list_head *head, u16 misc, 1143static 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,
1035int event__synthesize_build_ids(event__handler_t process, 1164int 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
1061int event__process_build_id(event_t *self, 1204int 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}