diff mbox series

[v6,8/8] perf cs-etm: Set sample flags for exception return packet

Message ID 20190119014347.27441-9-leo.yan@linaro.org
State Superseded
Headers show
Series perf cs-etm: Add support for sample flags | expand

Commit Message

Leo Yan Jan. 19, 2019, 1:43 a.m. UTC
When return from exception, we need to distinguish if it's system call
return or for other type exceptions for setting sample flags.  Due to
the exception return packet doesn't contain exception number, so we
cannot decide sample flags based on exception number.

On the other hand, the exception return packet is followed by an
instruction range packet; this range packet deliveries the start address
after exception handling, we can check if it is a SVC instruction just
before the start address.  If there has one SVC instruction is found
ahead the return address, this means it's an exception return for system
call; otherwise it is an normal return for other exceptions.

This patch is to set sample flags for exception return packet, firstly
it simply set sample flags as PERF_IP_FLAG_INTERRUPT for all exception
returns since at this point it doesn't know what's exactly the exception
type.  We will defer to decide if it's an exception return for system
call when the next instruction range packet comes, it checks if there
has one SVC instruction prior to the start address and if so we will
change sample flags to PERF_IP_FLAG_SYSCALLRET for system call
return.

Signed-off-by: Leo Yan <leo.yan@linaro.org>

---
 tools/perf/util/cs-etm.c | 44 ++++++++++++++++++++++++++++++++++++++++
 1 file changed, 44 insertions(+)

-- 
2.17.1

Comments

Mathieu Poirier Jan. 23, 2019, 9:51 p.m. UTC | #1
On Sat, Jan 19, 2019 at 09:43:47AM +0800, Leo Yan wrote:
> When return from exception, we need to distinguish if it's system call

> return or for other type exceptions for setting sample flags.  Due to

> the exception return packet doesn't contain exception number, so we

> cannot decide sample flags based on exception number.

> 

> On the other hand, the exception return packet is followed by an

> instruction range packet; this range packet deliveries the start address

> after exception handling, we can check if it is a SVC instruction just

> before the start address.  If there has one SVC instruction is found

> ahead the return address, this means it's an exception return for system

> call; otherwise it is an normal return for other exceptions.

> 

> This patch is to set sample flags for exception return packet, firstly

> it simply set sample flags as PERF_IP_FLAG_INTERRUPT for all exception

> returns since at this point it doesn't know what's exactly the exception

> type.  We will defer to decide if it's an exception return for system

> call when the next instruction range packet comes, it checks if there

> has one SVC instruction prior to the start address and if so we will

> change sample flags to PERF_IP_FLAG_SYSCALLRET for system call

> return.

> 

> Signed-off-by: Leo Yan <leo.yan@linaro.org>

> ---

>  tools/perf/util/cs-etm.c | 44 ++++++++++++++++++++++++++++++++++++++++

>  1 file changed, 44 insertions(+)

> 

> diff --git a/tools/perf/util/cs-etm.c b/tools/perf/util/cs-etm.c

> index 052805de6513..7547a7178f46 100644

> --- a/tools/perf/util/cs-etm.c

> +++ b/tools/perf/util/cs-etm.c

> @@ -1372,6 +1372,20 @@ static int cs_etm__set_sample_flags(struct cs_etm_queue *etmq)

>  		if (prev_packet->sample_type == CS_ETM_DISCONTINUITY)

>  			prev_packet->flags |= PERF_IP_FLAG_BRANCH |

>  					      PERF_IP_FLAG_TRACE_BEGIN;

> +

> +		/*

> +		 * If the previous packet is an exception return packet

> +		 * and the return address just follows SVC instuction,

> +		 * it needs to calibrate the previous packet sample flags

> +		 * as PERF_IP_FLAG_SYSCALLRET.

> +		 */

> +		if (prev_packet->flags == (PERF_IP_FLAG_BRANCH |

> +					   PERF_IP_FLAG_RETURN |

> +					   PERF_IP_FLAG_INTERRUPT) &&


Would it make more sense to just look for prev-packet->sample_type ==
CS_ETM_EXCEPTION_RET ?

> +		    cs_etm__is_svc_instr(etmq, packet, packet->start_addr))

> +			prev_packet->flags = PERF_IP_FLAG_BRANCH |

> +					     PERF_IP_FLAG_RETURN |

> +					     PERF_IP_FLAG_SYSCALLRET;

>  		break;

>  	case CS_ETM_DISCONTINUITY:

