arch/x86/events/intel/lbr.c

Source file repositories/reference/linux-study-clean/arch/x86/events/intel/lbr.c

File Facts

System
Linux kernel
Corpus path
arch/x86/events/intel/lbr.c
Extension
.c
Size
45296 bytes
Lines
1715
Domain
Architecture Layer
Bucket
arch/x86
Inferred role
Architecture Layer: exported/initcall integration point
Status
integration implementation candidate

Why This File Exists

CPU and platform-specific kernel glue: boot entry, traps, syscall entry, interrupts, page tables, context switch, and low-level barriers.

Dependency Surface

Detected Declarations

Annotated Snippet

task_context_opt(ctx)->lbr_stack_state == LBR_NONE) {
		intel_pmu_lbr_reset();
		return;
	}

	/*
	 * Does not restore the LBR registers, if
	 * - No one else touched them, and
	 * - Was not cleared in Cstate
	 */
	if ((ctx == cpuc->last_task_ctx) &&
	    (task_context_opt(ctx)->log_id == cpuc->last_log_id) &&
	    !lbr_is_reset_in_cstate(ctx)) {
		task_context_opt(ctx)->lbr_stack_state = LBR_NONE;
		return;
	}

	x86_pmu.lbr_restore(ctx);

	task_context_opt(ctx)->lbr_stack_state = LBR_NONE;
}

void intel_pmu_lbr_save(void *ctx)
{
	struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
	struct x86_perf_task_context *task_ctx = ctx;
	bool need_info = x86_pmu.lbr_has_info;
	unsigned lbr_idx, mask;
	u64 tos;
	int i;

	mask = x86_pmu.lbr_nr - 1;
	tos = intel_pmu_lbr_tos();
	for (i = 0; i < x86_pmu.lbr_nr; i++) {
		lbr_idx = (tos - i) & mask;
		if (!rdlbr_all(&task_ctx->lbr[i], lbr_idx, need_info))
			break;
	}
	task_ctx->valid_lbrs = i;
	task_ctx->tos = tos;

	if (cpuc->lbr_select)
		rdmsrq(MSR_LBR_SELECT, task_ctx->lbr_sel);
}

static void intel_pmu_arch_lbr_save(void *ctx)
{
	struct x86_perf_task_context_arch_lbr *task_ctx = ctx;
	struct lbr_entry *entries = task_ctx->entries;
	int i;

	for (i = 0; i < x86_pmu.lbr_nr; i++) {
		if (!rdlbr_all(&entries[i], i, true))
			break;
	}

	/* LBR call stack is not full. Reset is required in restore. */
	if (i < x86_pmu.lbr_nr)
		entries[x86_pmu.lbr_nr - 1].from = 0;
}

/*
 * Save the Architecture LBR state to the xsave area in the perf
 * context data for the task via the XSAVES instruction.
 */
static void intel_pmu_arch_lbr_xsaves(void *ctx)
{
	struct x86_perf_task_context_arch_lbr_xsave *task_ctx = ctx;

	xsaves(&task_ctx->xsave, XFEATURE_MASK_LBR);
}

static void __intel_pmu_lbr_save(void *ctx)
{
	struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);

	if (!has_lbr_callstack_users(ctx)) {
		task_context_opt(ctx)->lbr_stack_state = LBR_NONE;
		return;
	}

	x86_pmu.lbr_save(ctx);

	task_context_opt(ctx)->lbr_stack_state = LBR_VALID;

	cpuc->last_task_ctx = ctx;
	cpuc->last_log_id = ++task_context_opt(ctx)->log_id;
}

void intel_pmu_lbr_sched_task(struct perf_event_pmu_context *pmu_ctx,

Annotation

Implementation Notes