linux-perf-users.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [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).