>  		/*

> @@ -1422,6 +1436,36 @@ static int cs_etm__set_sample_flags(struct cs_etm_queue *etmq)

>  			prev_packet->flags = packet->flags;

>  		break;

>  	case CS_ETM_EXCEPTION_RET:

> +		/*

> +		 * When the exception return packet is inserted, since

> +		 * exception return packet is not used standalone for

> +		 * generating samples and it's affiliation to the previous

> +		 * instruction range packet; so set previous range packet

> +		 * flags to tell perf it is an exception return branch.

> +		 *

> +		 * The exception return can be for either system call or

> +		 * other exception types; unfortunately the packet doesn't

> +		 * contain exception type related info so we cannot decide

> +		 * the exception type purely based on exception return packet.

> +		 * If we record the exception number from exception packet and

> +		 * reuse it for excpetion return packet, this is not reliable

> +		 * due the trace can be discontinuity or the interrupt can

> +		 * be nested, thus the recorded exception number cannot be

> +		 * used for exception return packet for these two cases.

> +		 *

> +		 * For exception return packet, we only need to distinguish the

> +		 * packet is for system call or for other types.  Thus the

> +		 * decision can be deferred when receive the next packet which

> +		 * contains the return address, based on the return address we

> +		 * can read out the previous instruction and check if it's a

> +		 * system call instruction and then calibrate the sample flag

> +		 * as needed.

> +		 */

> +		if (prev_packet->sample_type == CS_ETM_RANGE)

> +			prev_packet->flags = PERF_IP_FLAG_BRANCH |

> +					     PERF_IP_FLAG_RETURN |

> +					     PERF_IP_FLAG_INTERRUPT;

> +		break;

>  	case CS_ETM_EMPTY:

>  	default:

>  		break;

> -- 

> 2.17.1

>
Leo Yan Jan. 23, 2019, 11:36 p.m. UTC | #2
Hi Mathieu,

On Wed, Jan 23, 2019 at 02:51:14PM -0700, Mathieu Poirier wrote:
> On Sat, Jan 19, 2019 at 09:43:47AM +0800, Leo Yan wrote:

> > When return from exception, we need to distinguish if it's system call

> > return or for other type exceptions for setting sample flags.  Due to

> > the exception return packet doesn't contain exception number, so we

> > cannot decide sample flags based on exception number.

> > 

> > On the other hand, the exception return packet is followed by an

> > instruction range packet; this range packet deliveries the start address

> > after exception handling, we can check if it is a SVC instruction just

> > before the start address.  If there has one SVC instruction is found

> > ahead the return address, this means it's an exception return for system

> > call; otherwise it is an normal return for other exceptions.

> > 

> > This patch is to set sample flags for exception return packet, firstly

> > it simply set sample flags as PERF_IP_FLAG_INTERRUPT for all exception

> > returns since at this point it doesn't know what's exactly the exception

> > type.  We will defer to decide if it's an exception return for system

> > call when the next instruction range packet comes, it checks if there

> > has one SVC instruction prior to the start address and if so we will

> > change sample flags to PERF_IP_FLAG_SYSCALLRET for system call

> > return.

> > 

> > Signed-off-by: Leo Yan <leo.yan@linaro.org>

> > ---

> >  tools/perf/util/cs-etm.c | 44 ++++++++++++++++++++++++++++++++++++++++

> >  1 file changed, 44 insertions(+)

> > 

> > diff --git a/tools/perf/util/cs-etm.c b/tools/perf/util/cs-etm.c

> > index 052805de6513..7547a7178f46 100644

> > --- a/tools/perf/util/cs-etm.c

> > +++ b/tools/perf/util/cs-etm.c

> > @@ -1372,6 +1372,20 @@ static int cs_etm__set_sample_flags(struct cs_etm_queue *etmq)

> >  		if (prev_packet->sample_type == CS_ETM_DISCONTINUITY)

> >  			prev_packet->flags |= PERF_IP_FLAG_BRANCH |

> >  					      PERF_IP_FLAG_TRACE_BEGIN;

> > +

> > +		/*

> > +		 * If the previous packet is an exception return packet

> > +		 * and the return address just follows SVC instuction,

> > +		 * it needs to calibrate the previous packet sample flags

> > +		 * as PERF_IP_FLAG_SYSCALLRET.

> > +		 */

> > +		if (prev_packet->flags == (PERF_IP_FLAG_BRANCH |

> > +					   PERF_IP_FLAG_RETURN |

> > +					   PERF_IP_FLAG_INTERRUPT) &&

> 

> Would it make more sense to just look for prev-packet->sample_type ==

> CS_ETM_EXCEPTION_RET ?


We cannot check 'prev-packet->sample_type == CS_ETM_EXCEPTION_RET',
since CS_ETM_EXCEPTION_RET is associated to its previous instruction
range packet but not a standalone instruction range packet, we don't
swap for exception and exception return packets, 'prev_packet' is
pointed to the previous instruction range packet at here.

This is why we need to use 'prev_packet->flags' but not
'prev_packet->sample_type' as checking condition.

Thanks,
Leo Yan

> > +		    cs_etm__is_svc_instr(etmq, packet, packet->start_addr))

> > +			prev_packet->flags = PERF_IP_FLAG_BRANCH |

> > +					     PERF_IP_FLAG_RETURN |

> > +					     PERF_IP_FLAG_SYSCALLRET;

> >  		break;

> >  	case CS_ETM_DISCONTINUITY:

