linux/kernel/time
Yu Liao dfe19aa913 tick/broadcast: Make takeover of broadcast hrtimer reliable
commit f7d43dd206 upstream.

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: 989dcb645c ("tick: Handle broadcast wakeup of multiple cpus")
Signed-off-by: Yu Liao <liaoyu15@huawei.com>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Cc: stable@vger.kernel.org
Link: https://lore.kernel.org/r/20240711124843.64167-1-liaoyu15@huawei.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2024-08-19 05:32:02 +02:00
..
alarmtimer.c alarmtimer: Prevent starvation by small intervals and SIG_IGN 2023-02-25 11:51:50 +01:00
clockevents.c clockevents: Warn if cpu_all_mask is used as cpumask 2018-08-02 14:55:53 +02:00
clocksource.c clocksource: Retry clock read if long delays detected 2021-07-20 16:15:46 +02:00
hrtimer.c hrtimer: Report offline hrtimer enqueue 2024-02-23 08:12:55 +01:00
itimer.c time: Prevent undefined behaviour in timespec64_to_ns() 2020-11-18 19:18:40 +01:00
jiffies.c
Kconfig
Makefile
ntp_internal.h timekeeping/ntp: Constify some function arguments 2018-07-19 17:08:05 -07:00
ntp.c ntp: Limit TAI-UTC offset 2019-07-26 09:14:10 +02:00
posix-clock.c ptp: fix the race between the release of ptp_clock and cdev 2020-01-04 19:13:35 +01:00
posix-cpu-timers.c kernel, fs: Introduce and use set_restart_fn() and arch_set_restart_data() 2021-03-24 11:07:37 +01:00
posix-stubs.c timers: Prevent union confusion from unexpected restart_syscall() 2023-03-11 16:31:46 +01:00
posix-timers.c posix-timers: Ensure timer ID search-loop limit is valid 2023-08-11 11:45:25 +02:00
posix-timers.h posix-timers: Make forward callback return s64 2018-07-02 11:33:25 +02:00
sched_clock.c timers/sched_clock: Prevent generic sched_clock wrap caused by tick_freeze() 2019-04-27 09:36:38 +02:00
test_udelay.c
tick-broadcast-hrtimer.c tick: broadcast-hrtimer: Fix a race in bc_set_next 2019-10-11 18:21:28 +02:00
tick-broadcast.c tick/broadcast: Make takeover of broadcast hrtimer reliable 2024-08-19 05:32:02 +02:00
tick-common.c tick/common: Touch watchdog in tick_unfreeze() on all CPUs 2020-11-18 19:18:46 +01:00
tick-internal.h Revert: Unify CLOCK_MONOTONIC and CLOCK_BOOTTIME 2018-04-26 14:53:32 +02:00
tick-oneshot.c clockevents: Fix kernel messages split across multiple lines 2018-04-17 17:18:04 +02:00
tick-sched.c tick/sched: Preserve number of idle sleeps across CPU hotplug events 2024-02-23 08:12:43 +01:00
tick-sched.h nohz: Gather tick_sched booleans under a common flag field 2018-04-09 11:54:57 +02:00
time.c y2038: make do_gettimeofday() and get_seconds() inline 2019-11-20 18:45:24 +01:00
timeconst.bc
timeconv.c
timecounter.c
timekeeping_debug.c timekeeping/ntp: Constify some function arguments 2018-07-19 17:08:05 -07:00
timekeeping_internal.h timekeeping/ntp: Constify some function arguments 2018-07-19 17:08:05 -07:00
timekeeping.c timekeeping: Fix cross-timestamp interpolation for non-x86 2024-03-26 18:22:34 -04:00
timekeeping.h timers/sched_clock: Prevent generic sched_clock wrap caused by tick_freeze() 2019-04-27 09:36:38 +02:00
timer_list.c timer_list: Guard procfs specific code 2019-07-26 09:14:10 +02:00
timer.c timers: Rename del_timer_sync() to timer_delete_sync() 2024-04-13 12:50:03 +02:00