mirror of
https://github.com/torvalds/linux.git
synced 2024-11-15 08:31:55 +00:00
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>
This commit is contained in:
parent
548b841669
commit
dc1d628a67
@ -965,7 +965,7 @@ armv6pmu_handle_irq(int irq_num,
|
|||||||
*/
|
*/
|
||||||
armv6_pmcr_write(pmcr);
|
armv6_pmcr_write(pmcr);
|
||||||
|
|
||||||
data.addr = 0;
|
perf_sample_data_init(&data, 0);
|
||||||
|
|
||||||
cpuc = &__get_cpu_var(cpu_hw_events);
|
cpuc = &__get_cpu_var(cpu_hw_events);
|
||||||
for (idx = 0; idx <= armpmu->num_events; ++idx) {
|
for (idx = 0; idx <= armpmu->num_events; ++idx) {
|
||||||
@ -1945,7 +1945,7 @@ static irqreturn_t armv7pmu_handle_irq(int irq_num, void *dev)
|
|||||||
*/
|
*/
|
||||||
regs = get_irq_regs();
|
regs = get_irq_regs();
|
||||||
|
|
||||||
data.addr = 0;
|
perf_sample_data_init(&data, 0);
|
||||||
|
|
||||||
cpuc = &__get_cpu_var(cpu_hw_events);
|
cpuc = &__get_cpu_var(cpu_hw_events);
|
||||||
for (idx = 0; idx <= armpmu->num_events; ++idx) {
|
for (idx = 0; idx <= armpmu->num_events; ++idx) {
|
||||||
|
@ -1164,10 +1164,10 @@ static void record_and_restart(struct perf_event *event, unsigned long val,
|
|||||||
* Finally record data if requested.
|
* Finally record data if requested.
|
||||||
*/
|
*/
|
||||||
if (record) {
|
if (record) {
|
||||||
struct perf_sample_data data = {
|
struct perf_sample_data data;
|
||||||
.addr = ~0ULL,
|
|
||||||
.period = event->hw.last_period,
|
perf_sample_data_init(&data, ~0ULL);
|
||||||
};
|
data.period = event->hw.last_period;
|
||||||
|
|
||||||
if (event->attr.sample_type & PERF_SAMPLE_ADDR)
|
if (event->attr.sample_type & PERF_SAMPLE_ADDR)
|
||||||
perf_get_data_addr(regs, &data.addr);
|
perf_get_data_addr(regs, &data.addr);
|
||||||
|
@ -1189,7 +1189,7 @@ static int __kprobes perf_event_nmi_handler(struct notifier_block *self,
|
|||||||
|
|
||||||
regs = args->regs;
|
regs = args->regs;
|
||||||
|
|
||||||
data.addr = 0;
|
perf_sample_data_init(&data, 0);
|
||||||
|
|
||||||
cpuc = &__get_cpu_var(cpu_hw_events);
|
cpuc = &__get_cpu_var(cpu_hw_events);
|
||||||
|
|
||||||
|
@ -1097,8 +1097,7 @@ static int x86_pmu_handle_irq(struct pt_regs *regs)
|
|||||||
int idx, handled = 0;
|
int idx, handled = 0;
|
||||||
u64 val;
|
u64 val;
|
||||||
|
|
||||||
data.addr = 0;
|
perf_sample_data_init(&data, 0);
|
||||||
data.raw = NULL;
|
|
||||||
|
|
||||||
cpuc = &__get_cpu_var(cpu_hw_events);
|
cpuc = &__get_cpu_var(cpu_hw_events);
|
||||||
|
|
||||||
|
@ -590,10 +590,9 @@ static void intel_pmu_drain_bts_buffer(void)
|
|||||||
|
|
||||||
ds->bts_index = ds->bts_buffer_base;
|
ds->bts_index = ds->bts_buffer_base;
|
||||||
|
|
||||||
|
perf_sample_data_init(&data, 0);
|
||||||
|
|
||||||
data.period = event->hw.last_period;
|
data.period = event->hw.last_period;
|
||||||
data.addr = 0;
|
|
||||||
data.raw = NULL;
|
|
||||||
regs.ip = 0;
|
regs.ip = 0;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -742,8 +741,7 @@ static int intel_pmu_handle_irq(struct pt_regs *regs)
|
|||||||
int bit, loops;
|
int bit, loops;
|
||||||
u64 ack, status;
|
u64 ack, status;
|
||||||
|
|
||||||
data.addr = 0;
|
perf_sample_data_init(&data, 0);
|
||||||
data.raw = NULL;
|
|
||||||
|
|
||||||
cpuc = &__get_cpu_var(cpu_hw_events);
|
cpuc = &__get_cpu_var(cpu_hw_events);
|
||||||
|
|
||||||
|
@ -801,6 +801,13 @@ struct perf_sample_data {
|
|||||||
struct perf_raw_record *raw;
|
struct perf_raw_record *raw;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static inline
|
||||||
|
void perf_sample_data_init(struct perf_sample_data *data, u64 addr)
|
||||||
|
{
|
||||||
|
data->addr = addr;
|
||||||
|
data->raw = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
extern void perf_output_sample(struct perf_output_handle *handle,
|
extern void perf_output_sample(struct perf_output_handle *handle,
|
||||||
struct perf_event_header *header,
|
struct perf_event_header *header,
|
||||||
struct perf_sample_data *data,
|
struct perf_sample_data *data,
|
||||||
|
@ -4108,8 +4108,7 @@ void __perf_sw_event(u32 event_id, u64 nr, int nmi,
|
|||||||
if (rctx < 0)
|
if (rctx < 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
data.addr = addr;
|
perf_sample_data_init(&data, addr);
|
||||||
data.raw = NULL;
|
|
||||||
|
|
||||||
do_perf_sw_event(PERF_TYPE_SOFTWARE, event_id, nr, nmi, &data, regs);
|
do_perf_sw_event(PERF_TYPE_SOFTWARE, event_id, nr, nmi, &data, regs);
|
||||||
|
|
||||||
@ -4154,11 +4153,10 @@ static enum hrtimer_restart perf_swevent_hrtimer(struct hrtimer *hrtimer)
|
|||||||
struct perf_event *event;
|
struct perf_event *event;
|
||||||
u64 period;
|
u64 period;
|
||||||
|
|
||||||
event = container_of(hrtimer, struct perf_event, hw.hrtimer);
|
event = container_of(hrtimer, struct perf_event, hw.hrtimer);
|
||||||
event->pmu->read(event);
|
event->pmu->read(event);
|
||||||
|
|
||||||
data.addr = 0;
|
perf_sample_data_init(&data, 0);
|
||||||
data.raw = NULL;
|
|
||||||
data.period = event->hw.last_period;
|
data.period = event->hw.last_period;
|
||||||
regs = get_irq_regs();
|
regs = get_irq_regs();
|
||||||
/*
|
/*
|
||||||
@ -4322,17 +4320,15 @@ static const struct pmu perf_ops_task_clock = {
|
|||||||
void perf_tp_event(int event_id, u64 addr, u64 count, void *record,
|
void perf_tp_event(int event_id, u64 addr, u64 count, void *record,
|
||||||
int entry_size)
|
int entry_size)
|
||||||
{
|
{
|
||||||
|
struct pt_regs *regs = get_irq_regs();
|
||||||
|
struct perf_sample_data data;
|
||||||
struct perf_raw_record raw = {
|
struct perf_raw_record raw = {
|
||||||
.size = entry_size,
|
.size = entry_size,
|
||||||
.data = record,
|
.data = record,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct perf_sample_data data = {
|
perf_sample_data_init(&data, addr);
|
||||||
.addr = addr,
|
data.raw = &raw;
|
||||||
.raw = &raw,
|
|
||||||
};
|
|
||||||
|
|
||||||
struct pt_regs *regs = get_irq_regs();
|
|
||||||
|
|
||||||
if (!regs)
|
if (!regs)
|
||||||
regs = task_pt_regs(current);
|
regs = task_pt_regs(current);
|
||||||
@ -4448,8 +4444,7 @@ void perf_bp_event(struct perf_event *bp, void *data)
|
|||||||
struct perf_sample_data sample;
|
struct perf_sample_data sample;
|
||||||
struct pt_regs *regs = data;
|
struct pt_regs *regs = data;
|
||||||
|
|
||||||
sample.raw = NULL;
|
perf_sample_data_init(&sample, bp->attr.bp_addr);
|
||||||
sample.addr = bp->attr.bp_addr;
|
|
||||||
|
|
||||||
if (!perf_exclude_event(bp, regs))
|
if (!perf_exclude_event(bp, regs))
|
||||||
perf_swevent_add(bp, 1, 1, &sample, regs);
|
perf_swevent_add(bp, 1, 1, &sample, regs);
|
||||||
|
Loading…
Reference in New Issue
Block a user