diff options
author | Hendrik Brueckner | 2013-12-12 18:05:20 +0100 |
---|---|---|
committer | Martin Schwidefsky | 2013-12-16 14:37:59 +0100 |
commit | dd127b3b977b81eab58d1d7ee037195cf0bbeba7 (patch) | |
tree | 034aae43391c8a50cad79d42ca91086d535df14d | |
parent | 443e802bab16916f9a51a34f2213f4dee6e8762c (diff) |
s390/cpum_sf: Filter perf events based event->attr.exclude_* settings
Introduce the perf_exclude_event() function to filter perf samples
according to event->attr.exclude_* settings. During event initialization,
reset event exclude settings that are not supported.
Signed-off-by: Hendrik Brueckner <brueckner@linux.vnet.ibm.com>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
-rw-r--r-- | arch/s390/kernel/perf_cpum_sf.c | 36 |
1 files changed, 35 insertions, 1 deletions
diff --git a/arch/s390/kernel/perf_cpum_sf.c b/arch/s390/kernel/perf_cpum_sf.c index d611facae599..28fa2f235158 100644 --- a/arch/s390/kernel/perf_cpum_sf.c +++ b/arch/s390/kernel/perf_cpum_sf.c @@ -723,10 +723,19 @@ static int cpumsf_pmu_event_init(struct perf_event *event) return -ENOENT; } + /* Check online status of the CPU to which the event is pinned */ if (event->cpu >= nr_cpumask_bits || (event->cpu >= 0 && !cpu_online(event->cpu))) return -ENODEV; + /* Force reset of idle/hv excludes regardless of what the + * user requested. + */ + if (event->attr.exclude_hv) + event->attr.exclude_hv = 0; + if (event->attr.exclude_idle) + event->attr.exclude_idle = 0; + err = __hw_perf_event_init(event); if (unlikely(err)) if (event->destroy) @@ -824,6 +833,29 @@ static void cpumsf_pmu_disable(struct pmu *pmu) cpuhw->flags &= ~PMU_F_ENABLED; } +/* perf_exclude_event() - Filter event + * @event: The perf event + * @regs: pt_regs structure + * @sde_regs: Sample-data-entry (sde) regs structure + * + * Filter perf events according to their exclude specification. + * + * Return non-zero if the event shall be excluded. + */ +static int perf_exclude_event(struct perf_event *event, struct pt_regs *regs, + struct perf_sf_sde_regs *sde_regs) +{ + if (event->attr.exclude_user && user_mode(regs)) + return 1; + if (event->attr.exclude_kernel && !user_mode(regs)) + return 1; + if (event->attr.exclude_guest && sde_regs->in_guest) + return 1; + if (event->attr.exclude_host && !sde_regs->in_guest) + return 1; + return 0; +} + /* perf_push_sample() - Push samples to perf * @event: The perf event * @sample: Hardware sample data @@ -894,12 +926,14 @@ static int perf_push_sample(struct perf_event *event, sde_regs->in_guest = 1; overflow = 0; + if (perf_exclude_event(event, ®s, sde_regs)) + goto out; if (perf_event_overflow(event, &data, ®s)) { overflow = 1; event->pmu->stop(event, 0); } perf_event_update_userpage(event); - +out: return overflow; } |