aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPeter Zijlstra <a.p.zijlstra@chello.nl>2010-03-03 09:55:04 -0500
committerIngo Molnar <mingo@elte.hu>2010-03-10 07:22:23 -0500
commitdc1d628a67a8f042e711ea5accc0beedc3ef0092 (patch)
tree728f72a5f9a8368b225890a95ea947c1c8cda301
parent548b84166917d6f5e2296123b85ad24aecd3801d (diff)
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>
-rw-r--r--arch/arm/kernel/perf_event.c4
-rw-r--r--arch/powerpc/kernel/perf_event.c8
-rw-r--r--arch/sparc/kernel/perf_event.c2
-rw-r--r--arch/x86/kernel/cpu/perf_event.c3
-rw-r--r--arch/x86/kernel/cpu/perf_event_intel.c6
-rw-r--r--include/linux/perf_event.h7
-rw-r--r--kernel/perf_event.c21
7 files changed, 25 insertions, 26 deletions
diff --git a/arch/arm/kernel/perf_event.c b/arch/arm/kernel/perf_event.c
index c54ceb3d1f97..3875d99cc40f 100644
--- a/arch/arm/kernel/perf_event.c
+++ b/arch/arm/kernel/perf_event.c
@@ -965,7 +965,7 @@ armv6pmu_handle_irq(int irq_num,
965 */ 965 */
966 armv6_pmcr_write(pmcr); 966 armv6_pmcr_write(pmcr);
967 967
968 data.addr = 0; 968 perf_sample_data_init(&data, 0);
969 969
970 cpuc = &__get_cpu_var(cpu_hw_events); 970 cpuc = &__get_cpu_var(cpu_hw_events);
971 for (idx = 0; idx <= armpmu->num_events; ++idx) { 971 for (idx = 0; idx <= armpmu->num_events; ++idx) {
@@ -1945,7 +1945,7 @@ static irqreturn_t armv7pmu_handle_irq(int irq_num, void *dev)
1945 */ 1945 */
1946 regs = get_irq_regs(); 1946 regs = get_irq_regs();
1947 1947
1948 data.addr = 0; 1948 perf_sample_data_init(&data, 0);
1949 1949
1950 cpuc = &__get_cpu_var(cpu_hw_events); 1950 cpuc = &__get_cpu_var(cpu_hw_events);
1951 for (idx = 0; idx <= armpmu->num_events; ++idx) { 1951 for (idx = 0; idx <= armpmu->num_events; ++idx) {
diff --git a/arch/powerpc/kernel/perf_event.c b/arch/powerpc/kernel/perf_event.c
index b6cf8f1f4d35..5120bd44f69a 100644
--- a/arch/powerpc/kernel/perf_event.c
+++ b/arch/powerpc/kernel/perf_event.c
@@ -1164,10 +1164,10 @@ static void record_and_restart(struct perf_event *event, unsigned long val,
1164 * Finally record data if requested. 1164 * Finally record data if requested.
1165 */ 1165 */
1166 if (record) { 1166 if (record) {
1167 struct perf_sample_data data = { 1167 struct perf_sample_data data;
1168 .addr = ~0ULL, 1168
1169 .period = event->hw.last_period, 1169 perf_sample_data_init(&data, ~0ULL);
1170 }; 1170 data.period = event->hw.last_period;
1171 1171
1172 if (event->attr.sample_type & PERF_SAMPLE_ADDR) 1172 if (event->attr.sample_type & PERF_SAMPLE_ADDR)
1173 perf_get_data_addr(regs, &data.addr); 1173 perf_get_data_addr(regs, &data.addr);
diff --git a/arch/sparc/kernel/perf_event.c b/arch/sparc/kernel/perf_event.c
index 9f2b2bac8b2b..6504208f375f 100644
--- a/arch/sparc/kernel/perf_event.c
+++ b/arch/sparc/kernel/perf_event.c
@@ -1189,7 +1189,7 @@ static int __kprobes perf_event_nmi_handler(struct notifier_block *self,
1189 1189
1190 regs = args->regs; 1190 regs = args->regs;
1191 1191
1192 data.addr = 0; 1192 perf_sample_data_init(&data, 0);
1193 1193
1194 cpuc = &__get_cpu_var(cpu_hw_events); 1194 cpuc = &__get_cpu_var(cpu_hw_events);
1195 1195
diff --git a/arch/x86/kernel/cpu/perf_event.c b/arch/x86/kernel/cpu/perf_event.c
index 97cddbf32936..42aafd11e170 100644
--- a/arch/x86/kernel/cpu/perf_event.c
+++ b/arch/x86/kernel/cpu/perf_event.c
@@ -1097,8 +1097,7 @@ static int x86_pmu_handle_irq(struct pt_regs *regs)
1097 int idx, handled = 0; 1097 int idx, handled = 0;
1098 u64 val; 1098 u64 val;
1099 1099
1100 data.addr = 0; 1100 perf_sample_data_init(&data, 0);
1101 data.raw = NULL;
1102 1101
1103 cpuc = &__get_cpu_var(cpu_hw_events); 1102 cpuc = &__get_cpu_var(cpu_hw_events);
1104 1103
diff --git a/arch/x86/kernel/cpu/perf_event_intel.c b/arch/x86/kernel/cpu/perf_event_intel.c
index 73102df8bfc1..44b60c852107 100644
--- a/arch/x86/kernel/cpu/perf_event_intel.c
+++ b/arch/x86/kernel/cpu/perf_event_intel.c
@@ -590,10 +590,9 @@ static void intel_pmu_drain_bts_buffer(void)
590 590
591 ds->bts_index = ds->bts_buffer_base; 591 ds->bts_index = ds->bts_buffer_base;
592 592
593 perf_sample_data_init(&data, 0);
593 594
594 data.period = event->hw.last_period; 595 data.period = event->hw.last_period;
595 data.addr = 0;
596 data.raw = NULL;
597 regs.ip = 0; 596 regs.ip = 0;
598 597
599 /* 598 /*
@@ -742,8 +741,7 @@ static int intel_pmu_handle_irq(struct pt_regs *regs)
742 int bit, loops; 741 int bit, loops;
743 u64 ack, status; 742 u64 ack, status;
744 743
745 data.addr = 0; 744 perf_sample_data_init(&data, 0);
746 data.raw = NULL;
747 745
748 cpuc = &__get_cpu_var(cpu_hw_events); 746 cpuc = &__get_cpu_var(cpu_hw_events);
749 747
diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h
index 90e0521b1690..6f8cd7da1a01 100644
--- a/include/linux/perf_event.h
+++ b/include/linux/perf_event.h
@@ -801,6 +801,13 @@ struct perf_sample_data {
801 struct perf_raw_record *raw; 801 struct perf_raw_record *raw;
802}; 802};
803 803
804static inline
805void perf_sample_data_init(struct perf_sample_data *data, u64 addr)
806{
807 data->addr = addr;
808 data->raw = NULL;
809}
810
804extern void perf_output_sample(struct perf_output_handle *handle, 811extern void perf_output_sample(struct perf_output_handle *handle,
805 struct perf_event_header *header, 812 struct perf_event_header *header,
806 struct perf_sample_data *data, 813 struct perf_sample_data *data,
diff --git a/kernel/perf_event.c b/kernel/perf_event.c
index e68745053013..4393b9e73740 100644
--- a/kernel/perf_event.c
+++ b/kernel/perf_event.c
@@ -4108,8 +4108,7 @@ void __perf_sw_event(u32 event_id, u64 nr, int nmi,
4108 if (rctx < 0) 4108 if (rctx < 0)
4109 return; 4109 return;
4110 4110
4111 data.addr = addr; 4111 perf_sample_data_init(&data, addr);
4112 data.raw = NULL;
4113 4112
4114 do_perf_sw_event(PERF_TYPE_SOFTWARE, event_id, nr, nmi, &data, regs); 4113 do_perf_sw_event(PERF_TYPE_SOFTWARE, event_id, nr, nmi, &data, regs);
4115 4114
@@ -4154,11 +4153,10 @@ static enum hrtimer_restart perf_swevent_hrtimer(struct hrtimer *hrtimer)
4154 struct perf_event *event; 4153 struct perf_event *event;
4155 u64 period; 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 event->pmu->read(event); 4157 event->pmu->read(event);
4159 4158
4160 data.addr = 0; 4159 perf_sample_data_init(&data, 0);
4161 data.raw = NULL;
4162 data.period = event->hw.last_period; 4160 data.period = event->hw.last_period;
4163 regs = get_irq_regs(); 4161 regs = get_irq_regs();
4164 /* 4162 /*
@@ -4322,17 +4320,15 @@ static const struct pmu perf_ops_task_clock = {
4322void perf_tp_event(int event_id, u64 addr, u64 count, void *record, 4320void perf_tp_event(int event_id, u64 addr, u64 count, void *record,
4323 int entry_size) 4321 int entry_size)
4324{ 4322{
4323 struct pt_regs *regs = get_irq_regs();
4324 struct perf_sample_data data;
4325 struct perf_raw_record raw = { 4325 struct perf_raw_record raw = {
4326 .size = entry_size, 4326 .size = entry_size,
4327 .data = record, 4327 .data = record,
4328 }; 4328 };
4329 4329
4330 struct perf_sample_data data = { 4330 perf_sample_data_init(&data, addr);
4331 .addr = addr, 4331 data.raw = &raw;
4332 .raw = &raw,
4333 };
4334
4335 struct pt_regs *regs = get_irq_regs();
4336 4332
4337 if (!regs) 4333 if (!regs)
4338 regs = task_pt_regs(current); 4334 regs = task_pt_regs(current);
@@ -4448,8 +4444,7 @@ void perf_bp_event(struct perf_event *bp, void *data)
4448 struct perf_sample_data sample; 4444 struct perf_sample_data sample;
4449 struct pt_regs *regs = data; 4445 struct pt_regs *regs = data;
4450 4446
4451 sample.raw = NULL; 4447 perf_sample_data_init(&sample, bp->attr.bp_addr);
4452 sample.addr = bp->attr.bp_addr;
4453 4448
4454 if (!perf_exclude_event(bp, regs)) 4449 if (!perf_exclude_event(bp, regs))
4455 perf_swevent_add(bp, 1, 1, &sample, regs); 4450 perf_swevent_add(bp, 1, 1, &sample, regs);