• Yu Liao's avatar
    tick/broadcast: Make takeover of broadcast hrtimer reliable · f7d43dd2
    Yu Liao authored
    Running the LTP hotplug stress test on a aarch64 machine results in
    rcu_sched stall warnings when the broadcast hrtimer was owned by the
    un-plugged CPU. The issue is the following:
    
    CPU1 (owns the broadcast hrtimer)	CPU2
    
    				tick_broadcast_enter()
    				  // shutdown local timer device
    				  broadcast_shutdown_local()
    				...
    				tick_broadcast_exit()
    				  clockevents_switch_state(dev, CLOCK_EVT_STATE_ONESHOT)
    				  // timer device is not programmed
    				  cpumask_set_cpu(cpu, tick_broadcast_force_mask)
    
    				initiates offlining of CPU1
    take_cpu_down()
    /*
     * CPU1 shuts down and does not
     * send broadcast IPI anymore
     */
    				takedown_cpu()
    				  hotplug_cpu__broadcast_tick_pull()
    				    // move broadcast hrtimer to this CPU
    				    clockevents_program_event()
    				      bc_set_next()
    					hrtimer_start()
    					/*
    					 * timer device is not programmed
    					 * because only the first expiring
    					 * timer will trigger clockevent
    					 * device reprogramming
    					 */
    
    What happens is that CPU2 exits broadcast mode with force bit set, then the
    local timer device is not reprogrammed and CPU2 expects to receive the
    expired event by the broadcast IPI. But this does not happen because CPU1
    is offlined by CPU2. CPU switches the clockevent device to ONESHOT state,
    but does not reprogram the device.
    
    The subsequent reprogramming of the hrtimer broadcast device does not
    program the clockevent device of CPU2 either because the pending expiry
    time is already in the past and the CPU expects the event to be delivered.
    As a consequence all CPUs which wait for a broadcast event to be delivered
    are stuck forever.
    
    Fix this issue by reprogramming the local timer device if the broadcast
    force bit of the CPU is set so that the broadcast hrtimer is delivered.
    
    [ tglx: Massage comment and change log. Add Fixes tag ]
    
    Fixes: 989dcb64 ("tick: Handle broadcast wakeup of multiple cpus")
    Signed-off-by: default avatarYu Liao <liaoyu15@huawei.com>
    Signed-off-by: default avatarThomas Gleixner <tglx@linutronix.de>
    Cc: stable@vger.kernel.org
    Link: https://lore.kernel.org/r/20240711124843.64167-1-liaoyu15@huawei.com
    f7d43dd2
tick-broadcast.c 33.5 KB