aboutsummaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
authorStephane Eranian <eranian@google.com>2014-09-24 07:48:39 -0400
committerIngo Molnar <mingo@kernel.org>2014-11-16 05:41:59 -0500
commit6a21c0b5c2abd2fdfa6fff79f11df3d6082c1873 (patch)
treeff097bc4f3a2a3d6b400b82853852cb49dc2036a /tools
parentaea48559ac454a065244d3eff0c94cc8af9c553e (diff)
perf tools: Add core support for sampling intr machine state regs
Add the infrastructure to setup, collect and report the interrupt machine state regs which can be captured by the kernel. Signed-off-by: Stephane Eranian <eranian@google.com> Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org> Cc: cebbert.lkml@gmail.com Cc: Adrian Hunter <adrian.hunter@intel.com> Cc: Andi Kleen <ak@linux.intel.com> Cc: Arnaldo Carvalho de Melo <acme@kernel.org> Cc: David Ahern <dsahern@gmail.com> Cc: Don Zickus <dzickus@redhat.com> Cc: Jean Pihet <jean.pihet@linaro.org> Cc: Jiri Olsa <jolsa@kernel.org> Cc: Jiri Olsa <jolsa@redhat.com> Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Namhyung Kim <namhyung@kernel.org> Cc: Paul Mackerras <paulus@samba.org> Cc: Stephane Eranian <eranian@google.com> Cc: Waiman Long <Waiman.Long@hp.com> Cc: Wang Nan <wangnan0@huawei.com> Link: http://lkml.kernel.org/r/1411559322-16548-4-git-send-email-eranian@google.com Signed-off-by: Ingo Molnar <mingo@kernel.org>
Diffstat (limited to 'tools')
-rw-r--r--tools/perf/perf.h1
-rw-r--r--tools/perf/util/event.h1
-rw-r--r--tools/perf/util/evsel.c46
-rw-r--r--tools/perf/util/header.c1
-rw-r--r--tools/perf/util/session.c44
5 files changed, 87 insertions, 6 deletions
diff --git a/tools/perf/perf.h b/tools/perf/perf.h
index 511c2831aa81..1dabb8553499 100644
--- a/tools/perf/perf.h
+++ b/tools/perf/perf.h
@@ -52,6 +52,7 @@ struct record_opts {
52 bool sample_weight; 52 bool sample_weight;
53 bool sample_time; 53 bool sample_time;
54 bool period; 54 bool period;
55 bool sample_intr_regs;
55 unsigned int freq; 56 unsigned int freq;
56 unsigned int mmap_pages; 57 unsigned int mmap_pages;
57 unsigned int user_freq; 58 unsigned int user_freq;
diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h
index 7be389735402..09b9e8d3fcf7 100644
--- a/tools/perf/util/event.h
+++ b/tools/perf/util/event.h
@@ -188,6 +188,7 @@ struct perf_sample {
188 struct ip_callchain *callchain; 188 struct ip_callchain *callchain;
189 struct branch_stack *branch_stack; 189 struct branch_stack *branch_stack;
190 struct regs_dump user_regs; 190 struct regs_dump user_regs;
191 struct regs_dump intr_regs;
191 struct stack_dump user_stack; 192 struct stack_dump user_stack;
192 struct sample_read read; 193 struct sample_read read;
193}; 194};
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index 12b4396c7175..34344ffa79ca 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -661,6 +661,11 @@ void perf_evsel__config(struct perf_evsel *evsel, struct record_opts *opts)
661 if (callchain_param.enabled && !evsel->no_aux_samples) 661 if (callchain_param.enabled && !evsel->no_aux_samples)
662 perf_evsel__config_callgraph(evsel); 662 perf_evsel__config_callgraph(evsel);
663 663
664 if (opts->sample_intr_regs) {
665 attr->sample_regs_intr = PERF_REGS_MASK;
666 perf_evsel__set_sample_bit(evsel, REGS_INTR);
667 }
668
664 if (target__has_cpu(&opts->target)) 669 if (target__has_cpu(&opts->target))
665 perf_evsel__set_sample_bit(evsel, CPU); 670 perf_evsel__set_sample_bit(evsel, CPU);
666 671
@@ -1037,6 +1042,7 @@ static size_t perf_event_attr__fprintf(struct perf_event_attr *attr, FILE *fp)
1037 ret += PRINT_ATTR_X64(branch_sample_type); 1042 ret += PRINT_ATTR_X64(branch_sample_type);
1038 ret += PRINT_ATTR_X64(sample_regs_user); 1043 ret += PRINT_ATTR_X64(sample_regs_user);
1039 ret += PRINT_ATTR_U32(sample_stack_user); 1044 ret += PRINT_ATTR_U32(sample_stack_user);
1045 ret += PRINT_ATTR_X64(sample_regs_intr);
1040 1046
1041 ret += fprintf(fp, "%.60s\n", graph_dotted_line); 1047 ret += fprintf(fp, "%.60s\n", graph_dotted_line);
1042 1048
@@ -1536,6 +1542,23 @@ int perf_evsel__parse_sample(struct perf_evsel *evsel, union perf_event *event,
1536 array++; 1542 array++;
1537 } 1543 }
1538 1544
1545 data->intr_regs.abi = PERF_SAMPLE_REGS_ABI_NONE;
1546 if (type & PERF_SAMPLE_REGS_INTR) {
1547 OVERFLOW_CHECK_u64(array);
1548 data->intr_regs.abi = *array;
1549 array++;
1550
1551 if (data->intr_regs.abi != PERF_SAMPLE_REGS_ABI_NONE) {
1552 u64 mask = evsel->attr.sample_regs_intr;
1553
1554 sz = hweight_long(mask) * sizeof(u64);
1555 OVERFLOW_CHECK(array, sz, max_size);
1556 data->intr_regs.mask = mask;
1557 data->intr_regs.regs = (u64 *)array;
1558 array = (void *)array + sz;
1559 }
1560 }
1561
1539 return 0; 1562 return 0;
1540} 1563}
1541 1564
@@ -1631,6 +1654,16 @@ size_t perf_event__sample_event_size(const struct perf_sample *sample, u64 type,
1631 if (type & PERF_SAMPLE_TRANSACTION) 1654 if (type & PERF_SAMPLE_TRANSACTION)
1632 result += sizeof(u64); 1655 result += sizeof(u64);
1633 1656
1657 if (type & PERF_SAMPLE_REGS_INTR) {
1658 if (sample->intr_regs.abi) {
1659 result += sizeof(u64);
1660 sz = hweight_long(sample->intr_regs.mask) * sizeof(u64);
1661 result += sz;
1662 } else {
1663 result += sizeof(u64);
1664 }
1665 }
1666
1634 return result; 1667 return result;
1635} 1668}
1636 1669
@@ -1809,6 +1842,17 @@ int perf_event__synthesize_sample(union perf_event *event, u64 type,
1809 array++; 1842 array++;
1810 } 1843 }
1811 1844
1845 if (type & PERF_SAMPLE_REGS_INTR) {
1846 if (sample->intr_regs.abi) {
1847 *array++ = sample->intr_regs.abi;
1848 sz = hweight_long(sample->intr_regs.mask) * sizeof(u64);
1849 memcpy(array, sample->intr_regs.regs, sz);
1850 array = (void *)array + sz;
1851 } else {
1852 *array++ = 0;
1853 }
1854 }
1855
1812 return 0; 1856 return 0;
1813} 1857}
1814 1858
@@ -1938,7 +1982,7 @@ static int sample_type__fprintf(FILE *fp, bool *first, u64 value)
1938 bit_name(READ), bit_name(CALLCHAIN), bit_name(ID), bit_name(CPU), 1982 bit_name(READ), bit_name(CALLCHAIN), bit_name(ID), bit_name(CPU),
1939 bit_name(PERIOD), bit_name(STREAM_ID), bit_name(RAW), 1983 bit_name(PERIOD), bit_name(STREAM_ID), bit_name(RAW),
1940 bit_name(BRANCH_STACK), bit_name(REGS_USER), bit_name(STACK_USER), 1984 bit_name(BRANCH_STACK), bit_name(REGS_USER), bit_name(STACK_USER),
1941 bit_name(IDENTIFIER), 1985 bit_name(IDENTIFIER), bit_name(REGS_INTR),
1942 { .name = NULL, } 1986 { .name = NULL, }
1943 }; 1987 };
1944#undef bit_name 1988#undef bit_name
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index 76442caca37e..05fab7a188dc 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -2143,6 +2143,7 @@ static const int attr_file_abi_sizes[] = {
2143 [1] = PERF_ATTR_SIZE_VER1, 2143 [1] = PERF_ATTR_SIZE_VER1,
2144 [2] = PERF_ATTR_SIZE_VER2, 2144 [2] = PERF_ATTR_SIZE_VER2,
2145 [3] = PERF_ATTR_SIZE_VER3, 2145 [3] = PERF_ATTR_SIZE_VER3,
2146 [4] = PERF_ATTR_SIZE_VER4,
2146 0, 2147 0,
2147}; 2148};
2148 2149
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index f4478ce72fdb..6ac62ae6b8fa 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -592,15 +592,46 @@ static void regs_dump__printf(u64 mask, u64 *regs)
592 } 592 }
593} 593}
594 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
595static void regs_user__printf(struct perf_sample *sample) 621static void regs_user__printf(struct perf_sample *sample)
596{ 622{
597 struct regs_dump *user_regs = &sample->user_regs; 623 struct regs_dump *user_regs = &sample->user_regs;
598 624
599 if (user_regs->regs) { 625 if (user_regs->regs)
600 u64 mask = user_regs->mask; 626 regs__printf("user", user_regs);
601 printf("... user regs: mask 0x%" PRIx64 "\n", mask); 627}
602 regs_dump__printf(mask, user_regs->regs); 628
603 } 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);
604} 635}
605 636
606static void stack_user__printf(struct stack_dump *dump) 637static void stack_user__printf(struct stack_dump *dump)
@@ -699,6 +730,9 @@ static void dump_sample(struct perf_evsel *evsel, union perf_event *event,
699 if (sample_type & PERF_SAMPLE_REGS_USER) 730 if (sample_type & PERF_SAMPLE_REGS_USER)
700 regs_user__printf(sample); 731 regs_user__printf(sample);
701 732
733 if (sample_type & PERF_SAMPLE_REGS_INTR)
734 regs_intr__printf(sample);
735
702 if (sample_type & PERF_SAMPLE_STACK_USER) 736 if (sample_type & PERF_SAMPLE_STACK_USER)
703 stack_user__printf(&sample->user_stack); 737 stack_user__printf(&sample->user_stack);
704 738