xref: /linux/arch/x86/events/amd/lbr.c (revision b8ea7da314c2efcb9c2f559ed65b7a36c869d68e)
1 // SPDX-License-Identifier: GPL-2.0
2 #include <linux/perf_event.h>
3 
4 #include <asm/cpuid/api.h>
5 #include <asm/msr.h>
6 #include <asm/perf_event.h>
7 
8 #include "../perf_event.h"
9 
10 /* LBR Branch Select valid bits */
11 #define LBR_SELECT_MASK		0x1ff
12 
13 /*
14  * LBR Branch Select filter bits which when set, ensures that the
15  * corresponding type of branches are not recorded
16  */
17 #define LBR_SELECT_KERNEL		0	/* Branches ending in CPL = 0 */
18 #define LBR_SELECT_USER			1	/* Branches ending in CPL > 0 */
19 #define LBR_SELECT_JCC			2	/* Conditional branches */
20 #define LBR_SELECT_CALL_NEAR_REL	3	/* Near relative calls */
21 #define LBR_SELECT_CALL_NEAR_IND	4	/* Indirect relative calls */
22 #define LBR_SELECT_RET_NEAR		5	/* Near returns */
23 #define LBR_SELECT_JMP_NEAR_IND		6	/* Near indirect jumps (excl. calls and returns) */
24 #define LBR_SELECT_JMP_NEAR_REL		7	/* Near relative jumps (excl. calls) */
25 #define LBR_SELECT_FAR_BRANCH		8	/* Far branches */
26 
27 #define LBR_KERNEL	BIT(LBR_SELECT_KERNEL)
28 #define LBR_USER	BIT(LBR_SELECT_USER)
29 #define LBR_JCC		BIT(LBR_SELECT_JCC)
30 #define LBR_REL_CALL	BIT(LBR_SELECT_CALL_NEAR_REL)
31 #define LBR_IND_CALL	BIT(LBR_SELECT_CALL_NEAR_IND)
32 #define LBR_RETURN	BIT(LBR_SELECT_RET_NEAR)
33 #define LBR_REL_JMP	BIT(LBR_SELECT_JMP_NEAR_REL)
34 #define LBR_IND_JMP	BIT(LBR_SELECT_JMP_NEAR_IND)
35 #define LBR_FAR		BIT(LBR_SELECT_FAR_BRANCH)
36 #define LBR_NOT_SUPP	-1	/* unsupported filter */
37 #define LBR_IGNORE	0
38 
39 #define LBR_ANY		\
40 	(LBR_JCC | LBR_REL_CALL | LBR_IND_CALL | LBR_RETURN |	\
41 	 LBR_REL_JMP | LBR_IND_JMP | LBR_FAR)
42 
43 struct branch_entry {
44 	union {
45 		struct {
46 			u64	ip:58;
47 			u64	ip_sign_ext:5;
48 			u64	mispredict:1;
49 		} split;
50 		u64		full;
51 	} from;
52 
53 	union {
54 		struct {
55 			u64	ip:58;
56 			u64	ip_sign_ext:3;
57 			u64	reserved:1;
58 			u64	spec:1;
59 			u64	valid:1;
60 		} split;
61 		u64		full;
62 	} to;
63 };
64 
65 static __always_inline void amd_pmu_lbr_set_from(unsigned int idx, u64 val)
66 {
67 	wrmsrq(MSR_AMD_SAMP_BR_FROM + idx * 2, val);
68 }
69 
70 static __always_inline void amd_pmu_lbr_set_to(unsigned int idx, u64 val)
71 {
72 	wrmsrq(MSR_AMD_SAMP_BR_FROM + idx * 2 + 1, val);
73 }
74 
75 static __always_inline u64 amd_pmu_lbr_get_from(unsigned int idx)
76 {
77 	u64 val;
78 
79 	rdmsrq(MSR_AMD_SAMP_BR_FROM + idx * 2, val);
80 
81 	return val;
82 }
83 
84 static __always_inline u64 amd_pmu_lbr_get_to(unsigned int idx)
85 {
86 	u64 val;
87 
88 	rdmsrq(MSR_AMD_SAMP_BR_FROM + idx * 2 + 1, val);
89 
90 	return val;
91 }
92 
93 static __always_inline u64 sign_ext_branch_ip(u64 ip)
94 {
95 	u32 shift = 64 - boot_cpu_data.x86_virt_bits;
96 
97 	return (u64)(((s64)ip << shift) >> shift);
98 }
99 
100 static void amd_pmu_lbr_filter(void)
101 {
102 	struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
103 	int br_sel = cpuc->br_sel, offset, type, i, j;
104 	bool compress = false;
105 	bool fused_only = false;
106 	u64 from, to;
107 
108 	/* If sampling all branches, there is nothing to filter */
109 	if (((br_sel & X86_BR_ALL) == X86_BR_ALL) &&
110 	    ((br_sel & X86_BR_TYPE_SAVE) != X86_BR_TYPE_SAVE))
111 		fused_only = true;
112 
113 	for (i = 0; i < cpuc->lbr_stack.nr; i++) {
114 		from = cpuc->lbr_entries[i].from;
115 		to = cpuc->lbr_entries[i].to;
116 		type = branch_type_fused(from, to, 0, &offset);
117 
118 		/*
119 		 * Adjust the branch from address in case of instruction
120 		 * fusion where it points to an instruction preceding the
121 		 * actual branch
122 		 */
123 		if (offset) {
124 			cpuc->lbr_entries[i].from += offset;
125 			if (fused_only)
126 				continue;
127 		}
128 
129 		/* If type does not correspond, then discard */
130 		if (type == X86_BR_NONE || (br_sel & type) != type) {
131 			cpuc->lbr_entries[i].from = 0;	/* mark invalid */
132 			compress = true;
133 		}
134 
135 		if ((br_sel & X86_BR_TYPE_SAVE) == X86_BR_TYPE_SAVE)
136 			cpuc->lbr_entries[i].type = common_branch_type(type);
137 	}
138 
139 	if (!compress)
140 		return;
141 
142 	/* Remove all invalid entries */
143 	for (i = 0; i < cpuc->lbr_stack.nr; ) {
144 		if (!cpuc->lbr_entries[i].from) {
145 			j = i;
146 			while (++j < cpuc->lbr_stack.nr)
147 				cpuc->lbr_entries[j - 1] = cpuc->lbr_entries[j];
148 			cpuc->lbr_stack.nr--;
149 			if (!cpuc->lbr_entries[i].from)
150 				continue;
151 		}
152 		i++;
153 	}
154 }
155 
156 static const int lbr_spec_map[PERF_BR_SPEC_MAX] = {
157 	PERF_BR_SPEC_NA,
158 	PERF_BR_SPEC_WRONG_PATH,
159 	PERF_BR_NON_SPEC_CORRECT_PATH,
160 	PERF_BR_SPEC_CORRECT_PATH,
161 };
162 
163 void amd_pmu_lbr_read(void)
164 {
165 	struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
166 	struct perf_branch_entry *br = cpuc->lbr_entries;
167 	struct branch_entry entry;
168 	int out = 0, idx, i;
169 
170 	if (!cpuc->lbr_users)
171 		return;
172 
173 	for (i = 0; i < x86_pmu.lbr_nr; i++) {
174 		entry.from.full	= amd_pmu_lbr_get_from(i);
175 		entry.to.full	= amd_pmu_lbr_get_to(i);
176 
177 		/*
178 		 * Check if a branch has been logged; if valid = 0, spec = 0
179 		 * then no branch was recorded; if reserved = 1 then an
180 		 * erroneous branch was recorded (see Erratum 1452)
181 		 */
182 		if ((!entry.to.split.valid && !entry.to.split.spec) ||
183 		    entry.to.split.reserved)
184 			continue;
185 
186 		perf_clear_branch_entry_bitfields(br + out);
187 
188 		br[out].from	= sign_ext_branch_ip(entry.from.split.ip);
189 		br[out].to	= sign_ext_branch_ip(entry.to.split.ip);
190 		br[out].mispred	= entry.from.split.mispredict;
191 		br[out].predicted = !br[out].mispred;
192 
193 		/*
194 		 * Set branch speculation information using the status of
195 		 * the valid and spec bits.
196 		 *
197 		 * When valid = 0, spec = 0, no branch was recorded and the
198 		 * entry is discarded as seen above.
199 		 *
200 		 * When valid = 0, spec = 1, the recorded branch was
201 		 * speculative but took the wrong path.
202 		 *
203 		 * When valid = 1, spec = 0, the recorded branch was
204 		 * non-speculative but took the correct path.
205 		 *
206 		 * When valid = 1, spec = 1, the recorded branch was
207 		 * speculative and took the correct path
208 		 */
209 		idx = (entry.to.split.valid << 1) | entry.to.split.spec;
210 		br[out].spec = lbr_spec_map[idx];
211 		out++;
212 	}
213 
214 	cpuc->lbr_stack.nr = out;
215 
216 	/*
217 	 * Internal register renaming always ensures that LBR From[0] and
218 	 * LBR To[0] always represent the TOS
219 	 */
220 	cpuc->lbr_stack.hw_idx = 0;
221 
222 	/* Perform further software filtering */
223 	amd_pmu_lbr_filter();
224 }
225 
226 static const int lbr_select_map[PERF_SAMPLE_BRANCH_MAX_SHIFT] = {
227 	[PERF_SAMPLE_BRANCH_USER_SHIFT]		= LBR_USER,
228 	[PERF_SAMPLE_BRANCH_KERNEL_SHIFT]	= LBR_KERNEL,
229 	[PERF_SAMPLE_BRANCH_HV_SHIFT]		= LBR_IGNORE,
230 
231 	[PERF_SAMPLE_BRANCH_ANY_SHIFT]		= LBR_ANY,
232 	[PERF_SAMPLE_BRANCH_ANY_CALL_SHIFT]	= LBR_REL_CALL | LBR_IND_CALL | LBR_FAR,
233 	[PERF_SAMPLE_BRANCH_ANY_RETURN_SHIFT]	= LBR_RETURN | LBR_FAR,
234 	[PERF_SAMPLE_BRANCH_IND_CALL_SHIFT]	= LBR_IND_CALL,
235 	[PERF_SAMPLE_BRANCH_ABORT_TX_SHIFT]	= LBR_NOT_SUPP,
236 	[PERF_SAMPLE_BRANCH_IN_TX_SHIFT]	= LBR_NOT_SUPP,
237 	[PERF_SAMPLE_BRANCH_NO_TX_SHIFT]	= LBR_NOT_SUPP,
238 	[PERF_SAMPLE_BRANCH_COND_SHIFT]		= LBR_JCC,
239 
240 	[PERF_SAMPLE_BRANCH_CALL_STACK_SHIFT]	= LBR_NOT_SUPP,
241 	[PERF_SAMPLE_BRANCH_IND_JUMP_SHIFT]	= LBR_IND_JMP,
242 	[PERF_SAMPLE_BRANCH_CALL_SHIFT]		= LBR_REL_CALL,
243 
244 	[PERF_SAMPLE_BRANCH_NO_FLAGS_SHIFT]	= LBR_NOT_SUPP,
245 	[PERF_SAMPLE_BRANCH_NO_CYCLES_SHIFT]	= LBR_NOT_SUPP,
246 };
247 
248 static int amd_pmu_lbr_setup_filter(struct perf_event *event)
249 {
250 	struct hw_perf_event_extra *reg = &event->hw.branch_reg;
251 	u64 br_type = event->attr.branch_sample_type;
252 	u64 mask = 0, v;
253 	int i;
254 
255 	/* No LBR support */
256 	if (!x86_pmu.lbr_nr)
257 		return -EOPNOTSUPP;
258 
259 	if (br_type & PERF_SAMPLE_BRANCH_USER)
260 		mask |= X86_BR_USER;
261 
262 	if (br_type & PERF_SAMPLE_BRANCH_KERNEL)
263 		mask |= X86_BR_KERNEL;
264 
265 	/* Ignore BRANCH_HV here */
266 
267 	if (br_type & PERF_SAMPLE_BRANCH_ANY)
268 		mask |= X86_BR_ANY;
269 
270 	if (br_type & PERF_SAMPLE_BRANCH_ANY_CALL)
271 		mask |= X86_BR_ANY_CALL;
272 
273 	if (br_type & PERF_SAMPLE_BRANCH_ANY_RETURN)
274 		mask |= X86_BR_RET | X86_BR_IRET | X86_BR_SYSRET;
275 
276 	if (br_type & PERF_SAMPLE_BRANCH_IND_CALL)
277 		mask |= X86_BR_IND_CALL;
278 
279 	if (br_type & PERF_SAMPLE_BRANCH_COND)
280 		mask |= X86_BR_JCC;
281 
282 	if (br_type & PERF_SAMPLE_BRANCH_IND_JUMP)
283 		mask |= X86_BR_IND_JMP;
284 
285 	if (br_type & PERF_SAMPLE_BRANCH_CALL)
286 		mask |= X86_BR_CALL | X86_BR_ZERO_CALL;
287 
288 	if (br_type & PERF_SAMPLE_BRANCH_TYPE_SAVE)
289 		mask |= X86_BR_TYPE_SAVE;
290 
291 	reg->reg = mask;
292 	mask = 0;
293 
294 	for (i = 0; i < PERF_SAMPLE_BRANCH_MAX_SHIFT; i++) {
295 		if (!(br_type & BIT_ULL(i)))
296 			continue;
297 
298 		v = lbr_select_map[i];
299 		if (v == LBR_NOT_SUPP)
300 			return -EOPNOTSUPP;
301 
302 		if (v != LBR_IGNORE)
303 			mask |= v;
304 	}
305 
306 	/* Filter bits operate in suppress mode */
307 	reg->config = mask ^ LBR_SELECT_MASK;
308 
309 	return 0;
310 }
311 
312 int amd_pmu_lbr_hw_config(struct perf_event *event)
313 {
314 	int ret = 0;
315 
316 	ret = amd_pmu_lbr_setup_filter(event);
317 	if (!ret)
318 		event->attach_state |= PERF_ATTACH_SCHED_CB;
319 
320 	return ret;
321 }
322 
323 void amd_pmu_lbr_reset(void)
324 {
325 	struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
326 	int i;
327 
328 	if (!x86_pmu.lbr_nr)
329 		return;
330 
331 	/* Reset all branch records individually */
332 	for (i = 0; i < x86_pmu.lbr_nr; i++) {
333 		amd_pmu_lbr_set_from(i, 0);
334 		amd_pmu_lbr_set_to(i, 0);
335 	}
336 
337 	cpuc->last_task_ctx = NULL;
338 	cpuc->last_log_id = 0;
339 	wrmsrq(MSR_AMD64_LBR_SELECT, 0);
340 }
341 
342 void amd_pmu_lbr_add(struct perf_event *event)
343 {
344 	struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
345 	struct hw_perf_event_extra *reg = &event->hw.branch_reg;
346 
347 	if (!x86_pmu.lbr_nr)
348 		return;
349 
350 	if (has_branch_stack(event)) {
351 		cpuc->lbr_select = 1;
352 		cpuc->lbr_sel->config = reg->config;
353 		cpuc->br_sel = reg->reg;
354 	}
355 
356 	perf_sched_cb_inc(event->pmu);
357 
358 	if (!cpuc->lbr_users++ && !event->total_time_running)
359 		amd_pmu_lbr_reset();
360 }
361 
362 void amd_pmu_lbr_del(struct perf_event *event)
363 {
364 	struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
365 
366 	if (!x86_pmu.lbr_nr)
367 		return;
368 
369 	if (has_branch_stack(event))
370 		cpuc->lbr_select = 0;
371 
372 	cpuc->lbr_users--;
373 	WARN_ON_ONCE(cpuc->lbr_users < 0);
374 	perf_sched_cb_dec(event->pmu);
375 }
376 
377 void amd_pmu_lbr_sched_task(struct perf_event_pmu_context *pmu_ctx,
378 			    struct task_struct *task, bool sched_in)
379 {
380 	struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
381 
382 	/*
383 	 * A context switch can flip the address space and LBR entries are
384 	 * not tagged with an identifier. Hence, branches cannot be resolved
385 	 * from the old address space and the LBR records should be wiped.
386 	 */
387 	if (cpuc->lbr_users && sched_in)
388 		amd_pmu_lbr_reset();
389 }
390 
391 void amd_pmu_lbr_enable_all(void)
392 {
393 	struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
394 	u64 lbr_select, dbg_ctl, dbg_extn_cfg;
395 
396 	if (!cpuc->lbr_users || !x86_pmu.lbr_nr)
397 		return;
398 
399 	/* Set hardware branch filter */
400 	if (cpuc->lbr_select) {
401 		lbr_select = cpuc->lbr_sel->config & LBR_SELECT_MASK;
402 		wrmsrq(MSR_AMD64_LBR_SELECT, lbr_select);
403 	}
404 
405 	if (cpu_feature_enabled(X86_FEATURE_AMD_LBR_PMC_FREEZE)) {
406 		rdmsrq(MSR_IA32_DEBUGCTLMSR, dbg_ctl);
407 		wrmsrq(MSR_IA32_DEBUGCTLMSR, dbg_ctl | DEBUGCTLMSR_FREEZE_LBRS_ON_PMI);
408 	}
409 
410 	rdmsrq(MSR_AMD_DBG_EXTN_CFG, dbg_extn_cfg);
411 	wrmsrq(MSR_AMD_DBG_EXTN_CFG, dbg_extn_cfg | DBG_EXTN_CFG_LBRV2EN);
412 }
413 
414 void amd_pmu_lbr_disable_all(void)
415 {
416 	struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
417 
418 	if (!cpuc->lbr_users || !x86_pmu.lbr_nr)
419 		return;
420 
421 	__amd_pmu_lbr_disable();
422 }
423 
424 __init int amd_pmu_lbr_init(void)
425 {
426 	union cpuid_0x80000022_ebx ebx;
427 
428 	if (x86_pmu.version < 2 || !boot_cpu_has(X86_FEATURE_AMD_LBR_V2))
429 		return -EOPNOTSUPP;
430 
431 	/* Set number of entries */
432 	ebx.full = cpuid_ebx(EXT_PERFMON_DEBUG_FEATURES);
433 	x86_pmu.lbr_nr = ebx.split.lbr_v2_stack_sz;
434 
435 	pr_cont("%d-deep LBR, ", x86_pmu.lbr_nr);
436 
437 	return 0;
438 }
439