> >  		/*

> > @@ -1422,6 +1436,36 @@ static int cs_etm__set_sample_flags(struct cs_etm_queue *etmq)

> >  			prev_packet->flags = packet->flags;

> >  		break;

> >  	case CS_ETM_EXCEPTION_RET:

> > +		/*

> > +		 * When the exception return packet is inserted, since

> > +		 * exception return packet is not used standalone for

> > +		 * generating samples and it's affiliation to the previous

> > +		 * instruction range packet; so set previous range packet

> > +		 * flags to tell perf it is an exception return branch.

> > +		 *

> > +		 * The exception return can be for either system call or

> > +		 * other exception types; unfortunately the packet doesn't

> > +		 * contain exception type related info so we cannot decide

> > +		 * the exception type purely based on exception return packet.

> > +		 * If we record the exception number from exception packet and

> > +		 * reuse it for excpetion return packet, this is not reliable

> > +		 * due the trace can be discontinuity or the interrupt can

> > +		 * be nested, thus the recorded exception number cannot be

> > +		 * used for exception return packet for these two cases.

> > +		 *

> > +		 * For exception return packet, we only need to distinguish the

> > +		 * packet is for system call or for other types.  Thus the

> > +		 * decision can be deferred when receive the next packet which

> > +		 * contains the return address, based on the return address we

> > +		 * can read out the previous instruction and check if it's a

> > +		 * system call instruction and then calibrate the sample flag

> > +		 * as needed.

> > +		 */

> > +		if (prev_packet->sample_type == CS_ETM_RANGE)

> > +			prev_packet->flags = PERF_IP_FLAG_BRANCH |

> > +					     PERF_IP_FLAG_RETURN |

> > +					     PERF_IP_FLAG_INTERRUPT;

> > +		break;

> >  	case CS_ETM_EMPTY:

> >  	default:

> >  		break;

> > -- 

> > 2.17.1

> >
diff mbox series

Patch

diff --git a/tools/perf/util/cs-etm.c b/tools/perf/util/cs-etm.c
index 052805de6513..7547a7178f46 100644
--- a/tools/perf/util/cs-etm.c
+++ b/tools/perf/util/cs-etm.c
@@ -1372,6 +1372,20 @@  static int cs_etm__set_sample_flags(struct cs_etm_queue *etmq)
 		if (prev_packet->sample_type == CS_ETM_DISCONTINUITY)
 			prev_packet->flags |= PERF_IP_FLAG_BRANCH |
 					      PERF_IP_FLAG_TRACE_BEGIN;
+
+		/*
+		 * If the previous packet is an exception return packet
+		 * and the return address just follows SVC instuction,
+		 * it needs to calibrate the previous packet sample flags
+		 * as PERF_IP_FLAG_SYSCALLRET.
+		 */
+		if (prev_packet->flags == (PERF_IP_FLAG_BRANCH |
+					   PERF_IP_FLAG_RETURN |
+					   PERF_IP_FLAG_INTERRUPT) &&
+		    cs_etm__is_svc_instr(etmq, packet, packet->start_addr))
+			prev_packet->flags = PERF_IP_FLAG_BRANCH |
+					     PERF_IP_FLAG_RETURN |
+					     PERF_IP_FLAG_SYSCALLRET;
 		break;
 	case CS_ETM_DISCONTINUITY:
 		/*
@@ -1422,6 +1436,36 @@  static int cs_etm__set_sample_flags(struct cs_etm_queue *etmq)
 			prev_packet->flags = packet->flags;
 		break;
 	case CS_ETM_EXCEPTION_RET:
+		/*
+		 * When the exception return packet is inserted, since
+		 * exception return packet is not used standalone for
+		 * generating samples and it's affiliation to the previous
+		 * instruction range packet; so set previous range packet
+		 * flags to tell perf it is an exception return branch.
+		 *
+		 * The exception return can be for either system call or
+		 * other exception types; unfortunately the packet doesn't
+		 * contain exception type related info so we cannot decide
+		 * the exception type purely based on exception return packet.
+		 * If we record the exception number from exception packet and
+		 * reuse it for excpetion return packet, this is not reliable
+		 * due the trace can be discontinuity or the interrupt can
+		 * be nested, thus the recorded exception number cannot be
+		 * used for exception return packet for these two cases.
+		 *
+		 * For exception return packet, we only need to distinguish the
+		 * packet is for system call or for other types.  Thus the
+		 * decision can be deferred when receive the next packet which
+		 * contains the return address, based on the return address we
+		 * can read out the previous instruction and check if it's a
+		 * system call instruction and then calibrate the sample flag
+		 * as needed.
+		 */
+		if (prev_packet->sample_type == CS_ETM_RANGE)
+			prev_packet->flags = PERF_IP_FLAG_BRANCH |
+					     PERF_IP_FLAG_RETURN |
+					     PERF_IP_FLAG_INTERRUPT;
+		break;
 	case CS_ETM_EMPTY:
 	default:
 		break;