linux/drivers/clocksource
Niklas Söderlund 4c8f911560 clocksource/drivers/sh_cmt: Address race condition for clock events
[ Upstream commit db19d3aa77 ]

There is a race condition in the CMT interrupt handler. In the interrupt
handler the driver sets a driver private flag, FLAG_IRQCONTEXT. This
flag is used to indicate any call to set_next_event() should not be
directly propagated to the device, but instead cached. This is done as
the interrupt handler itself reprograms the device when needed before it
completes and this avoids this operation to take place twice.

It is unclear why this design was chosen, my suspicion is to allow the
struct clock_event_device.event_handler callback, which is called while
the FLAG_IRQCONTEXT is set, can update the next event without having to
write to the device twice.

Unfortunately there is a race between when the FLAG_IRQCONTEXT flag is
set and later cleared where the interrupt handler have already started to
write the next event to the device. If set_next_event() is called in
this window the value is only cached in the driver but not written. This
leads to the board to misbehave, or worse lockup and produce a splat.

   rcu: INFO: rcu_preempt detected stalls on CPUs/tasks:
   rcu:     0-...!: (0 ticks this GP) idle=f5e0/0/0x0 softirq=519/519 fqs=0 (false positive?)
   rcu:     (detected by 1, t=6502 jiffies, g=-595, q=77 ncpus=2)
   Sending NMI from CPU 1 to CPUs 0:
   NMI backtrace for cpu 0
   CPU: 0 PID: 0 Comm: swapper/0 Not tainted 6.10.0-rc5-arm64-renesas-00019-g74a6f86eaf1c-dirty #20
   Hardware name: Renesas Salvator-X 2nd version board based on r8a77965 (DT)
   pstate: 60000005 (nZCv daif -PAN -UAO -TCO -DIT -SSBS BTYPE=--)
   pc : tick_check_broadcast_expired+0xc/0x40
   lr : cpu_idle_poll.isra.0+0x8c/0x168
   sp : ffff800081c63d70
   x29: ffff800081c63d70 x28: 00000000580000c8 x27: 00000000bfee5610
   x26: 0000000000000027 x25: 0000000000000000 x24: 0000000000000000
   x23: ffff00007fbb9100 x22: ffff8000818f1008 x21: ffff8000800ef07c
   x20: ffff800081c79ec0 x19: ffff800081c70c28 x18: 0000000000000000
   x17: 0000000000000000 x16: 0000000000000000 x15: 0000ffffc2c717d8
   x14: 0000000000000000 x13: ffff000009c18080 x12: ffff8000825f7fc0
   x11: 0000000000000000 x10: ffff8000818f3cd4 x9 : 0000000000000028
   x8 : ffff800081c79ec0 x7 : ffff800081c73000 x6 : 0000000000000000
   x5 : 0000000000000000 x4 : ffff7ffffe286000 x3 : 0000000000000000
   x2 : ffff7ffffe286000 x1 : ffff800082972900 x0 : ffff8000818f1008
   Call trace:
    tick_check_broadcast_expired+0xc/0x40
    do_idle+0x9c/0x280
    cpu_startup_entry+0x34/0x40
    kernel_init+0x0/0x11c
    do_one_initcall+0x0/0x260
    __primary_switched+0x80/0x88
   rcu: rcu_preempt kthread timer wakeup didn't happen for 6501 jiffies! g-595 f0x0 RCU_GP_WAIT_FQS(5) ->state=0x402
   rcu:     Possible timer handling issue on cpu=0 timer-softirq=262
   rcu: rcu_preempt kthread starved for 6502 jiffies! g-595 f0x0 RCU_GP_WAIT_FQS(5) ->state=0x402 ->cpu=0
   rcu:     Unless rcu_preempt kthread gets sufficient CPU time, OOM is now expected behavior.
   rcu: RCU grace-period kthread stack dump:
   task:rcu_preempt     state:I stack:0     pid:15    tgid:15    ppid:2      flags:0x00000008
   Call trace:
    __switch_to+0xbc/0x100
    __schedule+0x358/0xbe0
    schedule+0x48/0x148
    schedule_timeout+0xc4/0x138
    rcu_gp_fqs_loop+0x12c/0x764
    rcu_gp_kthread+0x208/0x298
    kthread+0x10c/0x110
    ret_from_fork+0x10/0x20

The design have been part of the driver since it was first merged in
early 2009. It becomes increasingly harder to trigger the issue the
older kernel version one tries. It only takes a few boots on v6.10-rc5,
while hundreds of boots are needed to trigger it on v5.10.

