[PATCH] powerpc/time: Sanity check of decrementer expiration is necessary

Anton Blanchard anton at samba.org
Mon Jun 4 12:31:04 EST 2012


Hi Paul,

> This reverts 68568add2c ("powerpc/time: Remove unnecessary sanity
> check of decrementer expiration").  We do need to check whether we
> have reached the expiration time of the next event, because we
> sometimes get an early decrementer interrupt, most notably when we
> set the decrementer to 1 in arch_irq_work_raise().  The effect of not
> having the sanity check is that if timer_interrupt() gets called
> early, we leave the decrementer set to its maximum value, which means
> we then don't get any more decrementer interrupts for about 4 seconds
> (or longer, depending on timebase frequency).  I saw these pauses as
> a consequence of getting a stray hypervisor decrementer interrupt
> left over from exiting a KVM guest.

Urgh, sorry for that mess.

Acked-by: Anton Blanchard <anton at samba.org>

Anton

> This isn't quite a straight revert because of changes to the
> surrounding code, but it restores the same algorithm as was
> previously used.
> 
> Cc: stable at kernel.org
> Cc: Anton Blanchard <anton at samba.org>
> Acked-by: Benjamin Herrenschmidt <benh at kernel.crashing.org>
> Signed-off-by: Paul Mackerras <paulus at samba.org>
> ---
> If there are no objections, I'll send this to Linus shortly.  This
> regression is present in 3.3 and 3.4 as well as current upstream.
> 
>  arch/powerpc/kernel/time.c |   14 +++++++++++---
>  1 file changed, 11 insertions(+), 3 deletions(-)
> 
> diff --git a/arch/powerpc/kernel/time.c b/arch/powerpc/kernel/time.c
> index 99a995c..be171ee 100644
> --- a/arch/powerpc/kernel/time.c
> +++ b/arch/powerpc/kernel/time.c
> @@ -475,6 +475,7 @@ void timer_interrupt(struct pt_regs * regs)
>  	struct pt_regs *old_regs;
>  	u64 *next_tb = &__get_cpu_var(decrementers_next_tb);
>  	struct clock_event_device *evt =
> &__get_cpu_var(decrementers);
> +	u64 now;
>  
>  	/* Ensure a positive value is written to the decrementer, or
> else
>  	 * some CPUs will continue to take decrementer exceptions.
> @@ -509,9 +510,16 @@ void timer_interrupt(struct pt_regs * regs)
>  		irq_work_run();
>  	}
>  
> -	*next_tb = ~(u64)0;
> -	if (evt->event_handler)
> -		evt->event_handler(evt);
> +	now = get_tb_or_rtc();
> +	if (now >= *next_tb) {
> +		*next_tb = ~(u64)0;
> +		if (evt->event_handler)
> +			evt->event_handler(evt);
> +	} else {
> +		now = *next_tb - now;
> +		if (now <= DECREMENTER_MAX)
> +			set_dec((int)now);
> +	}
>  
>  #ifdef CONFIG_PPC64
>  	/* collect purr register values often, for accurate
> calculations */



More information about the Linuxppc-dev mailing list