lbr.c (530bfff6480307d210734222a54d56af7f908957) lbr.c (f42be8651a7a9d5cb165e5d176fc0b09621b4f4d)
1// SPDX-License-Identifier: GPL-2.0
2#include <linux/perf_event.h>
3#include <linux/types.h>
4
5#include <asm/perf_event.h>
6#include <asm/msr.h>
7#include <asm/insn.h>
8

--- 341 unchanged lines hidden (view full) ---

350 }
351
352 wrmsrl(x86_pmu.lbr_tos, tos);
353
354 if (cpuc->lbr_select)
355 wrmsrl(MSR_LBR_SELECT, task_ctx->lbr_sel);
356}
357
1// SPDX-License-Identifier: GPL-2.0
2#include <linux/perf_event.h>
3#include <linux/types.h>
4
5#include <asm/perf_event.h>
6#include <asm/msr.h>
7#include <asm/insn.h>
8

--- 341 unchanged lines hidden (view full) ---

350 }
351
352 wrmsrl(x86_pmu.lbr_tos, tos);
353
354 if (cpuc->lbr_select)
355 wrmsrl(MSR_LBR_SELECT, task_ctx->lbr_sel);
356}
357
358static __always_inline bool
359lbr_is_reset_in_cstate(struct x86_perf_task_context *task_ctx)
358static __always_inline bool lbr_is_reset_in_cstate(void *ctx)
360{
359{
361 return !rdlbr_from(task_ctx->tos);
360 return !rdlbr_from(((struct x86_perf_task_context *)ctx)->tos);
362}
363
361}
362
364static void __intel_pmu_lbr_restore(struct x86_perf_task_context *task_ctx)
363static void __intel_pmu_lbr_restore(void *ctx)
365{
366 struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
367
364{
365 struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
366
368 if (task_ctx->opt.lbr_callstack_users == 0 ||
369 task_ctx->opt.lbr_stack_state == LBR_NONE) {
367 if (task_context_opt(ctx)->lbr_callstack_users == 0 ||
368 task_context_opt(ctx)->lbr_stack_state == LBR_NONE) {
370 intel_pmu_lbr_reset();
371 return;
372 }
373
374 /*
375 * Does not restore the LBR registers, if
376 * - No one else touched them, and
377 * - Was not cleared in Cstate
378 */
369 intel_pmu_lbr_reset();
370 return;
371 }
372
373 /*
374 * Does not restore the LBR registers, if
375 * - No one else touched them, and
376 * - Was not cleared in Cstate
377 */
379 if ((task_ctx == cpuc->last_task_ctx) &&
380 (task_ctx->opt.log_id == cpuc->last_log_id) &&
381 !lbr_is_reset_in_cstate(task_ctx)) {
382 task_ctx->opt.lbr_stack_state = LBR_NONE;
378 if ((ctx == cpuc->last_task_ctx) &&
379 (task_context_opt(ctx)->log_id == cpuc->last_log_id) &&
380 !lbr_is_reset_in_cstate(ctx)) {
381 task_context_opt(ctx)->lbr_stack_state = LBR_NONE;
383 return;
384 }
385
382 return;
383 }
384
386 x86_pmu.lbr_restore(task_ctx);
385 x86_pmu.lbr_restore(ctx);
387
386
388 task_ctx->opt.lbr_stack_state = LBR_NONE;
387 task_context_opt(ctx)->lbr_stack_state = LBR_NONE;
389}
390
391void intel_pmu_lbr_save(void *ctx)
392{
393 struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
394 struct x86_perf_task_context *task_ctx = ctx;
395 unsigned lbr_idx, mask;
396 u64 tos, from;

--- 13 unchanged lines hidden (view full) ---

410 }
411 task_ctx->valid_lbrs = i;
412 task_ctx->tos = tos;
413
414 if (cpuc->lbr_select)
415 rdmsrl(MSR_LBR_SELECT, task_ctx->lbr_sel);
416}
417
388}
389
390void intel_pmu_lbr_save(void *ctx)
391{
392 struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
393 struct x86_perf_task_context *task_ctx = ctx;
394 unsigned lbr_idx, mask;
395 u64 tos, from;

--- 13 unchanged lines hidden (view full) ---

409 }
410 task_ctx->valid_lbrs = i;
411 task_ctx->tos = tos;
412
413 if (cpuc->lbr_select)
414 rdmsrl(MSR_LBR_SELECT, task_ctx->lbr_sel);
415}
416
418static void __intel_pmu_lbr_save(struct x86_perf_task_context *task_ctx)
417static void __intel_pmu_lbr_save(void *ctx)
419{
420 struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
421
418{
419 struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
420
422 if (task_ctx->opt.lbr_callstack_users == 0) {
423 task_ctx->opt.lbr_stack_state = LBR_NONE;
421 if (task_context_opt(ctx)->lbr_callstack_users == 0) {
422 task_context_opt(ctx)->lbr_stack_state = LBR_NONE;
424 return;
425 }
426
423 return;
424 }
425
427 x86_pmu.lbr_save(task_ctx);
426 x86_pmu.lbr_save(ctx);
428
427
429 task_ctx->opt.lbr_stack_state = LBR_VALID;
428 task_context_opt(ctx)->lbr_stack_state = LBR_VALID;
430
429
431 cpuc->last_task_ctx = task_ctx;
432 cpuc->last_log_id = ++task_ctx->opt.log_id;
430 cpuc->last_task_ctx = ctx;
431 cpuc->last_log_id = ++task_context_opt(ctx)->log_id;
433}
434
435void intel_pmu_lbr_swap_task_ctx(struct perf_event_context *prev,
436 struct perf_event_context *next)
437{
432}
433
434void intel_pmu_lbr_swap_task_ctx(struct perf_event_context *prev,
435 struct perf_event_context *next)
436{
438 struct x86_perf_task_context *prev_ctx_data, *next_ctx_data;
437 void *prev_ctx_data, *next_ctx_data;
439
440 swap(prev->task_ctx_data, next->task_ctx_data);
441
442 /*
443 * Architecture specific synchronization makes sense in
444 * case both prev->task_ctx_data and next->task_ctx_data
445 * pointers are allocated.
446 */
447
448 prev_ctx_data = next->task_ctx_data;
449 next_ctx_data = prev->task_ctx_data;
450
451 if (!prev_ctx_data || !next_ctx_data)
452 return;
453
438
439 swap(prev->task_ctx_data, next->task_ctx_data);
440
441 /*
442 * Architecture specific synchronization makes sense in
443 * case both prev->task_ctx_data and next->task_ctx_data
444 * pointers are allocated.
445 */
446
447 prev_ctx_data = next->task_ctx_data;
448 next_ctx_data = prev->task_ctx_data;
449
450 if (!prev_ctx_data || !next_ctx_data)
451 return;
452
454 swap(prev_ctx_data->opt.lbr_callstack_users,
455 next_ctx_data->opt.lbr_callstack_users);
453 swap(task_context_opt(prev_ctx_data)->lbr_callstack_users,
454 task_context_opt(next_ctx_data)->lbr_callstack_users);
456}
457
458void intel_pmu_lbr_sched_task(struct perf_event_context *ctx, bool sched_in)
459{
460 struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
455}
456
457void intel_pmu_lbr_sched_task(struct perf_event_context *ctx, bool sched_in)
458{
459 struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
461 struct x86_perf_task_context *task_ctx;
460 void *task_ctx;
462
463 if (!cpuc->lbr_users)
464 return;
465
466 /*
467 * If LBR callstack feature is enabled and the stack was saved when
468 * the task was scheduled out, restore the stack. Otherwise flush
469 * the LBR stack.

--- 20 unchanged lines hidden (view full) ---

490static inline bool branch_user_callstack(unsigned br_sel)
491{
492 return (br_sel & X86_BR_USER) && (br_sel & X86_BR_CALL_STACK);
493}
494
495void intel_pmu_lbr_add(struct perf_event *event)
496{
497 struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
461
462 if (!cpuc->lbr_users)
463 return;
464
465 /*
466 * If LBR callstack feature is enabled and the stack was saved when
467 * the task was scheduled out, restore the stack. Otherwise flush
468 * the LBR stack.

--- 20 unchanged lines hidden (view full) ---

489static inline bool branch_user_callstack(unsigned br_sel)
490{
491 return (br_sel & X86_BR_USER) && (br_sel & X86_BR_CALL_STACK);
492}
493
494void intel_pmu_lbr_add(struct perf_event *event)
495{
496 struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
498 struct x86_perf_task_context *task_ctx;
499
500 if (!x86_pmu.lbr_nr)
501 return;
502
503 if (event->hw.flags & PERF_X86_EVENT_LBR_SELECT)
504 cpuc->lbr_select = 1;
505
506 cpuc->br_sel = event->hw.branch_reg.reg;
507
497
498 if (!x86_pmu.lbr_nr)
499 return;
500
501 if (event->hw.flags & PERF_X86_EVENT_LBR_SELECT)
502 cpuc->lbr_select = 1;
503
504 cpuc->br_sel = event->hw.branch_reg.reg;
505
508 if (branch_user_callstack(cpuc->br_sel) && event->ctx->task_ctx_data) {
509 task_ctx = event->ctx->task_ctx_data;
510 task_ctx->opt.lbr_callstack_users++;
511 }
506 if (branch_user_callstack(cpuc->br_sel) && event->ctx->task_ctx_data)
507 task_context_opt(event->ctx->task_ctx_data)->lbr_callstack_users++;
512
513 /*
514 * Request pmu::sched_task() callback, which will fire inside the
515 * regular perf event scheduling, so that call will:
516 *
517 * - restore or wipe; when LBR-callstack,
518 * - wipe; otherwise,
519 *

--- 14 unchanged lines hidden (view full) ---

534 perf_sched_cb_inc(event->ctx->pmu);
535 if (!cpuc->lbr_users++ && !event->total_time_running)
536 intel_pmu_lbr_reset();
537}
538
539void intel_pmu_lbr_del(struct perf_event *event)
540{
541 struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
508
509 /*
510 * Request pmu::sched_task() callback, which will fire inside the
511 * regular perf event scheduling, so that call will:
512 *
513 * - restore or wipe; when LBR-callstack,
514 * - wipe; otherwise,
515 *

--- 14 unchanged lines hidden (view full) ---

530 perf_sched_cb_inc(event->ctx->pmu);
531 if (!cpuc->lbr_users++ && !event->total_time_running)
532 intel_pmu_lbr_reset();
533}
534
535void intel_pmu_lbr_del(struct perf_event *event)
536{
537 struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
542 struct x86_perf_task_context *task_ctx;
543
544 if (!x86_pmu.lbr_nr)
545 return;
546
547 if (branch_user_callstack(cpuc->br_sel) &&
538
539 if (!x86_pmu.lbr_nr)
540 return;
541
542 if (branch_user_callstack(cpuc->br_sel) &&
548 event->ctx->task_ctx_data) {
549 task_ctx = event->ctx->task_ctx_data;
550 task_ctx->opt.lbr_callstack_users--;
551 }
543 event->ctx->task_ctx_data)
544 task_context_opt(event->ctx->task_ctx_data)->lbr_callstack_users--;
552
553 if (event->hw.flags & PERF_X86_EVENT_LBR_SELECT)
554 cpuc->lbr_select = 0;
555
556 if (x86_pmu.intel_cap.pebs_baseline && event->attr.precise_ip > 0)
557 cpuc->lbr_pebs_users--;
558 cpuc->lbr_users--;
559 WARN_ON_ONCE(cpuc->lbr_users < 0);

--- 837 unchanged lines hidden ---
545
546 if (event->hw.flags & PERF_X86_EVENT_LBR_SELECT)
547 cpuc->lbr_select = 0;
548
549 if (x86_pmu.intel_cap.pebs_baseline && event->attr.precise_ip > 0)
550 cpuc->lbr_pebs_users--;
551 cpuc->lbr_users--;
552 WARN_ON_ONCE(cpuc->lbr_users < 0);

--- 837 unchanged lines hidden ---