aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kernel/cpu/perf_event.c
diff options
context:
space:
mode:
authorStephane Eranian <eranian@google.com>2012-02-09 17:21:00 -0500
committerIngo Molnar <mingo@elte.hu>2012-03-05 08:55:42 -0500
commitd010b3326cf06b3406cdd88af16dcf4e4b6fec2e (patch)
treed0468d78582aeff6a603cb5d29b1a14310106896 /arch/x86/kernel/cpu/perf_event.c
parent2481c5fa6db0237e4f0168f88913178b2b495b7c (diff)
perf: Add callback to flush branch_stack on context switch
With branch stack sampling, it is possible to filter by priv levels. In system-wide mode, that means it is possible to capture only user level branches. The builtin SW LBR filter needs to disassemble code based on LBR captured addresses. For that, it needs to know the task the addresses are associated with. Because of context switches, the content of the branch stack buffer may contain addresses from different tasks. We need a callback on context switch to either flush the branch stack or save it. This patch adds a new callback in struct pmu which is called during context switches. The callback is called only when necessary. That is when a system-wide context has, at least, one event which uses PERF_SAMPLE_BRANCH_STACK. The callback is never called for per-thread context. In this version, the Intel x86 code simply flushes (resets) the LBR on context switches (fills it with zeroes). Those zeroed branches are then filtered out by the SW filter. Signed-off-by: Stephane Eranian <eranian@google.com> Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl> Link: http://lkml.kernel.org/r/1328826068-11713-11-git-send-email-eranian@google.com Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'arch/x86/kernel/cpu/perf_event.c')
-rw-r--r--arch/x86/kernel/cpu/perf_event.c21
1 files changed, 14 insertions, 7 deletions
diff --git a/arch/x86/kernel/cpu/perf_event.c b/arch/x86/kernel/cpu/perf_event.c
index cea56748327..0a18d16cb58 100644
--- a/arch/x86/kernel/cpu/perf_event.c
+++ b/arch/x86/kernel/cpu/perf_event.c
@@ -1671,25 +1671,32 @@ static const struct attribute_group *x86_pmu_attr_groups[] = {
1671 NULL, 1671 NULL,
1672}; 1672};
1673 1673
1674static void x86_pmu_flush_branch_stack(void)
1675{
1676 if (x86_pmu.flush_branch_stack)
1677 x86_pmu.flush_branch_stack();
1678}
1679
1674static struct pmu pmu = { 1680static struct pmu pmu = {
1675 .pmu_enable = x86_pmu_enable, 1681 .pmu_enable = x86_pmu_enable,
1676 .pmu_disable = x86_pmu_disable, 1682 .pmu_disable = x86_pmu_disable,
1677 1683
1678 .attr_groups = x86_pmu_attr_groups, 1684 .attr_groups = x86_pmu_attr_groups,
1679 1685
1680 .event_init = x86_pmu_event_init, 1686 .event_init = x86_pmu_event_init,
1681 1687
1682 .add = x86_pmu_add, 1688 .add = x86_pmu_add,
1683 .del = x86_pmu_del, 1689 .del = x86_pmu_del,
1684 .start = x86_pmu_start, 1690 .start = x86_pmu_start,
1685 .stop = x86_pmu_stop, 1691 .stop = x86_pmu_stop,
1686 .read = x86_pmu_read, 1692 .read = x86_pmu_read,
1687 1693
1688 .start_txn = x86_pmu_start_txn, 1694 .start_txn = x86_pmu_start_txn,
1689 .cancel_txn = x86_pmu_cancel_txn, 1695 .cancel_txn = x86_pmu_cancel_txn,
1690 .commit_txn = x86_pmu_commit_txn, 1696 .commit_txn = x86_pmu_commit_txn,
1691 1697
1692 .event_idx = x86_pmu_event_idx, 1698 .event_idx = x86_pmu_event_idx,
1699 .flush_branch_stack = x86_pmu_flush_branch_stack,
1693}; 1700};
1694 1701
1695void perf_update_user_clock(struct perf_event_mmap_page *userpg, u64 now) 1702void perf_update_user_clock(struct perf_event_mmap_page *userpg, u64 now)