Commit dc1d628a67a8f042e711ea5accc0beedc3ef0092

Authored by Peter Zijlstra
Committed by Ingo Molnar
1 parent 548b841669

perf: Provide generic perf_sample_data initialization

This makes it easier to extend perf_sample_data and fixes a bug on arm
and sparc, which failed to set ->raw to NULL, which can cause crashes
when combined with PERF_SAMPLE_RAW.

It also optimizes PowerPC and tracepoint, because the struct
initialization is forced to zero out the whole structure.

Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl>
Acked-by: Jean Pihet <jpihet@mvista.com>
Reviewed-by: Frederic Weisbecker <fweisbec@gmail.com>
Acked-by: David S. Miller <davem@davemloft.net>
Cc: Jamie Iles <jamie.iles@picochip.com>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Stephane Eranian <eranian@google.com>
Cc: stable@kernel.org
LKML-Reference: <20100304140100.315416040@chello.nl>
Signed-off-by: Ingo Molnar <mingo@elte.hu>

Showing 7 changed files with 25 additions and 26 deletions Side-by-side Diff

arch/arm/kernel/perf_event.c
... ... @@ -965,7 +965,7 @@
965 965 */
966 966 armv6_pmcr_write(pmcr);
967 967  
968   - data.addr = 0;
  968 + perf_sample_data_init(&data, 0);
969 969  
970 970 cpuc = &__get_cpu_var(cpu_hw_events);
971 971 for (idx = 0; idx <= armpmu->num_events; ++idx) {
... ... @@ -1945,7 +1945,7 @@
1945 1945 */
1946 1946 regs = get_irq_regs();
1947 1947  
1948   - data.addr = 0;
  1948 + perf_sample_data_init(&data, 0);
1949 1949  
1950 1950 cpuc = &__get_cpu_var(cpu_hw_events);
1951 1951 for (idx = 0; idx <= armpmu->num_events; ++idx) {
arch/powerpc/kernel/perf_event.c
... ... @@ -1164,10 +1164,10 @@
1164 1164 * Finally record data if requested.
1165 1165 */
1166 1166 if (record) {
1167   - struct perf_sample_data data = {
1168   - .addr = ~0ULL,
1169   - .period = event->hw.last_period,
1170   - };
  1167 + struct perf_sample_data data;
  1168 +
  1169 + perf_sample_data_init(&data, ~0ULL);
  1170 + data.period = event->hw.last_period;
1171 1171  
1172 1172 if (event->attr.sample_type & PERF_SAMPLE_ADDR)
1173 1173 perf_get_data_addr(regs, &data.addr);
arch/sparc/kernel/perf_event.c
... ... @@ -1189,7 +1189,7 @@
1189 1189  
1190 1190 regs = args->regs;
1191 1191  
1192   - data.addr = 0;
  1192 + perf_sample_data_init(&data, 0);
1193 1193  
1194 1194 cpuc = &__get_cpu_var(cpu_hw_events);
1195 1195  
arch/x86/kernel/cpu/perf_event.c
... ... @@ -1097,8 +1097,7 @@
1097 1097 int idx, handled = 0;
1098 1098 u64 val;
1099 1099  
1100   - data.addr = 0;
1101   - data.raw = NULL;
  1100 + perf_sample_data_init(&data, 0);
1102 1101  
1103 1102 cpuc = &__get_cpu_var(cpu_hw_events);
1104 1103  
arch/x86/kernel/cpu/perf_event_intel.c
... ... @@ -590,10 +590,9 @@
590 590  
591 591 ds->bts_index = ds->bts_buffer_base;
592 592  
  593 + perf_sample_data_init(&data, 0);
593 594  
594 595 data.period = event->hw.last_period;
595   - data.addr = 0;
596   - data.raw = NULL;
597 596 regs.ip = 0;
598 597  
599 598 /*
... ... @@ -742,8 +741,7 @@
742 741 int bit, loops;
743 742 u64 ack, status;
744 743  
745   - data.addr = 0;
746   - data.raw = NULL;
  744 + perf_sample_data_init(&data, 0);
747 745  
748 746 cpuc = &__get_cpu_var(cpu_hw_events);
749 747  
include/linux/perf_event.h
... ... @@ -801,6 +801,13 @@
801 801 struct perf_raw_record *raw;
802 802 };
803 803  
  804 +static inline
  805 +void perf_sample_data_init(struct perf_sample_data *data, u64 addr)
  806 +{
  807 + data->addr = addr;
  808 + data->raw = NULL;
  809 +}
  810 +
804 811 extern void perf_output_sample(struct perf_output_handle *handle,
805 812 struct perf_event_header *header,
806 813 struct perf_sample_data *data,
... ... @@ -4108,8 +4108,7 @@
4108 4108 if (rctx < 0)
4109 4109 return;
4110 4110  
4111   - data.addr = addr;
4112   - data.raw = NULL;
  4111 + perf_sample_data_init(&data, addr);
4113 4112  
4114 4113 do_perf_sw_event(PERF_TYPE_SOFTWARE, event_id, nr, nmi, &data, regs);
4115 4114  
4116 4115  
... ... @@ -4154,11 +4153,10 @@
4154 4153 struct perf_event *event;
4155 4154 u64 period;
4156 4155  
4157   - event = container_of(hrtimer, struct perf_event, hw.hrtimer);
  4156 + event = container_of(hrtimer, struct perf_event, hw.hrtimer);
4158 4157 event->pmu->read(event);
4159 4158  
4160   - data.addr = 0;
4161   - data.raw = NULL;
  4159 + perf_sample_data_init(&data, 0);
4162 4160 data.period = event->hw.last_period;
4163 4161 regs = get_irq_regs();
4164 4162 /*
4165 4163  
4166 4164  
... ... @@ -4322,18 +4320,16 @@
4322 4320 void perf_tp_event(int event_id, u64 addr, u64 count, void *record,
4323 4321 int entry_size)
4324 4322 {
  4323 + struct pt_regs *regs = get_irq_regs();
  4324 + struct perf_sample_data data;
4325 4325 struct perf_raw_record raw = {
4326 4326 .size = entry_size,
4327 4327 .data = record,
4328 4328 };
4329 4329  
4330   - struct perf_sample_data data = {
4331   - .addr = addr,
4332   - .raw = &raw,
4333   - };
  4330 + perf_sample_data_init(&data, addr);
  4331 + data.raw = &raw;
4334 4332  
4335   - struct pt_regs *regs = get_irq_regs();
4336   -
4337 4333 if (!regs)
4338 4334 regs = task_pt_regs(current);
4339 4335  
... ... @@ -4448,8 +4444,7 @@
4448 4444 struct perf_sample_data sample;
4449 4445 struct pt_regs *regs = data;
4450 4446  
4451   - sample.raw = NULL;
4452   - sample.addr = bp->attr.bp_addr;
  4447 + perf_sample_data_init(&sample, bp->attr.bp_addr);
4453 4448  
4454 4449 if (!perf_exclude_event(bp, regs))
4455 4450 perf_swevent_add(bp, 1, 1, &sample, regs);