Skip to content

Commit c2b98a8

Browse files
Alexey BudankovIngo Molnar
authored andcommitted
perf/x86: Synchronize PMU task contexts on optimized context switches
Install Intel specific PMU task context synchronization adapter and extend optimized context switch path with PMU specific task context synchronization to fix LBR callstack virtualization on context switches. Signed-off-by: Alexey Budankov <[email protected]> Signed-off-by: Peter Zijlstra (Intel) <[email protected]> Cc: Alexander Shishkin <[email protected]> Cc: Arnaldo Carvalho de Melo <[email protected]> Cc: Arnaldo Carvalho de Melo <[email protected]> Cc: Ian Rogers <[email protected]> Cc: Jiri Olsa <[email protected]> Cc: Kan Liang <[email protected]> Cc: Linus Torvalds <[email protected]> Cc: Mark Rutland <[email protected]> Cc: Namhyung Kim <[email protected]> Cc: Peter Zijlstra <[email protected]> Cc: Song Liu <[email protected]> Cc: Stephane Eranian <[email protected]> Cc: Thomas Gleixner <[email protected]> Cc: Vince Weaver <[email protected]> Link: https://lkml.kernel.org/r/[email protected] Signed-off-by: Ingo Molnar <[email protected]>
1 parent 421ca86 commit c2b98a8

File tree

2 files changed

+19
-1
lines changed

2 files changed

+19
-1
lines changed

arch/x86/events/intel/core.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3820,6 +3820,12 @@ static void intel_pmu_sched_task(struct perf_event_context *ctx,
38203820
intel_pmu_lbr_sched_task(ctx, sched_in);
38213821
}
38223822

3823+
static void intel_pmu_swap_task_ctx(struct perf_event_context *prev,
3824+
struct perf_event_context *next)
3825+
{
3826+
intel_pmu_lbr_swap_task_ctx(prev, next);
3827+
}
3828+
38233829
static int intel_pmu_check_period(struct perf_event *event, u64 value)
38243830
{
38253831
return intel_pmu_has_bts_period(event, value) ? -EINVAL : 0;
@@ -3955,6 +3961,7 @@ static __initconst const struct x86_pmu intel_pmu = {
39553961

39563962
.guest_get_msrs = intel_guest_get_msrs,
39573963
.sched_task = intel_pmu_sched_task,
3964+
.swap_task_ctx = intel_pmu_swap_task_ctx,
39583965

39593966
.check_period = intel_pmu_check_period,
39603967

kernel/events/core.c

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3204,10 +3204,21 @@ static void perf_event_context_sched_out(struct task_struct *task, int ctxn,
32043204
raw_spin_lock(&ctx->lock);
32053205
raw_spin_lock_nested(&next_ctx->lock, SINGLE_DEPTH_NESTING);
32063206
if (context_equiv(ctx, next_ctx)) {
3207+
struct pmu *pmu = ctx->pmu;
3208+
32073209
WRITE_ONCE(ctx->task, next);
32083210
WRITE_ONCE(next_ctx->task, task);
32093211

3210-
swap(ctx->task_ctx_data, next_ctx->task_ctx_data);
3212+
/*
3213+
* PMU specific parts of task perf context can require
3214+
* additional synchronization. As an example of such
3215+
* synchronization see implementation details of Intel
3216+
* LBR call stack data profiling;
3217+
*/
3218+
if (pmu->swap_task_ctx)
3219+
pmu->swap_task_ctx(ctx, next_ctx);
3220+
else
3221+
swap(ctx->task_ctx_data, next_ctx->task_ctx_data);
32113222

32123223
/*
32133224
* RCU_INIT_POINTER here is safe because we've not

0 commit comments

Comments
 (0)