Linux Perf Users
 help / color / mirror / Atom feed
From: "Mi, Dapeng" <dapeng1.mi@linux.intel.com>
To: sashiko-reviews@lists.linux.dev
Cc: linux-perf-users@vger.kernel.org, bpf@vger.kernel.org
Subject: Re: [Patch v4 1/5] perf/x86: Disable LBR if x86_pmu.lbr_nr exceeds MAX_LBR_ENTRIES
Date: Wed, 21 Oct 2026 14:16:05 +0800	[thread overview]
Message-ID: <e8e0c5e0-46c7-4f34-abff-5f24ceba12f7@linux.intel.com> (raw)
In-Reply-To: <sashiko-outbox-179814@kernel.org>


On 10/21/2026 1:42 PM, sashiko-bot@kernel.org wrote:
> Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
> - [Medium] perf/x86: init_hw_perf_events() disables LBR too late after vendor PMU init
> --
>
> commit c6c1bbb1f4feb929dd247ddd507177ce58d871e1
> Author: Dapeng Mi <dapeng1.mi@linux.intel.com>
>
> perf/x86: Disable LBR if x86_pmu.lbr_nr exceeds MAX_LBR_ENTRIES
>
> This commit disables last branch record support in init_hw_perf_events()
> if x86_pmu.lbr_nr exceeds MAX_LBR_ENTRIES to prevent out-of-bounds
> accesses in the cached branch stack handling path.
>
>> diff --git a/arch/x86/events/core.c b/arch/x86/events/core.c
>> index 4df792b139e05..002a04c149c29 100644
>> --- a/arch/x86/events/core.c
>> +++ b/arch/x86/events/core.c
>> @@ -2645,6 +2645,12 @@ static int __init init_hw_perf_events(void)
>>  	if (!x86_pmu.config_mask)
>>  		x86_pmu.config_mask = X86_RAW_EVENT_MASK;
>>  
>> +	if (x86_pmu.lbr_nr > MAX_LBR_ENTRIES) {
>> +		pr_warn("LBR entries %d exceeds max %d, disable LBR.\n",
>> +			x86_pmu.lbr_nr, MAX_LBR_ENTRIES);
>> +		x86_pmu.lbr_nr = 0;
>> +	}
>> +
>>  	perf_events_lapic_init();
>>  	register_nmi_handler(NMI_LOCAL, perf_event_nmi_handler, 0, "PMI");
> [Severity: Medium]
> Does zeroing x86_pmu.lbr_nr here in init_hw_perf_events() happen too late,
> after intel_pmu_init() and amd_pmu_init() have already configured hardware
> and driver state using the unvalidated x86_pmu.lbr_nr value?
>
> In arch/x86/events/intel/lbr.c:intel_pmu_arch_lbr_init(), if lbr_nr exceeds
> MAX_LBR_ENTRIES, initialization proceeds instead of taking the clear_arch_lbr
> path:
>
> 	lbr_nr = fls(eax.split.lbr_depth_mask) * 8;
> 	if (!lbr_nr)
> 		goto clear_arch_lbr;
>
> 	/* Apply the max depth of Arch LBR */
> 	if (wrmsrq_safe(MSR_ARCH_LBR_DEPTH, lbr_nr))
> 		goto clear_arch_lbr;
> 	...
> 	x86_pmu.lbr_counters = ecx.split.lbr_counters;
> 	x86_pmu.lbr_nr = lbr_nr;
>
> 	if (!!x86_pmu.lbr_counters)
> 		x86_pmu.flags |= PMU_FL_BR_CNTR | PMU_FL_DYN_CONSTRAINT;
>
> Because clear_arch_lbr is skipped, X86_FEATURE_ARCH_LBR remains enabled,
> MSR_ARCH_LBR_DEPTH is written, pmu->task_ctx_cache is allocated via
> create_lbr_kmem_cache(), and x86_pmu.lbr_ctl_map and static branches are
> configured.
>
> Subsequently, arch/x86/events/intel/lbr.c:reserve_lbr_buffers() checks the
> feature bit and task_ctx_cache rather than x86_pmu.lbr_nr:
>
> 	if (!cpu_feature_enabled(X86_FEATURE_ARCH_LBR))
> 		return;
>
> 	for_each_possible_cpu(cpu) {
> 		cpuc = per_cpu_ptr(&cpu_hw_events, cpu);
> 		kmem_cache = x86_get_pmu(cpu)->task_ctx_cache;
> 		if (!kmem_cache || cpuc->lbr_xsave)
> 			continue;
>
> 		cpuc->lbr_xsave = kmem_cache_alloc_node(kmem_cache,
> 							GFP_KERNEL | __GFP_ZERO,
> 							cpu_to_node(cpu));
> 	}
>
> Wouldn't this still allocate per-cpu cpuc->lbr_xsave buffers on hardware
> reservation even after x86_pmu.lbr_nr is set to 0?
>
> Similarly, in arch/x86/events/intel/core.c:lbr_is_visible(), leaving
> PMU_FL_BR_CNTR set in x86_pmu.flags keeps branch_counter_nr and
> branch_counter_width visible in sysfs when x86_pmu.lbr_nr is 0:
>
> 	/* branches */
> 	if (i == 0)
> 		return x86_pmu.lbr_nr ? attr->mode : 0;
>
> 	return (x86_pmu.flags & PMU_FL_BR_CNTR) ? attr->mode : 0;
>
> In addition, both arch/x86/events/intel/core.c:intel_pmu_init() and
> arch/x86/events/amd/core.c:amd_core_pmu_init() check x86_pmu.lbr_nr before
> init_hw_perf_events() clears it:
>
> 	if (x86_pmu.lbr_nr) {
> 		intel_pmu_lbr_init();
>
> 		pr_cont("%d-deep LBR, ", x86_pmu.lbr_nr);
>
> 		/* only support branch_stack snapshot for perfmon >= v2 */
> 		if (x86_pmu.disable_all == intel_pmu_disable_all) {
> 			if (boot_cpu_has(X86_FEATURE_ARCH_LBR)) {
> 				static_call_update(perf_snapshot_branch_stack,
> 						   intel_pmu_snapshot_arch_branch_stack);
> 			} else {
> 				static_call_update(perf_snapshot_branch_stack,
> 						   intel_pmu_snapshot_branch_stack);
> 			}
> 		}
> 	}
>
> And in amd_core_pmu_init():
>
> 	if (!amd_pmu_lbr_init()) {
> 		/* LBR requires flushing on context switch */
> 		x86_pmu.sched_task = amd_pmu_lbr_sched_task;
> 		static_call_update(amd_pmu_branch_hw_config, amd_pmu_lbr_hw_config);
> 		static_call_update(amd_pmu_branch_reset, amd_pmu_lbr_reset);
> 		static_call_update(amd_pmu_branch_add, amd_pmu_lbr_add);
> 		static_call_update(amd_pmu_branch_del, amd_pmu_lbr_del);
>
> 		/* Only support branch_stack snapshot on perfmon v2 */
> 		if (x86_pmu.handle_irq == amd_pmu_v2_handle_irq)
> 			static_call_update(perf_snapshot_branch_stack, amd_pmu_v2_snapshot_branch_stack);
> 	} else if (!amd_brs_init()) {
>
> If bpf_get_branch_snapshot() is later called when x86_pmu.lbr_nr is 0, won't
> the registered perf_snapshot_branch_stack callback still run, manipulate
> branch and global control registers, and unconditionally call
> intel_pmu_enable_all(0) or amd_pmu_v2_enable_all(0)?
>
> Should the MAX_LBR_ENTRIES check be performed before or during the
> vendor-specific initialization routines (such as intel_pmu_lbr_init(),
> intel_pmu_arch_lbr_init(), and amd_pmu_lbr_init()) so that None of the
> hardware state, slab caches, flags, or static calls are enabled when
> lbr_nr is out of range?

The change is good enough. The branch sampling perf event creation is
guarded with x86_pmu.lbr_nr regardless of on Intel or AMD platforms. If
x86_pmu.lbr_nr is 0, then no events with branch sampling can be created
successfully, and if no active LBR event is present, the LBR hardware is
not really enabled.

Since it's a common validation for all x86 vendor platforms, it should be
placed into the x86 common PMU initialization path.

Thanks.


>

  reply	other threads:[~2026-10-21  6:16 UTC|newest]

Thread overview: 14+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-10-21  5:07 [Patch v4 0/5] perf/x86: Limit branch snapshots to valid entries Dapeng Mi
2026-10-21  5:07 ` [Patch v4 1/5] perf/x86: Disable LBR if x86_pmu.lbr_nr exceeds MAX_LBR_ENTRIES Dapeng Mi
2026-10-21  5:42   ` sashiko-bot
2026-10-21  6:16     ` Mi, Dapeng [this message]
2026-10-21  5:07 ` [Patch v4 2/5] perf/x86/amd/lbr: Limit branch snapshots to valid entries Dapeng Mi
2026-10-21  5:31   ` sashiko-bot
2026-10-21  5:07 ` [Patch v4 3/5] perf/x86/intel/lbr: Reset the cached LBR stack in intel_pmu_lbr_reset() Dapeng Mi
2026-10-21  5:44   ` sashiko-bot
2026-10-21  5:07 ` [Patch v4 4/5] perf/x86/intel/lbr: Limit branch snapshots to valid entries Dapeng Mi
2026-10-21  5:37   ` sashiko-bot
2026-10-21  5:07 ` [Patch v4 5/5] pef/x86/intel: Always snapshot live hardware LBR state for BPF path Dapeng Mi
2026-10-21  6:05   ` sashiko-bot
2026-10-21  6:53     ` Mi, Dapeng
2026-10-21  6:59   ` Mi, Dapeng

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=e8e0c5e0-46c7-4f34-abff-5f24ceba12f7@linux.intel.com \
    --to=dapeng1.mi@linux.intel.com \
    --cc=bpf@vger.kernel.org \
    --cc=linux-perf-users@vger.kernel.org \
    --cc=sashiko-reviews@lists.linux.dev \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox