Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b28ae956 authored by Andi Kleen's avatar Andi Kleen Committed by Ingo Molnar
Browse files

perf/x86: Fix LBR call stack save/restore



This fixes a bug I added in the following commit:

  90405aa0 ("perf/x86/intel/lbr: Limit LBR accesses to TOS in callstack mode")

The bug could lead to lost LBR call stacks. When restoring the LBR state
we need to use the TOS of the previous context, not the current context.
To do that we need to save/restore the TOS.

Signed-off-by: default avatarAndi Kleen <ak@linux.intel.com>
Signed-off-by: default avatarPeter Zijlstra (Intel) <peterz@infradead.org>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Stephane Eranian <eranian@google.com>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Vince Weaver <vincent.weaver@maine.edu>
Cc: acme@kernel.org
Cc: jolsa@kernel.org
Link: http://lkml.kernel.org/r/1445366797-30894-1-git-send-email-andi@firstfloor.org


Signed-off-by: default avatarIngo Molnar <mingo@kernel.org>
parent daecbd26
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -627,6 +627,7 @@ struct x86_perf_task_context {
	u64 lbr_from[MAX_LBR_ENTRIES];
	u64 lbr_to[MAX_LBR_ENTRIES];
	u64 lbr_info[MAX_LBR_ENTRIES];
	int tos;
	int lbr_callstack_users;
	int lbr_stack_state;
};
+3 −1
Original line number Diff line number Diff line
@@ -239,7 +239,7 @@ static void __intel_pmu_lbr_restore(struct x86_perf_task_context *task_ctx)
	}

	mask = x86_pmu.lbr_nr - 1;
	tos = intel_pmu_lbr_tos();
	tos = task_ctx->tos;
	for (i = 0; i < tos; i++) {
		lbr_idx = (tos - i) & mask;
		wrmsrl(x86_pmu.lbr_from + lbr_idx, task_ctx->lbr_from[i]);
@@ -247,6 +247,7 @@ static void __intel_pmu_lbr_restore(struct x86_perf_task_context *task_ctx)
		if (x86_pmu.intel_cap.lbr_format == LBR_FORMAT_INFO)
			wrmsrl(MSR_LBR_INFO_0 + lbr_idx, task_ctx->lbr_info[i]);
	}
	wrmsrl(x86_pmu.lbr_tos, tos);
	task_ctx->lbr_stack_state = LBR_NONE;
}

@@ -270,6 +271,7 @@ static void __intel_pmu_lbr_save(struct x86_perf_task_context *task_ctx)
		if (x86_pmu.intel_cap.lbr_format == LBR_FORMAT_INFO)
			rdmsrl(MSR_LBR_INFO_0 + lbr_idx, task_ctx->lbr_info[i]);
	}
	task_ctx->tos = tos;
	task_ctx->lbr_stack_state = LBR_VALID;
}