aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf/util/session.c
diff options
context:
space:
mode:
authorIngo Molnar <mingo@kernel.org>2014-12-08 05:50:24 -0500
committerIngo Molnar <mingo@kernel.org>2014-12-08 05:50:24 -0500
commit2a2662bf88e693d477ef08351d03934f7bc0b51c (patch)
treecef243df159cc12ada7e97998a253df7c0abb2a2 /tools/perf/util/session.c
parentb2776bf7149bddd1f4161f14f79520f17fc1d71d (diff)
parent36748b9518a2437beffe861b47dff6d12b736b3f (diff)
Merge branch 'perf/core-v3' of git://git.kernel.org/pub/scm/linux/kernel/git/frederic/linux-dynticks into perf/hw_breakpoints
Pull AMD range breakpoints support from Frederic Weisbecker: " - Extend breakpoint tools and core to support address range through perf event with initial backend support for AMD extended breakpoints. Syntax is: perf record -e mem:addr/len:type For example set write breakpoint from 0x1000 to 0x1200 (0x1000 + 512) perf record -e mem:0x1000/512:w - Clean up a bit breakpoint code validation It has been acked by Jiri and Oleg. " Signed-off-by: Ingo Molnar <mingo@kernel.org>
Diffstat (limited to 'tools/perf/util/session.c')
-rw-r--r--tools/perf/util/session.c185
1 files changed, 177 insertions, 8 deletions
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index 6702ac28754b..6ac62ae6b8fa 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -228,6 +228,15 @@ static int process_finished_round(struct perf_tool *tool,
228 union perf_event *event, 228 union perf_event *event,
229 struct perf_session *session); 229 struct perf_session *session);
230 230
231static int process_id_index_stub(struct perf_tool *tool __maybe_unused,
232 union perf_event *event __maybe_unused,
233 struct perf_session *perf_session
234 __maybe_unused)
235{
236 dump_printf(": unhandled!\n");
237 return 0;
238}
239
231void perf_tool__fill_defaults(struct perf_tool *tool) 240void perf_tool__fill_defaults(struct perf_tool *tool)
232{ 241{
233 if (tool->sample == NULL) 242 if (tool->sample == NULL)
@@ -262,6 +271,8 @@ void perf_tool__fill_defaults(struct perf_tool *tool)
262 else 271 else
263 tool->finished_round = process_finished_round_stub; 272 tool->finished_round = process_finished_round_stub;
264 } 273 }
274 if (tool->id_index == NULL)
275 tool->id_index = process_id_index_stub;
265} 276}
266 277
267static void swap_sample_id_all(union perf_event *event, void *data) 278static void swap_sample_id_all(union perf_event *event, void *data)
@@ -460,6 +471,7 @@ static perf_event__swap_op perf_event__swap_ops[] = {
460 [PERF_RECORD_HEADER_EVENT_TYPE] = perf_event__event_type_swap, 471 [PERF_RECORD_HEADER_EVENT_TYPE] = perf_event__event_type_swap,
461 [PERF_RECORD_HEADER_TRACING_DATA] = perf_event__tracing_data_swap, 472 [PERF_RECORD_HEADER_TRACING_DATA] = perf_event__tracing_data_swap,
462 [PERF_RECORD_HEADER_BUILD_ID] = NULL, 473 [PERF_RECORD_HEADER_BUILD_ID] = NULL,
474 [PERF_RECORD_ID_INDEX] = perf_event__all64_swap,
463 [PERF_RECORD_HEADER_MAX] = NULL, 475 [PERF_RECORD_HEADER_MAX] = NULL,
464}; 476};
465 477
@@ -580,15 +592,46 @@ static void regs_dump__printf(u64 mask, u64 *regs)
580 } 592 }
581} 593}
582 594
595static const char *regs_abi[] = {
596 [PERF_SAMPLE_REGS_ABI_NONE] = "none",
597 [PERF_SAMPLE_REGS_ABI_32] = "32-bit",
598 [PERF_SAMPLE_REGS_ABI_64] = "64-bit",
599};
600
601static inline const char *regs_dump_abi(struct regs_dump *d)
602{
603 if (d->abi > PERF_SAMPLE_REGS_ABI_64)
604 return "unknown";
605
606 return regs_abi[d->abi];
607}
608
609static void regs__printf(const char *type, struct regs_dump *regs)
610{
611 u64 mask = regs->mask;
612
613 printf("... %s regs: mask 0x%" PRIx64 " ABI %s\n",
614 type,
615 mask,
616 regs_dump_abi(regs));
617
618 regs_dump__printf(mask, regs->regs);
619}
620
583static void regs_user__printf(struct perf_sample *sample) 621static void regs_user__printf(struct perf_sample *sample)
584{ 622{
585 struct regs_dump *user_regs = &sample->user_regs; 623 struct regs_dump *user_regs = &sample->user_regs;
586 624
587 if (user_regs->regs) { 625 if (user_regs->regs)
588 u64 mask = user_regs->mask; 626 regs__printf("user", user_regs);
589 printf("... user regs: mask 0x%" PRIx64 "\n", mask); 627}
590 regs_dump__printf(mask, user_regs->regs); 628
591 } 629static void regs_intr__printf(struct perf_sample *sample)
630{
631 struct regs_dump *intr_regs = &sample->intr_regs;
632
633 if (intr_regs->regs)
634 regs__printf("intr", intr_regs);
592} 635}
593 636
594static void stack_user__printf(struct stack_dump *dump) 637static void stack_user__printf(struct stack_dump *dump)
@@ -687,6 +730,9 @@ static void dump_sample(struct perf_evsel *evsel, union perf_event *event,
687 if (sample_type & PERF_SAMPLE_REGS_USER) 730 if (sample_type & PERF_SAMPLE_REGS_USER)
688 regs_user__printf(sample); 731 regs_user__printf(sample);
689 732
733 if (sample_type & PERF_SAMPLE_REGS_INTR)
734 regs_intr__printf(sample);
735
690 if (sample_type & PERF_SAMPLE_STACK_USER) 736 if (sample_type & PERF_SAMPLE_STACK_USER)
691 stack_user__printf(&sample->user_stack); 737 stack_user__printf(&sample->user_stack);
692 738
@@ -888,11 +934,26 @@ static s64 perf_session__process_user_event(struct perf_session *session,
888 return tool->build_id(tool, event, session); 934 return tool->build_id(tool, event, session);
889 case PERF_RECORD_FINISHED_ROUND: 935 case PERF_RECORD_FINISHED_ROUND:
890 return tool->finished_round(tool, event, session); 936 return tool->finished_round(tool, event, session);
937 case PERF_RECORD_ID_INDEX:
938 return tool->id_index(tool, event, session);
891 default: 939 default:
892 return -EINVAL; 940 return -EINVAL;
893 } 941 }
894} 942}
895 943
944int perf_session__deliver_synth_event(struct perf_session *session,
945 union perf_event *event,
946 struct perf_sample *sample,
947 struct perf_tool *tool)
948{
949 events_stats__inc(&session->stats, event->header.type);
950
951 if (event->header.type >= PERF_RECORD_USER_TYPE_START)
952 return perf_session__process_user_event(session, event, tool, 0);
953
954 return perf_session__deliver_event(session, event, sample, tool, 0);
955}
956
896static void event_swap(union perf_event *event, bool sample_id_all) 957static void event_swap(union perf_event *event, bool sample_id_all)
897{ 958{
898 perf_event__swap_op swap; 959 perf_event__swap_op swap;
@@ -1417,9 +1478,9 @@ void perf_evsel__print_ip(struct perf_evsel *evsel, struct perf_sample *sample,
1417 if (symbol_conf.use_callchain && sample->callchain) { 1478 if (symbol_conf.use_callchain && sample->callchain) {
1418 struct addr_location node_al; 1479 struct addr_location node_al;
1419 1480
1420 if (machine__resolve_callchain(al->machine, evsel, al->thread, 1481 if (thread__resolve_callchain(al->thread, evsel,
1421 sample, NULL, NULL, 1482 sample, NULL, NULL,
1422 PERF_MAX_STACK_DEPTH) != 0) { 1483 PERF_MAX_STACK_DEPTH) != 0) {
1423 if (verbose) 1484 if (verbose)
1424 error("Failed to resolve callchain. Skipping\n"); 1485 error("Failed to resolve callchain. Skipping\n");
1425 return; 1486 return;
@@ -1594,3 +1655,111 @@ int __perf_session__set_tracepoints_handlers(struct perf_session *session,
1594out: 1655out:
1595 return err; 1656 return err;
1596} 1657}
1658
1659int perf_event__process_id_index(struct perf_tool *tool __maybe_unused,
1660 union perf_event *event,
1661 struct perf_session *session)
1662{
1663 struct perf_evlist *evlist = session->evlist;
1664 struct id_index_event *ie = &event->id_index;
1665 size_t i, nr, max_nr;
1666
1667 max_nr = (ie->header.size - sizeof(struct id_index_event)) /
1668 sizeof(struct id_index_entry);
1669 nr = ie->nr;
1670 if (nr > max_nr)
1671 return -EINVAL;
1672
1673 if (dump_trace)
1674 fprintf(stdout, " nr: %zu\n", nr);
1675
1676 for (i = 0; i < nr; i++) {
1677 struct id_index_entry *e = &ie->entries[i];
1678 struct perf_sample_id *sid;
1679
1680 if (dump_trace) {
1681 fprintf(stdout, " ... id: %"PRIu64, e->id);
1682 fprintf(stdout, " idx: %"PRIu64, e->idx);
1683 fprintf(stdout, " cpu: %"PRId64, e->cpu);
1684 fprintf(stdout, " tid: %"PRId64"\n", e->tid);
1685 }
1686
1687 sid = perf_evlist__id2sid(evlist, e->id);
1688 if (!sid)
1689 return -ENOENT;
1690 sid->idx = e->idx;
1691 sid->cpu = e->cpu;
1692 sid->tid = e->tid;
1693 }
1694 return 0;
1695}
1696
1697int perf_event__synthesize_id_index(struct perf_tool *tool,
1698 perf_event__handler_t process,
1699 struct perf_evlist *evlist,
1700 struct machine *machine)
1701{
1702 union perf_event *ev;
1703 struct perf_evsel *evsel;
1704 size_t nr = 0, i = 0, sz, max_nr, n;
1705 int err;
1706
1707 pr_debug2("Synthesizing id index\n");
1708
1709 max_nr = (UINT16_MAX - sizeof(struct id_index_event)) /
1710 sizeof(struct id_index_entry);
1711
1712 evlist__for_each(evlist, evsel)
1713 nr += evsel->ids;
1714
1715 n = nr > max_nr ? max_nr : nr;
1716 sz = sizeof(struct id_index_event) + n * sizeof(struct id_index_entry);
1717 ev = zalloc(sz);
1718 if (!ev)
1719 return -ENOMEM;
1720
1721 ev->id_index.header.type = PERF_RECORD_ID_INDEX;
1722 ev->id_index.header.size = sz;
1723 ev->id_index.nr = n;
1724
1725 evlist__for_each(evlist, evsel) {
1726 u32 j;
1727
1728 for (j = 0; j < evsel->ids; j++) {
1729 struct id_index_entry *e;
1730 struct perf_sample_id *sid;
1731
1732 if (i >= n) {
1733 err = process(tool, ev, NULL, machine);
1734 if (err)
1735 goto out_err;
1736 nr -= n;
1737 i = 0;
1738 }
1739
1740 e = &ev->id_index.entries[i++];
1741
1742 e->id = evsel->id[j];
1743
1744 sid = perf_evlist__id2sid(evlist, e->id);
1745 if (!sid) {
1746 free(ev);
1747 return -ENOENT;
1748 }
1749
1750 e->idx = sid->idx;
1751 e->cpu = sid->cpu;
1752 e->tid = sid->tid;
1753 }
1754 }
1755
1756 sz = sizeof(struct id_index_event) + nr * sizeof(struct id_index_entry);
1757 ev->id_index.header.size = sz;
1758 ev->id_index.nr = nr;
1759
1760 err = process(tool, ev, NULL, machine);
1761out_err:
1762 free(ev);
1763
1764 return err;
1765}