* [PATCH] perf/x86/intel: Fix lbr event can placed into non lbr group
@ 2025-04-12 9:14 Luo Gengkun
2025-04-14 14:29 ` Liang, Kan
0 siblings, 1 reply; 7+ messages in thread
From: Luo Gengkun @ 2025-04-12 9:14 UTC (permalink / raw)
To: peterz
Cc: acme, namhyung, mark.rutland, alexander.shishkin, jolsa, irogers,
adrian.hunter, kan.liang, tglx, bp, dave.hansen, x86, hpa,
linux-perf-users, linux-kernel, luogengkun
The following perf command can trigger a warning on
intel_pmu_lbr_counters_reorder.
# perf record -e "{cpu-clock,cycles/call-graph="lbr"/}" -- sleep 1
The reason is that a lbr event are placed in non lbr group. And the
previous implememtation cannot force the leader to be a lbr event in this
case. And is_branch_counters_group will check if the group_leader supports
BRANCH_COUNTERS. So if a software event becomes a group_leader, which
hw.flags is -1, this check will alway pass.
To fix this problem, using has_branch_stack to judge if leader is lbr
event.
Fixes: 33744916196b ("perf/x86/intel: Support branch counters logging")
Signed-off-by: Luo Gengkun <luogengkun@huaweicloud.com>
---
arch/x86/events/intel/core.c | 14 +++++++-------
1 file changed, 7 insertions(+), 7 deletions(-)
diff --git a/arch/x86/events/intel/core.c b/arch/x86/events/intel/core.c
index 09d2d66c9f21..c6b394019e54 100644
--- a/arch/x86/events/intel/core.c
+++ b/arch/x86/events/intel/core.c
@@ -4114,6 +4114,13 @@ static int intel_pmu_hw_config(struct perf_event *event)
event->hw.flags |= PERF_X86_EVENT_NEEDS_BRANCH_STACK;
}
+ /*
+ * Force the leader to be a LBR event. So LBRs can be reset
+ * with the leader event. See intel_pmu_lbr_del() for details.
+ */
+ if (has_branch_stack(event) && !has_branch_stack(event->group_leader))
+ return -EINVAL;
+
if (branch_sample_counters(event)) {
struct perf_event *leader, *sibling;
int num = 0;
@@ -4157,13 +4164,6 @@ static int intel_pmu_hw_config(struct perf_event *event)
~(PERF_SAMPLE_BRANCH_PLM_ALL |
PERF_SAMPLE_BRANCH_COUNTERS)))
event->hw.flags &= ~PERF_X86_EVENT_NEEDS_BRANCH_STACK;
-
- /*
- * Force the leader to be a LBR event. So LBRs can be reset
- * with the leader event. See intel_pmu_lbr_del() for details.
- */
- if (!intel_pmu_needs_branch_stack(leader))
- return -EINVAL;
}
if (intel_pmu_needs_branch_stack(event)) {
--
2.34.1
^ permalink raw reply related [flat|nested] 7+ messages in thread
* Re: [PATCH] perf/x86/intel: Fix lbr event can placed into non lbr group
2025-04-12 9:14 [PATCH] perf/x86/intel: Fix lbr event can placed into non lbr group Luo Gengkun
@ 2025-04-14 14:29 ` Liang, Kan
2025-04-19 2:25 ` Luo Gengkun
0 siblings, 1 reply; 7+ messages in thread
From: Liang, Kan @ 2025-04-14 14:29 UTC (permalink / raw)
To: Luo Gengkun, peterz
Cc: acme, namhyung, mark.rutland, alexander.shishkin, jolsa, irogers,
adrian.hunter, tglx, bp, dave.hansen, x86, hpa, linux-perf-users,
linux-kernel
On 2025-04-12 5:14 a.m., Luo Gengkun wrote:
> The following perf command can trigger a warning on
> intel_pmu_lbr_counters_reorder.
>
> # perf record -e "{cpu-clock,cycles/call-graph="lbr"/}" -- sleep 1
>
> The reason is that a lbr event are placed in non lbr group. And the
> previous implememtation cannot force the leader to be a lbr event in this
> case.
Perf should only force the LBR leader for the branch counters case, so
perf only needs to reset the LBRs for the leader.
I don't think the leader restriction should be applied to other cases.
> And is_branch_counters_group will check if the group_leader supports
> BRANCH_COUNTERS.
> So if a software event becomes a group_leader, which
> hw.flags is -1, this check will alway pass.
I think the default flags for all events is 0. Can you point me to where
it is changed to -1?
Thanks,
Kan>
> To fix this problem, using has_branch_stack to judge if leader is lbr
> event.
>
> Fixes: 33744916196b ("perf/x86/intel: Support branch counters logging")
> Signed-off-by: Luo Gengkun <luogengkun@huaweicloud.com>
> ---
> arch/x86/events/intel/core.c | 14 +++++++-------
> 1 file changed, 7 insertions(+), 7 deletions(-)
>
> diff --git a/arch/x86/events/intel/core.c b/arch/x86/events/intel/core.c
> index 09d2d66c9f21..c6b394019e54 100644
> --- a/arch/x86/events/intel/core.c
> +++ b/arch/x86/events/intel/core.c
> @@ -4114,6 +4114,13 @@ static int intel_pmu_hw_config(struct perf_event *event)
> event->hw.flags |= PERF_X86_EVENT_NEEDS_BRANCH_STACK;
> }
>
> + /*
> + * Force the leader to be a LBR event. So LBRs can be reset
> + * with the leader event. See intel_pmu_lbr_del() for details.
> + */
> + if (has_branch_stack(event) && !has_branch_stack(event->group_leader))
> + return -EINVAL;
> +
> if (branch_sample_counters(event)) {
> struct perf_event *leader, *sibling;
> int num = 0;
> @@ -4157,13 +4164,6 @@ static int intel_pmu_hw_config(struct perf_event *event)
> ~(PERF_SAMPLE_BRANCH_PLM_ALL |
> PERF_SAMPLE_BRANCH_COUNTERS)))
> event->hw.flags &= ~PERF_X86_EVENT_NEEDS_BRANCH_STACK;
> -
> - /*
> - * Force the leader to be a LBR event. So LBRs can be reset
> - * with the leader event. See intel_pmu_lbr_del() for details.
> - */
> - if (!intel_pmu_needs_branch_stack(leader))
> - return -EINVAL;
> }
>
> if (intel_pmu_needs_branch_stack(event)) {
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH] perf/x86/intel: Fix lbr event can placed into non lbr group
2025-04-14 14:29 ` Liang, Kan
@ 2025-04-19 2:25 ` Luo Gengkun
2025-04-19 4:50 ` Luo Gengkun
0 siblings, 1 reply; 7+ messages in thread
From: Luo Gengkun @ 2025-04-19 2:25 UTC (permalink / raw)
To: Liang, Kan, peterz
Cc: acme, namhyung, mark.rutland, alexander.shishkin, jolsa, irogers,
adrian.hunter, tglx, bp, dave.hansen, x86, hpa, linux-perf-users,
linux-kernel
On 2025/4/14 22:29, Liang, Kan wrote:
>
> On 2025-04-12 5:14 a.m., Luo Gengkun wrote:
>> The following perf command can trigger a warning on
>> intel_pmu_lbr_counters_reorder.
>>
>> # perf record -e "{cpu-clock,cycles/call-graph="lbr"/}" -- sleep 1
>>
>> The reason is that a lbr event are placed in non lbr group. And the
>> previous implememtation cannot force the leader to be a lbr event in this
>> case.
> Perf should only force the LBR leader for the branch counters case, so
> perf only needs to reset the LBRs for the leader.
> I don't think the leader restriction should be applied to other cases.
Yes, the commit message should be updated. The code implementation only
restricts the leader to be an LBRs.
>> And is_branch_counters_group will check if the group_leader supports
>> BRANCH_COUNTERS.
>> So if a software event becomes a group_leader, which
>> hw.flags is -1, this check will alway pass.
> I think the default flags for all events is 0. Can you point me to where
> it is changed to -1?
>
> Thanks,
> Kan>
The hw_perf_event contains a union, hw.flags is used only for hardware
events.
For the software events, it uses hrtimer. Therefor, when
perf_swevent_init_hrtimer
is called, it changes the value of hw.flags too.
Thanks,
Gengkun
>> To fix this problem, using has_branch_stack to judge if leader is lbr
>> event.
>>
>> Fixes: 33744916196b ("perf/x86/intel: Support branch counters logging")
>> Signed-off-by: Luo Gengkun <luogengkun@huaweicloud.com>
>> ---
>> arch/x86/events/intel/core.c | 14 +++++++-------
>> 1 file changed, 7 insertions(+), 7 deletions(-)
>>
>> diff --git a/arch/x86/events/intel/core.c b/arch/x86/events/intel/core.c
>> index 09d2d66c9f21..c6b394019e54 100644
>> --- a/arch/x86/events/intel/core.c
>> +++ b/arch/x86/events/intel/core.c
>> @@ -4114,6 +4114,13 @@ static int intel_pmu_hw_config(struct perf_event *event)
>> event->hw.flags |= PERF_X86_EVENT_NEEDS_BRANCH_STACK;
>> }
>>
>> + /*
>> + * Force the leader to be a LBR event. So LBRs can be reset
>> + * with the leader event. See intel_pmu_lbr_del() for details.
>> + */
>> + if (has_branch_stack(event) && !has_branch_stack(event->group_leader))
>> + return -EINVAL;
>> +
>> if (branch_sample_counters(event)) {
>> struct perf_event *leader, *sibling;
>> int num = 0;
>> @@ -4157,13 +4164,6 @@ static int intel_pmu_hw_config(struct perf_event *event)
>> ~(PERF_SAMPLE_BRANCH_PLM_ALL |
>> PERF_SAMPLE_BRANCH_COUNTERS)))
>> event->hw.flags &= ~PERF_X86_EVENT_NEEDS_BRANCH_STACK;
>> -
>> - /*
>> - * Force the leader to be a LBR event. So LBRs can be reset
>> - * with the leader event. See intel_pmu_lbr_del() for details.
>> - */
>> - if (!intel_pmu_needs_branch_stack(leader))
>> - return -EINVAL;
>> }
>>
>> if (intel_pmu_needs_branch_stack(event)) {
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH] perf/x86/intel: Fix lbr event can placed into non lbr group
2025-04-19 2:25 ` Luo Gengkun
@ 2025-04-19 4:50 ` Luo Gengkun
2025-04-21 14:56 ` Liang, Kan
0 siblings, 1 reply; 7+ messages in thread
From: Luo Gengkun @ 2025-04-19 4:50 UTC (permalink / raw)
To: Liang, Kan, peterz
Cc: acme, namhyung, mark.rutland, alexander.shishkin, jolsa, irogers,
adrian.hunter, tglx, bp, dave.hansen, x86, hpa, linux-perf-users,
linux-kernel
On 2025/4/19 10:25, Luo Gengkun wrote:
>
> On 2025/4/14 22:29, Liang, Kan wrote:
>>
>> On 2025-04-12 5:14 a.m., Luo Gengkun wrote:
>>> The following perf command can trigger a warning on
>>> intel_pmu_lbr_counters_reorder.
>>>
>>> # perf record -e "{cpu-clock,cycles/call-graph="lbr"/}" -- sleep 1
>>>
>>> The reason is that a lbr event are placed in non lbr group. And the
>>> previous implememtation cannot force the leader to be a lbr event in
>>> this
>>> case.
>> Perf should only force the LBR leader for the branch counters case, so
>> perf only needs to reset the LBRs for the leader.
>> I don't think the leader restriction should be applied to other cases.
>
> Yes, the commit message should be updated. The code implementation only
>
> restricts the leader to be an LBRs.
>
>>> And is_branch_counters_group will check if the group_leader supports
>>> BRANCH_COUNTERS.
>>> So if a software event becomes a group_leader, which
>>> hw.flags is -1, this check will alway pass.
>> I think the default flags for all events is 0. Can you point me to where
>> it is changed to -1?
>>
>> Thanks,
>> Kan>
>
> The hw_perf_event contains a union, hw.flags is used only for hardware
> events.
>
> For the software events, it uses hrtimer. Therefor, when
> perf_swevent_init_hrtimer
>
> is called, it changes the value of hw.flags too.
>
>
> Thanks,
>
> Gengkun
It seems that using union is dangerous because different types of
perf_events can be
placed in the same group. Currently, a large number of codes directly
access the hw
of the leader, which is insecure. This part of the logic needs to be
redesigned to void
similar problems. And I am happy to work for this.
Thanks,
Gengkun
>>> To fix this problem, using has_branch_stack to judge if leader is lbr
>>> event.
>>>
>>> Fixes: 33744916196b ("perf/x86/intel: Support branch counters logging")
>>> Signed-off-by: Luo Gengkun <luogengkun@huaweicloud.com>
>>> ---
>>> arch/x86/events/intel/core.c | 14 +++++++-------
>>> 1 file changed, 7 insertions(+), 7 deletions(-)
>>>
>>> diff --git a/arch/x86/events/intel/core.c
>>> b/arch/x86/events/intel/core.c
>>> index 09d2d66c9f21..c6b394019e54 100644
>>> --- a/arch/x86/events/intel/core.c
>>> +++ b/arch/x86/events/intel/core.c
>>> @@ -4114,6 +4114,13 @@ static int intel_pmu_hw_config(struct
>>> perf_event *event)
>>> event->hw.flags |= PERF_X86_EVENT_NEEDS_BRANCH_STACK;
>>> }
>>> + /*
>>> + * Force the leader to be a LBR event. So LBRs can be reset
>>> + * with the leader event. See intel_pmu_lbr_del() for details.
>>> + */
>>> + if (has_branch_stack(event) &&
>>> !has_branch_stack(event->group_leader))
>>> + return -EINVAL;
>>> +
>>> if (branch_sample_counters(event)) {
>>> struct perf_event *leader, *sibling;
>>> int num = 0;
>>> @@ -4157,13 +4164,6 @@ static int intel_pmu_hw_config(struct
>>> perf_event *event)
>>> ~(PERF_SAMPLE_BRANCH_PLM_ALL |
>>> PERF_SAMPLE_BRANCH_COUNTERS)))
>>> event->hw.flags &= ~PERF_X86_EVENT_NEEDS_BRANCH_STACK;
>>> -
>>> - /*
>>> - * Force the leader to be a LBR event. So LBRs can be reset
>>> - * with the leader event. See intel_pmu_lbr_del() for details.
>>> - */
>>> - if (!intel_pmu_needs_branch_stack(leader))
>>> - return -EINVAL;
>>> }
>>> if (intel_pmu_needs_branch_stack(event)) {
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH] perf/x86/intel: Fix lbr event can placed into non lbr group
2025-04-19 4:50 ` Luo Gengkun
@ 2025-04-21 14:56 ` Liang, Kan
2025-04-23 22:11 ` Liang, Kan
0 siblings, 1 reply; 7+ messages in thread
From: Liang, Kan @ 2025-04-21 14:56 UTC (permalink / raw)
To: Luo Gengkun, peterz
Cc: acme, namhyung, mark.rutland, alexander.shishkin, jolsa, irogers,
adrian.hunter, tglx, bp, dave.hansen, x86, hpa, linux-perf-users,
linux-kernel
On 2025-04-19 12:50 a.m., Luo Gengkun wrote:
>
> On 2025/4/19 10:25, Luo Gengkun wrote:
>>
>> On 2025/4/14 22:29, Liang, Kan wrote:
>>>
>>> On 2025-04-12 5:14 a.m., Luo Gengkun wrote:
>>>> The following perf command can trigger a warning on
>>>> intel_pmu_lbr_counters_reorder.
>>>>
>>>> # perf record -e "{cpu-clock,cycles/call-graph="lbr"/}" -- sleep 1
>>>>
>>>> The reason is that a lbr event are placed in non lbr group. And the
>>>> previous implememtation cannot force the leader to be a lbr event in
>>>> this
>>>> case.
>>> Perf should only force the LBR leader for the branch counters case, so
>>> perf only needs to reset the LBRs for the leader.
>>> I don't think the leader restriction should be applied to other cases.
>>
>> Yes, the commit message should be updated. The code implementation only
>>
>> restricts the leader to be an LBRs.
>>
>>>> And is_branch_counters_group will check if the group_leader supports
>>>> BRANCH_COUNTERS.
>>>> So if a software event becomes a group_leader, which
>>>> hw.flags is -1, this check will alway pass.
>>> I think the default flags for all events is 0. Can you point me to where
>>> it is changed to -1?
>>>
>>> Thanks,
>>> Kan>
>>
>> The hw_perf_event contains a union, hw.flags is used only for hardware
>> events.
>>
>> For the software events, it uses hrtimer. Therefor, when
>> perf_swevent_init_hrtimer
>>
>> is called, it changes the value of hw.flags too.
>>
>>
>> Thanks,
>>
>> Gengkun
>
>
> It seems that using union is dangerous because different types of
> perf_events can be
> placed in the same group.
Only the PMU with perf_sw_context can be placed in the same group with
other types.
> Currently, a large number of codes directly
> access the hw
> of the leader, which is insecure.
For X86, the topdown, ACR and branch counters will touch the
leader.hw->flags. The topdown and ACR have already checked the leader
before updating the flags. The branch counters missed it. I think a
check is required for the branch counters as well, which should be good
enough to address the issue.
diff --git a/arch/x86/events/intel/core.c b/arch/x86/events/intel/core.c
index 16f8aea33243..406f58b3b5d4 100644
--- a/arch/x86/events/intel/core.c
+++ b/arch/x86/events/intel/core.c
@@ -4256,6 +4256,12 @@ static int intel_pmu_hw_config(struct perf_event
*event)
* group, which requires the extra space to store the counters.
*/
leader = event->group_leader;
+ /*
+ * The leader's hw.flags will be used to determine a
+ * branch counter logging group. Force it a X86 event.
+ */
+ if (!is_x86_event(leader))
+ return -EINVAL;
if (branch_sample_call_stack(leader))
return -EINVAL;
if (branch_sample_counters(leader)) {
> This part of the logic needs to be
> redesigned to void
> similar problems. And I am happy to work for this.
>
OK. Please share your idea.
Thanks,
Kan
>
> Thanks,
> Gengkun
>>>> To fix this problem, using has_branch_stack to judge if leader is lbr
>>>> event.
>>>>
>>>> Fixes: 33744916196b ("perf/x86/intel: Support branch counters logging")
>>>> Signed-off-by: Luo Gengkun <luogengkun@huaweicloud.com>
>>>> ---
>>>> arch/x86/events/intel/core.c | 14 +++++++-------
>>>> 1 file changed, 7 insertions(+), 7 deletions(-)
>>>>
>>>> diff --git a/arch/x86/events/intel/core.c b/arch/x86/events/intel/
>>>> core.c
>>>> index 09d2d66c9f21..c6b394019e54 100644
>>>> --- a/arch/x86/events/intel/core.c
>>>> +++ b/arch/x86/events/intel/core.c
>>>> @@ -4114,6 +4114,13 @@ static int intel_pmu_hw_config(struct
>>>> perf_event *event)
>>>> event->hw.flags |= PERF_X86_EVENT_NEEDS_BRANCH_STACK;
>>>> }
>>>> + /*
>>>> + * Force the leader to be a LBR event. So LBRs can be reset
>>>> + * with the leader event. See intel_pmu_lbr_del() for details.
>>>> + */
>>>> + if (has_branch_stack(event) && !has_branch_stack(event-
>>>> >group_leader))
>>>> + return -EINVAL;
>>>> +
>>>> if (branch_sample_counters(event)) {
>>>> struct perf_event *leader, *sibling;
>>>> int num = 0;
>>>> @@ -4157,13 +4164,6 @@ static int intel_pmu_hw_config(struct
>>>> perf_event *event)
>>>> ~(PERF_SAMPLE_BRANCH_PLM_ALL |
>>>> PERF_SAMPLE_BRANCH_COUNTERS)))
>>>> event->hw.flags &= ~PERF_X86_EVENT_NEEDS_BRANCH_STACK;
>>>> -
>>>> - /*
>>>> - * Force the leader to be a LBR event. So LBRs can be reset
>>>> - * with the leader event. See intel_pmu_lbr_del() for details.
>>>> - */
>>>> - if (!intel_pmu_needs_branch_stack(leader))
>>>> - return -EINVAL;
>>>> }
>>>> if (intel_pmu_needs_branch_stack(event)) {
>
^ permalink raw reply related [flat|nested] 7+ messages in thread
* Re: [PATCH] perf/x86/intel: Fix lbr event can placed into non lbr group
2025-04-21 14:56 ` Liang, Kan
@ 2025-04-23 22:11 ` Liang, Kan
2025-04-25 3:44 ` Luo Gengkun
0 siblings, 1 reply; 7+ messages in thread
From: Liang, Kan @ 2025-04-23 22:11 UTC (permalink / raw)
To: Luo Gengkun, peterz
Cc: acme, namhyung, mark.rutland, alexander.shishkin, jolsa, irogers,
adrian.hunter, tglx, bp, dave.hansen, x86, hpa, linux-perf-users,
linux-kernel
On 2025-04-21 10:56 a.m., Liang, Kan wrote:
>
>
> On 2025-04-19 12:50 a.m., Luo Gengkun wrote:
>>
>> On 2025/4/19 10:25, Luo Gengkun wrote:
>>>
>>> On 2025/4/14 22:29, Liang, Kan wrote:
>>>>
>>>> On 2025-04-12 5:14 a.m., Luo Gengkun wrote:
>>>>> The following perf command can trigger a warning on
>>>>> intel_pmu_lbr_counters_reorder.
>>>>>
>>>>> # perf record -e "{cpu-clock,cycles/call-graph="lbr"/}" -- sleep 1
>>>>>
>>>>> The reason is that a lbr event are placed in non lbr group. And the
>>>>> previous implememtation cannot force the leader to be a lbr event in
>>>>> this
>>>>> case.
>>>> Perf should only force the LBR leader for the branch counters case, so
>>>> perf only needs to reset the LBRs for the leader.
>>>> I don't think the leader restriction should be applied to other cases.
>>>
>>> Yes, the commit message should be updated. The code implementation only
>>>
>>> restricts the leader to be an LBRs.
>>>
>>>>> And is_branch_counters_group will check if the group_leader supports
>>>>> BRANCH_COUNTERS.
>>>>> So if a software event becomes a group_leader, which
>>>>> hw.flags is -1, this check will alway pass.
>>>> I think the default flags for all events is 0. Can you point me to where
>>>> it is changed to -1?
>>>>
>>>> Thanks,
>>>> Kan>
>>>
>>> The hw_perf_event contains a union, hw.flags is used only for hardware
>>> events.
>>>
>>> For the software events, it uses hrtimer. Therefor, when
>>> perf_swevent_init_hrtimer
>>>
>>> is called, it changes the value of hw.flags too.
>>>
>>>
>>> Thanks,
>>>
>>> Gengkun
>>
>>
>> It seems that using union is dangerous because different types of
>> perf_events can be
>> placed in the same group.
>
> Only the PMU with perf_sw_context can be placed in the same group with
> other types.
>
>> Currently, a large number of codes directly
>> access the hw
>> of the leader, which is insecure.
>
> For X86, the topdown, ACR and branch counters will touch the
> leader.hw->flags. The topdown and ACR have already checked the leader
> before updating the flags. The branch counters missed it. I think a
> check is required for the branch counters as well, which should be good
> enough to address the issue.
>
> diff --git a/arch/x86/events/intel/core.c b/arch/x86/events/intel/core.c
> index 16f8aea33243..406f58b3b5d4 100644
> --- a/arch/x86/events/intel/core.c
> +++ b/arch/x86/events/intel/core.c
> @@ -4256,6 +4256,12 @@ static int intel_pmu_hw_config(struct perf_event
> *event)
> * group, which requires the extra space to store the counters.
> */
> leader = event->group_leader;
> + /*
> + * The leader's hw.flags will be used to determine a
> + * branch counter logging group. Force it a X86 event.
> + */
> + if (!is_x86_event(leader))
> + return -EINVAL;
> if (branch_sample_call_stack(leader))
> return -EINVAL;
> if (branch_sample_counters(leader)) {
>
The above check may not enough, since the
intel_pmu_lbr_counters_reorder() can be invoked without branch counters
event.
I've posted a fix to address the issue. Please take a look.
https://lore.kernel.org/lkml/20250423221015.268949-1-kan.liang@linux.intel.com/
Thanks,
Kan
>> This part of the logic needs to be
>> redesigned to void
>> similar problems. And I am happy to work for this.
>>
>
> OK. Please share your idea.
>
> Thanks,
> Kan
>>
>> Thanks,
>> Gengkun
>>>>> To fix this problem, using has_branch_stack to judge if leader is lbr
>>>>> event.
>>>>>
>>>>> Fixes: 33744916196b ("perf/x86/intel: Support branch counters logging")
>>>>> Signed-off-by: Luo Gengkun <luogengkun@huaweicloud.com>
>>>>> ---
>>>>> arch/x86/events/intel/core.c | 14 +++++++-------
>>>>> 1 file changed, 7 insertions(+), 7 deletions(-)
>>>>>
>>>>> diff --git a/arch/x86/events/intel/core.c b/arch/x86/events/intel/
>>>>> core.c
>>>>> index 09d2d66c9f21..c6b394019e54 100644
>>>>> --- a/arch/x86/events/intel/core.c
>>>>> +++ b/arch/x86/events/intel/core.c
>>>>> @@ -4114,6 +4114,13 @@ static int intel_pmu_hw_config(struct
>>>>> perf_event *event)
>>>>> event->hw.flags |= PERF_X86_EVENT_NEEDS_BRANCH_STACK;
>>>>> }
>>>>> + /*
>>>>> + * Force the leader to be a LBR event. So LBRs can be reset
>>>>> + * with the leader event. See intel_pmu_lbr_del() for details.
>>>>> + */
>>>>> + if (has_branch_stack(event) && !has_branch_stack(event-
>>>>>> group_leader))
>>>>> + return -EINVAL;
>>>>> +
>>>>> if (branch_sample_counters(event)) {
>>>>> struct perf_event *leader, *sibling;
>>>>> int num = 0;
>>>>> @@ -4157,13 +4164,6 @@ static int intel_pmu_hw_config(struct
>>>>> perf_event *event)
>>>>> ~(PERF_SAMPLE_BRANCH_PLM_ALL |
>>>>> PERF_SAMPLE_BRANCH_COUNTERS)))
>>>>> event->hw.flags &= ~PERF_X86_EVENT_NEEDS_BRANCH_STACK;
>>>>> -
>>>>> - /*
>>>>> - * Force the leader to be a LBR event. So LBRs can be reset
>>>>> - * with the leader event. See intel_pmu_lbr_del() for details.
>>>>> - */
>>>>> - if (!intel_pmu_needs_branch_stack(leader))
>>>>> - return -EINVAL;
>>>>> }
>>>>> if (intel_pmu_needs_branch_stack(event)) {
>>
>
>
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH] perf/x86/intel: Fix lbr event can placed into non lbr group
2025-04-23 22:11 ` Liang, Kan
@ 2025-04-25 3:44 ` Luo Gengkun
0 siblings, 0 replies; 7+ messages in thread
From: Luo Gengkun @ 2025-04-25 3:44 UTC (permalink / raw)
To: Liang, Kan, peterz
Cc: acme, namhyung, mark.rutland, alexander.shishkin, jolsa, irogers,
adrian.hunter, tglx, bp, dave.hansen, x86, hpa, linux-perf-users,
linux-kernel
On 2025/4/24 6:11, Liang, Kan wrote:
>
> On 2025-04-21 10:56 a.m., Liang, Kan wrote:
>>
>> On 2025-04-19 12:50 a.m., Luo Gengkun wrote:
>>> On 2025/4/19 10:25, Luo Gengkun wrote:
>>>> On 2025/4/14 22:29, Liang, Kan wrote:
>>>>> On 2025-04-12 5:14 a.m., Luo Gengkun wrote:
>>>>>> The following perf command can trigger a warning on
>>>>>> intel_pmu_lbr_counters_reorder.
>>>>>>
>>>>>> # perf record -e "{cpu-clock,cycles/call-graph="lbr"/}" -- sleep 1
>>>>>>
>>>>>> The reason is that a lbr event are placed in non lbr group. And the
>>>>>> previous implememtation cannot force the leader to be a lbr event in
>>>>>> this
>>>>>> case.
>>>>> Perf should only force the LBR leader for the branch counters case, so
>>>>> perf only needs to reset the LBRs for the leader.
>>>>> I don't think the leader restriction should be applied to other cases.
>>>> Yes, the commit message should be updated. The code implementation only
>>>>
>>>> restricts the leader to be an LBRs.
>>>>
>>>>>> And is_branch_counters_group will check if the group_leader supports
>>>>>> BRANCH_COUNTERS.
>>>>>> So if a software event becomes a group_leader, which
>>>>>> hw.flags is -1, this check will alway pass.
>>>>> I think the default flags for all events is 0. Can you point me to where
>>>>> it is changed to -1?
>>>>>
>>>>> Thanks,
>>>>> Kan>
>>>> The hw_perf_event contains a union, hw.flags is used only for hardware
>>>> events.
>>>>
>>>> For the software events, it uses hrtimer. Therefor, when
>>>> perf_swevent_init_hrtimer
>>>>
>>>> is called, it changes the value of hw.flags too.
>>>>
>>>>
>>>> Thanks,
>>>>
>>>> Gengkun
>>>
>>> It seems that using union is dangerous because different types of
>>> perf_events can be
>>> placed in the same group.
>> Only the PMU with perf_sw_context can be placed in the same group with
>> other types.
>>
>>> Currently, a large number of codes directly
>>> access the hw
>>> of the leader, which is insecure.
>> For X86, the topdown, ACR and branch counters will touch the
>> leader.hw->flags. The topdown and ACR have already checked the leader
>> before updating the flags. The branch counters missed it. I think a
>> check is required for the branch counters as well, which should be good
>> enough to address the issue.
>>
>> diff --git a/arch/x86/events/intel/core.c b/arch/x86/events/intel/core.c
>> index 16f8aea33243..406f58b3b5d4 100644
>> --- a/arch/x86/events/intel/core.c
>> +++ b/arch/x86/events/intel/core.c
>> @@ -4256,6 +4256,12 @@ static int intel_pmu_hw_config(struct perf_event
>> *event)
>> * group, which requires the extra space to store the counters.
>> */
>> leader = event->group_leader;
>> + /*
>> + * The leader's hw.flags will be used to determine a
>> + * branch counter logging group. Force it a X86 event.
>> + */
>> + if (!is_x86_event(leader))
>> + return -EINVAL;
>> if (branch_sample_call_stack(leader))
>> return -EINVAL;
>> if (branch_sample_counters(leader)) {
>>
> The above check may not enough, since the
> intel_pmu_lbr_counters_reorder() can be invoked without branch counters
> event.
>
> I've posted a fix to address the issue. Please take a look.
> https://lore.kernel.org/lkml/20250423221015.268949-1-kan.liang@linux.intel.com/
>
> Thanks,
> Kan
LGTM.
Thanks,
Gengkun
>>> This part of the logic needs to be
>>> redesigned to void
>>> similar problems. And I am happy to work for this.
>>>
>> OK. Please share your idea.
>>
>> Thanks,
>> Kan
>>> Thanks,
>>> Gengkun
>>>>>> To fix this problem, using has_branch_stack to judge if leader is lbr
>>>>>> event.
>>>>>>
>>>>>> Fixes: 33744916196b ("perf/x86/intel: Support branch counters logging")
>>>>>> Signed-off-by: Luo Gengkun <luogengkun@huaweicloud.com>
>>>>>> ---
>>>>>> arch/x86/events/intel/core.c | 14 +++++++-------
>>>>>> 1 file changed, 7 insertions(+), 7 deletions(-)
>>>>>>
>>>>>> diff --git a/arch/x86/events/intel/core.c b/arch/x86/events/intel/
>>>>>> core.c
>>>>>> index 09d2d66c9f21..c6b394019e54 100644
>>>>>> --- a/arch/x86/events/intel/core.c
>>>>>> +++ b/arch/x86/events/intel/core.c
>>>>>> @@ -4114,6 +4114,13 @@ static int intel_pmu_hw_config(struct
>>>>>> perf_event *event)
>>>>>> event->hw.flags |= PERF_X86_EVENT_NEEDS_BRANCH_STACK;
>>>>>> }
>>>>>> + /*
>>>>>> + * Force the leader to be a LBR event. So LBRs can be reset
>>>>>> + * with the leader event. See intel_pmu_lbr_del() for details.
>>>>>> + */
>>>>>> + if (has_branch_stack(event) && !has_branch_stack(event-
>>>>>>> group_leader))
>>>>>> + return -EINVAL;
>>>>>> +
>>>>>> if (branch_sample_counters(event)) {
>>>>>> struct perf_event *leader, *sibling;
>>>>>> int num = 0;
>>>>>> @@ -4157,13 +4164,6 @@ static int intel_pmu_hw_config(struct
>>>>>> perf_event *event)
>>>>>> ~(PERF_SAMPLE_BRANCH_PLM_ALL |
>>>>>> PERF_SAMPLE_BRANCH_COUNTERS)))
>>>>>> event->hw.flags &= ~PERF_X86_EVENT_NEEDS_BRANCH_STACK;
>>>>>> -
>>>>>> - /*
>>>>>> - * Force the leader to be a LBR event. So LBRs can be reset
>>>>>> - * with the leader event. See intel_pmu_lbr_del() for details.
>>>>>> - */
>>>>>> - if (!intel_pmu_needs_branch_stack(leader))
>>>>>> - return -EINVAL;
>>>>>> }
>>>>>> if (intel_pmu_needs_branch_stack(event)) {
>>
^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2025-04-25 3:44 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-04-12 9:14 [PATCH] perf/x86/intel: Fix lbr event can placed into non lbr group Luo Gengkun
2025-04-14 14:29 ` Liang, Kan
2025-04-19 2:25 ` Luo Gengkun
2025-04-19 4:50 ` Luo Gengkun
2025-04-21 14:56 ` Liang, Kan
2025-04-23 22:11 ` Liang, Kan
2025-04-25 3:44 ` Luo Gengkun
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).