[PATCH] ARM: perf: limit sample_period to half max_period in non-sampling mode

Ming Lei ming.lei at canonical.com
Mon Feb 20 07:39:11 EST 2012


Hi,

On Mon, Feb 20, 2012 at 8:07 PM, Will Deacon <will.deacon at arm.com> wrote:
> On ARM, the PMU does not stop counting after an overflow and therefore
> IRQ latency affects the new counter value read by the kernel. This is
> significant for non-sampling runs where it is possible for the new value
> to overtake the previous one, causing the delta to be out by up to
> max_period events.
>
> Commit a737823d ("ARM: 6835/1: perf: ensure overflows aren't missed due
> to IRQ latency") attempted to fix this problem by allowing interrupt
> handlers to pass an overflow flag to the event update function, causing
> the overflow calculation to assume that the counter passed through zero
> when going from prev to new. Unfortunately, this doesn't work when
> overflow occurs on the perf_task_tick path because we have the flag
> cleared and end up computing a large negative delta.
>
> This patch removes the overflow flag from armpmu_event_update and
> instead limits the sample_period to half of the max_period for
> non-sampling profiling runs.
>
> Cc: Ming Lei <ming.lei at canonical.com>
> Signed-off-by: Will Deacon <will.deacon at arm.com>
> ---
>  arch/arm/include/asm/pmu.h          |    2 +-
>  arch/arm/kernel/perf_event.c        |   22 +++++++++++-----------
>  arch/arm/kernel/perf_event_v6.c     |    2 +-
>  arch/arm/kernel/perf_event_v7.c     |    2 +-
>  arch/arm/kernel/perf_event_xscale.c |    4 ++--
>  5 files changed, 16 insertions(+), 16 deletions(-)
>
> diff --git a/arch/arm/include/asm/pmu.h b/arch/arm/include/asm/pmu.h
> index b5a5be2..90114fa 100644
> --- a/arch/arm/include/asm/pmu.h
> +++ b/arch/arm/include/asm/pmu.h
> @@ -134,7 +134,7 @@ int __init armpmu_register(struct arm_pmu *armpmu, char *name, int type);
>
>  u64 armpmu_event_update(struct perf_event *event,
>                        struct hw_perf_event *hwc,
> -                       int idx, int overflow);
> +                       int idx);
>
>  int armpmu_event_set_period(struct perf_event *event,
>                            struct hw_perf_event *hwc,
> diff --git a/arch/arm/kernel/perf_event.c b/arch/arm/kernel/perf_event.c
> index 5bb91bf..56173ae 100644
> --- a/arch/arm/kernel/perf_event.c
> +++ b/arch/arm/kernel/perf_event.c
> @@ -180,7 +180,7 @@ armpmu_event_set_period(struct perf_event *event,
>  u64
>  armpmu_event_update(struct perf_event *event,
>                    struct hw_perf_event *hwc,
> -                   int idx, int overflow)
> +                   int idx)
>  {
>        struct arm_pmu *armpmu = to_arm_pmu(event->pmu);
>        u64 delta, prev_raw_count, new_raw_count;
> @@ -193,13 +193,7 @@ again:
>                             new_raw_count) != prev_raw_count)
>                goto again;
>
> -       new_raw_count &= armpmu->max_period;
> -       prev_raw_count &= armpmu->max_period;
> -
> -       if (overflow)
> -               delta = armpmu->max_period - prev_raw_count + new_raw_count + 1;
> -       else
> -               delta = new_raw_count - prev_raw_count;
> +       delta = (new_raw_count - prev_raw_count) & armpmu->max_period;

Please add

           Signed-off-by: Ming Lei <ming.lei at canonical.com>

since I found the problem caused by incorrect 'delta' and the above change is
based on the original patch[1] from me.


[1], http://marc.info/?l=linux-kernel&m=132938793724425&w=2

thanks,
--
Ming Lei



More information about the linux-arm-kernel mailing list