aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHendrik Brueckner2013-12-12 18:05:20 +0100
committerMartin Schwidefsky2013-12-16 14:37:59 +0100
commitdd127b3b977b81eab58d1d7ee037195cf0bbeba7 (patch)
tree034aae43391c8a50cad79d42ca91086d535df14d
parent443e802bab16916f9a51a34f2213f4dee6e8762c (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.c36
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, &regs, sde_regs))
+ goto out;
if (perf_event_overflow(event, &data, &regs)) {
overflow = 1;
event->pmu->stop(event, 0);
}
perf_event_update_userpage(event);
-
+out:
return overflow;
}