Close the race condition by using the CMT channel lock for the two
competing sections. The channel lock was added to the driver after its
initial design.

Signed-off-by: Niklas Söderlund <niklas.soderlund+renesas@ragnatech.se>
Link: https://lore.kernel.org/r/20240702190230.3825292-1-niklas.soderlund+renesas@ragnatech.se
Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
2024-08-19 05:33:46 +02:00
..
acpi_pm.c clocksource: acpi_pm: fix return value of __setup handler 2022-04-15 14:18:05 +02:00
arc_timer.c Merge branch 'timers/vdso' into timers/core 2019-07-03 10:50:21 +02:00
arm_arch_timer.c clocksource/arm_arch_timer: Improve Allwinner A64 timer workaround 2021-07-19 08:53:15 +02:00
arm_global_timer.c treewide: Replace GPLv2 boilerplate/reference with SPDX - rule 500 2019-06-19 17:09:55 +02:00
armv7m_systick.c treewide: Replace GPLv2 boilerplate/reference with SPDX - rule 194 2019-05-30 11:29:22 -07:00
asm9260_timer.c clocksource/drivers/asm9260: Add a check for of_clk_get 2020-01-04 19:17:07 +01:00
bcm2835_timer.c clocksource/drivers/bcm2835_timer: Fix memory leak of timer 2020-02-24 08:36:28 +01:00
bcm_kona_timer.c clocksource/drivers: Rename CLOCKSOURCE_OF_DECLARE to TIMER_OF_DECLARE 2017-06-14 11:58:45 +02:00
clksrc_st_lpc.c treewide: Replace GPLv2 boilerplate/reference with SPDX - rule 152 2019-05-30 11:26:32 -07:00
clksrc-dbx500-prcmu.c treewide: Replace GPLv2 boilerplate/reference with SPDX - rule 197 2019-05-30 11:29:22 -07:00
clps711x-timer.c treewide: Replace GPLv2 boilerplate/reference with SPDX - rule 152 2019-05-30 11:26:32 -07:00
dummy_timer.c treewide: Replace GPLv2 boilerplate/reference with SPDX - rule 500 2019-06-19 17:09:55 +02:00
dw_apb_timer_of.c clocksource: dw_apb_timer_of: Fix missing clockevent timers 2020-06-22 09:30:55 +02:00
dw_apb_timer.c clocksource: dw_apb_timer: Make CPU-affiliation being optional 2020-06-22 09:30:55 +02:00
em_sti.c clocksource: Remove dev_err() usage after platform_get_irq() 2019-08-27 00:31:39 +02:00
exynos_mct.c Merge branch 'timers/vdso' into timers/core 2019-07-03 10:50:21 +02:00
h8300_timer8.c clocksource/drivers/h8300_timer8: Fix wrong return value in h8300_8timer_init() 2020-10-01 13:18:16 +02:00
h8300_timer16.c License cleanup: add SPDX GPL-2.0 license identifier to files with no license 2017-11-02 11:10:55 +01:00
h8300_tpu.c License cleanup: add SPDX GPL-2.0 license identifier to files with no license 2017-11-02 11:10:55 +01:00
hyperv_timer.c clocksource: hyper-v: unexport __init-annotated hv_init_clocksource() 2022-06-22 14:11:21 +02:00
i8253.c clockevents/drivers/i8253: Add support for PIT shutdown quirk 2018-11-04 11:04:46 +01:00
ingenic-timer.c clocksource: Add a new timer-ingenic driver 2019-08-08 15:30:08 -07:00
jcore-pit.c clocksource/drivers: Rename CLOCKSOURCE_OF_DECLARE to TIMER_OF_DECLARE 2017-06-14 11:58:45 +02:00
Kconfig clocksource/drivers/timer-ti-dm: Select TIMER_OF 2021-11-17 09:48:39 +01:00
Makefile clocksource: Add a new timer-ingenic driver 2019-08-08 15:30:08 -07:00
mips-gic-timer.c clocksource/drivers/mips-gic-timer: Make gic_compare_irqaction static 2019-03-22 22:59:33 +01:00
mmio.c treewide: Replace GPLv2 boilerplate/reference with SPDX - rule 500 2019-06-19 17:09:55 +02:00
mps2-timer.c treewide: Replace GPLv2 boilerplate/reference with SPDX - rule 500 2019-06-19 17:09:55 +02:00
mxs_timer.c clocksource/drivers/mxs_timer: Add missing semicolon when DEBUG is defined 2021-03-04 10:26:29 +01:00
nomadik-mtu.c treewide: Replace GPLv2 boilerplate/reference with SPDX - rule 500 2019-06-19 17:09:55 +02:00
numachip.c treewide: Replace GPLv2 boilerplate/reference with SPDX - rule 282 2019-06-05 17:36:37 +02:00
renesas-ostm.c clocksource/drivers/renesas-ostm: Use DIV_ROUND_CLOSEST() helper 2019-08-27 00:31:39 +02:00
samsung_pwm_timer.c treewide: Replace GPLv2 boilerplate/reference with SPDX - rule 500 2019-06-19 17:09:55 +02:00
scx200_hrt.c treewide: Replace GPLv2 boilerplate/reference with SPDX - rule 152 2019-05-30 11:26:32 -07:00
sh_cmt.c clocksource/drivers/sh_cmt: Address race condition for clock events 2024-08-19 05:33:46 +02:00
sh_mtu2.c clocksource/drivers/sh_mtu2: Do not loop using platform_get_irq_by_name() 2019-10-18 07:55:16 +02:00
sh_tmu.c clocksource: Remove dev_err() usage after platform_get_irq() 2019-08-27 00:31:39 +02:00
timer-armada-370-xp.c clocksource/drivers: Unify the names to timer-* format 2018-10-03 14:37:02 +02:00
timer-atcpit100.c clocksource/drivers: Set clockevent device cpumask to cpu_possible_mask 2018-07-26 11:26:30 +02:00
timer-atlas7.c treewide: Replace GPLv2 boilerplate/reference with SPDX - rule 4 2019-05-21 11:28:40 +02:00
timer-atmel-pit.c treewide: Replace GPLv2 boilerplate/reference with SPDX - rule 500 2019-06-19 17:09:55 +02:00
timer-atmel-st.c treewide: Replace GPLv2 boilerplate/reference with SPDX - rule 156 2019-05-30 11:26:35 -07:00
timer-atmel-tcb.c clocksource/drivers/timer-atmel-tcb: Fix initialization on SAM9 hardware 2023-11-28 16:50:13 +00:00
timer-cadence-ttc.c clocksource/drivers/cadence-ttc: Fix memory leak in ttc_timer_probe 2023-07-27 08:37:05 +02:00
timer-cs5535.c treewide: Replace GPLv2 boilerplate/reference with SPDX - rule 206 2019-05-30 11:29:53 -07:00
timer-davinci.c clocksource/drivers/davinci: Fix memory leak in davinci_timer_register when init fails 2023-05-17 11:35:53 +02:00
timer-digicolor.c clocksource/drivers: Rename CLOCKSOURCE_OF_DECLARE to TIMER_OF_DECLARE 2017-06-14 11:58:45 +02:00
timer-efm32.c treewide: Replace GPLv2 boilerplate/reference with SPDX - rule 500 2019-06-19 17:09:55 +02:00
timer-fsl-ftm.c treewide: Replace GPLv2 boilerplate/reference with SPDX - rule 152 2019-05-30 11:26:32 -07:00
timer-fttmr010.c clocksource/drivers/fttmr010: Fix invalid interrupt register access 2018-12-18 22:22:23 +01:00
timer-gx6605s.c clocksource/drivers/timer-gx6605s: Fixup counter reload 2020-10-07 08:01:25 +02:00
timer-imx-gpt.c clocksource/drivers/timer-imx-gpt: Fix potential memory leak 2023-11-28 16:50:13 +00:00
timer-imx-sysctr.c clocksource/drivers/imx-sysctr: Add internal clock divider handle 2019-08-27 00:31:39 +02:00
timer-imx-tpm.c clocksource/drivers/timer-imx-tpm: Specify clock name for timer-of 2018-12-18 22:22:23 +01:00
timer-integrator-ap.c treewide: Replace GPLv2 boilerplate/reference with SPDX - rule 156 2019-05-30 11:26:35 -07:00
timer-ixp4xx.c clocksource/drivers/ixp4xx: remove EXPORT_SYMBOL_GPL from ixp4xx_timer_setup() 2022-07-07 17:36:53 +02:00
timer-keystone.c treewide: Replace GPLv2 boilerplate/reference with SPDX - rule 500 2019-06-19 17:09:55 +02:00
timer-lpc32xx.c clocksource/drivers: Unify the names to timer-* format 2018-10-03 14:37:02 +02:00
timer-mediatek.c clocksource/drivers/mediatek: Fix error handling 2019-10-16 17:04:50 +02:00
timer-meson6.c clocksource/drivers/timer-meson6: Update with SPDX Licence identifier 2019-06-25 19:49:18 +02:00
timer-milbeaut.c clocksource/drivers/timer-milbeaut: Cleanup common register accesses 2019-05-02 21:55:58 +02:00
timer-mp-csky.c clocksource/drivers/c-sky: fixup ftrace call-graph panic 2018-12-31 23:17:23 +08:00
timer-npcm7xx.c clocksource/drivers/npcm: Fix GENMASK and timer operation 2019-08-27 00:31:39 +02:00
timer-nps.c clocksource/drivers: Rename CLOCKSOURCE_OF_DECLARE to TIMER_OF_DECLARE 2017-06-14 11:58:45 +02:00
timer-of.c clocksource/drivers/timer-of: Check return value of of_iomap in timer_of_base_init() 2022-04-15 14:18:05 +02:00
timer-of.h clocksource/drivers/timer-of: Store the device node pointer in 'struct timer_of' 2018-01-08 17:57:24 +01:00
timer-orion.c clocksource/drivers/orion: Add missing clk_disable_unprepare() on error path 2020-12-30 11:51:17 +01:00
timer-owl.c treewide: Replace GPLv2 boilerplate/reference with SPDX - rule 152 2019-05-30 11:26:32 -07:00
timer-oxnas-rps.c clocksource/drivers/oxnas-rps: Fix irq_of_parse_and_map() return value 2022-06-14 18:11:54 +02:00
timer-pistachio.c clocksource/drivers: Unify the names to timer-* format 2018-10-03 14:37:02 +02:00
timer-prima2.c treewide: Replace GPLv2 boilerplate/reference with SPDX - rule 4 2019-05-21 11:28:40 +02:00
timer-probe.c clocksource/drivers: Do not warn on probe defer 2019-08-27 00:31:39 +02:00
timer-pxa.c treewide: Replace GPLv2 boilerplate/reference with SPDX - rule 500 2019-06-19 17:09:55 +02:00
timer-qcom.c treewide: Replace GPLv2 boilerplate/reference with SPDX - rule 282 2019-06-05 17:36:37 +02:00
timer-rda.c clocksource/drivers/rda: Add clock driver for RDA8810PL SoC 2018-12-18 22:22:23 +01:00
timer-riscv.c Revert "clocksource/drivers/riscv: Events are stopped during CPU suspend" 2022-12-08 11:23:06 +01:00
timer-rockchip.c treewide: Replace GPLv2 boilerplate/reference with SPDX - rule 500 2019-06-19 17:09:55 +02:00
timer-sp804.c clocksource/drivers/sp804: Avoid error on multiple instances 2022-06-14 18:12:00 +02:00
timer-sp.h License cleanup: add SPDX GPL-2.0 license identifier to files with no license 2017-11-02 11:10:55 +01:00
timer-sprd.c clocksource/drivers/sprd: Register one always-on timer to compensate suspend time 2018-07-26 11:26:34 +02:00
timer-stm32.c treewide: Replace GPLv2 boilerplate/reference with SPDX - rule 194 2019-05-30 11:29:22 -07:00
timer-sun4i.c clocksource: sun4i: Add missing compatibles 2019-08-27 00:31:39 +02:00
timer-sun5i.c clocksource/drivers/sun5i: Fail gracefully when clock rate is unavailable 2019-02-23 12:13:45 +01:00
timer-tango-xtal.c clocksource/drivers/tango-xtal: Rename the file for consistency 2019-02-23 12:13:45 +01:00
timer-tegra.c clocksource/drivers/tegra: Set up maximum-ticks limit properly 2019-06-25 19:49:18 +02:00
timer-ti-32k.c treewide: Replace GPLv2 boilerplate/reference with SPDX - rule 341 2019-06-05 17:37:07 +02:00
timer-ti-dm.c clocksource/drivers/timer-ti-dm: Change to new style declaration 2019-05-24 15:51:30 +02:00
timer-u300.c treewide: Replace GPLv2 boilerplate/reference with SPDX - rule 194 2019-05-30 11:29:22 -07:00
timer-versatile.c treewide: Replace GPLv2 boilerplate/reference with SPDX - rule 174 2019-05-30 11:26:41 -07:00
timer-vf-pit.c treewide: Replace GPLv2 boilerplate/reference with SPDX - rule 152 2019-05-30 11:26:32 -07:00
timer-vt8500.c treewide: Replace GPLv2 boilerplate/reference with SPDX - rule 156 2019-05-30 11:26:35 -07:00
timer-zevio.c treewide: Replace GPLv2 boilerplate/reference with SPDX - rule 500 2019-06-19 17:09:55 +02:00