aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/perf_counter.h15
-rw-r--r--kernel/perf_counter.c92
-rw-r--r--tools/perf/builtin-annotate.c24
-rw-r--r--tools/perf/builtin-report.c24
4 files changed, 35 insertions, 120 deletions
diff --git a/include/linux/perf_counter.h b/include/linux/perf_counter.h
index 5e970c7d3fd5..bd15d7a5f5ce 100644
--- a/include/linux/perf_counter.h
+++ b/include/linux/perf_counter.h
@@ -120,8 +120,9 @@ enum perf_counter_sample_format {
120 PERF_SAMPLE_ID = 1U << 6, 120 PERF_SAMPLE_ID = 1U << 6,
121 PERF_SAMPLE_CPU = 1U << 7, 121 PERF_SAMPLE_CPU = 1U << 7,
122 PERF_SAMPLE_PERIOD = 1U << 8, 122 PERF_SAMPLE_PERIOD = 1U << 8,
123 PERF_SAMPLE_STREAM_ID = 1U << 9,
123 124
124 PERF_SAMPLE_MAX = 1U << 9, /* non-ABI */ 125 PERF_SAMPLE_MAX = 1U << 10, /* non-ABI */
125}; 126};
126 127
127/* 128/*
@@ -312,16 +313,7 @@ enum perf_event_type {
312 * struct perf_event_header header; 313 * struct perf_event_header header;
313 * u64 time; 314 * u64 time;
314 * u64 id; 315 * u64 id;
315 * u64 sample_period; 316 * u64 stream_id;
316 * };
317 */
318 PERF_EVENT_PERIOD = 4,
319
320 /*
321 * struct {
322 * struct perf_event_header header;
323 * u64 time;
324 * u64 id;
325 * }; 317 * };
326 */ 318 */
327 PERF_EVENT_THROTTLE = 5, 319 PERF_EVENT_THROTTLE = 5,
@@ -356,6 +348,7 @@ enum perf_event_type {
356 * { u64 time; } && PERF_SAMPLE_TIME 348 * { u64 time; } && PERF_SAMPLE_TIME
357 * { u64 addr; } && PERF_SAMPLE_ADDR 349 * { u64 addr; } && PERF_SAMPLE_ADDR
358 * { u64 id; } && PERF_SAMPLE_ID 350 * { u64 id; } && PERF_SAMPLE_ID
351 * { u64 stream_id;} && PERF_SAMPLE_STREAM_ID
359 * { u32 cpu, res; } && PERF_SAMPLE_CPU 352 * { u32 cpu, res; } && PERF_SAMPLE_CPU
360 * { u64 period; } && PERF_SAMPLE_PERIOD 353 * { u64 period; } && PERF_SAMPLE_PERIOD
361 * 354 *
diff --git a/kernel/perf_counter.c b/kernel/perf_counter.c
index e1d6a3aa1333..7530588fa5c5 100644
--- a/kernel/perf_counter.c
+++ b/kernel/perf_counter.c
@@ -155,6 +155,20 @@ static void unclone_ctx(struct perf_counter_context *ctx)
155} 155}
156 156
157/* 157/*
158 * If we inherit counters we want to return the parent counter id
159 * to userspace.
160 */
161static u64 primary_counter_id(struct perf_counter *counter)
162{
163 u64 id = counter->id;
164
165 if (counter->parent)
166 id = counter->parent->id;
167
168 return id;
169}
170
171/*
158 * Get the perf_counter_context for a task and lock it. 172 * Get the perf_counter_context for a task and lock it.
159 * This has to cope with with the fact that until it is locked, 173 * This has to cope with with the fact that until it is locked,
160 * the context could get moved to another task. 174 * the context could get moved to another task.
@@ -1296,7 +1310,6 @@ static void perf_counter_cpu_sched_in(struct perf_cpu_context *cpuctx, int cpu)
1296#define MAX_INTERRUPTS (~0ULL) 1310#define MAX_INTERRUPTS (~0ULL)
1297 1311
1298static void perf_log_throttle(struct perf_counter *counter, int enable); 1312static void perf_log_throttle(struct perf_counter *counter, int enable);
1299static void perf_log_period(struct perf_counter *counter, u64 period);
1300 1313
1301static void perf_adjust_period(struct perf_counter *counter, u64 events) 1314static void perf_adjust_period(struct perf_counter *counter, u64 events)
1302{ 1315{
@@ -1315,8 +1328,6 @@ static void perf_adjust_period(struct perf_counter *counter, u64 events)
1315 if (!sample_period) 1328 if (!sample_period)
1316 sample_period = 1; 1329 sample_period = 1;
1317 1330
1318 perf_log_period(counter, sample_period);
1319
1320 hwc->sample_period = sample_period; 1331 hwc->sample_period = sample_period;
1321} 1332}
1322 1333
@@ -1705,7 +1716,7 @@ perf_read_hw(struct perf_counter *counter, char __user *buf, size_t count)
1705 values[n++] = counter->total_time_running + 1716 values[n++] = counter->total_time_running +
1706 atomic64_read(&counter->child_total_time_running); 1717 atomic64_read(&counter->child_total_time_running);
1707 if (counter->attr.read_format & PERF_FORMAT_ID) 1718 if (counter->attr.read_format & PERF_FORMAT_ID)
1708 values[n++] = counter->id; 1719 values[n++] = primary_counter_id(counter);
1709 mutex_unlock(&counter->child_mutex); 1720 mutex_unlock(&counter->child_mutex);
1710 1721
1711 if (count < n * sizeof(u64)) 1722 if (count < n * sizeof(u64))
@@ -1812,8 +1823,6 @@ static int perf_counter_period(struct perf_counter *counter, u64 __user *arg)
1812 1823
1813 counter->attr.sample_freq = value; 1824 counter->attr.sample_freq = value;
1814 } else { 1825 } else {
1815 perf_log_period(counter, value);
1816
1817 counter->attr.sample_period = value; 1826 counter->attr.sample_period = value;
1818 counter->hw.sample_period = value; 1827 counter->hw.sample_period = value;
1819 } 1828 }
@@ -2662,6 +2671,9 @@ static void perf_counter_output(struct perf_counter *counter, int nmi,
2662 if (sample_type & PERF_SAMPLE_ID) 2671 if (sample_type & PERF_SAMPLE_ID)
2663 header.size += sizeof(u64); 2672 header.size += sizeof(u64);
2664 2673
2674 if (sample_type & PERF_SAMPLE_STREAM_ID)
2675 header.size += sizeof(u64);
2676
2665 if (sample_type & PERF_SAMPLE_CPU) { 2677 if (sample_type & PERF_SAMPLE_CPU) {
2666 header.size += sizeof(cpu_entry); 2678 header.size += sizeof(cpu_entry);
2667 2679
@@ -2705,7 +2717,13 @@ static void perf_counter_output(struct perf_counter *counter, int nmi,
2705 if (sample_type & PERF_SAMPLE_ADDR) 2717 if (sample_type & PERF_SAMPLE_ADDR)
2706 perf_output_put(&handle, data->addr); 2718 perf_output_put(&handle, data->addr);
2707 2719
2708 if (sample_type & PERF_SAMPLE_ID) 2720 if (sample_type & PERF_SAMPLE_ID) {
2721 u64 id = primary_counter_id(counter);
2722
2723 perf_output_put(&handle, id);
2724 }
2725
2726 if (sample_type & PERF_SAMPLE_STREAM_ID)
2709 perf_output_put(&handle, counter->id); 2727 perf_output_put(&handle, counter->id);
2710 2728
2711 if (sample_type & PERF_SAMPLE_CPU) 2729 if (sample_type & PERF_SAMPLE_CPU)
@@ -2728,7 +2746,7 @@ static void perf_counter_output(struct perf_counter *counter, int nmi,
2728 if (sub != counter) 2746 if (sub != counter)
2729 sub->pmu->read(sub); 2747 sub->pmu->read(sub);
2730 2748
2731 group_entry.id = sub->id; 2749 group_entry.id = primary_counter_id(sub);
2732 group_entry.counter = atomic64_read(&sub->count); 2750 group_entry.counter = atomic64_read(&sub->count);
2733 2751
2734 perf_output_put(&handle, group_entry); 2752 perf_output_put(&handle, group_entry);
@@ -2788,15 +2806,8 @@ perf_counter_read_event(struct perf_counter *counter,
2788 } 2806 }
2789 2807
2790 if (counter->attr.read_format & PERF_FORMAT_ID) { 2808 if (counter->attr.read_format & PERF_FORMAT_ID) {
2791 u64 id;
2792
2793 event.header.size += sizeof(u64); 2809 event.header.size += sizeof(u64);
2794 if (counter->parent) 2810 event.format[i++] = primary_counter_id(counter);
2795 id = counter->parent->id;
2796 else
2797 id = counter->id;
2798
2799 event.format[i++] = id;
2800 } 2811 }
2801 2812
2802 ret = perf_output_begin(&handle, counter, event.header.size, 0, 0); 2813 ret = perf_output_begin(&handle, counter, event.header.size, 0, 0);
@@ -3191,49 +3202,6 @@ void __perf_counter_mmap(struct vm_area_struct *vma)
3191} 3202}
3192 3203
3193/* 3204/*
3194 * Log sample_period changes so that analyzing tools can re-normalize the
3195 * event flow.
3196 */
3197
3198struct freq_event {
3199 struct perf_event_header header;
3200 u64 time;
3201 u64 id;
3202 u64 period;
3203};
3204
3205static void perf_log_period(struct perf_counter *counter, u64 period)
3206{
3207 struct perf_output_handle handle;
3208 struct freq_event event;
3209 int ret;
3210
3211 if (counter->hw.sample_period == period)
3212 return;
3213
3214 if (counter->attr.sample_type & PERF_SAMPLE_PERIOD)
3215 return;
3216
3217 event = (struct freq_event) {
3218 .header = {
3219 .type = PERF_EVENT_PERIOD,
3220 .misc = 0,
3221 .size = sizeof(event),
3222 },
3223 .time = sched_clock(),
3224 .id = counter->id,
3225 .period = period,
3226 };
3227
3228 ret = perf_output_begin(&handle, counter, sizeof(event), 1, 0);
3229 if (ret)
3230 return;
3231
3232 perf_output_put(&handle, event);
3233 perf_output_end(&handle);
3234}
3235
3236/*
3237 * IRQ throttle logging 3205 * IRQ throttle logging
3238 */ 3206 */
3239 3207
@@ -3246,14 +3214,16 @@ static void perf_log_throttle(struct perf_counter *counter, int enable)
3246 struct perf_event_header header; 3214 struct perf_event_header header;
3247 u64 time; 3215 u64 time;
3248 u64 id; 3216 u64 id;
3217 u64 stream_id;
3249 } throttle_event = { 3218 } throttle_event = {
3250 .header = { 3219 .header = {
3251 .type = PERF_EVENT_THROTTLE + 1, 3220 .type = PERF_EVENT_THROTTLE + 1,
3252 .misc = 0, 3221 .misc = 0,
3253 .size = sizeof(throttle_event), 3222 .size = sizeof(throttle_event),
3254 }, 3223 },
3255 .time = sched_clock(), 3224 .time = sched_clock(),
3256 .id = counter->id, 3225 .id = primary_counter_id(counter),
3226 .stream_id = counter->id,
3257 }; 3227 };
3258 3228
3259 ret = perf_output_begin(&handle, counter, sizeof(throttle_event), 1, 0); 3229 ret = perf_output_begin(&handle, counter, sizeof(throttle_event), 1, 0);
diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c
index 5f9eefecc574..1dba568e1941 100644
--- a/tools/perf/builtin-annotate.c
+++ b/tools/perf/builtin-annotate.c
@@ -74,20 +74,12 @@ struct fork_event {
74 u32 pid, ppid; 74 u32 pid, ppid;
75}; 75};
76 76
77struct period_event {
78 struct perf_event_header header;
79 u64 time;
80 u64 id;
81 u64 sample_period;
82};
83
84typedef union event_union { 77typedef union event_union {
85 struct perf_event_header header; 78 struct perf_event_header header;
86 struct ip_event ip; 79 struct ip_event ip;
87 struct mmap_event mmap; 80 struct mmap_event mmap;
88 struct comm_event comm; 81 struct comm_event comm;
89 struct fork_event fork; 82 struct fork_event fork;
90 struct period_event period;
91} event_t; 83} event_t;
92 84
93 85
@@ -998,19 +990,6 @@ process_fork_event(event_t *event, unsigned long offset, unsigned long head)
998} 990}
999 991
1000static int 992static int
1001process_period_event(event_t *event, unsigned long offset, unsigned long head)
1002{
1003 dprintf("%p [%p]: PERF_EVENT_PERIOD: time:%Ld, id:%Ld: period:%Ld\n",
1004 (void *)(offset + head),
1005 (void *)(long)(event->header.size),
1006 event->period.time,
1007 event->period.id,
1008 event->period.sample_period);
1009
1010 return 0;
1011}
1012
1013static int
1014process_event(event_t *event, unsigned long offset, unsigned long head) 993process_event(event_t *event, unsigned long offset, unsigned long head)
1015{ 994{
1016 switch (event->header.type) { 995 switch (event->header.type) {
@@ -1025,9 +1004,6 @@ process_event(event_t *event, unsigned long offset, unsigned long head)
1025 1004
1026 case PERF_EVENT_FORK: 1005 case PERF_EVENT_FORK:
1027 return process_fork_event(event, offset, head); 1006 return process_fork_event(event, offset, head);
1028
1029 case PERF_EVENT_PERIOD:
1030 return process_period_event(event, offset, head);
1031 /* 1007 /*
1032 * We dont process them right now but they are fine: 1008 * We dont process them right now but they are fine:
1033 */ 1009 */
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index a118bc77286d..b20a4b6e31b7 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -101,13 +101,6 @@ struct fork_event {
101 u32 pid, ppid; 101 u32 pid, ppid;
102}; 102};
103 103
104struct period_event {
105 struct perf_event_header header;
106 u64 time;
107 u64 id;
108 u64 sample_period;
109};
110
111struct lost_event { 104struct lost_event {
112 struct perf_event_header header; 105 struct perf_event_header header;
113 u64 id; 106 u64 id;
@@ -127,7 +120,6 @@ typedef union event_union {
127 struct mmap_event mmap; 120 struct mmap_event mmap;
128 struct comm_event comm; 121 struct comm_event comm;
129 struct fork_event fork; 122 struct fork_event fork;
130 struct period_event period;
131 struct lost_event lost; 123 struct lost_event lost;
132 struct read_event read; 124 struct read_event read;
133} event_t; 125} event_t;
@@ -1636,19 +1628,6 @@ process_fork_event(event_t *event, unsigned long offset, unsigned long head)
1636} 1628}
1637 1629
1638static int 1630static int
1639process_period_event(event_t *event, unsigned long offset, unsigned long head)
1640{
1641 dprintf("%p [%p]: PERF_EVENT_PERIOD: time:%Ld, id:%Ld: period:%Ld\n",
1642 (void *)(offset + head),
1643 (void *)(long)(event->header.size),
1644 event->period.time,
1645 event->period.id,
1646 event->period.sample_period);
1647
1648 return 0;
1649}
1650
1651static int
1652process_lost_event(event_t *event, unsigned long offset, unsigned long head) 1631process_lost_event(event_t *event, unsigned long offset, unsigned long head)
1653{ 1632{
1654 dprintf("%p [%p]: PERF_EVENT_LOST: id:%Ld: lost:%Ld\n", 1633 dprintf("%p [%p]: PERF_EVENT_LOST: id:%Ld: lost:%Ld\n",
@@ -1729,9 +1708,6 @@ process_event(event_t *event, unsigned long offset, unsigned long head)
1729 case PERF_EVENT_FORK: 1708 case PERF_EVENT_FORK:
1730 return process_fork_event(event, offset, head); 1709 return process_fork_event(event, offset, head);
1731 1710
1732 case PERF_EVENT_PERIOD:
1733 return process_period_event(event, offset, head);
1734
1735 case PERF_EVENT_LOST: 1711 case PERF_EVENT_LOST:
1736 return process_lost_event(event, offset, head); 1712 return process_lost_event(event, offset, head);
1737 1713