Commit dc1d628a67a8f042e711ea5accc0beedc3ef0092
Committed by
Ingo Molnar
1 parent
548b841669
Exists in
master
and in
7 other branches
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
arch/x86/kernel/cpu/perf_event.c
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, |
kernel/perf_event.c
... | ... | @@ -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); |