diff mbox series

[5/5] powerpc/perf: use regs->nip when siar is zero

Message ID 20201021085329.384535-5-maddy@linux.ibm.com (mailing list archive)
State Accepted
Commit 2ca13a4cc56c920a6c9fc8ee45d02bccacd7f46c
Headers show
Series [1/5] powerpc/perf: Add new power pmu flag "PPMU_P10_DD1" for power10 DD1 | expand

Checks

Context Check Description
snowpatch_ozlabs/apply_patch success Successfully applied on branch powerpc/merge (598b738031de83cadbcf745ad0ad2bd69a0ee012)
snowpatch_ozlabs/build-ppc64le warning Upstream build failed, couldn't test patch
snowpatch_ozlabs/build-ppc64be warning Upstream build failed, couldn't test patch
snowpatch_ozlabs/build-ppc64e warning Upstream build failed, couldn't test patch
snowpatch_ozlabs/build-pmac32 warning Upstream build failed, couldn't test patch
snowpatch_ozlabs/checkpatch success
snowpatch_ozlabs/needsstable success Patch has no Fixes tags

Commit Message

Madhavan Srinivasan Oct. 21, 2020, 8:53 a.m. UTC
In power10 DD1, there is an issue where the
Sampled Instruction Address Register (SIAR)
not latching to the sampled address during
random sampling. This results in value of 0s
in the SIAR. Patch adds a check to use regs->nip
when SIAR is zero.

Signed-off-by: Madhavan Srinivasan <maddy@linux.ibm.com>
---
 arch/powerpc/perf/core-book3s.c | 21 +++++++++++++++++----
 1 file changed, 17 insertions(+), 4 deletions(-)

Comments

Christophe Leroy Oct. 21, 2020, 9:13 a.m. UTC | #1
Le 21/10/2020 à 10:53, Madhavan Srinivasan a écrit :
> In power10 DD1, there is an issue where the
> Sampled Instruction Address Register (SIAR)
> not latching to the sampled address during
> random sampling. This results in value of 0s
> in the SIAR. Patch adds a check to use regs->nip
> when SIAR is zero.

Why not use regs->nip at all time in that case, and not read SPRN_SIAR at all ?

Christophe


