18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
28c2ecf20Sopenharmony_ci#include <linux/perf_event.h>
38c2ecf20Sopenharmony_ci#include <linux/types.h>
48c2ecf20Sopenharmony_ci
58c2ecf20Sopenharmony_ci#include <asm/perf_event.h>
68c2ecf20Sopenharmony_ci#include <asm/msr.h>
78c2ecf20Sopenharmony_ci#include <asm/insn.h>
88c2ecf20Sopenharmony_ci
98c2ecf20Sopenharmony_ci#include "../perf_event.h"
108c2ecf20Sopenharmony_ci
118c2ecf20Sopenharmony_cistatic const enum {
128c2ecf20Sopenharmony_ci	LBR_EIP_FLAGS		= 1,
138c2ecf20Sopenharmony_ci	LBR_TSX			= 2,
148c2ecf20Sopenharmony_ci} lbr_desc[LBR_FORMAT_MAX_KNOWN + 1] = {
158c2ecf20Sopenharmony_ci	[LBR_FORMAT_EIP_FLAGS]  = LBR_EIP_FLAGS,
168c2ecf20Sopenharmony_ci	[LBR_FORMAT_EIP_FLAGS2] = LBR_EIP_FLAGS | LBR_TSX,
178c2ecf20Sopenharmony_ci};
188c2ecf20Sopenharmony_ci
198c2ecf20Sopenharmony_ci/*
208c2ecf20Sopenharmony_ci * Intel LBR_SELECT bits
218c2ecf20Sopenharmony_ci * Intel Vol3a, April 2011, Section 16.7 Table 16-10
228c2ecf20Sopenharmony_ci *
238c2ecf20Sopenharmony_ci * Hardware branch filter (not available on all CPUs)
248c2ecf20Sopenharmony_ci */
258c2ecf20Sopenharmony_ci#define LBR_KERNEL_BIT		0 /* do not capture at ring0 */
268c2ecf20Sopenharmony_ci#define LBR_USER_BIT		1 /* do not capture at ring > 0 */
278c2ecf20Sopenharmony_ci#define LBR_JCC_BIT		2 /* do not capture conditional branches */
288c2ecf20Sopenharmony_ci#define LBR_REL_CALL_BIT	3 /* do not capture relative calls */
298c2ecf20Sopenharmony_ci#define LBR_IND_CALL_BIT	4 /* do not capture indirect calls */
308c2ecf20Sopenharmony_ci#define LBR_RETURN_BIT		5 /* do not capture near returns */
318c2ecf20Sopenharmony_ci#define LBR_IND_JMP_BIT		6 /* do not capture indirect jumps */
328c2ecf20Sopenharmony_ci#define LBR_REL_JMP_BIT		7 /* do not capture relative jumps */
338c2ecf20Sopenharmony_ci#define LBR_FAR_BIT		8 /* do not capture far branches */
348c2ecf20Sopenharmony_ci#define LBR_CALL_STACK_BIT	9 /* enable call stack */
358c2ecf20Sopenharmony_ci
368c2ecf20Sopenharmony_ci/*
378c2ecf20Sopenharmony_ci * Following bit only exists in Linux; we mask it out before writing it to
388c2ecf20Sopenharmony_ci * the actual MSR. But it helps the constraint perf code to understand
398c2ecf20Sopenharmony_ci * that this is a separate configuration.
408c2ecf20Sopenharmony_ci */
418c2ecf20Sopenharmony_ci#define LBR_NO_INFO_BIT	       63 /* don't read LBR_INFO. */
428c2ecf20Sopenharmony_ci
438c2ecf20Sopenharmony_ci#define LBR_KERNEL	(1 << LBR_KERNEL_BIT)
448c2ecf20Sopenharmony_ci#define LBR_USER	(1 << LBR_USER_BIT)
458c2ecf20Sopenharmony_ci#define LBR_JCC		(1 << LBR_JCC_BIT)
468c2ecf20Sopenharmony_ci#define LBR_REL_CALL	(1 << LBR_REL_CALL_BIT)
478c2ecf20Sopenharmony_ci#define LBR_IND_CALL	(1 << LBR_IND_CALL_BIT)
488c2ecf20Sopenharmony_ci#define LBR_RETURN	(1 << LBR_RETURN_BIT)
498c2ecf20Sopenharmony_ci#define LBR_REL_JMP	(1 << LBR_REL_JMP_BIT)
508c2ecf20Sopenharmony_ci#define LBR_IND_JMP	(1 << LBR_IND_JMP_BIT)
518c2ecf20Sopenharmony_ci#define LBR_FAR		(1 << LBR_FAR_BIT)
528c2ecf20Sopenharmony_ci#define LBR_CALL_STACK	(1 << LBR_CALL_STACK_BIT)
538c2ecf20Sopenharmony_ci#define LBR_NO_INFO	(1ULL << LBR_NO_INFO_BIT)
548c2ecf20Sopenharmony_ci
558c2ecf20Sopenharmony_ci#define LBR_PLM (LBR_KERNEL | LBR_USER)
568c2ecf20Sopenharmony_ci
578c2ecf20Sopenharmony_ci#define LBR_SEL_MASK	0x3ff	/* valid bits in LBR_SELECT */
588c2ecf20Sopenharmony_ci#define LBR_NOT_SUPP	-1	/* LBR filter not supported */
598c2ecf20Sopenharmony_ci#define LBR_IGN		0	/* ignored */
608c2ecf20Sopenharmony_ci
618c2ecf20Sopenharmony_ci#define LBR_ANY		 \
628c2ecf20Sopenharmony_ci	(LBR_JCC	|\
638c2ecf20Sopenharmony_ci	 LBR_REL_CALL	|\
648c2ecf20Sopenharmony_ci	 LBR_IND_CALL	|\
658c2ecf20Sopenharmony_ci	 LBR_RETURN	|\
668c2ecf20Sopenharmony_ci	 LBR_REL_JMP	|\
678c2ecf20Sopenharmony_ci	 LBR_IND_JMP	|\
688c2ecf20Sopenharmony_ci	 LBR_FAR)
698c2ecf20Sopenharmony_ci
708c2ecf20Sopenharmony_ci#define LBR_FROM_FLAG_MISPRED	BIT_ULL(63)
718c2ecf20Sopenharmony_ci#define LBR_FROM_FLAG_IN_TX	BIT_ULL(62)
728c2ecf20Sopenharmony_ci#define LBR_FROM_FLAG_ABORT	BIT_ULL(61)
738c2ecf20Sopenharmony_ci
748c2ecf20Sopenharmony_ci#define LBR_FROM_SIGNEXT_2MSB	(BIT_ULL(60) | BIT_ULL(59))
758c2ecf20Sopenharmony_ci
768c2ecf20Sopenharmony_ci/*
778c2ecf20Sopenharmony_ci * x86control flow change classification
788c2ecf20Sopenharmony_ci * x86control flow changes include branches, interrupts, traps, faults
798c2ecf20Sopenharmony_ci */
808c2ecf20Sopenharmony_cienum {
818c2ecf20Sopenharmony_ci	X86_BR_NONE		= 0,      /* unknown */
828c2ecf20Sopenharmony_ci
838c2ecf20Sopenharmony_ci	X86_BR_USER		= 1 << 0, /* branch target is user */
848c2ecf20Sopenharmony_ci	X86_BR_KERNEL		= 1 << 1, /* branch target is kernel */
858c2ecf20Sopenharmony_ci
868c2ecf20Sopenharmony_ci	X86_BR_CALL		= 1 << 2, /* call */
878c2ecf20Sopenharmony_ci	X86_BR_RET		= 1 << 3, /* return */
888c2ecf20Sopenharmony_ci	X86_BR_SYSCALL		= 1 << 4, /* syscall */
898c2ecf20Sopenharmony_ci	X86_BR_SYSRET		= 1 << 5, /* syscall return */
908c2ecf20Sopenharmony_ci	X86_BR_INT		= 1 << 6, /* sw interrupt */
918c2ecf20Sopenharmony_ci	X86_BR_IRET		= 1 << 7, /* return from interrupt */
928c2ecf20Sopenharmony_ci	X86_BR_JCC		= 1 << 8, /* conditional */
938c2ecf20Sopenharmony_ci	X86_BR_JMP		= 1 << 9, /* jump */
948c2ecf20Sopenharmony_ci	X86_BR_IRQ		= 1 << 10,/* hw interrupt or trap or fault */
958c2ecf20Sopenharmony_ci	X86_BR_IND_CALL		= 1 << 11,/* indirect calls */
968c2ecf20Sopenharmony_ci	X86_BR_ABORT		= 1 << 12,/* transaction abort */
978c2ecf20Sopenharmony_ci	X86_BR_IN_TX		= 1 << 13,/* in transaction */
988c2ecf20Sopenharmony_ci	X86_BR_NO_TX		= 1 << 14,/* not in transaction */
998c2ecf20Sopenharmony_ci	X86_BR_ZERO_CALL	= 1 << 15,/* zero length call */
1008c2ecf20Sopenharmony_ci	X86_BR_CALL_STACK	= 1 << 16,/* call stack */
1018c2ecf20Sopenharmony_ci	X86_BR_IND_JMP		= 1 << 17,/* indirect jump */
1028c2ecf20Sopenharmony_ci
1038c2ecf20Sopenharmony_ci	X86_BR_TYPE_SAVE	= 1 << 18,/* indicate to save branch type */
1048c2ecf20Sopenharmony_ci
1058c2ecf20Sopenharmony_ci};
1068c2ecf20Sopenharmony_ci
1078c2ecf20Sopenharmony_ci#define X86_BR_PLM (X86_BR_USER | X86_BR_KERNEL)
1088c2ecf20Sopenharmony_ci#define X86_BR_ANYTX (X86_BR_NO_TX | X86_BR_IN_TX)
1098c2ecf20Sopenharmony_ci
1108c2ecf20Sopenharmony_ci#define X86_BR_ANY       \
1118c2ecf20Sopenharmony_ci	(X86_BR_CALL    |\
1128c2ecf20Sopenharmony_ci	 X86_BR_RET     |\
1138c2ecf20Sopenharmony_ci	 X86_BR_SYSCALL |\
1148c2ecf20Sopenharmony_ci	 X86_BR_SYSRET  |\
1158c2ecf20Sopenharmony_ci	 X86_BR_INT     |\
1168c2ecf20Sopenharmony_ci	 X86_BR_IRET    |\
1178c2ecf20Sopenharmony_ci	 X86_BR_JCC     |\
1188c2ecf20Sopenharmony_ci	 X86_BR_JMP	 |\
1198c2ecf20Sopenharmony_ci	 X86_BR_IRQ	 |\
1208c2ecf20Sopenharmony_ci	 X86_BR_ABORT	 |\
1218c2ecf20Sopenharmony_ci	 X86_BR_IND_CALL |\
1228c2ecf20Sopenharmony_ci	 X86_BR_IND_JMP  |\
1238c2ecf20Sopenharmony_ci	 X86_BR_ZERO_CALL)
1248c2ecf20Sopenharmony_ci
1258c2ecf20Sopenharmony_ci#define X86_BR_ALL (X86_BR_PLM | X86_BR_ANY)
1268c2ecf20Sopenharmony_ci
1278c2ecf20Sopenharmony_ci#define X86_BR_ANY_CALL		 \
1288c2ecf20Sopenharmony_ci	(X86_BR_CALL		|\
1298c2ecf20Sopenharmony_ci	 X86_BR_IND_CALL	|\
1308c2ecf20Sopenharmony_ci	 X86_BR_ZERO_CALL	|\
1318c2ecf20Sopenharmony_ci	 X86_BR_SYSCALL		|\
1328c2ecf20Sopenharmony_ci	 X86_BR_IRQ		|\
1338c2ecf20Sopenharmony_ci	 X86_BR_INT)
1348c2ecf20Sopenharmony_ci
1358c2ecf20Sopenharmony_ci/*
1368c2ecf20Sopenharmony_ci * Intel LBR_CTL bits
1378c2ecf20Sopenharmony_ci *
1388c2ecf20Sopenharmony_ci * Hardware branch filter for Arch LBR
1398c2ecf20Sopenharmony_ci */
1408c2ecf20Sopenharmony_ci#define ARCH_LBR_KERNEL_BIT		1  /* capture at ring0 */
1418c2ecf20Sopenharmony_ci#define ARCH_LBR_USER_BIT		2  /* capture at ring > 0 */
1428c2ecf20Sopenharmony_ci#define ARCH_LBR_CALL_STACK_BIT		3  /* enable call stack */
1438c2ecf20Sopenharmony_ci#define ARCH_LBR_JCC_BIT		16 /* capture conditional branches */
1448c2ecf20Sopenharmony_ci#define ARCH_LBR_REL_JMP_BIT		17 /* capture relative jumps */
1458c2ecf20Sopenharmony_ci#define ARCH_LBR_IND_JMP_BIT		18 /* capture indirect jumps */
1468c2ecf20Sopenharmony_ci#define ARCH_LBR_REL_CALL_BIT		19 /* capture relative calls */
1478c2ecf20Sopenharmony_ci#define ARCH_LBR_IND_CALL_BIT		20 /* capture indirect calls */
1488c2ecf20Sopenharmony_ci#define ARCH_LBR_RETURN_BIT		21 /* capture near returns */
1498c2ecf20Sopenharmony_ci#define ARCH_LBR_OTHER_BRANCH_BIT	22 /* capture other branches */
1508c2ecf20Sopenharmony_ci
1518c2ecf20Sopenharmony_ci#define ARCH_LBR_KERNEL			(1ULL << ARCH_LBR_KERNEL_BIT)
1528c2ecf20Sopenharmony_ci#define ARCH_LBR_USER			(1ULL << ARCH_LBR_USER_BIT)
1538c2ecf20Sopenharmony_ci#define ARCH_LBR_CALL_STACK		(1ULL << ARCH_LBR_CALL_STACK_BIT)
1548c2ecf20Sopenharmony_ci#define ARCH_LBR_JCC			(1ULL << ARCH_LBR_JCC_BIT)
1558c2ecf20Sopenharmony_ci#define ARCH_LBR_REL_JMP		(1ULL << ARCH_LBR_REL_JMP_BIT)
1568c2ecf20Sopenharmony_ci#define ARCH_LBR_IND_JMP		(1ULL << ARCH_LBR_IND_JMP_BIT)
1578c2ecf20Sopenharmony_ci#define ARCH_LBR_REL_CALL		(1ULL << ARCH_LBR_REL_CALL_BIT)
1588c2ecf20Sopenharmony_ci#define ARCH_LBR_IND_CALL		(1ULL << ARCH_LBR_IND_CALL_BIT)
1598c2ecf20Sopenharmony_ci#define ARCH_LBR_RETURN			(1ULL << ARCH_LBR_RETURN_BIT)
1608c2ecf20Sopenharmony_ci#define ARCH_LBR_OTHER_BRANCH		(1ULL << ARCH_LBR_OTHER_BRANCH_BIT)
1618c2ecf20Sopenharmony_ci
1628c2ecf20Sopenharmony_ci#define ARCH_LBR_ANY			 \
1638c2ecf20Sopenharmony_ci	(ARCH_LBR_JCC			|\
1648c2ecf20Sopenharmony_ci	 ARCH_LBR_REL_JMP		|\
1658c2ecf20Sopenharmony_ci	 ARCH_LBR_IND_JMP		|\
1668c2ecf20Sopenharmony_ci	 ARCH_LBR_REL_CALL		|\
1678c2ecf20Sopenharmony_ci	 ARCH_LBR_IND_CALL		|\
1688c2ecf20Sopenharmony_ci	 ARCH_LBR_RETURN		|\
1698c2ecf20Sopenharmony_ci	 ARCH_LBR_OTHER_BRANCH)
1708c2ecf20Sopenharmony_ci
1718c2ecf20Sopenharmony_ci#define ARCH_LBR_CTL_MASK			0x7f000e
1728c2ecf20Sopenharmony_ci
1738c2ecf20Sopenharmony_cistatic void intel_pmu_lbr_filter(struct cpu_hw_events *cpuc);
1748c2ecf20Sopenharmony_ci
1758c2ecf20Sopenharmony_cistatic __always_inline bool is_lbr_call_stack_bit_set(u64 config)
1768c2ecf20Sopenharmony_ci{
1778c2ecf20Sopenharmony_ci	if (static_cpu_has(X86_FEATURE_ARCH_LBR))
1788c2ecf20Sopenharmony_ci		return !!(config & ARCH_LBR_CALL_STACK);
1798c2ecf20Sopenharmony_ci
1808c2ecf20Sopenharmony_ci	return !!(config & LBR_CALL_STACK);
1818c2ecf20Sopenharmony_ci}
1828c2ecf20Sopenharmony_ci
1838c2ecf20Sopenharmony_ci/*
1848c2ecf20Sopenharmony_ci * We only support LBR implementations that have FREEZE_LBRS_ON_PMI
1858c2ecf20Sopenharmony_ci * otherwise it becomes near impossible to get a reliable stack.
1868c2ecf20Sopenharmony_ci */
1878c2ecf20Sopenharmony_ci
1888c2ecf20Sopenharmony_cistatic void __intel_pmu_lbr_enable(bool pmi)
1898c2ecf20Sopenharmony_ci{
1908c2ecf20Sopenharmony_ci	struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
1918c2ecf20Sopenharmony_ci	u64 debugctl, lbr_select = 0, orig_debugctl;
1928c2ecf20Sopenharmony_ci
1938c2ecf20Sopenharmony_ci	/*
1948c2ecf20Sopenharmony_ci	 * No need to unfreeze manually, as v4 can do that as part
1958c2ecf20Sopenharmony_ci	 * of the GLOBAL_STATUS ack.
1968c2ecf20Sopenharmony_ci	 */
1978c2ecf20Sopenharmony_ci	if (pmi && x86_pmu.version >= 4)
1988c2ecf20Sopenharmony_ci		return;
1998c2ecf20Sopenharmony_ci
2008c2ecf20Sopenharmony_ci	/*
2018c2ecf20Sopenharmony_ci	 * No need to reprogram LBR_SELECT in a PMI, as it
2028c2ecf20Sopenharmony_ci	 * did not change.
2038c2ecf20Sopenharmony_ci	 */
2048c2ecf20Sopenharmony_ci	if (cpuc->lbr_sel)
2058c2ecf20Sopenharmony_ci		lbr_select = cpuc->lbr_sel->config & x86_pmu.lbr_sel_mask;
2068c2ecf20Sopenharmony_ci	if (!static_cpu_has(X86_FEATURE_ARCH_LBR) && !pmi && cpuc->lbr_sel)
2078c2ecf20Sopenharmony_ci		wrmsrl(MSR_LBR_SELECT, lbr_select);
2088c2ecf20Sopenharmony_ci
2098c2ecf20Sopenharmony_ci	rdmsrl(MSR_IA32_DEBUGCTLMSR, debugctl);
2108c2ecf20Sopenharmony_ci	orig_debugctl = debugctl;
2118c2ecf20Sopenharmony_ci
2128c2ecf20Sopenharmony_ci	if (!static_cpu_has(X86_FEATURE_ARCH_LBR))
2138c2ecf20Sopenharmony_ci		debugctl |= DEBUGCTLMSR_LBR;
2148c2ecf20Sopenharmony_ci	/*
2158c2ecf20Sopenharmony_ci	 * LBR callstack does not work well with FREEZE_LBRS_ON_PMI.
2168c2ecf20Sopenharmony_ci	 * If FREEZE_LBRS_ON_PMI is set, PMI near call/return instructions
2178c2ecf20Sopenharmony_ci	 * may cause superfluous increase/decrease of LBR_TOS.
2188c2ecf20Sopenharmony_ci	 */
2198c2ecf20Sopenharmony_ci	if (is_lbr_call_stack_bit_set(lbr_select))
2208c2ecf20Sopenharmony_ci		debugctl &= ~DEBUGCTLMSR_FREEZE_LBRS_ON_PMI;
2218c2ecf20Sopenharmony_ci	else
2228c2ecf20Sopenharmony_ci		debugctl |= DEBUGCTLMSR_FREEZE_LBRS_ON_PMI;
2238c2ecf20Sopenharmony_ci
2248c2ecf20Sopenharmony_ci	if (orig_debugctl != debugctl)
2258c2ecf20Sopenharmony_ci		wrmsrl(MSR_IA32_DEBUGCTLMSR, debugctl);
2268c2ecf20Sopenharmony_ci
2278c2ecf20Sopenharmony_ci	if (static_cpu_has(X86_FEATURE_ARCH_LBR))
2288c2ecf20Sopenharmony_ci		wrmsrl(MSR_ARCH_LBR_CTL, lbr_select | ARCH_LBR_CTL_LBREN);
2298c2ecf20Sopenharmony_ci}
2308c2ecf20Sopenharmony_ci
2318c2ecf20Sopenharmony_cistatic void __intel_pmu_lbr_disable(void)
2328c2ecf20Sopenharmony_ci{
2338c2ecf20Sopenharmony_ci	u64 debugctl;
2348c2ecf20Sopenharmony_ci
2358c2ecf20Sopenharmony_ci	if (static_cpu_has(X86_FEATURE_ARCH_LBR)) {
2368c2ecf20Sopenharmony_ci		wrmsrl(MSR_ARCH_LBR_CTL, 0);
2378c2ecf20Sopenharmony_ci		return;
2388c2ecf20Sopenharmony_ci	}
2398c2ecf20Sopenharmony_ci
2408c2ecf20Sopenharmony_ci	rdmsrl(MSR_IA32_DEBUGCTLMSR, debugctl);
2418c2ecf20Sopenharmony_ci	debugctl &= ~(DEBUGCTLMSR_LBR | DEBUGCTLMSR_FREEZE_LBRS_ON_PMI);
2428c2ecf20Sopenharmony_ci	wrmsrl(MSR_IA32_DEBUGCTLMSR, debugctl);
2438c2ecf20Sopenharmony_ci}
2448c2ecf20Sopenharmony_ci
2458c2ecf20Sopenharmony_civoid intel_pmu_lbr_reset_32(void)
2468c2ecf20Sopenharmony_ci{
2478c2ecf20Sopenharmony_ci	int i;
2488c2ecf20Sopenharmony_ci
2498c2ecf20Sopenharmony_ci	for (i = 0; i < x86_pmu.lbr_nr; i++)
2508c2ecf20Sopenharmony_ci		wrmsrl(x86_pmu.lbr_from + i, 0);
2518c2ecf20Sopenharmony_ci}
2528c2ecf20Sopenharmony_ci
2538c2ecf20Sopenharmony_civoid intel_pmu_lbr_reset_64(void)
2548c2ecf20Sopenharmony_ci{
2558c2ecf20Sopenharmony_ci	int i;
2568c2ecf20Sopenharmony_ci
2578c2ecf20Sopenharmony_ci	for (i = 0; i < x86_pmu.lbr_nr; i++) {
2588c2ecf20Sopenharmony_ci		wrmsrl(x86_pmu.lbr_from + i, 0);
2598c2ecf20Sopenharmony_ci		wrmsrl(x86_pmu.lbr_to   + i, 0);
2608c2ecf20Sopenharmony_ci		if (x86_pmu.intel_cap.lbr_format == LBR_FORMAT_INFO)
2618c2ecf20Sopenharmony_ci			wrmsrl(x86_pmu.lbr_info + i, 0);
2628c2ecf20Sopenharmony_ci	}
2638c2ecf20Sopenharmony_ci}
2648c2ecf20Sopenharmony_ci
2658c2ecf20Sopenharmony_cistatic void intel_pmu_arch_lbr_reset(void)
2668c2ecf20Sopenharmony_ci{
2678c2ecf20Sopenharmony_ci	/* Write to ARCH_LBR_DEPTH MSR, all LBR entries are reset to 0 */
2688c2ecf20Sopenharmony_ci	wrmsrl(MSR_ARCH_LBR_DEPTH, x86_pmu.lbr_nr);
2698c2ecf20Sopenharmony_ci}
2708c2ecf20Sopenharmony_ci
2718c2ecf20Sopenharmony_civoid intel_pmu_lbr_reset(void)
2728c2ecf20Sopenharmony_ci{
2738c2ecf20Sopenharmony_ci	struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
2748c2ecf20Sopenharmony_ci
2758c2ecf20Sopenharmony_ci	if (!x86_pmu.lbr_nr)
2768c2ecf20Sopenharmony_ci		return;
2778c2ecf20Sopenharmony_ci
2788c2ecf20Sopenharmony_ci	x86_pmu.lbr_reset();
2798c2ecf20Sopenharmony_ci
2808c2ecf20Sopenharmony_ci	cpuc->last_task_ctx = NULL;
2818c2ecf20Sopenharmony_ci	cpuc->last_log_id = 0;
2828c2ecf20Sopenharmony_ci}
2838c2ecf20Sopenharmony_ci
2848c2ecf20Sopenharmony_ci/*
2858c2ecf20Sopenharmony_ci * TOS = most recently recorded branch
2868c2ecf20Sopenharmony_ci */
2878c2ecf20Sopenharmony_cistatic inline u64 intel_pmu_lbr_tos(void)
2888c2ecf20Sopenharmony_ci{
2898c2ecf20Sopenharmony_ci	u64 tos;
2908c2ecf20Sopenharmony_ci
2918c2ecf20Sopenharmony_ci	rdmsrl(x86_pmu.lbr_tos, tos);
2928c2ecf20Sopenharmony_ci	return tos;
2938c2ecf20Sopenharmony_ci}
2948c2ecf20Sopenharmony_ci
2958c2ecf20Sopenharmony_cienum {
2968c2ecf20Sopenharmony_ci	LBR_NONE,
2978c2ecf20Sopenharmony_ci	LBR_VALID,
2988c2ecf20Sopenharmony_ci};
2998c2ecf20Sopenharmony_ci
3008c2ecf20Sopenharmony_ci/*
3018c2ecf20Sopenharmony_ci * For formats with LBR_TSX flags (e.g. LBR_FORMAT_EIP_FLAGS2), bits 61:62 in
3028c2ecf20Sopenharmony_ci * MSR_LAST_BRANCH_FROM_x are the TSX flags when TSX is supported, but when
3038c2ecf20Sopenharmony_ci * TSX is not supported they have no consistent behavior:
3048c2ecf20Sopenharmony_ci *
3058c2ecf20Sopenharmony_ci *   - For wrmsr(), bits 61:62 are considered part of the sign extension.
3068c2ecf20Sopenharmony_ci *   - For HW updates (branch captures) bits 61:62 are always OFF and are not
3078c2ecf20Sopenharmony_ci *     part of the sign extension.
3088c2ecf20Sopenharmony_ci *
3098c2ecf20Sopenharmony_ci * Therefore, if:
3108c2ecf20Sopenharmony_ci *
3118c2ecf20Sopenharmony_ci *   1) LBR has TSX format
3128c2ecf20Sopenharmony_ci *   2) CPU has no TSX support enabled
3138c2ecf20Sopenharmony_ci *
3148c2ecf20Sopenharmony_ci * ... then any value passed to wrmsr() must be sign extended to 63 bits and any
3158c2ecf20Sopenharmony_ci * value from rdmsr() must be converted to have a 61 bits sign extension,
3168c2ecf20Sopenharmony_ci * ignoring the TSX flags.
3178c2ecf20Sopenharmony_ci */
3188c2ecf20Sopenharmony_cistatic inline bool lbr_from_signext_quirk_needed(void)
3198c2ecf20Sopenharmony_ci{
3208c2ecf20Sopenharmony_ci	int lbr_format = x86_pmu.intel_cap.lbr_format;
3218c2ecf20Sopenharmony_ci	bool tsx_support = boot_cpu_has(X86_FEATURE_HLE) ||
3228c2ecf20Sopenharmony_ci			   boot_cpu_has(X86_FEATURE_RTM);
3238c2ecf20Sopenharmony_ci
3248c2ecf20Sopenharmony_ci	return !tsx_support && (lbr_desc[lbr_format] & LBR_TSX);
3258c2ecf20Sopenharmony_ci}
3268c2ecf20Sopenharmony_ci
3278c2ecf20Sopenharmony_cistatic DEFINE_STATIC_KEY_FALSE(lbr_from_quirk_key);
3288c2ecf20Sopenharmony_ci
3298c2ecf20Sopenharmony_ci/* If quirk is enabled, ensure sign extension is 63 bits: */
3308c2ecf20Sopenharmony_ciinline u64 lbr_from_signext_quirk_wr(u64 val)
3318c2ecf20Sopenharmony_ci{
3328c2ecf20Sopenharmony_ci	if (static_branch_unlikely(&lbr_from_quirk_key)) {
3338c2ecf20Sopenharmony_ci		/*
3348c2ecf20Sopenharmony_ci		 * Sign extend into bits 61:62 while preserving bit 63.
3358c2ecf20Sopenharmony_ci		 *
3368c2ecf20Sopenharmony_ci		 * Quirk is enabled when TSX is disabled. Therefore TSX bits
3378c2ecf20Sopenharmony_ci		 * in val are always OFF and must be changed to be sign
3388c2ecf20Sopenharmony_ci		 * extension bits. Since bits 59:60 are guaranteed to be
3398c2ecf20Sopenharmony_ci		 * part of the sign extension bits, we can just copy them
3408c2ecf20Sopenharmony_ci		 * to 61:62.
3418c2ecf20Sopenharmony_ci		 */
3428c2ecf20Sopenharmony_ci		val |= (LBR_FROM_SIGNEXT_2MSB & val) << 2;
3438c2ecf20Sopenharmony_ci	}
3448c2ecf20Sopenharmony_ci	return val;
3458c2ecf20Sopenharmony_ci}
3468c2ecf20Sopenharmony_ci
3478c2ecf20Sopenharmony_ci/*
3488c2ecf20Sopenharmony_ci * If quirk is needed, ensure sign extension is 61 bits:
3498c2ecf20Sopenharmony_ci */
3508c2ecf20Sopenharmony_cistatic u64 lbr_from_signext_quirk_rd(u64 val)
3518c2ecf20Sopenharmony_ci{
3528c2ecf20Sopenharmony_ci	if (static_branch_unlikely(&lbr_from_quirk_key)) {
3538c2ecf20Sopenharmony_ci		/*
3548c2ecf20Sopenharmony_ci		 * Quirk is on when TSX is not enabled. Therefore TSX
3558c2ecf20Sopenharmony_ci		 * flags must be read as OFF.
3568c2ecf20Sopenharmony_ci		 */
3578c2ecf20Sopenharmony_ci		val &= ~(LBR_FROM_FLAG_IN_TX | LBR_FROM_FLAG_ABORT);
3588c2ecf20Sopenharmony_ci	}
3598c2ecf20Sopenharmony_ci	return val;
3608c2ecf20Sopenharmony_ci}
3618c2ecf20Sopenharmony_ci
3628c2ecf20Sopenharmony_cistatic __always_inline void wrlbr_from(unsigned int idx, u64 val)
3638c2ecf20Sopenharmony_ci{
3648c2ecf20Sopenharmony_ci	val = lbr_from_signext_quirk_wr(val);
3658c2ecf20Sopenharmony_ci	wrmsrl(x86_pmu.lbr_from + idx, val);
3668c2ecf20Sopenharmony_ci}
3678c2ecf20Sopenharmony_ci
3688c2ecf20Sopenharmony_cistatic __always_inline void wrlbr_to(unsigned int idx, u64 val)
3698c2ecf20Sopenharmony_ci{
3708c2ecf20Sopenharmony_ci	wrmsrl(x86_pmu.lbr_to + idx, val);
3718c2ecf20Sopenharmony_ci}
3728c2ecf20Sopenharmony_ci
3738c2ecf20Sopenharmony_cistatic __always_inline void wrlbr_info(unsigned int idx, u64 val)
3748c2ecf20Sopenharmony_ci{
3758c2ecf20Sopenharmony_ci	wrmsrl(x86_pmu.lbr_info + idx, val);
3768c2ecf20Sopenharmony_ci}
3778c2ecf20Sopenharmony_ci
3788c2ecf20Sopenharmony_cistatic __always_inline u64 rdlbr_from(unsigned int idx, struct lbr_entry *lbr)
3798c2ecf20Sopenharmony_ci{
3808c2ecf20Sopenharmony_ci	u64 val;
3818c2ecf20Sopenharmony_ci
3828c2ecf20Sopenharmony_ci	if (lbr)
3838c2ecf20Sopenharmony_ci		return lbr->from;
3848c2ecf20Sopenharmony_ci
3858c2ecf20Sopenharmony_ci	rdmsrl(x86_pmu.lbr_from + idx, val);
3868c2ecf20Sopenharmony_ci
3878c2ecf20Sopenharmony_ci	return lbr_from_signext_quirk_rd(val);
3888c2ecf20Sopenharmony_ci}
3898c2ecf20Sopenharmony_ci
3908c2ecf20Sopenharmony_cistatic __always_inline u64 rdlbr_to(unsigned int idx, struct lbr_entry *lbr)
3918c2ecf20Sopenharmony_ci{
3928c2ecf20Sopenharmony_ci	u64 val;
3938c2ecf20Sopenharmony_ci
3948c2ecf20Sopenharmony_ci	if (lbr)
3958c2ecf20Sopenharmony_ci		return lbr->to;
3968c2ecf20Sopenharmony_ci
3978c2ecf20Sopenharmony_ci	rdmsrl(x86_pmu.lbr_to + idx, val);
3988c2ecf20Sopenharmony_ci
3998c2ecf20Sopenharmony_ci	return val;
4008c2ecf20Sopenharmony_ci}
4018c2ecf20Sopenharmony_ci
4028c2ecf20Sopenharmony_cistatic __always_inline u64 rdlbr_info(unsigned int idx, struct lbr_entry *lbr)
4038c2ecf20Sopenharmony_ci{
4048c2ecf20Sopenharmony_ci	u64 val;
4058c2ecf20Sopenharmony_ci
4068c2ecf20Sopenharmony_ci	if (lbr)
4078c2ecf20Sopenharmony_ci		return lbr->info;
4088c2ecf20Sopenharmony_ci
4098c2ecf20Sopenharmony_ci	rdmsrl(x86_pmu.lbr_info + idx, val);
4108c2ecf20Sopenharmony_ci
4118c2ecf20Sopenharmony_ci	return val;
4128c2ecf20Sopenharmony_ci}
4138c2ecf20Sopenharmony_ci
4148c2ecf20Sopenharmony_cistatic inline void
4158c2ecf20Sopenharmony_ciwrlbr_all(struct lbr_entry *lbr, unsigned int idx, bool need_info)
4168c2ecf20Sopenharmony_ci{
4178c2ecf20Sopenharmony_ci	wrlbr_from(idx, lbr->from);
4188c2ecf20Sopenharmony_ci	wrlbr_to(idx, lbr->to);
4198c2ecf20Sopenharmony_ci	if (need_info)
4208c2ecf20Sopenharmony_ci		wrlbr_info(idx, lbr->info);
4218c2ecf20Sopenharmony_ci}
4228c2ecf20Sopenharmony_ci
4238c2ecf20Sopenharmony_cistatic inline bool
4248c2ecf20Sopenharmony_cirdlbr_all(struct lbr_entry *lbr, unsigned int idx, bool need_info)
4258c2ecf20Sopenharmony_ci{
4268c2ecf20Sopenharmony_ci	u64 from = rdlbr_from(idx, NULL);
4278c2ecf20Sopenharmony_ci
4288c2ecf20Sopenharmony_ci	/* Don't read invalid entry */
4298c2ecf20Sopenharmony_ci	if (!from)
4308c2ecf20Sopenharmony_ci		return false;
4318c2ecf20Sopenharmony_ci
4328c2ecf20Sopenharmony_ci	lbr->from = from;
4338c2ecf20Sopenharmony_ci	lbr->to = rdlbr_to(idx, NULL);
4348c2ecf20Sopenharmony_ci	if (need_info)
4358c2ecf20Sopenharmony_ci		lbr->info = rdlbr_info(idx, NULL);
4368c2ecf20Sopenharmony_ci
4378c2ecf20Sopenharmony_ci	return true;
4388c2ecf20Sopenharmony_ci}
4398c2ecf20Sopenharmony_ci
4408c2ecf20Sopenharmony_civoid intel_pmu_lbr_restore(void *ctx)
4418c2ecf20Sopenharmony_ci{
4428c2ecf20Sopenharmony_ci	bool need_info = x86_pmu.intel_cap.lbr_format == LBR_FORMAT_INFO;
4438c2ecf20Sopenharmony_ci	struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
4448c2ecf20Sopenharmony_ci	struct x86_perf_task_context *task_ctx = ctx;
4458c2ecf20Sopenharmony_ci	int i;
4468c2ecf20Sopenharmony_ci	unsigned lbr_idx, mask;
4478c2ecf20Sopenharmony_ci	u64 tos = task_ctx->tos;
4488c2ecf20Sopenharmony_ci
4498c2ecf20Sopenharmony_ci	mask = x86_pmu.lbr_nr - 1;
4508c2ecf20Sopenharmony_ci	for (i = 0; i < task_ctx->valid_lbrs; i++) {
4518c2ecf20Sopenharmony_ci		lbr_idx = (tos - i) & mask;
4528c2ecf20Sopenharmony_ci		wrlbr_all(&task_ctx->lbr[i], lbr_idx, need_info);
4538c2ecf20Sopenharmony_ci	}
4548c2ecf20Sopenharmony_ci
4558c2ecf20Sopenharmony_ci	for (; i < x86_pmu.lbr_nr; i++) {
4568c2ecf20Sopenharmony_ci		lbr_idx = (tos - i) & mask;
4578c2ecf20Sopenharmony_ci		wrlbr_from(lbr_idx, 0);
4588c2ecf20Sopenharmony_ci		wrlbr_to(lbr_idx, 0);
4598c2ecf20Sopenharmony_ci		if (x86_pmu.intel_cap.lbr_format == LBR_FORMAT_INFO)
4608c2ecf20Sopenharmony_ci			wrlbr_info(lbr_idx, 0);
4618c2ecf20Sopenharmony_ci	}
4628c2ecf20Sopenharmony_ci
4638c2ecf20Sopenharmony_ci	wrmsrl(x86_pmu.lbr_tos, tos);
4648c2ecf20Sopenharmony_ci
4658c2ecf20Sopenharmony_ci	if (cpuc->lbr_select)
4668c2ecf20Sopenharmony_ci		wrmsrl(MSR_LBR_SELECT, task_ctx->lbr_sel);
4678c2ecf20Sopenharmony_ci}
4688c2ecf20Sopenharmony_ci
4698c2ecf20Sopenharmony_cistatic void intel_pmu_arch_lbr_restore(void *ctx)
4708c2ecf20Sopenharmony_ci{
4718c2ecf20Sopenharmony_ci	struct x86_perf_task_context_arch_lbr *task_ctx = ctx;
4728c2ecf20Sopenharmony_ci	struct lbr_entry *entries = task_ctx->entries;
4738c2ecf20Sopenharmony_ci	int i;
4748c2ecf20Sopenharmony_ci
4758c2ecf20Sopenharmony_ci	/* Fast reset the LBRs before restore if the call stack is not full. */
4768c2ecf20Sopenharmony_ci	if (!entries[x86_pmu.lbr_nr - 1].from)
4778c2ecf20Sopenharmony_ci		intel_pmu_arch_lbr_reset();
4788c2ecf20Sopenharmony_ci
4798c2ecf20Sopenharmony_ci	for (i = 0; i < x86_pmu.lbr_nr; i++) {
4808c2ecf20Sopenharmony_ci		if (!entries[i].from)
4818c2ecf20Sopenharmony_ci			break;
4828c2ecf20Sopenharmony_ci		wrlbr_all(&entries[i], i, true);
4838c2ecf20Sopenharmony_ci	}
4848c2ecf20Sopenharmony_ci}
4858c2ecf20Sopenharmony_ci
4868c2ecf20Sopenharmony_ci/*
4878c2ecf20Sopenharmony_ci * Restore the Architecture LBR state from the xsave area in the perf
4888c2ecf20Sopenharmony_ci * context data for the task via the XRSTORS instruction.
4898c2ecf20Sopenharmony_ci */
4908c2ecf20Sopenharmony_cistatic void intel_pmu_arch_lbr_xrstors(void *ctx)
4918c2ecf20Sopenharmony_ci{
4928c2ecf20Sopenharmony_ci	struct x86_perf_task_context_arch_lbr_xsave *task_ctx = ctx;
4938c2ecf20Sopenharmony_ci
4948c2ecf20Sopenharmony_ci	copy_kernel_to_dynamic_supervisor(&task_ctx->xsave, XFEATURE_MASK_LBR);
4958c2ecf20Sopenharmony_ci}
4968c2ecf20Sopenharmony_ci
4978c2ecf20Sopenharmony_cistatic __always_inline bool lbr_is_reset_in_cstate(void *ctx)
4988c2ecf20Sopenharmony_ci{
4998c2ecf20Sopenharmony_ci	if (static_cpu_has(X86_FEATURE_ARCH_LBR))
5008c2ecf20Sopenharmony_ci		return x86_pmu.lbr_deep_c_reset && !rdlbr_from(0, NULL);
5018c2ecf20Sopenharmony_ci
5028c2ecf20Sopenharmony_ci	return !rdlbr_from(((struct x86_perf_task_context *)ctx)->tos, NULL);
5038c2ecf20Sopenharmony_ci}
5048c2ecf20Sopenharmony_ci
5058c2ecf20Sopenharmony_cistatic void __intel_pmu_lbr_restore(void *ctx)
5068c2ecf20Sopenharmony_ci{
5078c2ecf20Sopenharmony_ci	struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
5088c2ecf20Sopenharmony_ci
5098c2ecf20Sopenharmony_ci	if (task_context_opt(ctx)->lbr_callstack_users == 0 ||
5108c2ecf20Sopenharmony_ci	    task_context_opt(ctx)->lbr_stack_state == LBR_NONE) {
5118c2ecf20Sopenharmony_ci		intel_pmu_lbr_reset();
5128c2ecf20Sopenharmony_ci		return;
5138c2ecf20Sopenharmony_ci	}
5148c2ecf20Sopenharmony_ci
5158c2ecf20Sopenharmony_ci	/*
5168c2ecf20Sopenharmony_ci	 * Does not restore the LBR registers, if
5178c2ecf20Sopenharmony_ci	 * - No one else touched them, and
5188c2ecf20Sopenharmony_ci	 * - Was not cleared in Cstate
5198c2ecf20Sopenharmony_ci	 */
5208c2ecf20Sopenharmony_ci	if ((ctx == cpuc->last_task_ctx) &&
5218c2ecf20Sopenharmony_ci	    (task_context_opt(ctx)->log_id == cpuc->last_log_id) &&
5228c2ecf20Sopenharmony_ci	    !lbr_is_reset_in_cstate(ctx)) {
5238c2ecf20Sopenharmony_ci		task_context_opt(ctx)->lbr_stack_state = LBR_NONE;
5248c2ecf20Sopenharmony_ci		return;
5258c2ecf20Sopenharmony_ci	}
5268c2ecf20Sopenharmony_ci
5278c2ecf20Sopenharmony_ci	x86_pmu.lbr_restore(ctx);
5288c2ecf20Sopenharmony_ci
5298c2ecf20Sopenharmony_ci	task_context_opt(ctx)->lbr_stack_state = LBR_NONE;
5308c2ecf20Sopenharmony_ci}
5318c2ecf20Sopenharmony_ci
5328c2ecf20Sopenharmony_civoid intel_pmu_lbr_save(void *ctx)
5338c2ecf20Sopenharmony_ci{
5348c2ecf20Sopenharmony_ci	bool need_info = x86_pmu.intel_cap.lbr_format == LBR_FORMAT_INFO;
5358c2ecf20Sopenharmony_ci	struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
5368c2ecf20Sopenharmony_ci	struct x86_perf_task_context *task_ctx = ctx;
5378c2ecf20Sopenharmony_ci	unsigned lbr_idx, mask;
5388c2ecf20Sopenharmony_ci	u64 tos;
5398c2ecf20Sopenharmony_ci	int i;
5408c2ecf20Sopenharmony_ci
5418c2ecf20Sopenharmony_ci	mask = x86_pmu.lbr_nr - 1;
5428c2ecf20Sopenharmony_ci	tos = intel_pmu_lbr_tos();
5438c2ecf20Sopenharmony_ci	for (i = 0; i < x86_pmu.lbr_nr; i++) {
5448c2ecf20Sopenharmony_ci		lbr_idx = (tos - i) & mask;
5458c2ecf20Sopenharmony_ci		if (!rdlbr_all(&task_ctx->lbr[i], lbr_idx, need_info))
5468c2ecf20Sopenharmony_ci			break;
5478c2ecf20Sopenharmony_ci	}
5488c2ecf20Sopenharmony_ci	task_ctx->valid_lbrs = i;
5498c2ecf20Sopenharmony_ci	task_ctx->tos = tos;
5508c2ecf20Sopenharmony_ci
5518c2ecf20Sopenharmony_ci	if (cpuc->lbr_select)
5528c2ecf20Sopenharmony_ci		rdmsrl(MSR_LBR_SELECT, task_ctx->lbr_sel);
5538c2ecf20Sopenharmony_ci}
5548c2ecf20Sopenharmony_ci
5558c2ecf20Sopenharmony_cistatic void intel_pmu_arch_lbr_save(void *ctx)
5568c2ecf20Sopenharmony_ci{
5578c2ecf20Sopenharmony_ci	struct x86_perf_task_context_arch_lbr *task_ctx = ctx;
5588c2ecf20Sopenharmony_ci	struct lbr_entry *entries = task_ctx->entries;
5598c2ecf20Sopenharmony_ci	int i;
5608c2ecf20Sopenharmony_ci
5618c2ecf20Sopenharmony_ci	for (i = 0; i < x86_pmu.lbr_nr; i++) {
5628c2ecf20Sopenharmony_ci		if (!rdlbr_all(&entries[i], i, true))
5638c2ecf20Sopenharmony_ci			break;
5648c2ecf20Sopenharmony_ci	}
5658c2ecf20Sopenharmony_ci
5668c2ecf20Sopenharmony_ci	/* LBR call stack is not full. Reset is required in restore. */
5678c2ecf20Sopenharmony_ci	if (i < x86_pmu.lbr_nr)
5688c2ecf20Sopenharmony_ci		entries[x86_pmu.lbr_nr - 1].from = 0;
5698c2ecf20Sopenharmony_ci}
5708c2ecf20Sopenharmony_ci
5718c2ecf20Sopenharmony_ci/*
5728c2ecf20Sopenharmony_ci * Save the Architecture LBR state to the xsave area in the perf
5738c2ecf20Sopenharmony_ci * context data for the task via the XSAVES instruction.
5748c2ecf20Sopenharmony_ci */
5758c2ecf20Sopenharmony_cistatic void intel_pmu_arch_lbr_xsaves(void *ctx)
5768c2ecf20Sopenharmony_ci{
5778c2ecf20Sopenharmony_ci	struct x86_perf_task_context_arch_lbr_xsave *task_ctx = ctx;
5788c2ecf20Sopenharmony_ci
5798c2ecf20Sopenharmony_ci	copy_dynamic_supervisor_to_kernel(&task_ctx->xsave, XFEATURE_MASK_LBR);
5808c2ecf20Sopenharmony_ci}
5818c2ecf20Sopenharmony_ci
5828c2ecf20Sopenharmony_cistatic void __intel_pmu_lbr_save(void *ctx)
5838c2ecf20Sopenharmony_ci{
5848c2ecf20Sopenharmony_ci	struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
5858c2ecf20Sopenharmony_ci
5868c2ecf20Sopenharmony_ci	if (task_context_opt(ctx)->lbr_callstack_users == 0) {
5878c2ecf20Sopenharmony_ci		task_context_opt(ctx)->lbr_stack_state = LBR_NONE;
5888c2ecf20Sopenharmony_ci		return;
5898c2ecf20Sopenharmony_ci	}
5908c2ecf20Sopenharmony_ci
5918c2ecf20Sopenharmony_ci	x86_pmu.lbr_save(ctx);
5928c2ecf20Sopenharmony_ci
5938c2ecf20Sopenharmony_ci	task_context_opt(ctx)->lbr_stack_state = LBR_VALID;
5948c2ecf20Sopenharmony_ci
5958c2ecf20Sopenharmony_ci	cpuc->last_task_ctx = ctx;
5968c2ecf20Sopenharmony_ci	cpuc->last_log_id = ++task_context_opt(ctx)->log_id;
5978c2ecf20Sopenharmony_ci}
5988c2ecf20Sopenharmony_ci
5998c2ecf20Sopenharmony_civoid intel_pmu_lbr_swap_task_ctx(struct perf_event_context *prev,
6008c2ecf20Sopenharmony_ci				 struct perf_event_context *next)
6018c2ecf20Sopenharmony_ci{
6028c2ecf20Sopenharmony_ci	void *prev_ctx_data, *next_ctx_data;
6038c2ecf20Sopenharmony_ci
6048c2ecf20Sopenharmony_ci	swap(prev->task_ctx_data, next->task_ctx_data);
6058c2ecf20Sopenharmony_ci
6068c2ecf20Sopenharmony_ci	/*
6078c2ecf20Sopenharmony_ci	 * Architecture specific synchronization makes sense in
6088c2ecf20Sopenharmony_ci	 * case both prev->task_ctx_data and next->task_ctx_data
6098c2ecf20Sopenharmony_ci	 * pointers are allocated.
6108c2ecf20Sopenharmony_ci	 */
6118c2ecf20Sopenharmony_ci
6128c2ecf20Sopenharmony_ci	prev_ctx_data = next->task_ctx_data;
6138c2ecf20Sopenharmony_ci	next_ctx_data = prev->task_ctx_data;
6148c2ecf20Sopenharmony_ci
6158c2ecf20Sopenharmony_ci	if (!prev_ctx_data || !next_ctx_data)
6168c2ecf20Sopenharmony_ci		return;
6178c2ecf20Sopenharmony_ci
6188c2ecf20Sopenharmony_ci	swap(task_context_opt(prev_ctx_data)->lbr_callstack_users,
6198c2ecf20Sopenharmony_ci	     task_context_opt(next_ctx_data)->lbr_callstack_users);
6208c2ecf20Sopenharmony_ci}
6218c2ecf20Sopenharmony_ci
6228c2ecf20Sopenharmony_civoid intel_pmu_lbr_sched_task(struct perf_event_context *ctx, bool sched_in)
6238c2ecf20Sopenharmony_ci{
6248c2ecf20Sopenharmony_ci	struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
6258c2ecf20Sopenharmony_ci	void *task_ctx;
6268c2ecf20Sopenharmony_ci
6278c2ecf20Sopenharmony_ci	if (!cpuc->lbr_users)
6288c2ecf20Sopenharmony_ci		return;
6298c2ecf20Sopenharmony_ci
6308c2ecf20Sopenharmony_ci	/*
6318c2ecf20Sopenharmony_ci	 * If LBR callstack feature is enabled and the stack was saved when
6328c2ecf20Sopenharmony_ci	 * the task was scheduled out, restore the stack. Otherwise flush
6338c2ecf20Sopenharmony_ci	 * the LBR stack.
6348c2ecf20Sopenharmony_ci	 */
6358c2ecf20Sopenharmony_ci	task_ctx = ctx ? ctx->task_ctx_data : NULL;
6368c2ecf20Sopenharmony_ci	if (task_ctx) {
6378c2ecf20Sopenharmony_ci		if (sched_in)
6388c2ecf20Sopenharmony_ci			__intel_pmu_lbr_restore(task_ctx);
6398c2ecf20Sopenharmony_ci		else
6408c2ecf20Sopenharmony_ci			__intel_pmu_lbr_save(task_ctx);
6418c2ecf20Sopenharmony_ci		return;
6428c2ecf20Sopenharmony_ci	}
6438c2ecf20Sopenharmony_ci
6448c2ecf20Sopenharmony_ci	/*
6458c2ecf20Sopenharmony_ci	 * Since a context switch can flip the address space and LBR entries
6468c2ecf20Sopenharmony_ci	 * are not tagged with an identifier, we need to wipe the LBR, even for
6478c2ecf20Sopenharmony_ci	 * per-cpu events. You simply cannot resolve the branches from the old
6488c2ecf20Sopenharmony_ci	 * address space.
6498c2ecf20Sopenharmony_ci	 */
6508c2ecf20Sopenharmony_ci	if (sched_in)
6518c2ecf20Sopenharmony_ci		intel_pmu_lbr_reset();
6528c2ecf20Sopenharmony_ci}
6538c2ecf20Sopenharmony_ci
6548c2ecf20Sopenharmony_cistatic inline bool branch_user_callstack(unsigned br_sel)
6558c2ecf20Sopenharmony_ci{
6568c2ecf20Sopenharmony_ci	return (br_sel & X86_BR_USER) && (br_sel & X86_BR_CALL_STACK);
6578c2ecf20Sopenharmony_ci}
6588c2ecf20Sopenharmony_ci
6598c2ecf20Sopenharmony_civoid intel_pmu_lbr_add(struct perf_event *event)
6608c2ecf20Sopenharmony_ci{
6618c2ecf20Sopenharmony_ci	struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
6628c2ecf20Sopenharmony_ci
6638c2ecf20Sopenharmony_ci	if (!x86_pmu.lbr_nr)
6648c2ecf20Sopenharmony_ci		return;
6658c2ecf20Sopenharmony_ci
6668c2ecf20Sopenharmony_ci	if (event->hw.flags & PERF_X86_EVENT_LBR_SELECT)
6678c2ecf20Sopenharmony_ci		cpuc->lbr_select = 1;
6688c2ecf20Sopenharmony_ci
6698c2ecf20Sopenharmony_ci	cpuc->br_sel = event->hw.branch_reg.reg;
6708c2ecf20Sopenharmony_ci
6718c2ecf20Sopenharmony_ci	if (branch_user_callstack(cpuc->br_sel) && event->ctx->task_ctx_data)
6728c2ecf20Sopenharmony_ci		task_context_opt(event->ctx->task_ctx_data)->lbr_callstack_users++;
6738c2ecf20Sopenharmony_ci
6748c2ecf20Sopenharmony_ci	/*
6758c2ecf20Sopenharmony_ci	 * Request pmu::sched_task() callback, which will fire inside the
6768c2ecf20Sopenharmony_ci	 * regular perf event scheduling, so that call will:
6778c2ecf20Sopenharmony_ci	 *
6788c2ecf20Sopenharmony_ci	 *  - restore or wipe; when LBR-callstack,
6798c2ecf20Sopenharmony_ci	 *  - wipe; otherwise,
6808c2ecf20Sopenharmony_ci	 *
6818c2ecf20Sopenharmony_ci	 * when this is from __perf_event_task_sched_in().
6828c2ecf20Sopenharmony_ci	 *
6838c2ecf20Sopenharmony_ci	 * However, if this is from perf_install_in_context(), no such callback
6848c2ecf20Sopenharmony_ci	 * will follow and we'll need to reset the LBR here if this is the
6858c2ecf20Sopenharmony_ci	 * first LBR event.
6868c2ecf20Sopenharmony_ci	 *
6878c2ecf20Sopenharmony_ci	 * The problem is, we cannot tell these cases apart... but we can
6888c2ecf20Sopenharmony_ci	 * exclude the biggest chunk of cases by looking at
6898c2ecf20Sopenharmony_ci	 * event->total_time_running. An event that has accrued runtime cannot
6908c2ecf20Sopenharmony_ci	 * be 'new'. Conversely, a new event can get installed through the
6918c2ecf20Sopenharmony_ci	 * context switch path for the first time.
6928c2ecf20Sopenharmony_ci	 */
6938c2ecf20Sopenharmony_ci	if (x86_pmu.intel_cap.pebs_baseline && event->attr.precise_ip > 0)
6948c2ecf20Sopenharmony_ci		cpuc->lbr_pebs_users++;
6958c2ecf20Sopenharmony_ci	perf_sched_cb_inc(event->ctx->pmu);
6968c2ecf20Sopenharmony_ci	if (!cpuc->lbr_users++ && !event->total_time_running)
6978c2ecf20Sopenharmony_ci		intel_pmu_lbr_reset();
6988c2ecf20Sopenharmony_ci}
6998c2ecf20Sopenharmony_ci
7008c2ecf20Sopenharmony_civoid release_lbr_buffers(void)
7018c2ecf20Sopenharmony_ci{
7028c2ecf20Sopenharmony_ci	struct kmem_cache *kmem_cache;
7038c2ecf20Sopenharmony_ci	struct cpu_hw_events *cpuc;
7048c2ecf20Sopenharmony_ci	int cpu;
7058c2ecf20Sopenharmony_ci
7068c2ecf20Sopenharmony_ci	if (!static_cpu_has(X86_FEATURE_ARCH_LBR))
7078c2ecf20Sopenharmony_ci		return;
7088c2ecf20Sopenharmony_ci
7098c2ecf20Sopenharmony_ci	for_each_possible_cpu(cpu) {
7108c2ecf20Sopenharmony_ci		cpuc = per_cpu_ptr(&cpu_hw_events, cpu);
7118c2ecf20Sopenharmony_ci		kmem_cache = x86_get_pmu(cpu)->task_ctx_cache;
7128c2ecf20Sopenharmony_ci		if (kmem_cache && cpuc->lbr_xsave) {
7138c2ecf20Sopenharmony_ci			kmem_cache_free(kmem_cache, cpuc->lbr_xsave);
7148c2ecf20Sopenharmony_ci			cpuc->lbr_xsave = NULL;
7158c2ecf20Sopenharmony_ci		}
7168c2ecf20Sopenharmony_ci	}
7178c2ecf20Sopenharmony_ci}
7188c2ecf20Sopenharmony_ci
7198c2ecf20Sopenharmony_civoid reserve_lbr_buffers(void)
7208c2ecf20Sopenharmony_ci{
7218c2ecf20Sopenharmony_ci	struct kmem_cache *kmem_cache;
7228c2ecf20Sopenharmony_ci	struct cpu_hw_events *cpuc;
7238c2ecf20Sopenharmony_ci	int cpu;
7248c2ecf20Sopenharmony_ci
7258c2ecf20Sopenharmony_ci	if (!static_cpu_has(X86_FEATURE_ARCH_LBR))
7268c2ecf20Sopenharmony_ci		return;
7278c2ecf20Sopenharmony_ci
7288c2ecf20Sopenharmony_ci	for_each_possible_cpu(cpu) {
7298c2ecf20Sopenharmony_ci		cpuc = per_cpu_ptr(&cpu_hw_events, cpu);
7308c2ecf20Sopenharmony_ci		kmem_cache = x86_get_pmu(cpu)->task_ctx_cache;
7318c2ecf20Sopenharmony_ci		if (!kmem_cache || cpuc->lbr_xsave)
7328c2ecf20Sopenharmony_ci			continue;
7338c2ecf20Sopenharmony_ci
7348c2ecf20Sopenharmony_ci		cpuc->lbr_xsave = kmem_cache_alloc_node(kmem_cache,
7358c2ecf20Sopenharmony_ci							GFP_KERNEL | __GFP_ZERO,
7368c2ecf20Sopenharmony_ci							cpu_to_node(cpu));
7378c2ecf20Sopenharmony_ci	}
7388c2ecf20Sopenharmony_ci}
7398c2ecf20Sopenharmony_ci
7408c2ecf20Sopenharmony_civoid intel_pmu_lbr_del(struct perf_event *event)
7418c2ecf20Sopenharmony_ci{
7428c2ecf20Sopenharmony_ci	struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
7438c2ecf20Sopenharmony_ci
7448c2ecf20Sopenharmony_ci	if (!x86_pmu.lbr_nr)
7458c2ecf20Sopenharmony_ci		return;
7468c2ecf20Sopenharmony_ci
7478c2ecf20Sopenharmony_ci	if (branch_user_callstack(cpuc->br_sel) &&
7488c2ecf20Sopenharmony_ci	    event->ctx->task_ctx_data)
7498c2ecf20Sopenharmony_ci		task_context_opt(event->ctx->task_ctx_data)->lbr_callstack_users--;
7508c2ecf20Sopenharmony_ci
7518c2ecf20Sopenharmony_ci	if (event->hw.flags & PERF_X86_EVENT_LBR_SELECT)
7528c2ecf20Sopenharmony_ci		cpuc->lbr_select = 0;
7538c2ecf20Sopenharmony_ci
7548c2ecf20Sopenharmony_ci	if (x86_pmu.intel_cap.pebs_baseline && event->attr.precise_ip > 0)
7558c2ecf20Sopenharmony_ci		cpuc->lbr_pebs_users--;
7568c2ecf20Sopenharmony_ci	cpuc->lbr_users--;
7578c2ecf20Sopenharmony_ci	WARN_ON_ONCE(cpuc->lbr_users < 0);
7588c2ecf20Sopenharmony_ci	WARN_ON_ONCE(cpuc->lbr_pebs_users < 0);
7598c2ecf20Sopenharmony_ci	perf_sched_cb_dec(event->ctx->pmu);
7608c2ecf20Sopenharmony_ci}
7618c2ecf20Sopenharmony_ci
7628c2ecf20Sopenharmony_cistatic inline bool vlbr_exclude_host(void)
7638c2ecf20Sopenharmony_ci{
7648c2ecf20Sopenharmony_ci	struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
7658c2ecf20Sopenharmony_ci
7668c2ecf20Sopenharmony_ci	return test_bit(INTEL_PMC_IDX_FIXED_VLBR,
7678c2ecf20Sopenharmony_ci		(unsigned long *)&cpuc->intel_ctrl_guest_mask);
7688c2ecf20Sopenharmony_ci}
7698c2ecf20Sopenharmony_ci
7708c2ecf20Sopenharmony_civoid intel_pmu_lbr_enable_all(bool pmi)
7718c2ecf20Sopenharmony_ci{
7728c2ecf20Sopenharmony_ci	struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
7738c2ecf20Sopenharmony_ci
7748c2ecf20Sopenharmony_ci	if (cpuc->lbr_users && !vlbr_exclude_host())
7758c2ecf20Sopenharmony_ci		__intel_pmu_lbr_enable(pmi);
7768c2ecf20Sopenharmony_ci}
7778c2ecf20Sopenharmony_ci
7788c2ecf20Sopenharmony_civoid intel_pmu_lbr_disable_all(void)
7798c2ecf20Sopenharmony_ci{
7808c2ecf20Sopenharmony_ci	struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
7818c2ecf20Sopenharmony_ci
7828c2ecf20Sopenharmony_ci	if (cpuc->lbr_users && !vlbr_exclude_host())
7838c2ecf20Sopenharmony_ci		__intel_pmu_lbr_disable();
7848c2ecf20Sopenharmony_ci}
7858c2ecf20Sopenharmony_ci
7868c2ecf20Sopenharmony_civoid intel_pmu_lbr_read_32(struct cpu_hw_events *cpuc)
7878c2ecf20Sopenharmony_ci{
7888c2ecf20Sopenharmony_ci	unsigned long mask = x86_pmu.lbr_nr - 1;
7898c2ecf20Sopenharmony_ci	u64 tos = intel_pmu_lbr_tos();
7908c2ecf20Sopenharmony_ci	int i;
7918c2ecf20Sopenharmony_ci
7928c2ecf20Sopenharmony_ci	for (i = 0; i < x86_pmu.lbr_nr; i++) {
7938c2ecf20Sopenharmony_ci		unsigned long lbr_idx = (tos - i) & mask;
7948c2ecf20Sopenharmony_ci		union {
7958c2ecf20Sopenharmony_ci			struct {
7968c2ecf20Sopenharmony_ci				u32 from;
7978c2ecf20Sopenharmony_ci				u32 to;
7988c2ecf20Sopenharmony_ci			};
7998c2ecf20Sopenharmony_ci			u64     lbr;
8008c2ecf20Sopenharmony_ci		} msr_lastbranch;
8018c2ecf20Sopenharmony_ci
8028c2ecf20Sopenharmony_ci		rdmsrl(x86_pmu.lbr_from + lbr_idx, msr_lastbranch.lbr);
8038c2ecf20Sopenharmony_ci
8048c2ecf20Sopenharmony_ci		cpuc->lbr_entries[i].from	= msr_lastbranch.from;
8058c2ecf20Sopenharmony_ci		cpuc->lbr_entries[i].to		= msr_lastbranch.to;
8068c2ecf20Sopenharmony_ci		cpuc->lbr_entries[i].mispred	= 0;
8078c2ecf20Sopenharmony_ci		cpuc->lbr_entries[i].predicted	= 0;
8088c2ecf20Sopenharmony_ci		cpuc->lbr_entries[i].in_tx	= 0;
8098c2ecf20Sopenharmony_ci		cpuc->lbr_entries[i].abort	= 0;
8108c2ecf20Sopenharmony_ci		cpuc->lbr_entries[i].cycles	= 0;
8118c2ecf20Sopenharmony_ci		cpuc->lbr_entries[i].type	= 0;
8128c2ecf20Sopenharmony_ci		cpuc->lbr_entries[i].reserved	= 0;
8138c2ecf20Sopenharmony_ci	}
8148c2ecf20Sopenharmony_ci	cpuc->lbr_stack.nr = i;
8158c2ecf20Sopenharmony_ci	cpuc->lbr_stack.hw_idx = tos;
8168c2ecf20Sopenharmony_ci}
8178c2ecf20Sopenharmony_ci
8188c2ecf20Sopenharmony_ci/*
8198c2ecf20Sopenharmony_ci * Due to lack of segmentation in Linux the effective address (offset)
8208c2ecf20Sopenharmony_ci * is the same as the linear address, allowing us to merge the LIP and EIP
8218c2ecf20Sopenharmony_ci * LBR formats.
8228c2ecf20Sopenharmony_ci */
8238c2ecf20Sopenharmony_civoid intel_pmu_lbr_read_64(struct cpu_hw_events *cpuc)
8248c2ecf20Sopenharmony_ci{
8258c2ecf20Sopenharmony_ci	bool need_info = false, call_stack = false;
8268c2ecf20Sopenharmony_ci	unsigned long mask = x86_pmu.lbr_nr - 1;
8278c2ecf20Sopenharmony_ci	int lbr_format = x86_pmu.intel_cap.lbr_format;
8288c2ecf20Sopenharmony_ci	u64 tos = intel_pmu_lbr_tos();
8298c2ecf20Sopenharmony_ci	int i;
8308c2ecf20Sopenharmony_ci	int out = 0;
8318c2ecf20Sopenharmony_ci	int num = x86_pmu.lbr_nr;
8328c2ecf20Sopenharmony_ci
8338c2ecf20Sopenharmony_ci	if (cpuc->lbr_sel) {
8348c2ecf20Sopenharmony_ci		need_info = !(cpuc->lbr_sel->config & LBR_NO_INFO);
8358c2ecf20Sopenharmony_ci		if (cpuc->lbr_sel->config & LBR_CALL_STACK)
8368c2ecf20Sopenharmony_ci			call_stack = true;
8378c2ecf20Sopenharmony_ci	}
8388c2ecf20Sopenharmony_ci
8398c2ecf20Sopenharmony_ci	for (i = 0; i < num; i++) {
8408c2ecf20Sopenharmony_ci		unsigned long lbr_idx = (tos - i) & mask;
8418c2ecf20Sopenharmony_ci		u64 from, to, mis = 0, pred = 0, in_tx = 0, abort = 0;
8428c2ecf20Sopenharmony_ci		int skip = 0;
8438c2ecf20Sopenharmony_ci		u16 cycles = 0;
8448c2ecf20Sopenharmony_ci		int lbr_flags = lbr_desc[lbr_format];
8458c2ecf20Sopenharmony_ci
8468c2ecf20Sopenharmony_ci		from = rdlbr_from(lbr_idx, NULL);
8478c2ecf20Sopenharmony_ci		to   = rdlbr_to(lbr_idx, NULL);
8488c2ecf20Sopenharmony_ci
8498c2ecf20Sopenharmony_ci		/*
8508c2ecf20Sopenharmony_ci		 * Read LBR call stack entries
8518c2ecf20Sopenharmony_ci		 * until invalid entry (0s) is detected.
8528c2ecf20Sopenharmony_ci		 */
8538c2ecf20Sopenharmony_ci		if (call_stack && !from)
8548c2ecf20Sopenharmony_ci			break;
8558c2ecf20Sopenharmony_ci
8568c2ecf20Sopenharmony_ci		if (lbr_format == LBR_FORMAT_INFO && need_info) {
8578c2ecf20Sopenharmony_ci			u64 info;
8588c2ecf20Sopenharmony_ci
8598c2ecf20Sopenharmony_ci			info = rdlbr_info(lbr_idx, NULL);
8608c2ecf20Sopenharmony_ci			mis = !!(info & LBR_INFO_MISPRED);
8618c2ecf20Sopenharmony_ci			pred = !mis;
8628c2ecf20Sopenharmony_ci			in_tx = !!(info & LBR_INFO_IN_TX);
8638c2ecf20Sopenharmony_ci			abort = !!(info & LBR_INFO_ABORT);
8648c2ecf20Sopenharmony_ci			cycles = (info & LBR_INFO_CYCLES);
8658c2ecf20Sopenharmony_ci		}
8668c2ecf20Sopenharmony_ci
8678c2ecf20Sopenharmony_ci		if (lbr_format == LBR_FORMAT_TIME) {
8688c2ecf20Sopenharmony_ci			mis = !!(from & LBR_FROM_FLAG_MISPRED);
8698c2ecf20Sopenharmony_ci			pred = !mis;
8708c2ecf20Sopenharmony_ci			skip = 1;
8718c2ecf20Sopenharmony_ci			cycles = ((to >> 48) & LBR_INFO_CYCLES);
8728c2ecf20Sopenharmony_ci
8738c2ecf20Sopenharmony_ci			to = (u64)((((s64)to) << 16) >> 16);
8748c2ecf20Sopenharmony_ci		}
8758c2ecf20Sopenharmony_ci
8768c2ecf20Sopenharmony_ci		if (lbr_flags & LBR_EIP_FLAGS) {
8778c2ecf20Sopenharmony_ci			mis = !!(from & LBR_FROM_FLAG_MISPRED);
8788c2ecf20Sopenharmony_ci			pred = !mis;
8798c2ecf20Sopenharmony_ci			skip = 1;
8808c2ecf20Sopenharmony_ci		}
8818c2ecf20Sopenharmony_ci		if (lbr_flags & LBR_TSX) {
8828c2ecf20Sopenharmony_ci			in_tx = !!(from & LBR_FROM_FLAG_IN_TX);
8838c2ecf20Sopenharmony_ci			abort = !!(from & LBR_FROM_FLAG_ABORT);
8848c2ecf20Sopenharmony_ci			skip = 3;
8858c2ecf20Sopenharmony_ci		}
8868c2ecf20Sopenharmony_ci		from = (u64)((((s64)from) << skip) >> skip);
8878c2ecf20Sopenharmony_ci
8888c2ecf20Sopenharmony_ci		/*
8898c2ecf20Sopenharmony_ci		 * Some CPUs report duplicated abort records,
8908c2ecf20Sopenharmony_ci		 * with the second entry not having an abort bit set.
8918c2ecf20Sopenharmony_ci		 * Skip them here. This loop runs backwards,
8928c2ecf20Sopenharmony_ci		 * so we need to undo the previous record.
8938c2ecf20Sopenharmony_ci		 * If the abort just happened outside the window
8948c2ecf20Sopenharmony_ci		 * the extra entry cannot be removed.
8958c2ecf20Sopenharmony_ci		 */
8968c2ecf20Sopenharmony_ci		if (abort && x86_pmu.lbr_double_abort && out > 0)
8978c2ecf20Sopenharmony_ci			out--;
8988c2ecf20Sopenharmony_ci
8998c2ecf20Sopenharmony_ci		cpuc->lbr_entries[out].from	 = from;
9008c2ecf20Sopenharmony_ci		cpuc->lbr_entries[out].to	 = to;
9018c2ecf20Sopenharmony_ci		cpuc->lbr_entries[out].mispred	 = mis;
9028c2ecf20Sopenharmony_ci		cpuc->lbr_entries[out].predicted = pred;
9038c2ecf20Sopenharmony_ci		cpuc->lbr_entries[out].in_tx	 = in_tx;
9048c2ecf20Sopenharmony_ci		cpuc->lbr_entries[out].abort	 = abort;
9058c2ecf20Sopenharmony_ci		cpuc->lbr_entries[out].cycles	 = cycles;
9068c2ecf20Sopenharmony_ci		cpuc->lbr_entries[out].type	 = 0;
9078c2ecf20Sopenharmony_ci		cpuc->lbr_entries[out].reserved	 = 0;
9088c2ecf20Sopenharmony_ci		out++;
9098c2ecf20Sopenharmony_ci	}
9108c2ecf20Sopenharmony_ci	cpuc->lbr_stack.nr = out;
9118c2ecf20Sopenharmony_ci	cpuc->lbr_stack.hw_idx = tos;
9128c2ecf20Sopenharmony_ci}
9138c2ecf20Sopenharmony_ci
9148c2ecf20Sopenharmony_cistatic __always_inline int get_lbr_br_type(u64 info)
9158c2ecf20Sopenharmony_ci{
9168c2ecf20Sopenharmony_ci	if (!static_cpu_has(X86_FEATURE_ARCH_LBR) || !x86_pmu.lbr_br_type)
9178c2ecf20Sopenharmony_ci		return 0;
9188c2ecf20Sopenharmony_ci
9198c2ecf20Sopenharmony_ci	return (info & LBR_INFO_BR_TYPE) >> LBR_INFO_BR_TYPE_OFFSET;
9208c2ecf20Sopenharmony_ci}
9218c2ecf20Sopenharmony_ci
9228c2ecf20Sopenharmony_cistatic __always_inline bool get_lbr_mispred(u64 info)
9238c2ecf20Sopenharmony_ci{
9248c2ecf20Sopenharmony_ci	if (static_cpu_has(X86_FEATURE_ARCH_LBR) && !x86_pmu.lbr_mispred)
9258c2ecf20Sopenharmony_ci		return 0;
9268c2ecf20Sopenharmony_ci
9278c2ecf20Sopenharmony_ci	return !!(info & LBR_INFO_MISPRED);
9288c2ecf20Sopenharmony_ci}
9298c2ecf20Sopenharmony_ci
9308c2ecf20Sopenharmony_cistatic __always_inline bool get_lbr_predicted(u64 info)
9318c2ecf20Sopenharmony_ci{
9328c2ecf20Sopenharmony_ci	if (static_cpu_has(X86_FEATURE_ARCH_LBR) && !x86_pmu.lbr_mispred)
9338c2ecf20Sopenharmony_ci		return 0;
9348c2ecf20Sopenharmony_ci
9358c2ecf20Sopenharmony_ci	return !(info & LBR_INFO_MISPRED);
9368c2ecf20Sopenharmony_ci}
9378c2ecf20Sopenharmony_ci
9388c2ecf20Sopenharmony_cistatic __always_inline u16 get_lbr_cycles(u64 info)
9398c2ecf20Sopenharmony_ci{
9408c2ecf20Sopenharmony_ci	if (static_cpu_has(X86_FEATURE_ARCH_LBR) &&
9418c2ecf20Sopenharmony_ci	    !(x86_pmu.lbr_timed_lbr && info & LBR_INFO_CYC_CNT_VALID))
9428c2ecf20Sopenharmony_ci		return 0;
9438c2ecf20Sopenharmony_ci
9448c2ecf20Sopenharmony_ci	return info & LBR_INFO_CYCLES;
9458c2ecf20Sopenharmony_ci}
9468c2ecf20Sopenharmony_ci
9478c2ecf20Sopenharmony_cistatic void intel_pmu_store_lbr(struct cpu_hw_events *cpuc,
9488c2ecf20Sopenharmony_ci				struct lbr_entry *entries)
9498c2ecf20Sopenharmony_ci{
9508c2ecf20Sopenharmony_ci	struct perf_branch_entry *e;
9518c2ecf20Sopenharmony_ci	struct lbr_entry *lbr;
9528c2ecf20Sopenharmony_ci	u64 from, to, info;
9538c2ecf20Sopenharmony_ci	int i;
9548c2ecf20Sopenharmony_ci
9558c2ecf20Sopenharmony_ci	for (i = 0; i < x86_pmu.lbr_nr; i++) {
9568c2ecf20Sopenharmony_ci		lbr = entries ? &entries[i] : NULL;
9578c2ecf20Sopenharmony_ci		e = &cpuc->lbr_entries[i];
9588c2ecf20Sopenharmony_ci
9598c2ecf20Sopenharmony_ci		from = rdlbr_from(i, lbr);
9608c2ecf20Sopenharmony_ci		/*
9618c2ecf20Sopenharmony_ci		 * Read LBR entries until invalid entry (0s) is detected.
9628c2ecf20Sopenharmony_ci		 */
9638c2ecf20Sopenharmony_ci		if (!from)
9648c2ecf20Sopenharmony_ci			break;
9658c2ecf20Sopenharmony_ci
9668c2ecf20Sopenharmony_ci		to = rdlbr_to(i, lbr);
9678c2ecf20Sopenharmony_ci		info = rdlbr_info(i, lbr);
9688c2ecf20Sopenharmony_ci
9698c2ecf20Sopenharmony_ci		e->from		= from;
9708c2ecf20Sopenharmony_ci		e->to		= to;
9718c2ecf20Sopenharmony_ci		e->mispred	= get_lbr_mispred(info);
9728c2ecf20Sopenharmony_ci		e->predicted	= get_lbr_predicted(info);
9738c2ecf20Sopenharmony_ci		e->in_tx	= !!(info & LBR_INFO_IN_TX);
9748c2ecf20Sopenharmony_ci		e->abort	= !!(info & LBR_INFO_ABORT);
9758c2ecf20Sopenharmony_ci		e->cycles	= get_lbr_cycles(info);
9768c2ecf20Sopenharmony_ci		e->type		= get_lbr_br_type(info);
9778c2ecf20Sopenharmony_ci		e->reserved	= 0;
9788c2ecf20Sopenharmony_ci	}
9798c2ecf20Sopenharmony_ci
9808c2ecf20Sopenharmony_ci	cpuc->lbr_stack.nr = i;
9818c2ecf20Sopenharmony_ci}
9828c2ecf20Sopenharmony_ci
9838c2ecf20Sopenharmony_cistatic void intel_pmu_arch_lbr_read(struct cpu_hw_events *cpuc)
9848c2ecf20Sopenharmony_ci{
9858c2ecf20Sopenharmony_ci	intel_pmu_store_lbr(cpuc, NULL);
9868c2ecf20Sopenharmony_ci}
9878c2ecf20Sopenharmony_ci
9888c2ecf20Sopenharmony_cistatic void intel_pmu_arch_lbr_read_xsave(struct cpu_hw_events *cpuc)
9898c2ecf20Sopenharmony_ci{
9908c2ecf20Sopenharmony_ci	struct x86_perf_task_context_arch_lbr_xsave *xsave = cpuc->lbr_xsave;
9918c2ecf20Sopenharmony_ci
9928c2ecf20Sopenharmony_ci	if (!xsave) {
9938c2ecf20Sopenharmony_ci		intel_pmu_store_lbr(cpuc, NULL);
9948c2ecf20Sopenharmony_ci		return;
9958c2ecf20Sopenharmony_ci	}
9968c2ecf20Sopenharmony_ci	copy_dynamic_supervisor_to_kernel(&xsave->xsave, XFEATURE_MASK_LBR);
9978c2ecf20Sopenharmony_ci
9988c2ecf20Sopenharmony_ci	intel_pmu_store_lbr(cpuc, xsave->lbr.entries);
9998c2ecf20Sopenharmony_ci}
10008c2ecf20Sopenharmony_ci
10018c2ecf20Sopenharmony_civoid intel_pmu_lbr_read(void)
10028c2ecf20Sopenharmony_ci{
10038c2ecf20Sopenharmony_ci	struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
10048c2ecf20Sopenharmony_ci
10058c2ecf20Sopenharmony_ci	/*
10068c2ecf20Sopenharmony_ci	 * Don't read when all LBRs users are using adaptive PEBS.
10078c2ecf20Sopenharmony_ci	 *
10088c2ecf20Sopenharmony_ci	 * This could be smarter and actually check the event,
10098c2ecf20Sopenharmony_ci	 * but this simple approach seems to work for now.
10108c2ecf20Sopenharmony_ci	 */
10118c2ecf20Sopenharmony_ci	if (!cpuc->lbr_users || vlbr_exclude_host() ||
10128c2ecf20Sopenharmony_ci	    cpuc->lbr_users == cpuc->lbr_pebs_users)
10138c2ecf20Sopenharmony_ci		return;
10148c2ecf20Sopenharmony_ci
10158c2ecf20Sopenharmony_ci	x86_pmu.lbr_read(cpuc);
10168c2ecf20Sopenharmony_ci
10178c2ecf20Sopenharmony_ci	intel_pmu_lbr_filter(cpuc);
10188c2ecf20Sopenharmony_ci}
10198c2ecf20Sopenharmony_ci
10208c2ecf20Sopenharmony_ci/*
10218c2ecf20Sopenharmony_ci * SW filter is used:
10228c2ecf20Sopenharmony_ci * - in case there is no HW filter
10238c2ecf20Sopenharmony_ci * - in case the HW filter has errata or limitations
10248c2ecf20Sopenharmony_ci */
10258c2ecf20Sopenharmony_cistatic int intel_pmu_setup_sw_lbr_filter(struct perf_event *event)
10268c2ecf20Sopenharmony_ci{
10278c2ecf20Sopenharmony_ci	u64 br_type = event->attr.branch_sample_type;
10288c2ecf20Sopenharmony_ci	int mask = 0;
10298c2ecf20Sopenharmony_ci
10308c2ecf20Sopenharmony_ci	if (br_type & PERF_SAMPLE_BRANCH_USER)
10318c2ecf20Sopenharmony_ci		mask |= X86_BR_USER;
10328c2ecf20Sopenharmony_ci
10338c2ecf20Sopenharmony_ci	if (br_type & PERF_SAMPLE_BRANCH_KERNEL)
10348c2ecf20Sopenharmony_ci		mask |= X86_BR_KERNEL;
10358c2ecf20Sopenharmony_ci
10368c2ecf20Sopenharmony_ci	/* we ignore BRANCH_HV here */
10378c2ecf20Sopenharmony_ci
10388c2ecf20Sopenharmony_ci	if (br_type & PERF_SAMPLE_BRANCH_ANY)
10398c2ecf20Sopenharmony_ci		mask |= X86_BR_ANY;
10408c2ecf20Sopenharmony_ci
10418c2ecf20Sopenharmony_ci	if (br_type & PERF_SAMPLE_BRANCH_ANY_CALL)
10428c2ecf20Sopenharmony_ci		mask |= X86_BR_ANY_CALL;
10438c2ecf20Sopenharmony_ci
10448c2ecf20Sopenharmony_ci	if (br_type & PERF_SAMPLE_BRANCH_ANY_RETURN)
10458c2ecf20Sopenharmony_ci		mask |= X86_BR_RET | X86_BR_IRET | X86_BR_SYSRET;
10468c2ecf20Sopenharmony_ci
10478c2ecf20Sopenharmony_ci	if (br_type & PERF_SAMPLE_BRANCH_IND_CALL)
10488c2ecf20Sopenharmony_ci		mask |= X86_BR_IND_CALL;
10498c2ecf20Sopenharmony_ci
10508c2ecf20Sopenharmony_ci	if (br_type & PERF_SAMPLE_BRANCH_ABORT_TX)
10518c2ecf20Sopenharmony_ci		mask |= X86_BR_ABORT;
10528c2ecf20Sopenharmony_ci
10538c2ecf20Sopenharmony_ci	if (br_type & PERF_SAMPLE_BRANCH_IN_TX)
10548c2ecf20Sopenharmony_ci		mask |= X86_BR_IN_TX;
10558c2ecf20Sopenharmony_ci
10568c2ecf20Sopenharmony_ci	if (br_type & PERF_SAMPLE_BRANCH_NO_TX)
10578c2ecf20Sopenharmony_ci		mask |= X86_BR_NO_TX;
10588c2ecf20Sopenharmony_ci
10598c2ecf20Sopenharmony_ci	if (br_type & PERF_SAMPLE_BRANCH_COND)
10608c2ecf20Sopenharmony_ci		mask |= X86_BR_JCC;
10618c2ecf20Sopenharmony_ci
10628c2ecf20Sopenharmony_ci	if (br_type & PERF_SAMPLE_BRANCH_CALL_STACK) {
10638c2ecf20Sopenharmony_ci		if (!x86_pmu_has_lbr_callstack())
10648c2ecf20Sopenharmony_ci			return -EOPNOTSUPP;
10658c2ecf20Sopenharmony_ci		if (mask & ~(X86_BR_USER | X86_BR_KERNEL))
10668c2ecf20Sopenharmony_ci			return -EINVAL;
10678c2ecf20Sopenharmony_ci		mask |= X86_BR_CALL | X86_BR_IND_CALL | X86_BR_RET |
10688c2ecf20Sopenharmony_ci			X86_BR_CALL_STACK;
10698c2ecf20Sopenharmony_ci	}
10708c2ecf20Sopenharmony_ci
10718c2ecf20Sopenharmony_ci	if (br_type & PERF_SAMPLE_BRANCH_IND_JUMP)
10728c2ecf20Sopenharmony_ci		mask |= X86_BR_IND_JMP;
10738c2ecf20Sopenharmony_ci
10748c2ecf20Sopenharmony_ci	if (br_type & PERF_SAMPLE_BRANCH_CALL)
10758c2ecf20Sopenharmony_ci		mask |= X86_BR_CALL | X86_BR_ZERO_CALL;
10768c2ecf20Sopenharmony_ci
10778c2ecf20Sopenharmony_ci	if (br_type & PERF_SAMPLE_BRANCH_TYPE_SAVE)
10788c2ecf20Sopenharmony_ci		mask |= X86_BR_TYPE_SAVE;
10798c2ecf20Sopenharmony_ci
10808c2ecf20Sopenharmony_ci	/*
10818c2ecf20Sopenharmony_ci	 * stash actual user request into reg, it may
10828c2ecf20Sopenharmony_ci	 * be used by fixup code for some CPU
10838c2ecf20Sopenharmony_ci	 */
10848c2ecf20Sopenharmony_ci	event->hw.branch_reg.reg = mask;
10858c2ecf20Sopenharmony_ci	return 0;
10868c2ecf20Sopenharmony_ci}
10878c2ecf20Sopenharmony_ci
10888c2ecf20Sopenharmony_ci/*
10898c2ecf20Sopenharmony_ci * setup the HW LBR filter
10908c2ecf20Sopenharmony_ci * Used only when available, may not be enough to disambiguate
10918c2ecf20Sopenharmony_ci * all branches, may need the help of the SW filter
10928c2ecf20Sopenharmony_ci */
10938c2ecf20Sopenharmony_cistatic int intel_pmu_setup_hw_lbr_filter(struct perf_event *event)
10948c2ecf20Sopenharmony_ci{
10958c2ecf20Sopenharmony_ci	struct hw_perf_event_extra *reg;
10968c2ecf20Sopenharmony_ci	u64 br_type = event->attr.branch_sample_type;
10978c2ecf20Sopenharmony_ci	u64 mask = 0, v;
10988c2ecf20Sopenharmony_ci	int i;
10998c2ecf20Sopenharmony_ci
11008c2ecf20Sopenharmony_ci	for (i = 0; i < PERF_SAMPLE_BRANCH_MAX_SHIFT; i++) {
11018c2ecf20Sopenharmony_ci		if (!(br_type & (1ULL << i)))
11028c2ecf20Sopenharmony_ci			continue;
11038c2ecf20Sopenharmony_ci
11048c2ecf20Sopenharmony_ci		v = x86_pmu.lbr_sel_map[i];
11058c2ecf20Sopenharmony_ci		if (v == LBR_NOT_SUPP)
11068c2ecf20Sopenharmony_ci			return -EOPNOTSUPP;
11078c2ecf20Sopenharmony_ci
11088c2ecf20Sopenharmony_ci		if (v != LBR_IGN)
11098c2ecf20Sopenharmony_ci			mask |= v;
11108c2ecf20Sopenharmony_ci	}
11118c2ecf20Sopenharmony_ci
11128c2ecf20Sopenharmony_ci	reg = &event->hw.branch_reg;
11138c2ecf20Sopenharmony_ci	reg->idx = EXTRA_REG_LBR;
11148c2ecf20Sopenharmony_ci
11158c2ecf20Sopenharmony_ci	if (static_cpu_has(X86_FEATURE_ARCH_LBR)) {
11168c2ecf20Sopenharmony_ci		reg->config = mask;
11178c2ecf20Sopenharmony_ci
11188c2ecf20Sopenharmony_ci		/*
11198c2ecf20Sopenharmony_ci		 * The Arch LBR HW can retrieve the common branch types
11208c2ecf20Sopenharmony_ci		 * from the LBR_INFO. It doesn't require the high overhead
11218c2ecf20Sopenharmony_ci		 * SW disassemble.
11228c2ecf20Sopenharmony_ci		 * Enable the branch type by default for the Arch LBR.
11238c2ecf20Sopenharmony_ci		 */
11248c2ecf20Sopenharmony_ci		reg->reg |= X86_BR_TYPE_SAVE;
11258c2ecf20Sopenharmony_ci		return 0;
11268c2ecf20Sopenharmony_ci	}
11278c2ecf20Sopenharmony_ci
11288c2ecf20Sopenharmony_ci	/*
11298c2ecf20Sopenharmony_ci	 * The first 9 bits (LBR_SEL_MASK) in LBR_SELECT operate
11308c2ecf20Sopenharmony_ci	 * in suppress mode. So LBR_SELECT should be set to
11318c2ecf20Sopenharmony_ci	 * (~mask & LBR_SEL_MASK) | (mask & ~LBR_SEL_MASK)
11328c2ecf20Sopenharmony_ci	 * But the 10th bit LBR_CALL_STACK does not operate
11338c2ecf20Sopenharmony_ci	 * in suppress mode.
11348c2ecf20Sopenharmony_ci	 */
11358c2ecf20Sopenharmony_ci	reg->config = mask ^ (x86_pmu.lbr_sel_mask & ~LBR_CALL_STACK);
11368c2ecf20Sopenharmony_ci
11378c2ecf20Sopenharmony_ci	if ((br_type & PERF_SAMPLE_BRANCH_NO_CYCLES) &&
11388c2ecf20Sopenharmony_ci	    (br_type & PERF_SAMPLE_BRANCH_NO_FLAGS) &&
11398c2ecf20Sopenharmony_ci	    (x86_pmu.intel_cap.lbr_format == LBR_FORMAT_INFO))
11408c2ecf20Sopenharmony_ci		reg->config |= LBR_NO_INFO;
11418c2ecf20Sopenharmony_ci
11428c2ecf20Sopenharmony_ci	return 0;
11438c2ecf20Sopenharmony_ci}
11448c2ecf20Sopenharmony_ci
11458c2ecf20Sopenharmony_ciint intel_pmu_setup_lbr_filter(struct perf_event *event)
11468c2ecf20Sopenharmony_ci{
11478c2ecf20Sopenharmony_ci	int ret = 0;
11488c2ecf20Sopenharmony_ci
11498c2ecf20Sopenharmony_ci	/*
11508c2ecf20Sopenharmony_ci	 * no LBR on this PMU
11518c2ecf20Sopenharmony_ci	 */
11528c2ecf20Sopenharmony_ci	if (!x86_pmu.lbr_nr)
11538c2ecf20Sopenharmony_ci		return -EOPNOTSUPP;
11548c2ecf20Sopenharmony_ci
11558c2ecf20Sopenharmony_ci	/*
11568c2ecf20Sopenharmony_ci	 * setup SW LBR filter
11578c2ecf20Sopenharmony_ci	 */
11588c2ecf20Sopenharmony_ci	ret = intel_pmu_setup_sw_lbr_filter(event);
11598c2ecf20Sopenharmony_ci	if (ret)
11608c2ecf20Sopenharmony_ci		return ret;
11618c2ecf20Sopenharmony_ci
11628c2ecf20Sopenharmony_ci	/*
11638c2ecf20Sopenharmony_ci	 * setup HW LBR filter, if any
11648c2ecf20Sopenharmony_ci	 */
11658c2ecf20Sopenharmony_ci	if (x86_pmu.lbr_sel_map)
11668c2ecf20Sopenharmony_ci		ret = intel_pmu_setup_hw_lbr_filter(event);
11678c2ecf20Sopenharmony_ci
11688c2ecf20Sopenharmony_ci	return ret;
11698c2ecf20Sopenharmony_ci}
11708c2ecf20Sopenharmony_ci
11718c2ecf20Sopenharmony_ci/*
11728c2ecf20Sopenharmony_ci * return the type of control flow change at address "from"
11738c2ecf20Sopenharmony_ci * instruction is not necessarily a branch (in case of interrupt).
11748c2ecf20Sopenharmony_ci *
11758c2ecf20Sopenharmony_ci * The branch type returned also includes the priv level of the
11768c2ecf20Sopenharmony_ci * target of the control flow change (X86_BR_USER, X86_BR_KERNEL).
11778c2ecf20Sopenharmony_ci *
11788c2ecf20Sopenharmony_ci * If a branch type is unknown OR the instruction cannot be
11798c2ecf20Sopenharmony_ci * decoded (e.g., text page not present), then X86_BR_NONE is
11808c2ecf20Sopenharmony_ci * returned.
11818c2ecf20Sopenharmony_ci */
11828c2ecf20Sopenharmony_cistatic int branch_type(unsigned long from, unsigned long to, int abort)
11838c2ecf20Sopenharmony_ci{
11848c2ecf20Sopenharmony_ci	struct insn insn;
11858c2ecf20Sopenharmony_ci	void *addr;
11868c2ecf20Sopenharmony_ci	int bytes_read, bytes_left;
11878c2ecf20Sopenharmony_ci	int ret = X86_BR_NONE;
11888c2ecf20Sopenharmony_ci	int ext, to_plm, from_plm;
11898c2ecf20Sopenharmony_ci	u8 buf[MAX_INSN_SIZE];
11908c2ecf20Sopenharmony_ci	int is64 = 0;
11918c2ecf20Sopenharmony_ci
11928c2ecf20Sopenharmony_ci	to_plm = kernel_ip(to) ? X86_BR_KERNEL : X86_BR_USER;
11938c2ecf20Sopenharmony_ci	from_plm = kernel_ip(from) ? X86_BR_KERNEL : X86_BR_USER;
11948c2ecf20Sopenharmony_ci
11958c2ecf20Sopenharmony_ci	/*
11968c2ecf20Sopenharmony_ci	 * maybe zero if lbr did not fill up after a reset by the time
11978c2ecf20Sopenharmony_ci	 * we get a PMU interrupt
11988c2ecf20Sopenharmony_ci	 */
11998c2ecf20Sopenharmony_ci	if (from == 0 || to == 0)
12008c2ecf20Sopenharmony_ci		return X86_BR_NONE;
12018c2ecf20Sopenharmony_ci
12028c2ecf20Sopenharmony_ci	if (abort)
12038c2ecf20Sopenharmony_ci		return X86_BR_ABORT | to_plm;
12048c2ecf20Sopenharmony_ci
12058c2ecf20Sopenharmony_ci	if (from_plm == X86_BR_USER) {
12068c2ecf20Sopenharmony_ci		/*
12078c2ecf20Sopenharmony_ci		 * can happen if measuring at the user level only
12088c2ecf20Sopenharmony_ci		 * and we interrupt in a kernel thread, e.g., idle.
12098c2ecf20Sopenharmony_ci		 */
12108c2ecf20Sopenharmony_ci		if (!current->mm)
12118c2ecf20Sopenharmony_ci			return X86_BR_NONE;
12128c2ecf20Sopenharmony_ci
12138c2ecf20Sopenharmony_ci		/* may fail if text not present */
12148c2ecf20Sopenharmony_ci		bytes_left = copy_from_user_nmi(buf, (void __user *)from,
12158c2ecf20Sopenharmony_ci						MAX_INSN_SIZE);
12168c2ecf20Sopenharmony_ci		bytes_read = MAX_INSN_SIZE - bytes_left;
12178c2ecf20Sopenharmony_ci		if (!bytes_read)
12188c2ecf20Sopenharmony_ci			return X86_BR_NONE;
12198c2ecf20Sopenharmony_ci
12208c2ecf20Sopenharmony_ci		addr = buf;
12218c2ecf20Sopenharmony_ci	} else {
12228c2ecf20Sopenharmony_ci		/*
12238c2ecf20Sopenharmony_ci		 * The LBR logs any address in the IP, even if the IP just
12248c2ecf20Sopenharmony_ci		 * faulted. This means userspace can control the from address.
12258c2ecf20Sopenharmony_ci		 * Ensure we don't blindy read any address by validating it is
12268c2ecf20Sopenharmony_ci		 * a known text address.
12278c2ecf20Sopenharmony_ci		 */
12288c2ecf20Sopenharmony_ci		if (kernel_text_address(from)) {
12298c2ecf20Sopenharmony_ci			addr = (void *)from;
12308c2ecf20Sopenharmony_ci			/*
12318c2ecf20Sopenharmony_ci			 * Assume we can get the maximum possible size
12328c2ecf20Sopenharmony_ci			 * when grabbing kernel data.  This is not
12338c2ecf20Sopenharmony_ci			 * _strictly_ true since we could possibly be
12348c2ecf20Sopenharmony_ci			 * executing up next to a memory hole, but
12358c2ecf20Sopenharmony_ci			 * it is very unlikely to be a problem.
12368c2ecf20Sopenharmony_ci			 */
12378c2ecf20Sopenharmony_ci			bytes_read = MAX_INSN_SIZE;
12388c2ecf20Sopenharmony_ci		} else {
12398c2ecf20Sopenharmony_ci			return X86_BR_NONE;
12408c2ecf20Sopenharmony_ci		}
12418c2ecf20Sopenharmony_ci	}
12428c2ecf20Sopenharmony_ci
12438c2ecf20Sopenharmony_ci	/*
12448c2ecf20Sopenharmony_ci	 * decoder needs to know the ABI especially
12458c2ecf20Sopenharmony_ci	 * on 64-bit systems running 32-bit apps
12468c2ecf20Sopenharmony_ci	 */
12478c2ecf20Sopenharmony_ci#ifdef CONFIG_X86_64
12488c2ecf20Sopenharmony_ci	is64 = kernel_ip((unsigned long)addr) || !test_thread_flag(TIF_IA32);
12498c2ecf20Sopenharmony_ci#endif
12508c2ecf20Sopenharmony_ci	insn_init(&insn, addr, bytes_read, is64);
12518c2ecf20Sopenharmony_ci	insn_get_opcode(&insn);
12528c2ecf20Sopenharmony_ci	if (!insn.opcode.got)
12538c2ecf20Sopenharmony_ci		return X86_BR_ABORT;
12548c2ecf20Sopenharmony_ci
12558c2ecf20Sopenharmony_ci	switch (insn.opcode.bytes[0]) {
12568c2ecf20Sopenharmony_ci	case 0xf:
12578c2ecf20Sopenharmony_ci		switch (insn.opcode.bytes[1]) {
12588c2ecf20Sopenharmony_ci		case 0x05: /* syscall */
12598c2ecf20Sopenharmony_ci		case 0x34: /* sysenter */
12608c2ecf20Sopenharmony_ci			ret = X86_BR_SYSCALL;
12618c2ecf20Sopenharmony_ci			break;
12628c2ecf20Sopenharmony_ci		case 0x07: /* sysret */
12638c2ecf20Sopenharmony_ci		case 0x35: /* sysexit */
12648c2ecf20Sopenharmony_ci			ret = X86_BR_SYSRET;
12658c2ecf20Sopenharmony_ci			break;
12668c2ecf20Sopenharmony_ci		case 0x80 ... 0x8f: /* conditional */
12678c2ecf20Sopenharmony_ci			ret = X86_BR_JCC;
12688c2ecf20Sopenharmony_ci			break;
12698c2ecf20Sopenharmony_ci		default:
12708c2ecf20Sopenharmony_ci			ret = X86_BR_NONE;
12718c2ecf20Sopenharmony_ci		}
12728c2ecf20Sopenharmony_ci		break;
12738c2ecf20Sopenharmony_ci	case 0x70 ... 0x7f: /* conditional */
12748c2ecf20Sopenharmony_ci		ret = X86_BR_JCC;
12758c2ecf20Sopenharmony_ci		break;
12768c2ecf20Sopenharmony_ci	case 0xc2: /* near ret */
12778c2ecf20Sopenharmony_ci	case 0xc3: /* near ret */
12788c2ecf20Sopenharmony_ci	case 0xca: /* far ret */
12798c2ecf20Sopenharmony_ci	case 0xcb: /* far ret */
12808c2ecf20Sopenharmony_ci		ret = X86_BR_RET;
12818c2ecf20Sopenharmony_ci		break;
12828c2ecf20Sopenharmony_ci	case 0xcf: /* iret */
12838c2ecf20Sopenharmony_ci		ret = X86_BR_IRET;
12848c2ecf20Sopenharmony_ci		break;
12858c2ecf20Sopenharmony_ci	case 0xcc ... 0xce: /* int */
12868c2ecf20Sopenharmony_ci		ret = X86_BR_INT;
12878c2ecf20Sopenharmony_ci		break;
12888c2ecf20Sopenharmony_ci	case 0xe8: /* call near rel */
12898c2ecf20Sopenharmony_ci		insn_get_immediate(&insn);
12908c2ecf20Sopenharmony_ci		if (insn.immediate1.value == 0) {
12918c2ecf20Sopenharmony_ci			/* zero length call */
12928c2ecf20Sopenharmony_ci			ret = X86_BR_ZERO_CALL;
12938c2ecf20Sopenharmony_ci			break;
12948c2ecf20Sopenharmony_ci		}
12958c2ecf20Sopenharmony_ci		fallthrough;
12968c2ecf20Sopenharmony_ci	case 0x9a: /* call far absolute */
12978c2ecf20Sopenharmony_ci		ret = X86_BR_CALL;
12988c2ecf20Sopenharmony_ci		break;
12998c2ecf20Sopenharmony_ci	case 0xe0 ... 0xe3: /* loop jmp */
13008c2ecf20Sopenharmony_ci		ret = X86_BR_JCC;
13018c2ecf20Sopenharmony_ci		break;
13028c2ecf20Sopenharmony_ci	case 0xe9 ... 0xeb: /* jmp */
13038c2ecf20Sopenharmony_ci		ret = X86_BR_JMP;
13048c2ecf20Sopenharmony_ci		break;
13058c2ecf20Sopenharmony_ci	case 0xff: /* call near absolute, call far absolute ind */
13068c2ecf20Sopenharmony_ci		insn_get_modrm(&insn);
13078c2ecf20Sopenharmony_ci		ext = (insn.modrm.bytes[0] >> 3) & 0x7;
13088c2ecf20Sopenharmony_ci		switch (ext) {
13098c2ecf20Sopenharmony_ci		case 2: /* near ind call */
13108c2ecf20Sopenharmony_ci		case 3: /* far ind call */
13118c2ecf20Sopenharmony_ci			ret = X86_BR_IND_CALL;
13128c2ecf20Sopenharmony_ci			break;
13138c2ecf20Sopenharmony_ci		case 4:
13148c2ecf20Sopenharmony_ci		case 5:
13158c2ecf20Sopenharmony_ci			ret = X86_BR_IND_JMP;
13168c2ecf20Sopenharmony_ci			break;
13178c2ecf20Sopenharmony_ci		}
13188c2ecf20Sopenharmony_ci		break;
13198c2ecf20Sopenharmony_ci	default:
13208c2ecf20Sopenharmony_ci		ret = X86_BR_NONE;
13218c2ecf20Sopenharmony_ci	}
13228c2ecf20Sopenharmony_ci	/*
13238c2ecf20Sopenharmony_ci	 * interrupts, traps, faults (and thus ring transition) may
13248c2ecf20Sopenharmony_ci	 * occur on any instructions. Thus, to classify them correctly,
13258c2ecf20Sopenharmony_ci	 * we need to first look at the from and to priv levels. If they
13268c2ecf20Sopenharmony_ci	 * are different and to is in the kernel, then it indicates
13278c2ecf20Sopenharmony_ci	 * a ring transition. If the from instruction is not a ring
13288c2ecf20Sopenharmony_ci	 * transition instr (syscall, systenter, int), then it means
13298c2ecf20Sopenharmony_ci	 * it was a irq, trap or fault.
13308c2ecf20Sopenharmony_ci	 *
13318c2ecf20Sopenharmony_ci	 * we have no way of detecting kernel to kernel faults.
13328c2ecf20Sopenharmony_ci	 */
13338c2ecf20Sopenharmony_ci	if (from_plm == X86_BR_USER && to_plm == X86_BR_KERNEL
13348c2ecf20Sopenharmony_ci	    && ret != X86_BR_SYSCALL && ret != X86_BR_INT)
13358c2ecf20Sopenharmony_ci		ret = X86_BR_IRQ;
13368c2ecf20Sopenharmony_ci
13378c2ecf20Sopenharmony_ci	/*
13388c2ecf20Sopenharmony_ci	 * branch priv level determined by target as
13398c2ecf20Sopenharmony_ci	 * is done by HW when LBR_SELECT is implemented
13408c2ecf20Sopenharmony_ci	 */
13418c2ecf20Sopenharmony_ci	if (ret != X86_BR_NONE)
13428c2ecf20Sopenharmony_ci		ret |= to_plm;
13438c2ecf20Sopenharmony_ci
13448c2ecf20Sopenharmony_ci	return ret;
13458c2ecf20Sopenharmony_ci}
13468c2ecf20Sopenharmony_ci
13478c2ecf20Sopenharmony_ci#define X86_BR_TYPE_MAP_MAX	16
13488c2ecf20Sopenharmony_ci
13498c2ecf20Sopenharmony_cistatic int branch_map[X86_BR_TYPE_MAP_MAX] = {
13508c2ecf20Sopenharmony_ci	PERF_BR_CALL,		/* X86_BR_CALL */
13518c2ecf20Sopenharmony_ci	PERF_BR_RET,		/* X86_BR_RET */
13528c2ecf20Sopenharmony_ci	PERF_BR_SYSCALL,	/* X86_BR_SYSCALL */
13538c2ecf20Sopenharmony_ci	PERF_BR_SYSRET,		/* X86_BR_SYSRET */
13548c2ecf20Sopenharmony_ci	PERF_BR_UNKNOWN,	/* X86_BR_INT */
13558c2ecf20Sopenharmony_ci	PERF_BR_UNKNOWN,	/* X86_BR_IRET */
13568c2ecf20Sopenharmony_ci	PERF_BR_COND,		/* X86_BR_JCC */
13578c2ecf20Sopenharmony_ci	PERF_BR_UNCOND,		/* X86_BR_JMP */
13588c2ecf20Sopenharmony_ci	PERF_BR_UNKNOWN,	/* X86_BR_IRQ */
13598c2ecf20Sopenharmony_ci	PERF_BR_IND_CALL,	/* X86_BR_IND_CALL */
13608c2ecf20Sopenharmony_ci	PERF_BR_UNKNOWN,	/* X86_BR_ABORT */
13618c2ecf20Sopenharmony_ci	PERF_BR_UNKNOWN,	/* X86_BR_IN_TX */
13628c2ecf20Sopenharmony_ci	PERF_BR_UNKNOWN,	/* X86_BR_NO_TX */
13638c2ecf20Sopenharmony_ci	PERF_BR_CALL,		/* X86_BR_ZERO_CALL */
13648c2ecf20Sopenharmony_ci	PERF_BR_UNKNOWN,	/* X86_BR_CALL_STACK */
13658c2ecf20Sopenharmony_ci	PERF_BR_IND,		/* X86_BR_IND_JMP */
13668c2ecf20Sopenharmony_ci};
13678c2ecf20Sopenharmony_ci
13688c2ecf20Sopenharmony_cistatic int
13698c2ecf20Sopenharmony_cicommon_branch_type(int type)
13708c2ecf20Sopenharmony_ci{
13718c2ecf20Sopenharmony_ci	int i;
13728c2ecf20Sopenharmony_ci
13738c2ecf20Sopenharmony_ci	type >>= 2; /* skip X86_BR_USER and X86_BR_KERNEL */
13748c2ecf20Sopenharmony_ci
13758c2ecf20Sopenharmony_ci	if (type) {
13768c2ecf20Sopenharmony_ci		i = __ffs(type);
13778c2ecf20Sopenharmony_ci		if (i < X86_BR_TYPE_MAP_MAX)
13788c2ecf20Sopenharmony_ci			return branch_map[i];
13798c2ecf20Sopenharmony_ci	}
13808c2ecf20Sopenharmony_ci
13818c2ecf20Sopenharmony_ci	return PERF_BR_UNKNOWN;
13828c2ecf20Sopenharmony_ci}
13838c2ecf20Sopenharmony_ci
13848c2ecf20Sopenharmony_cienum {
13858c2ecf20Sopenharmony_ci	ARCH_LBR_BR_TYPE_JCC			= 0,
13868c2ecf20Sopenharmony_ci	ARCH_LBR_BR_TYPE_NEAR_IND_JMP		= 1,
13878c2ecf20Sopenharmony_ci	ARCH_LBR_BR_TYPE_NEAR_REL_JMP		= 2,
13888c2ecf20Sopenharmony_ci	ARCH_LBR_BR_TYPE_NEAR_IND_CALL		= 3,
13898c2ecf20Sopenharmony_ci	ARCH_LBR_BR_TYPE_NEAR_REL_CALL		= 4,
13908c2ecf20Sopenharmony_ci	ARCH_LBR_BR_TYPE_NEAR_RET		= 5,
13918c2ecf20Sopenharmony_ci	ARCH_LBR_BR_TYPE_KNOWN_MAX		= ARCH_LBR_BR_TYPE_NEAR_RET,
13928c2ecf20Sopenharmony_ci
13938c2ecf20Sopenharmony_ci	ARCH_LBR_BR_TYPE_MAP_MAX		= 16,
13948c2ecf20Sopenharmony_ci};
13958c2ecf20Sopenharmony_ci
13968c2ecf20Sopenharmony_cistatic const int arch_lbr_br_type_map[ARCH_LBR_BR_TYPE_MAP_MAX] = {
13978c2ecf20Sopenharmony_ci	[ARCH_LBR_BR_TYPE_JCC]			= X86_BR_JCC,
13988c2ecf20Sopenharmony_ci	[ARCH_LBR_BR_TYPE_NEAR_IND_JMP]		= X86_BR_IND_JMP,
13998c2ecf20Sopenharmony_ci	[ARCH_LBR_BR_TYPE_NEAR_REL_JMP]		= X86_BR_JMP,
14008c2ecf20Sopenharmony_ci	[ARCH_LBR_BR_TYPE_NEAR_IND_CALL]	= X86_BR_IND_CALL,
14018c2ecf20Sopenharmony_ci	[ARCH_LBR_BR_TYPE_NEAR_REL_CALL]	= X86_BR_CALL,
14028c2ecf20Sopenharmony_ci	[ARCH_LBR_BR_TYPE_NEAR_RET]		= X86_BR_RET,
14038c2ecf20Sopenharmony_ci};
14048c2ecf20Sopenharmony_ci
14058c2ecf20Sopenharmony_ci/*
14068c2ecf20Sopenharmony_ci * implement actual branch filter based on user demand.
14078c2ecf20Sopenharmony_ci * Hardware may not exactly satisfy that request, thus
14088c2ecf20Sopenharmony_ci * we need to inspect opcodes. Mismatched branches are
14098c2ecf20Sopenharmony_ci * discarded. Therefore, the number of branches returned
14108c2ecf20Sopenharmony_ci * in PERF_SAMPLE_BRANCH_STACK sample may vary.
14118c2ecf20Sopenharmony_ci */
14128c2ecf20Sopenharmony_cistatic void
14138c2ecf20Sopenharmony_ciintel_pmu_lbr_filter(struct cpu_hw_events *cpuc)
14148c2ecf20Sopenharmony_ci{
14158c2ecf20Sopenharmony_ci	u64 from, to;
14168c2ecf20Sopenharmony_ci	int br_sel = cpuc->br_sel;
14178c2ecf20Sopenharmony_ci	int i, j, type, to_plm;
14188c2ecf20Sopenharmony_ci	bool compress = false;
14198c2ecf20Sopenharmony_ci
14208c2ecf20Sopenharmony_ci	/* if sampling all branches, then nothing to filter */
14218c2ecf20Sopenharmony_ci	if (((br_sel & X86_BR_ALL) == X86_BR_ALL) &&
14228c2ecf20Sopenharmony_ci	    ((br_sel & X86_BR_TYPE_SAVE) != X86_BR_TYPE_SAVE))
14238c2ecf20Sopenharmony_ci		return;
14248c2ecf20Sopenharmony_ci
14258c2ecf20Sopenharmony_ci	for (i = 0; i < cpuc->lbr_stack.nr; i++) {
14268c2ecf20Sopenharmony_ci
14278c2ecf20Sopenharmony_ci		from = cpuc->lbr_entries[i].from;
14288c2ecf20Sopenharmony_ci		to = cpuc->lbr_entries[i].to;
14298c2ecf20Sopenharmony_ci		type = cpuc->lbr_entries[i].type;
14308c2ecf20Sopenharmony_ci
14318c2ecf20Sopenharmony_ci		/*
14328c2ecf20Sopenharmony_ci		 * Parse the branch type recorded in LBR_x_INFO MSR.
14338c2ecf20Sopenharmony_ci		 * Doesn't support OTHER_BRANCH decoding for now.
14348c2ecf20Sopenharmony_ci		 * OTHER_BRANCH branch type still rely on software decoding.
14358c2ecf20Sopenharmony_ci		 */
14368c2ecf20Sopenharmony_ci		if (static_cpu_has(X86_FEATURE_ARCH_LBR) &&
14378c2ecf20Sopenharmony_ci		    type <= ARCH_LBR_BR_TYPE_KNOWN_MAX) {
14388c2ecf20Sopenharmony_ci			to_plm = kernel_ip(to) ? X86_BR_KERNEL : X86_BR_USER;
14398c2ecf20Sopenharmony_ci			type = arch_lbr_br_type_map[type] | to_plm;
14408c2ecf20Sopenharmony_ci		} else
14418c2ecf20Sopenharmony_ci			type = branch_type(from, to, cpuc->lbr_entries[i].abort);
14428c2ecf20Sopenharmony_ci		if (type != X86_BR_NONE && (br_sel & X86_BR_ANYTX)) {
14438c2ecf20Sopenharmony_ci			if (cpuc->lbr_entries[i].in_tx)
14448c2ecf20Sopenharmony_ci				type |= X86_BR_IN_TX;
14458c2ecf20Sopenharmony_ci			else
14468c2ecf20Sopenharmony_ci				type |= X86_BR_NO_TX;
14478c2ecf20Sopenharmony_ci		}
14488c2ecf20Sopenharmony_ci
14498c2ecf20Sopenharmony_ci		/* if type does not correspond, then discard */
14508c2ecf20Sopenharmony_ci		if (type == X86_BR_NONE || (br_sel & type) != type) {
14518c2ecf20Sopenharmony_ci			cpuc->lbr_entries[i].from = 0;
14528c2ecf20Sopenharmony_ci			compress = true;
14538c2ecf20Sopenharmony_ci		}
14548c2ecf20Sopenharmony_ci
14558c2ecf20Sopenharmony_ci		if ((br_sel & X86_BR_TYPE_SAVE) == X86_BR_TYPE_SAVE)
14568c2ecf20Sopenharmony_ci			cpuc->lbr_entries[i].type = common_branch_type(type);
14578c2ecf20Sopenharmony_ci	}
14588c2ecf20Sopenharmony_ci
14598c2ecf20Sopenharmony_ci	if (!compress)
14608c2ecf20Sopenharmony_ci		return;
14618c2ecf20Sopenharmony_ci
14628c2ecf20Sopenharmony_ci	/* remove all entries with from=0 */
14638c2ecf20Sopenharmony_ci	for (i = 0; i < cpuc->lbr_stack.nr; ) {
14648c2ecf20Sopenharmony_ci		if (!cpuc->lbr_entries[i].from) {
14658c2ecf20Sopenharmony_ci			j = i;
14668c2ecf20Sopenharmony_ci			while (++j < cpuc->lbr_stack.nr)
14678c2ecf20Sopenharmony_ci				cpuc->lbr_entries[j-1] = cpuc->lbr_entries[j];
14688c2ecf20Sopenharmony_ci			cpuc->lbr_stack.nr--;
14698c2ecf20Sopenharmony_ci			if (!cpuc->lbr_entries[i].from)
14708c2ecf20Sopenharmony_ci				continue;
14718c2ecf20Sopenharmony_ci		}
14728c2ecf20Sopenharmony_ci		i++;
14738c2ecf20Sopenharmony_ci	}
14748c2ecf20Sopenharmony_ci}
14758c2ecf20Sopenharmony_ci
14768c2ecf20Sopenharmony_civoid intel_pmu_store_pebs_lbrs(struct lbr_entry *lbr)
14778c2ecf20Sopenharmony_ci{
14788c2ecf20Sopenharmony_ci	struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
14798c2ecf20Sopenharmony_ci
14808c2ecf20Sopenharmony_ci	/* Cannot get TOS for large PEBS and Arch LBR */
14818c2ecf20Sopenharmony_ci	if (static_cpu_has(X86_FEATURE_ARCH_LBR) ||
14828c2ecf20Sopenharmony_ci	    (cpuc->n_pebs == cpuc->n_large_pebs))
14838c2ecf20Sopenharmony_ci		cpuc->lbr_stack.hw_idx = -1ULL;
14848c2ecf20Sopenharmony_ci	else
14858c2ecf20Sopenharmony_ci		cpuc->lbr_stack.hw_idx = intel_pmu_lbr_tos();
14868c2ecf20Sopenharmony_ci
14878c2ecf20Sopenharmony_ci	intel_pmu_store_lbr(cpuc, lbr);
14888c2ecf20Sopenharmony_ci	intel_pmu_lbr_filter(cpuc);
14898c2ecf20Sopenharmony_ci}
14908c2ecf20Sopenharmony_ci
14918c2ecf20Sopenharmony_ci/*
14928c2ecf20Sopenharmony_ci * Map interface branch filters onto LBR filters
14938c2ecf20Sopenharmony_ci */
14948c2ecf20Sopenharmony_cistatic const int nhm_lbr_sel_map[PERF_SAMPLE_BRANCH_MAX_SHIFT] = {
14958c2ecf20Sopenharmony_ci	[PERF_SAMPLE_BRANCH_ANY_SHIFT]		= LBR_ANY,
14968c2ecf20Sopenharmony_ci	[PERF_SAMPLE_BRANCH_USER_SHIFT]		= LBR_USER,
14978c2ecf20Sopenharmony_ci	[PERF_SAMPLE_BRANCH_KERNEL_SHIFT]	= LBR_KERNEL,
14988c2ecf20Sopenharmony_ci	[PERF_SAMPLE_BRANCH_HV_SHIFT]		= LBR_IGN,
14998c2ecf20Sopenharmony_ci	[PERF_SAMPLE_BRANCH_ANY_RETURN_SHIFT]	= LBR_RETURN | LBR_REL_JMP
15008c2ecf20Sopenharmony_ci						| LBR_IND_JMP | LBR_FAR,
15018c2ecf20Sopenharmony_ci	/*
15028c2ecf20Sopenharmony_ci	 * NHM/WSM erratum: must include REL_JMP+IND_JMP to get CALL branches
15038c2ecf20Sopenharmony_ci	 */
15048c2ecf20Sopenharmony_ci	[PERF_SAMPLE_BRANCH_ANY_CALL_SHIFT] =
15058c2ecf20Sopenharmony_ci	 LBR_REL_CALL | LBR_IND_CALL | LBR_REL_JMP | LBR_IND_JMP | LBR_FAR,
15068c2ecf20Sopenharmony_ci	/*
15078c2ecf20Sopenharmony_ci	 * NHM/WSM erratum: must include IND_JMP to capture IND_CALL
15088c2ecf20Sopenharmony_ci	 */
15098c2ecf20Sopenharmony_ci	[PERF_SAMPLE_BRANCH_IND_CALL_SHIFT] = LBR_IND_CALL | LBR_IND_JMP,
15108c2ecf20Sopenharmony_ci	[PERF_SAMPLE_BRANCH_COND_SHIFT]     = LBR_JCC,
15118c2ecf20Sopenharmony_ci	[PERF_SAMPLE_BRANCH_IND_JUMP_SHIFT] = LBR_IND_JMP,
15128c2ecf20Sopenharmony_ci};
15138c2ecf20Sopenharmony_ci
15148c2ecf20Sopenharmony_cistatic const int snb_lbr_sel_map[PERF_SAMPLE_BRANCH_MAX_SHIFT] = {
15158c2ecf20Sopenharmony_ci	[PERF_SAMPLE_BRANCH_ANY_SHIFT]		= LBR_ANY,
15168c2ecf20Sopenharmony_ci	[PERF_SAMPLE_BRANCH_USER_SHIFT]		= LBR_USER,
15178c2ecf20Sopenharmony_ci	[PERF_SAMPLE_BRANCH_KERNEL_SHIFT]	= LBR_KERNEL,
15188c2ecf20Sopenharmony_ci	[PERF_SAMPLE_BRANCH_HV_SHIFT]		= LBR_IGN,
15198c2ecf20Sopenharmony_ci	[PERF_SAMPLE_BRANCH_ANY_RETURN_SHIFT]	= LBR_RETURN | LBR_FAR,
15208c2ecf20Sopenharmony_ci	[PERF_SAMPLE_BRANCH_ANY_CALL_SHIFT]	= LBR_REL_CALL | LBR_IND_CALL
15218c2ecf20Sopenharmony_ci						| LBR_FAR,
15228c2ecf20Sopenharmony_ci	[PERF_SAMPLE_BRANCH_IND_CALL_SHIFT]	= LBR_IND_CALL,
15238c2ecf20Sopenharmony_ci	[PERF_SAMPLE_BRANCH_COND_SHIFT]		= LBR_JCC,
15248c2ecf20Sopenharmony_ci	[PERF_SAMPLE_BRANCH_IND_JUMP_SHIFT]	= LBR_IND_JMP,
15258c2ecf20Sopenharmony_ci	[PERF_SAMPLE_BRANCH_CALL_SHIFT]		= LBR_REL_CALL,
15268c2ecf20Sopenharmony_ci};
15278c2ecf20Sopenharmony_ci
15288c2ecf20Sopenharmony_cistatic const int hsw_lbr_sel_map[PERF_SAMPLE_BRANCH_MAX_SHIFT] = {
15298c2ecf20Sopenharmony_ci	[PERF_SAMPLE_BRANCH_ANY_SHIFT]		= LBR_ANY,
15308c2ecf20Sopenharmony_ci	[PERF_SAMPLE_BRANCH_USER_SHIFT]		= LBR_USER,
15318c2ecf20Sopenharmony_ci	[PERF_SAMPLE_BRANCH_KERNEL_SHIFT]	= LBR_KERNEL,
15328c2ecf20Sopenharmony_ci	[PERF_SAMPLE_BRANCH_HV_SHIFT]		= LBR_IGN,
15338c2ecf20Sopenharmony_ci	[PERF_SAMPLE_BRANCH_ANY_RETURN_SHIFT]	= LBR_RETURN | LBR_FAR,
15348c2ecf20Sopenharmony_ci	[PERF_SAMPLE_BRANCH_ANY_CALL_SHIFT]	= LBR_REL_CALL | LBR_IND_CALL
15358c2ecf20Sopenharmony_ci						| LBR_FAR,
15368c2ecf20Sopenharmony_ci	[PERF_SAMPLE_BRANCH_IND_CALL_SHIFT]	= LBR_IND_CALL,
15378c2ecf20Sopenharmony_ci	[PERF_SAMPLE_BRANCH_COND_SHIFT]		= LBR_JCC,
15388c2ecf20Sopenharmony_ci	[PERF_SAMPLE_BRANCH_CALL_STACK_SHIFT]	= LBR_REL_CALL | LBR_IND_CALL
15398c2ecf20Sopenharmony_ci						| LBR_RETURN | LBR_CALL_STACK,
15408c2ecf20Sopenharmony_ci	[PERF_SAMPLE_BRANCH_IND_JUMP_SHIFT]	= LBR_IND_JMP,
15418c2ecf20Sopenharmony_ci	[PERF_SAMPLE_BRANCH_CALL_SHIFT]		= LBR_REL_CALL,
15428c2ecf20Sopenharmony_ci};
15438c2ecf20Sopenharmony_ci
15448c2ecf20Sopenharmony_cistatic int arch_lbr_ctl_map[PERF_SAMPLE_BRANCH_MAX_SHIFT] = {
15458c2ecf20Sopenharmony_ci	[PERF_SAMPLE_BRANCH_ANY_SHIFT]		= ARCH_LBR_ANY,
15468c2ecf20Sopenharmony_ci	[PERF_SAMPLE_BRANCH_USER_SHIFT]		= ARCH_LBR_USER,
15478c2ecf20Sopenharmony_ci	[PERF_SAMPLE_BRANCH_KERNEL_SHIFT]	= ARCH_LBR_KERNEL,
15488c2ecf20Sopenharmony_ci	[PERF_SAMPLE_BRANCH_HV_SHIFT]		= LBR_IGN,
15498c2ecf20Sopenharmony_ci	[PERF_SAMPLE_BRANCH_ANY_RETURN_SHIFT]	= ARCH_LBR_RETURN |
15508c2ecf20Sopenharmony_ci						  ARCH_LBR_OTHER_BRANCH,
15518c2ecf20Sopenharmony_ci	[PERF_SAMPLE_BRANCH_ANY_CALL_SHIFT]     = ARCH_LBR_REL_CALL |
15528c2ecf20Sopenharmony_ci						  ARCH_LBR_IND_CALL |
15538c2ecf20Sopenharmony_ci						  ARCH_LBR_OTHER_BRANCH,
15548c2ecf20Sopenharmony_ci	[PERF_SAMPLE_BRANCH_IND_CALL_SHIFT]     = ARCH_LBR_IND_CALL,
15558c2ecf20Sopenharmony_ci	[PERF_SAMPLE_BRANCH_COND_SHIFT]         = ARCH_LBR_JCC,
15568c2ecf20Sopenharmony_ci	[PERF_SAMPLE_BRANCH_CALL_STACK_SHIFT]   = ARCH_LBR_REL_CALL |
15578c2ecf20Sopenharmony_ci						  ARCH_LBR_IND_CALL |
15588c2ecf20Sopenharmony_ci						  ARCH_LBR_RETURN |
15598c2ecf20Sopenharmony_ci						  ARCH_LBR_CALL_STACK,
15608c2ecf20Sopenharmony_ci	[PERF_SAMPLE_BRANCH_IND_JUMP_SHIFT]	= ARCH_LBR_IND_JMP,
15618c2ecf20Sopenharmony_ci	[PERF_SAMPLE_BRANCH_CALL_SHIFT]		= ARCH_LBR_REL_CALL,
15628c2ecf20Sopenharmony_ci};
15638c2ecf20Sopenharmony_ci
15648c2ecf20Sopenharmony_ci/* core */
15658c2ecf20Sopenharmony_civoid __init intel_pmu_lbr_init_core(void)
15668c2ecf20Sopenharmony_ci{
15678c2ecf20Sopenharmony_ci	x86_pmu.lbr_nr     = 4;
15688c2ecf20Sopenharmony_ci	x86_pmu.lbr_tos    = MSR_LBR_TOS;
15698c2ecf20Sopenharmony_ci	x86_pmu.lbr_from   = MSR_LBR_CORE_FROM;
15708c2ecf20Sopenharmony_ci	x86_pmu.lbr_to     = MSR_LBR_CORE_TO;
15718c2ecf20Sopenharmony_ci
15728c2ecf20Sopenharmony_ci	/*
15738c2ecf20Sopenharmony_ci	 * SW branch filter usage:
15748c2ecf20Sopenharmony_ci	 * - compensate for lack of HW filter
15758c2ecf20Sopenharmony_ci	 */
15768c2ecf20Sopenharmony_ci}
15778c2ecf20Sopenharmony_ci
15788c2ecf20Sopenharmony_ci/* nehalem/westmere */
15798c2ecf20Sopenharmony_civoid __init intel_pmu_lbr_init_nhm(void)
15808c2ecf20Sopenharmony_ci{
15818c2ecf20Sopenharmony_ci	x86_pmu.lbr_nr     = 16;
15828c2ecf20Sopenharmony_ci	x86_pmu.lbr_tos    = MSR_LBR_TOS;
15838c2ecf20Sopenharmony_ci	x86_pmu.lbr_from   = MSR_LBR_NHM_FROM;
15848c2ecf20Sopenharmony_ci	x86_pmu.lbr_to     = MSR_LBR_NHM_TO;
15858c2ecf20Sopenharmony_ci
15868c2ecf20Sopenharmony_ci	x86_pmu.lbr_sel_mask = LBR_SEL_MASK;
15878c2ecf20Sopenharmony_ci	x86_pmu.lbr_sel_map  = nhm_lbr_sel_map;
15888c2ecf20Sopenharmony_ci
15898c2ecf20Sopenharmony_ci	/*
15908c2ecf20Sopenharmony_ci	 * SW branch filter usage:
15918c2ecf20Sopenharmony_ci	 * - workaround LBR_SEL errata (see above)
15928c2ecf20Sopenharmony_ci	 * - support syscall, sysret capture.
15938c2ecf20Sopenharmony_ci	 *   That requires LBR_FAR but that means far
15948c2ecf20Sopenharmony_ci	 *   jmp need to be filtered out
15958c2ecf20Sopenharmony_ci	 */
15968c2ecf20Sopenharmony_ci}
15978c2ecf20Sopenharmony_ci
15988c2ecf20Sopenharmony_ci/* sandy bridge */
15998c2ecf20Sopenharmony_civoid __init intel_pmu_lbr_init_snb(void)
16008c2ecf20Sopenharmony_ci{
16018c2ecf20Sopenharmony_ci	x86_pmu.lbr_nr	 = 16;
16028c2ecf20Sopenharmony_ci	x86_pmu.lbr_tos	 = MSR_LBR_TOS;
16038c2ecf20Sopenharmony_ci	x86_pmu.lbr_from = MSR_LBR_NHM_FROM;
16048c2ecf20Sopenharmony_ci	x86_pmu.lbr_to   = MSR_LBR_NHM_TO;
16058c2ecf20Sopenharmony_ci
16068c2ecf20Sopenharmony_ci	x86_pmu.lbr_sel_mask = LBR_SEL_MASK;
16078c2ecf20Sopenharmony_ci	x86_pmu.lbr_sel_map  = snb_lbr_sel_map;
16088c2ecf20Sopenharmony_ci
16098c2ecf20Sopenharmony_ci	/*
16108c2ecf20Sopenharmony_ci	 * SW branch filter usage:
16118c2ecf20Sopenharmony_ci	 * - support syscall, sysret capture.
16128c2ecf20Sopenharmony_ci	 *   That requires LBR_FAR but that means far
16138c2ecf20Sopenharmony_ci	 *   jmp need to be filtered out
16148c2ecf20Sopenharmony_ci	 */
16158c2ecf20Sopenharmony_ci}
16168c2ecf20Sopenharmony_ci
16178c2ecf20Sopenharmony_cistatic inline struct kmem_cache *
16188c2ecf20Sopenharmony_cicreate_lbr_kmem_cache(size_t size, size_t align)
16198c2ecf20Sopenharmony_ci{
16208c2ecf20Sopenharmony_ci	return kmem_cache_create("x86_lbr", size, align, 0, NULL);
16218c2ecf20Sopenharmony_ci}
16228c2ecf20Sopenharmony_ci
16238c2ecf20Sopenharmony_ci/* haswell */
16248c2ecf20Sopenharmony_civoid intel_pmu_lbr_init_hsw(void)
16258c2ecf20Sopenharmony_ci{
16268c2ecf20Sopenharmony_ci	size_t size = sizeof(struct x86_perf_task_context);
16278c2ecf20Sopenharmony_ci
16288c2ecf20Sopenharmony_ci	x86_pmu.lbr_nr	 = 16;
16298c2ecf20Sopenharmony_ci	x86_pmu.lbr_tos	 = MSR_LBR_TOS;
16308c2ecf20Sopenharmony_ci	x86_pmu.lbr_from = MSR_LBR_NHM_FROM;
16318c2ecf20Sopenharmony_ci	x86_pmu.lbr_to   = MSR_LBR_NHM_TO;
16328c2ecf20Sopenharmony_ci
16338c2ecf20Sopenharmony_ci	x86_pmu.lbr_sel_mask = LBR_SEL_MASK;
16348c2ecf20Sopenharmony_ci	x86_pmu.lbr_sel_map  = hsw_lbr_sel_map;
16358c2ecf20Sopenharmony_ci
16368c2ecf20Sopenharmony_ci	x86_get_pmu(smp_processor_id())->task_ctx_cache = create_lbr_kmem_cache(size, 0);
16378c2ecf20Sopenharmony_ci
16388c2ecf20Sopenharmony_ci	if (lbr_from_signext_quirk_needed())
16398c2ecf20Sopenharmony_ci		static_branch_enable(&lbr_from_quirk_key);
16408c2ecf20Sopenharmony_ci}
16418c2ecf20Sopenharmony_ci
16428c2ecf20Sopenharmony_ci/* skylake */
16438c2ecf20Sopenharmony_ci__init void intel_pmu_lbr_init_skl(void)
16448c2ecf20Sopenharmony_ci{
16458c2ecf20Sopenharmony_ci	size_t size = sizeof(struct x86_perf_task_context);
16468c2ecf20Sopenharmony_ci
16478c2ecf20Sopenharmony_ci	x86_pmu.lbr_nr	 = 32;
16488c2ecf20Sopenharmony_ci	x86_pmu.lbr_tos	 = MSR_LBR_TOS;
16498c2ecf20Sopenharmony_ci	x86_pmu.lbr_from = MSR_LBR_NHM_FROM;
16508c2ecf20Sopenharmony_ci	x86_pmu.lbr_to   = MSR_LBR_NHM_TO;
16518c2ecf20Sopenharmony_ci	x86_pmu.lbr_info = MSR_LBR_INFO_0;
16528c2ecf20Sopenharmony_ci
16538c2ecf20Sopenharmony_ci	x86_pmu.lbr_sel_mask = LBR_SEL_MASK;
16548c2ecf20Sopenharmony_ci	x86_pmu.lbr_sel_map  = hsw_lbr_sel_map;
16558c2ecf20Sopenharmony_ci
16568c2ecf20Sopenharmony_ci	x86_get_pmu(smp_processor_id())->task_ctx_cache = create_lbr_kmem_cache(size, 0);
16578c2ecf20Sopenharmony_ci
16588c2ecf20Sopenharmony_ci	/*
16598c2ecf20Sopenharmony_ci	 * SW branch filter usage:
16608c2ecf20Sopenharmony_ci	 * - support syscall, sysret capture.
16618c2ecf20Sopenharmony_ci	 *   That requires LBR_FAR but that means far
16628c2ecf20Sopenharmony_ci	 *   jmp need to be filtered out
16638c2ecf20Sopenharmony_ci	 */
16648c2ecf20Sopenharmony_ci}
16658c2ecf20Sopenharmony_ci
16668c2ecf20Sopenharmony_ci/* atom */
16678c2ecf20Sopenharmony_civoid __init intel_pmu_lbr_init_atom(void)
16688c2ecf20Sopenharmony_ci{
16698c2ecf20Sopenharmony_ci	/*
16708c2ecf20Sopenharmony_ci	 * only models starting at stepping 10 seems
16718c2ecf20Sopenharmony_ci	 * to have an operational LBR which can freeze
16728c2ecf20Sopenharmony_ci	 * on PMU interrupt
16738c2ecf20Sopenharmony_ci	 */
16748c2ecf20Sopenharmony_ci	if (boot_cpu_data.x86_model == 28
16758c2ecf20Sopenharmony_ci	    && boot_cpu_data.x86_stepping < 10) {
16768c2ecf20Sopenharmony_ci		pr_cont("LBR disabled due to erratum");
16778c2ecf20Sopenharmony_ci		return;
16788c2ecf20Sopenharmony_ci	}
16798c2ecf20Sopenharmony_ci
16808c2ecf20Sopenharmony_ci	x86_pmu.lbr_nr	   = 8;
16818c2ecf20Sopenharmony_ci	x86_pmu.lbr_tos    = MSR_LBR_TOS;
16828c2ecf20Sopenharmony_ci	x86_pmu.lbr_from   = MSR_LBR_CORE_FROM;
16838c2ecf20Sopenharmony_ci	x86_pmu.lbr_to     = MSR_LBR_CORE_TO;
16848c2ecf20Sopenharmony_ci
16858c2ecf20Sopenharmony_ci	/*
16868c2ecf20Sopenharmony_ci	 * SW branch filter usage:
16878c2ecf20Sopenharmony_ci	 * - compensate for lack of HW filter
16888c2ecf20Sopenharmony_ci	 */
16898c2ecf20Sopenharmony_ci}
16908c2ecf20Sopenharmony_ci
16918c2ecf20Sopenharmony_ci/* slm */
16928c2ecf20Sopenharmony_civoid __init intel_pmu_lbr_init_slm(void)
16938c2ecf20Sopenharmony_ci{
16948c2ecf20Sopenharmony_ci	x86_pmu.lbr_nr	   = 8;
16958c2ecf20Sopenharmony_ci	x86_pmu.lbr_tos    = MSR_LBR_TOS;
16968c2ecf20Sopenharmony_ci	x86_pmu.lbr_from   = MSR_LBR_CORE_FROM;
16978c2ecf20Sopenharmony_ci	x86_pmu.lbr_to     = MSR_LBR_CORE_TO;
16988c2ecf20Sopenharmony_ci
16998c2ecf20Sopenharmony_ci	x86_pmu.lbr_sel_mask = LBR_SEL_MASK;
17008c2ecf20Sopenharmony_ci	x86_pmu.lbr_sel_map  = nhm_lbr_sel_map;
17018c2ecf20Sopenharmony_ci
17028c2ecf20Sopenharmony_ci	/*
17038c2ecf20Sopenharmony_ci	 * SW branch filter usage:
17048c2ecf20Sopenharmony_ci	 * - compensate for lack of HW filter
17058c2ecf20Sopenharmony_ci	 */
17068c2ecf20Sopenharmony_ci	pr_cont("8-deep LBR, ");
17078c2ecf20Sopenharmony_ci}
17088c2ecf20Sopenharmony_ci
17098c2ecf20Sopenharmony_ci/* Knights Landing */
17108c2ecf20Sopenharmony_civoid intel_pmu_lbr_init_knl(void)
17118c2ecf20Sopenharmony_ci{
17128c2ecf20Sopenharmony_ci	x86_pmu.lbr_nr	   = 8;
17138c2ecf20Sopenharmony_ci	x86_pmu.lbr_tos    = MSR_LBR_TOS;
17148c2ecf20Sopenharmony_ci	x86_pmu.lbr_from   = MSR_LBR_NHM_FROM;
17158c2ecf20Sopenharmony_ci	x86_pmu.lbr_to     = MSR_LBR_NHM_TO;
17168c2ecf20Sopenharmony_ci
17178c2ecf20Sopenharmony_ci	x86_pmu.lbr_sel_mask = LBR_SEL_MASK;
17188c2ecf20Sopenharmony_ci	x86_pmu.lbr_sel_map  = snb_lbr_sel_map;
17198c2ecf20Sopenharmony_ci
17208c2ecf20Sopenharmony_ci	/* Knights Landing does have MISPREDICT bit */
17218c2ecf20Sopenharmony_ci	if (x86_pmu.intel_cap.lbr_format == LBR_FORMAT_LIP)
17228c2ecf20Sopenharmony_ci		x86_pmu.intel_cap.lbr_format = LBR_FORMAT_EIP_FLAGS;
17238c2ecf20Sopenharmony_ci}
17248c2ecf20Sopenharmony_ci
17258c2ecf20Sopenharmony_ci/*
17268c2ecf20Sopenharmony_ci * LBR state size is variable based on the max number of registers.
17278c2ecf20Sopenharmony_ci * This calculates the expected state size, which should match
17288c2ecf20Sopenharmony_ci * what the hardware enumerates for the size of XFEATURE_LBR.
17298c2ecf20Sopenharmony_ci */
17308c2ecf20Sopenharmony_cistatic inline unsigned int get_lbr_state_size(void)
17318c2ecf20Sopenharmony_ci{
17328c2ecf20Sopenharmony_ci	return sizeof(struct arch_lbr_state) +
17338c2ecf20Sopenharmony_ci	       x86_pmu.lbr_nr * sizeof(struct lbr_entry);
17348c2ecf20Sopenharmony_ci}
17358c2ecf20Sopenharmony_ci
17368c2ecf20Sopenharmony_cistatic bool is_arch_lbr_xsave_available(void)
17378c2ecf20Sopenharmony_ci{
17388c2ecf20Sopenharmony_ci	if (!boot_cpu_has(X86_FEATURE_XSAVES))
17398c2ecf20Sopenharmony_ci		return false;
17408c2ecf20Sopenharmony_ci
17418c2ecf20Sopenharmony_ci	/*
17428c2ecf20Sopenharmony_ci	 * Check the LBR state with the corresponding software structure.
17438c2ecf20Sopenharmony_ci	 * Disable LBR XSAVES support if the size doesn't match.
17448c2ecf20Sopenharmony_ci	 */
17458c2ecf20Sopenharmony_ci	if (xfeature_size(XFEATURE_LBR) == 0)
17468c2ecf20Sopenharmony_ci		return false;
17478c2ecf20Sopenharmony_ci
17488c2ecf20Sopenharmony_ci	if (WARN_ON(xfeature_size(XFEATURE_LBR) != get_lbr_state_size()))
17498c2ecf20Sopenharmony_ci		return false;
17508c2ecf20Sopenharmony_ci
17518c2ecf20Sopenharmony_ci	return true;
17528c2ecf20Sopenharmony_ci}
17538c2ecf20Sopenharmony_ci
17548c2ecf20Sopenharmony_civoid __init intel_pmu_arch_lbr_init(void)
17558c2ecf20Sopenharmony_ci{
17568c2ecf20Sopenharmony_ci	struct pmu *pmu = x86_get_pmu(smp_processor_id());
17578c2ecf20Sopenharmony_ci	union cpuid28_eax eax;
17588c2ecf20Sopenharmony_ci	union cpuid28_ebx ebx;
17598c2ecf20Sopenharmony_ci	union cpuid28_ecx ecx;
17608c2ecf20Sopenharmony_ci	unsigned int unused_edx;
17618c2ecf20Sopenharmony_ci	bool arch_lbr_xsave;
17628c2ecf20Sopenharmony_ci	size_t size;
17638c2ecf20Sopenharmony_ci	u64 lbr_nr;
17648c2ecf20Sopenharmony_ci
17658c2ecf20Sopenharmony_ci	/* Arch LBR Capabilities */
17668c2ecf20Sopenharmony_ci	cpuid(28, &eax.full, &ebx.full, &ecx.full, &unused_edx);
17678c2ecf20Sopenharmony_ci
17688c2ecf20Sopenharmony_ci	lbr_nr = fls(eax.split.lbr_depth_mask) * 8;
17698c2ecf20Sopenharmony_ci	if (!lbr_nr)
17708c2ecf20Sopenharmony_ci		goto clear_arch_lbr;
17718c2ecf20Sopenharmony_ci
17728c2ecf20Sopenharmony_ci	/* Apply the max depth of Arch LBR */
17738c2ecf20Sopenharmony_ci	if (wrmsrl_safe(MSR_ARCH_LBR_DEPTH, lbr_nr))
17748c2ecf20Sopenharmony_ci		goto clear_arch_lbr;
17758c2ecf20Sopenharmony_ci
17768c2ecf20Sopenharmony_ci	x86_pmu.lbr_depth_mask = eax.split.lbr_depth_mask;
17778c2ecf20Sopenharmony_ci	x86_pmu.lbr_deep_c_reset = eax.split.lbr_deep_c_reset;
17788c2ecf20Sopenharmony_ci	x86_pmu.lbr_lip = eax.split.lbr_lip;
17798c2ecf20Sopenharmony_ci	x86_pmu.lbr_cpl = ebx.split.lbr_cpl;
17808c2ecf20Sopenharmony_ci	x86_pmu.lbr_filter = ebx.split.lbr_filter;
17818c2ecf20Sopenharmony_ci	x86_pmu.lbr_call_stack = ebx.split.lbr_call_stack;
17828c2ecf20Sopenharmony_ci	x86_pmu.lbr_mispred = ecx.split.lbr_mispred;
17838c2ecf20Sopenharmony_ci	x86_pmu.lbr_timed_lbr = ecx.split.lbr_timed_lbr;
17848c2ecf20Sopenharmony_ci	x86_pmu.lbr_br_type = ecx.split.lbr_br_type;
17858c2ecf20Sopenharmony_ci	x86_pmu.lbr_nr = lbr_nr;
17868c2ecf20Sopenharmony_ci
17878c2ecf20Sopenharmony_ci
17888c2ecf20Sopenharmony_ci	arch_lbr_xsave = is_arch_lbr_xsave_available();
17898c2ecf20Sopenharmony_ci	if (arch_lbr_xsave) {
17908c2ecf20Sopenharmony_ci		size = sizeof(struct x86_perf_task_context_arch_lbr_xsave) +
17918c2ecf20Sopenharmony_ci		       get_lbr_state_size();
17928c2ecf20Sopenharmony_ci		pmu->task_ctx_cache = create_lbr_kmem_cache(size,
17938c2ecf20Sopenharmony_ci							    XSAVE_ALIGNMENT);
17948c2ecf20Sopenharmony_ci	}
17958c2ecf20Sopenharmony_ci
17968c2ecf20Sopenharmony_ci	if (!pmu->task_ctx_cache) {
17978c2ecf20Sopenharmony_ci		arch_lbr_xsave = false;
17988c2ecf20Sopenharmony_ci
17998c2ecf20Sopenharmony_ci		size = sizeof(struct x86_perf_task_context_arch_lbr) +
18008c2ecf20Sopenharmony_ci		       lbr_nr * sizeof(struct lbr_entry);
18018c2ecf20Sopenharmony_ci		pmu->task_ctx_cache = create_lbr_kmem_cache(size, 0);
18028c2ecf20Sopenharmony_ci	}
18038c2ecf20Sopenharmony_ci
18048c2ecf20Sopenharmony_ci	x86_pmu.lbr_from = MSR_ARCH_LBR_FROM_0;
18058c2ecf20Sopenharmony_ci	x86_pmu.lbr_to = MSR_ARCH_LBR_TO_0;
18068c2ecf20Sopenharmony_ci	x86_pmu.lbr_info = MSR_ARCH_LBR_INFO_0;
18078c2ecf20Sopenharmony_ci
18088c2ecf20Sopenharmony_ci	/* LBR callstack requires both CPL and Branch Filtering support */
18098c2ecf20Sopenharmony_ci	if (!x86_pmu.lbr_cpl ||
18108c2ecf20Sopenharmony_ci	    !x86_pmu.lbr_filter ||
18118c2ecf20Sopenharmony_ci	    !x86_pmu.lbr_call_stack)
18128c2ecf20Sopenharmony_ci		arch_lbr_ctl_map[PERF_SAMPLE_BRANCH_CALL_STACK_SHIFT] = LBR_NOT_SUPP;
18138c2ecf20Sopenharmony_ci
18148c2ecf20Sopenharmony_ci	if (!x86_pmu.lbr_cpl) {
18158c2ecf20Sopenharmony_ci		arch_lbr_ctl_map[PERF_SAMPLE_BRANCH_USER_SHIFT] = LBR_NOT_SUPP;
18168c2ecf20Sopenharmony_ci		arch_lbr_ctl_map[PERF_SAMPLE_BRANCH_KERNEL_SHIFT] = LBR_NOT_SUPP;
18178c2ecf20Sopenharmony_ci	} else if (!x86_pmu.lbr_filter) {
18188c2ecf20Sopenharmony_ci		arch_lbr_ctl_map[PERF_SAMPLE_BRANCH_ANY_SHIFT] = LBR_NOT_SUPP;
18198c2ecf20Sopenharmony_ci		arch_lbr_ctl_map[PERF_SAMPLE_BRANCH_ANY_RETURN_SHIFT] = LBR_NOT_SUPP;
18208c2ecf20Sopenharmony_ci		arch_lbr_ctl_map[PERF_SAMPLE_BRANCH_ANY_CALL_SHIFT] = LBR_NOT_SUPP;
18218c2ecf20Sopenharmony_ci		arch_lbr_ctl_map[PERF_SAMPLE_BRANCH_IND_CALL_SHIFT] = LBR_NOT_SUPP;
18228c2ecf20Sopenharmony_ci		arch_lbr_ctl_map[PERF_SAMPLE_BRANCH_COND_SHIFT] = LBR_NOT_SUPP;
18238c2ecf20Sopenharmony_ci		arch_lbr_ctl_map[PERF_SAMPLE_BRANCH_IND_JUMP_SHIFT] = LBR_NOT_SUPP;
18248c2ecf20Sopenharmony_ci		arch_lbr_ctl_map[PERF_SAMPLE_BRANCH_CALL_SHIFT] = LBR_NOT_SUPP;
18258c2ecf20Sopenharmony_ci	}
18268c2ecf20Sopenharmony_ci
18278c2ecf20Sopenharmony_ci	x86_pmu.lbr_ctl_mask = ARCH_LBR_CTL_MASK;
18288c2ecf20Sopenharmony_ci	x86_pmu.lbr_ctl_map  = arch_lbr_ctl_map;
18298c2ecf20Sopenharmony_ci
18308c2ecf20Sopenharmony_ci	if (!x86_pmu.lbr_cpl && !x86_pmu.lbr_filter)
18318c2ecf20Sopenharmony_ci		x86_pmu.lbr_ctl_map = NULL;
18328c2ecf20Sopenharmony_ci
18338c2ecf20Sopenharmony_ci	x86_pmu.lbr_reset = intel_pmu_arch_lbr_reset;
18348c2ecf20Sopenharmony_ci	if (arch_lbr_xsave) {
18358c2ecf20Sopenharmony_ci		x86_pmu.lbr_save = intel_pmu_arch_lbr_xsaves;
18368c2ecf20Sopenharmony_ci		x86_pmu.lbr_restore = intel_pmu_arch_lbr_xrstors;
18378c2ecf20Sopenharmony_ci		x86_pmu.lbr_read = intel_pmu_arch_lbr_read_xsave;
18388c2ecf20Sopenharmony_ci		pr_cont("XSAVE ");
18398c2ecf20Sopenharmony_ci	} else {
18408c2ecf20Sopenharmony_ci		x86_pmu.lbr_save = intel_pmu_arch_lbr_save;
18418c2ecf20Sopenharmony_ci		x86_pmu.lbr_restore = intel_pmu_arch_lbr_restore;
18428c2ecf20Sopenharmony_ci		x86_pmu.lbr_read = intel_pmu_arch_lbr_read;
18438c2ecf20Sopenharmony_ci	}
18448c2ecf20Sopenharmony_ci
18458c2ecf20Sopenharmony_ci	pr_cont("Architectural LBR, ");
18468c2ecf20Sopenharmony_ci
18478c2ecf20Sopenharmony_ci	return;
18488c2ecf20Sopenharmony_ci
18498c2ecf20Sopenharmony_ciclear_arch_lbr:
18508c2ecf20Sopenharmony_ci	setup_clear_cpu_cap(X86_FEATURE_ARCH_LBR);
18518c2ecf20Sopenharmony_ci}
18528c2ecf20Sopenharmony_ci
18538c2ecf20Sopenharmony_ci/**
18548c2ecf20Sopenharmony_ci * x86_perf_get_lbr - get the LBR records information
18558c2ecf20Sopenharmony_ci *
18568c2ecf20Sopenharmony_ci * @lbr: the caller's memory to store the LBR records information
18578c2ecf20Sopenharmony_ci *
18588c2ecf20Sopenharmony_ci * Returns: 0 indicates the LBR info has been successfully obtained
18598c2ecf20Sopenharmony_ci */
18608c2ecf20Sopenharmony_ciint x86_perf_get_lbr(struct x86_pmu_lbr *lbr)
18618c2ecf20Sopenharmony_ci{
18628c2ecf20Sopenharmony_ci	int lbr_fmt = x86_pmu.intel_cap.lbr_format;
18638c2ecf20Sopenharmony_ci
18648c2ecf20Sopenharmony_ci	lbr->nr = x86_pmu.lbr_nr;
18658c2ecf20Sopenharmony_ci	lbr->from = x86_pmu.lbr_from;
18668c2ecf20Sopenharmony_ci	lbr->to = x86_pmu.lbr_to;
18678c2ecf20Sopenharmony_ci	lbr->info = (lbr_fmt == LBR_FORMAT_INFO) ? x86_pmu.lbr_info : 0;
18688c2ecf20Sopenharmony_ci
18698c2ecf20Sopenharmony_ci	return 0;
18708c2ecf20Sopenharmony_ci}
18718c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(x86_perf_get_lbr);
18728c2ecf20Sopenharmony_ci
18738c2ecf20Sopenharmony_cistruct event_constraint vlbr_constraint =
18748c2ecf20Sopenharmony_ci	__EVENT_CONSTRAINT(INTEL_FIXED_VLBR_EVENT, (1ULL << INTEL_PMC_IDX_FIXED_VLBR),
18758c2ecf20Sopenharmony_ci			  FIXED_EVENT_FLAGS, 1, 0, PERF_X86_EVENT_LBR_SELECT);
1876