> 
> Signed-off-by: Madhavan Srinivasan <maddy@linux.ibm.com>
> ---
>   arch/powerpc/perf/core-book3s.c | 21 +++++++++++++++++----
>   1 file changed, 17 insertions(+), 4 deletions(-)
> 
> diff --git a/arch/powerpc/perf/core-book3s.c b/arch/powerpc/perf/core-book3s.c
> index e675c7c8ce0e..63de77eb0ac0 100644
> --- a/arch/powerpc/perf/core-book3s.c
> +++ b/arch/powerpc/perf/core-book3s.c
> @@ -263,9 +263,16 @@ static inline u32 perf_get_misc_flags(struct pt_regs *regs)
>   	 * DD1.
>   	 */
>   	if (marked && (ppmu->flags & PPMU_P10_DD1)) {
> -		if (is_kernel_addr(mfspr(SPRN_SIAR)))
> -			return PERF_RECORD_MISC_KERNEL;
> -		return PERF_RECORD_MISC_USER;
> +		unsigned long siar = mfspr(SPRN_SIAR);
> +		if (siar) {
> +			if (is_kernel_addr(siar))
> +				return PERF_RECORD_MISC_KERNEL;
> +			return PERF_RECORD_MISC_USER;
> +		} else {
> +			if (is_kernel_addr(regs->nip))
> +				return PERF_RECORD_MISC_KERNEL;
> +			return PERF_RECORD_MISC_USER;
> +		}
>   	}
>   
>   	/*
> @@ -2211,8 +2218,14 @@ unsigned long perf_misc_flags(struct pt_regs *regs)
>   unsigned long perf_instruction_pointer(struct pt_regs *regs)
>   {
>   	bool use_siar = regs_use_siar(regs);
> +	unsigned long siar = mfspr(SPRN_SIAR);
>   
> -	if (use_siar && siar_valid(regs))
> +	if (ppmu->flags & PPMU_P10_DD1) {
> +		if (siar)
> +			return siar;
> +		else
> +			return regs->nip;
> +	} else if (use_siar && siar_valid(regs))
>   		return mfspr(SPRN_SIAR) + perf_ip_adjust(regs);
>   	else if (use_siar)
>   		return 0;		// no valid instruction pointer
>
Michael Ellerman Oct. 22, 2020, 1:25 a.m. UTC | #2
Christophe Leroy <christophe.leroy@csgroup.eu> writes:
> Le 21/10/2020 à 10:53, Madhavan Srinivasan a écrit :
>> In power10 DD1, there is an issue where the
>> Sampled Instruction Address Register (SIAR)
>> not latching to the sampled address during
>> random sampling. This results in value of 0s
>> in the SIAR. Patch adds a check to use regs->nip
>> when SIAR is zero.
>
> Why not use regs->nip at all time in that case, and not read SPRN_SIAR at all ?

Yeah that's a reasonable question.

I can't really find anywhere in the ISA that explains it.

I believe the main (or only?) reason is that interrupts might be
disabled when the PMU samples the instruction. So in that case the SIAR
will point at an instruction somewhere in interrupts-off code, whereas
the NIP will point to the location where we re-enabled interrupts and
took the PMU interrupt.

cheers
Madhavan Srinivasan Oct. 27, 2020, 2:31 a.m. UTC | #3
On 10/22/20 6:55 AM, Michael Ellerman wrote:
> Christophe Leroy <christophe.leroy@csgroup.eu> writes:
>> Le 21/10/2020 à 10:53, Madhavan Srinivasan a écrit :
>>> In power10 DD1, there is an issue where the
>>> Sampled Instruction Address Register (SIAR)
>>> not latching to the sampled address during
>>> random sampling. This results in value of 0s
>>> in the SIAR. Patch adds a check to use regs->nip
>>> when SIAR is zero.
>> Why not use regs->nip at all time in that case, and not read SPRN_SIAR at all ?
> Yeah that's a reasonable question.
>
> I can't really find anywhere in the ISA that explains it.
>
> I believe the main (or only?) reason is that interrupts might be
> disabled when the PMU samples the instruction. So in that case the SIAR
> will point at an instruction somewhere in interrupts-off code, whereas
> the NIP will point to the location where we re-enabled interrupts and
> took the PMU interrupt.

sorry for the delayed response, was out.

thats correct and also we see SIAR zeroing only for some of
the events. We still want to use the SIAR address for
the sample creation and use nip only if it  zero.

Maddy


>
> cheers
diff mbox series

Patch

diff --git a/arch/powerpc/perf/core-book3s.c b/arch/powerpc/perf/core-book3s.c
index e675c7c8ce0e..63de77eb0ac0 100644
--- a/arch/powerpc/perf/core-book3s.c
+++ b/arch/powerpc/perf/core-book3s.c
@@ -263,9 +263,16 @@  static inline u32 perf_get_misc_flags(struct pt_regs *regs)
 	 * DD1.
 	 */
 	if (marked && (ppmu->flags & PPMU_P10_DD1)) {
-		if (is_kernel_addr(mfspr(SPRN_SIAR)))
-			return PERF_RECORD_MISC_KERNEL;
-		return PERF_RECORD_MISC_USER;
+		unsigned long siar = mfspr(SPRN_SIAR);
+		if (siar) {
+			if (is_kernel_addr(siar))
+				return PERF_RECORD_MISC_KERNEL;
+			return PERF_RECORD_MISC_USER;
+		} else {
+			if (is_kernel_addr(regs->nip))
+				return PERF_RECORD_MISC_KERNEL;
+			return PERF_RECORD_MISC_USER;
+		}
 	}
 
 	/*
@@ -2211,8 +2218,14 @@  unsigned long perf_misc_flags(struct pt_regs *regs)
 unsigned long perf_instruction_pointer(struct pt_regs *regs)
 {
 	bool use_siar = regs_use_siar(regs);
+	unsigned long siar = mfspr(SPRN_SIAR);
 
-	if (use_siar && siar_valid(regs))
+	if (ppmu->flags & PPMU_P10_DD1) {
+		if (siar)
+			return siar;
+		else
+			return regs->nip;
+	} else if (use_siar && siar_valid(regs))
 		return mfspr(SPRN_SIAR) + perf_ip_adjust(regs);
 	else if (use_siar)
 		return 0;		// no valid instruction pointer