From 2a177ef905914356ab377be981a04c3c3cbaba55 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Mon, 20 Apr 2026 20:44:48 +0200 Subject: [PATCH] drop clockevents-prevent-timer-interrupt-starvation.patch --- ...s-prevent-timer-interrupt-starvation.patch | 218 ------------------ queue-5.15/series | 1 - ...s-prevent-timer-interrupt-starvation.patch | 218 ------------------ queue-6.1/series | 1 - ...s-prevent-timer-interrupt-starvation.patch | 218 ------------------ queue-6.12/series | 1 - ...s-prevent-timer-interrupt-starvation.patch | 218 ------------------ queue-6.18/series | 1 - ...s-prevent-timer-interrupt-starvation.patch | 218 ------------------ queue-6.19/series | 1 - ...s-prevent-timer-interrupt-starvation.patch | 218 ------------------ queue-6.6/series | 1 - 12 files changed, 1314 deletions(-) delete mode 100644 queue-5.15/clockevents-prevent-timer-interrupt-starvation.patch delete mode 100644 queue-6.1/clockevents-prevent-timer-interrupt-starvation.patch delete mode 100644 queue-6.12/clockevents-prevent-timer-interrupt-starvation.patch delete mode 100644 queue-6.18/clockevents-prevent-timer-interrupt-starvation.patch delete mode 100644 queue-6.19/clockevents-prevent-timer-interrupt-starvation.patch delete mode 100644 queue-6.6/clockevents-prevent-timer-interrupt-starvation.patch diff --git a/queue-5.15/clockevents-prevent-timer-interrupt-starvation.patch b/queue-5.15/clockevents-prevent-timer-interrupt-starvation.patch deleted file mode 100644 index 01ffd7f692..0000000000 --- a/queue-5.15/clockevents-prevent-timer-interrupt-starvation.patch +++ /dev/null @@ -1,218 +0,0 @@ -From 4b95adf98f5c5c0219c6eba726aa9626cdb3a351 Mon Sep 17 00:00:00 2001 -From: Sasha Levin -Date: Tue, 7 Apr 2026 10:54:17 +0200 -Subject: clockevents: Prevent timer interrupt starvation - -From: Thomas Gleixner - -[ Upstream commit d6e152d905bdb1f32f9d99775e2f453350399a6a ] - -Calvin reported an odd NMI watchdog lockup which claims that the CPU locked -up in user space. He provided a reproducer, which sets up a timerfd based -timer and then rearms it in a loop with an absolute expiry time of 1ns. - -As the expiry time is in the past, the timer ends up as the first expiring -timer in the per CPU hrtimer base and the clockevent device is programmed -with the minimum delta value. If the machine is fast enough, this ends up -in a endless loop of programming the delta value to the minimum value -defined by the clock event device, before the timer interrupt can fire, -which starves the interrupt and consequently triggers the lockup detector -because the hrtimer callback of the lockup mechanism is never invoked. - -As a first step to prevent this, avoid reprogramming the clock event device -when: - - a forced minimum delta event is pending - - the new expiry delta is less then or equal to the minimum delta - -Thanks to Calvin for providing the reproducer and to Borislav for testing -and providing data from his Zen5 machine. - -The problem is not limited to Zen5, but depending on the underlying -clock event device (e.g. TSC deadline timer on Intel) and the CPU speed -not necessarily observable. - -This change serves only as the last resort and further changes will be made -to prevent this scenario earlier in the call chain as far as possible. - -[ tglx: Updated to restore the old behaviour vs. !force and delta <= 0 and - fixed up the tick-broadcast handlers as pointed out by Borislav ] - -Fixes: d316c57ff6bf ("[PATCH] clockevents: add core functionality") -Reported-by: Calvin Owens -Signed-off-by: Thomas Gleixner -Tested-by: Calvin Owens -Tested-by: Borislav Petkov -Link: https://lore.kernel.org/lkml/acMe-QZUel-bBYUh@mozart.vkv.me/ -Link: https://patch.msgid.link/20260407083247.562657657@kernel.org -Signed-off-by: Sasha Levin ---- - include/linux/clockchips.h | 2 ++ - kernel/time/clockevents.c | 27 +++++++++++++++++++-------- - kernel/time/hrtimer.c | 1 + - kernel/time/tick-broadcast.c | 8 +++++++- - kernel/time/tick-common.c | 1 + - kernel/time/tick-sched.c | 1 + - 6 files changed, 31 insertions(+), 9 deletions(-) - -diff --git a/include/linux/clockchips.h b/include/linux/clockchips.h -index 8ae9a95ebf5b5..046c6d8d91a69 100644 ---- a/include/linux/clockchips.h -+++ b/include/linux/clockchips.h -@@ -80,6 +80,7 @@ enum clock_event_state { - * @shift: nanoseconds to cycles divisor (power of two) - * @state_use_accessors:current state of the device, assigned by the core code - * @features: features -+ * @next_event_forced: True if the last programming was a forced event - * @retries: number of forced programming retries - * @set_state_periodic: switch state to periodic - * @set_state_oneshot: switch state to oneshot -@@ -108,6 +109,7 @@ struct clock_event_device { - u32 shift; - enum clock_event_state state_use_accessors; - unsigned int features; -+ unsigned int next_event_forced; - unsigned long retries; - - int (*set_state_periodic)(struct clock_event_device *); -diff --git a/kernel/time/clockevents.c b/kernel/time/clockevents.c -index 003ccf338d201..a41701ae38126 100644 ---- a/kernel/time/clockevents.c -+++ b/kernel/time/clockevents.c -@@ -172,6 +172,7 @@ void clockevents_shutdown(struct clock_event_device *dev) - { - clockevents_switch_state(dev, CLOCK_EVT_STATE_SHUTDOWN); - dev->next_event = KTIME_MAX; -+ dev->next_event_forced = 0; - } - - /** -@@ -305,7 +306,6 @@ int clockevents_program_event(struct clock_event_device *dev, ktime_t expires, - { - unsigned long long clc; - int64_t delta; -- int rc; - - if (WARN_ON_ONCE(expires < 0)) - return -ETIME; -@@ -324,16 +324,27 @@ int clockevents_program_event(struct clock_event_device *dev, ktime_t expires, - return dev->set_next_ktime(expires, dev); - - delta = ktime_to_ns(ktime_sub(expires, ktime_get())); -- if (delta <= 0) -- return force ? clockevents_program_min_delta(dev) : -ETIME; - -- delta = min(delta, (int64_t) dev->max_delta_ns); -- delta = max(delta, (int64_t) dev->min_delta_ns); -+ /* Required for tick_periodic() during early boot */ -+ if (delta <= 0 && !force) -+ return -ETIME; -+ -+ if (delta > (int64_t)dev->min_delta_ns) { -+ delta = min(delta, (int64_t) dev->max_delta_ns); -+ clc = ((unsigned long long) delta * dev->mult) >> dev->shift; -+ if (!dev->set_next_event((unsigned long) clc, dev)) -+ return 0; -+ } - -- clc = ((unsigned long long) delta * dev->mult) >> dev->shift; -- rc = dev->set_next_event((unsigned long) clc, dev); -+ if (dev->next_event_forced) -+ return 0; - -- return (rc && force) ? clockevents_program_min_delta(dev) : rc; -+ if (dev->set_next_event(dev->min_delta_ticks, dev)) { -+ if (!force || clockevents_program_min_delta(dev)) -+ return -ETIME; -+ } -+ dev->next_event_forced = 1; -+ return 0; - } - - /* -diff --git a/kernel/time/hrtimer.c b/kernel/time/hrtimer.c -index 0246b32e907d2..459bd5ab95101 100644 ---- a/kernel/time/hrtimer.c -+++ b/kernel/time/hrtimer.c -@@ -1788,6 +1788,7 @@ void hrtimer_interrupt(struct clock_event_device *dev) - BUG_ON(!cpu_base->hres_active); - cpu_base->nr_events++; - dev->next_event = KTIME_MAX; -+ dev->next_event_forced = 0; - - raw_spin_lock_irqsave(&cpu_base->lock, flags); - entry_time = now = hrtimer_update_base(cpu_base); -diff --git a/kernel/time/tick-broadcast.c b/kernel/time/tick-broadcast.c -index 13a71a894cc16..369f7e52b5e51 100644 ---- a/kernel/time/tick-broadcast.c -+++ b/kernel/time/tick-broadcast.c -@@ -76,8 +76,10 @@ const struct clock_event_device *tick_get_wakeup_device(int cpu) - */ - static void tick_broadcast_start_periodic(struct clock_event_device *bc) - { -- if (bc) -+ if (bc) { -+ bc->next_event_forced = 0; - tick_setup_periodic(bc, 1); -+ } - } - - /* -@@ -403,6 +405,7 @@ static void tick_handle_periodic_broadcast(struct clock_event_device *dev) - bool bc_local; - - raw_spin_lock(&tick_broadcast_lock); -+ tick_broadcast_device.evtdev->next_event_forced = 0; - - /* Handle spurious interrupts gracefully */ - if (clockevent_state_shutdown(tick_broadcast_device.evtdev)) { -@@ -692,6 +695,7 @@ static void tick_handle_oneshot_broadcast(struct clock_event_device *dev) - - raw_spin_lock(&tick_broadcast_lock); - dev->next_event = KTIME_MAX; -+ tick_broadcast_device.evtdev->next_event_forced = 0; - next_event = KTIME_MAX; - cpumask_clear(tmpmask); - now = ktime_get(); -@@ -1057,6 +1061,7 @@ static void tick_broadcast_setup_oneshot(struct clock_event_device *bc, - - - bc->event_handler = tick_handle_oneshot_broadcast; -+ bc->next_event_forced = 0; - bc->next_event = KTIME_MAX; - - /* -@@ -1169,6 +1174,7 @@ void hotplug_cpu__broadcast_tick_pull(int deadcpu) - } - - /* This moves the broadcast assignment to this CPU: */ -+ bc->next_event_forced = 0; - clockevents_program_event(bc, bc->next_event, 1); - } - raw_spin_unlock_irqrestore(&tick_broadcast_lock, flags); -diff --git a/kernel/time/tick-common.c b/kernel/time/tick-common.c -index 7f2b17fc8ce40..79ae1adf635bd 100644 ---- a/kernel/time/tick-common.c -+++ b/kernel/time/tick-common.c -@@ -109,6 +109,7 @@ void tick_handle_periodic(struct clock_event_device *dev) - int cpu = smp_processor_id(); - ktime_t next = dev->next_event; - -+ dev->next_event_forced = 0; - tick_periodic(cpu); - - #if defined(CONFIG_HIGH_RES_TIMERS) || defined(CONFIG_NO_HZ_COMMON) -diff --git a/kernel/time/tick-sched.c b/kernel/time/tick-sched.c -index ae1b207c64479..6a3d0c0c8ffaf 100644 ---- a/kernel/time/tick-sched.c -+++ b/kernel/time/tick-sched.c -@@ -1354,6 +1354,7 @@ static void tick_nohz_handler(struct clock_event_device *dev) - ktime_t now = ktime_get(); - - dev->next_event = KTIME_MAX; -+ dev->next_event_forced = 0; - - tick_sched_do_timer(ts, now); - tick_sched_handle(ts, regs); --- -2.53.0 - diff --git a/queue-5.15/series b/queue-5.15/series index 92548a4c82..f3c877b1da 100644 --- a/queue-5.15/series +++ b/queue-5.15/series @@ -39,7 +39,6 @@ af_unix-read-unix_diag_vfs-data-under-unix_state_loc.patch l2tp-drop-large-packets-with-udp-encap.patch gpio-tegra-fix-irq_release_resources-calling-enable-.patch perf-x86-intel-uncore-skip-discovery-table-for-offli.patch -clockevents-prevent-timer-interrupt-starvation.patch crypto-algif_aead-fix-minimum-rx-size-check-for-decr.patch i3c-fix-uninitialized-variable-use-in-i2c-setup.patch netfilter-conntrack-add-missing-netlink-policy-valid.patch diff --git a/queue-6.1/clockevents-prevent-timer-interrupt-starvation.patch b/queue-6.1/clockevents-prevent-timer-interrupt-starvation.patch deleted file mode 100644 index add1136b61..0000000000 --- a/queue-6.1/clockevents-prevent-timer-interrupt-starvation.patch +++ /dev/null @@ -1,218 +0,0 @@ -From a53e2c11e05c64e57807aea194c2c4819d1369dd Mon Sep 17 00:00:00 2001 -From: Sasha Levin -Date: Tue, 7 Apr 2026 10:54:17 +0200 -Subject: clockevents: Prevent timer interrupt starvation - -From: Thomas Gleixner - -[ Upstream commit d6e152d905bdb1f32f9d99775e2f453350399a6a ] - -Calvin reported an odd NMI watchdog lockup which claims that the CPU locked -up in user space. He provided a reproducer, which sets up a timerfd based -timer and then rearms it in a loop with an absolute expiry time of 1ns. - -As the expiry time is in the past, the timer ends up as the first expiring -timer in the per CPU hrtimer base and the clockevent device is programmed -with the minimum delta value. If the machine is fast enough, this ends up -in a endless loop of programming the delta value to the minimum value -defined by the clock event device, before the timer interrupt can fire, -which starves the interrupt and consequently triggers the lockup detector -because the hrtimer callback of the lockup mechanism is never invoked. - -As a first step to prevent this, avoid reprogramming the clock event device -when: - - a forced minimum delta event is pending - - the new expiry delta is less then or equal to the minimum delta - -Thanks to Calvin for providing the reproducer and to Borislav for testing -and providing data from his Zen5 machine. - -The problem is not limited to Zen5, but depending on the underlying -clock event device (e.g. TSC deadline timer on Intel) and the CPU speed -not necessarily observable. - -This change serves only as the last resort and further changes will be made -to prevent this scenario earlier in the call chain as far as possible. - -[ tglx: Updated to restore the old behaviour vs. !force and delta <= 0 and - fixed up the tick-broadcast handlers as pointed out by Borislav ] - -Fixes: d316c57ff6bf ("[PATCH] clockevents: add core functionality") -Reported-by: Calvin Owens -Signed-off-by: Thomas Gleixner -Tested-by: Calvin Owens -Tested-by: Borislav Petkov -Link: https://lore.kernel.org/lkml/acMe-QZUel-bBYUh@mozart.vkv.me/ -Link: https://patch.msgid.link/20260407083247.562657657@kernel.org -Signed-off-by: Sasha Levin ---- - include/linux/clockchips.h | 2 ++ - kernel/time/clockevents.c | 27 +++++++++++++++++++-------- - kernel/time/hrtimer.c | 1 + - kernel/time/tick-broadcast.c | 8 +++++++- - kernel/time/tick-common.c | 1 + - kernel/time/tick-sched.c | 1 + - 6 files changed, 31 insertions(+), 9 deletions(-) - -diff --git a/include/linux/clockchips.h b/include/linux/clockchips.h -index 8ae9a95ebf5b5..046c6d8d91a69 100644 ---- a/include/linux/clockchips.h -+++ b/include/linux/clockchips.h -@@ -80,6 +80,7 @@ enum clock_event_state { - * @shift: nanoseconds to cycles divisor (power of two) - * @state_use_accessors:current state of the device, assigned by the core code - * @features: features -+ * @next_event_forced: True if the last programming was a forced event - * @retries: number of forced programming retries - * @set_state_periodic: switch state to periodic - * @set_state_oneshot: switch state to oneshot -@@ -108,6 +109,7 @@ struct clock_event_device { - u32 shift; - enum clock_event_state state_use_accessors; - unsigned int features; -+ unsigned int next_event_forced; - unsigned long retries; - - int (*set_state_periodic)(struct clock_event_device *); -diff --git a/kernel/time/clockevents.c b/kernel/time/clockevents.c -index 5d85014d59b5f..78cd81a99ea03 100644 ---- a/kernel/time/clockevents.c -+++ b/kernel/time/clockevents.c -@@ -172,6 +172,7 @@ void clockevents_shutdown(struct clock_event_device *dev) - { - clockevents_switch_state(dev, CLOCK_EVT_STATE_SHUTDOWN); - dev->next_event = KTIME_MAX; -+ dev->next_event_forced = 0; - } - - /** -@@ -305,7 +306,6 @@ int clockevents_program_event(struct clock_event_device *dev, ktime_t expires, - { - unsigned long long clc; - int64_t delta; -- int rc; - - if (WARN_ON_ONCE(expires < 0)) - return -ETIME; -@@ -324,16 +324,27 @@ int clockevents_program_event(struct clock_event_device *dev, ktime_t expires, - return dev->set_next_ktime(expires, dev); - - delta = ktime_to_ns(ktime_sub(expires, ktime_get())); -- if (delta <= 0) -- return force ? clockevents_program_min_delta(dev) : -ETIME; - -- delta = min(delta, (int64_t) dev->max_delta_ns); -- delta = max(delta, (int64_t) dev->min_delta_ns); -+ /* Required for tick_periodic() during early boot */ -+ if (delta <= 0 && !force) -+ return -ETIME; -+ -+ if (delta > (int64_t)dev->min_delta_ns) { -+ delta = min(delta, (int64_t) dev->max_delta_ns); -+ clc = ((unsigned long long) delta * dev->mult) >> dev->shift; -+ if (!dev->set_next_event((unsigned long) clc, dev)) -+ return 0; -+ } - -- clc = ((unsigned long long) delta * dev->mult) >> dev->shift; -- rc = dev->set_next_event((unsigned long) clc, dev); -+ if (dev->next_event_forced) -+ return 0; - -- return (rc && force) ? clockevents_program_min_delta(dev) : rc; -+ if (dev->set_next_event(dev->min_delta_ticks, dev)) { -+ if (!force || clockevents_program_min_delta(dev)) -+ return -ETIME; -+ } -+ dev->next_event_forced = 1; -+ return 0; - } - - /* -diff --git a/kernel/time/hrtimer.c b/kernel/time/hrtimer.c -index 002b29e566cb3..d5bb051d6e167 100644 ---- a/kernel/time/hrtimer.c -+++ b/kernel/time/hrtimer.c -@@ -1850,6 +1850,7 @@ void hrtimer_interrupt(struct clock_event_device *dev) - BUG_ON(!cpu_base->hres_active); - cpu_base->nr_events++; - dev->next_event = KTIME_MAX; -+ dev->next_event_forced = 0; - - raw_spin_lock_irqsave(&cpu_base->lock, flags); - entry_time = now = hrtimer_update_base(cpu_base); -diff --git a/kernel/time/tick-broadcast.c b/kernel/time/tick-broadcast.c -index 13a71a894cc16..369f7e52b5e51 100644 ---- a/kernel/time/tick-broadcast.c -+++ b/kernel/time/tick-broadcast.c -@@ -76,8 +76,10 @@ const struct clock_event_device *tick_get_wakeup_device(int cpu) - */ - static void tick_broadcast_start_periodic(struct clock_event_device *bc) - { -- if (bc) -+ if (bc) { -+ bc->next_event_forced = 0; - tick_setup_periodic(bc, 1); -+ } - } - - /* -@@ -403,6 +405,7 @@ static void tick_handle_periodic_broadcast(struct clock_event_device *dev) - bool bc_local; - - raw_spin_lock(&tick_broadcast_lock); -+ tick_broadcast_device.evtdev->next_event_forced = 0; - - /* Handle spurious interrupts gracefully */ - if (clockevent_state_shutdown(tick_broadcast_device.evtdev)) { -@@ -692,6 +695,7 @@ static void tick_handle_oneshot_broadcast(struct clock_event_device *dev) - - raw_spin_lock(&tick_broadcast_lock); - dev->next_event = KTIME_MAX; -+ tick_broadcast_device.evtdev->next_event_forced = 0; - next_event = KTIME_MAX; - cpumask_clear(tmpmask); - now = ktime_get(); -@@ -1057,6 +1061,7 @@ static void tick_broadcast_setup_oneshot(struct clock_event_device *bc, - - - bc->event_handler = tick_handle_oneshot_broadcast; -+ bc->next_event_forced = 0; - bc->next_event = KTIME_MAX; - - /* -@@ -1169,6 +1174,7 @@ void hotplug_cpu__broadcast_tick_pull(int deadcpu) - } - - /* This moves the broadcast assignment to this CPU: */ -+ bc->next_event_forced = 0; - clockevents_program_event(bc, bc->next_event, 1); - } - raw_spin_unlock_irqrestore(&tick_broadcast_lock, flags); -diff --git a/kernel/time/tick-common.c b/kernel/time/tick-common.c -index 7f2b17fc8ce40..79ae1adf635bd 100644 ---- a/kernel/time/tick-common.c -+++ b/kernel/time/tick-common.c -@@ -109,6 +109,7 @@ void tick_handle_periodic(struct clock_event_device *dev) - int cpu = smp_processor_id(); - ktime_t next = dev->next_event; - -+ dev->next_event_forced = 0; - tick_periodic(cpu); - - #if defined(CONFIG_HIGH_RES_TIMERS) || defined(CONFIG_NO_HZ_COMMON) -diff --git a/kernel/time/tick-sched.c b/kernel/time/tick-sched.c -index 8cfdc6b978d76..3a017b5555250 100644 ---- a/kernel/time/tick-sched.c -+++ b/kernel/time/tick-sched.c -@@ -1382,6 +1382,7 @@ static void tick_nohz_handler(struct clock_event_device *dev) - ktime_t now = ktime_get(); - - dev->next_event = KTIME_MAX; -+ dev->next_event_forced = 0; - - tick_sched_do_timer(ts, now); - tick_sched_handle(ts, regs); --- -2.53.0 - diff --git a/queue-6.1/series b/queue-6.1/series index c3547790b1..a6bfb839de 100644 --- a/queue-6.1/series +++ b/queue-6.1/series @@ -50,7 +50,6 @@ af_unix-read-unix_diag_vfs-data-under-unix_state_loc.patch l2tp-drop-large-packets-with-udp-encap.patch gpio-tegra-fix-irq_release_resources-calling-enable-.patch perf-x86-intel-uncore-skip-discovery-table-for-offli.patch -clockevents-prevent-timer-interrupt-starvation.patch crypto-algif_aead-fix-minimum-rx-size-check-for-decr.patch revert-drm-fix-use-after-free-on-framebuffers-and-pr.patch netfilter-conntrack-add-missing-netlink-policy-valid.patch diff --git a/queue-6.12/clockevents-prevent-timer-interrupt-starvation.patch b/queue-6.12/clockevents-prevent-timer-interrupt-starvation.patch deleted file mode 100644 index 1430415187..0000000000 --- a/queue-6.12/clockevents-prevent-timer-interrupt-starvation.patch +++ /dev/null @@ -1,218 +0,0 @@ -From f0aa641eb7fe25dd725ef6835dde2dd178fc55e8 Mon Sep 17 00:00:00 2001 -From: Sasha Levin -Date: Tue, 7 Apr 2026 10:54:17 +0200 -Subject: clockevents: Prevent timer interrupt starvation - -From: Thomas Gleixner - -[ Upstream commit d6e152d905bdb1f32f9d99775e2f453350399a6a ] - -Calvin reported an odd NMI watchdog lockup which claims that the CPU locked -up in user space. He provided a reproducer, which sets up a timerfd based -timer and then rearms it in a loop with an absolute expiry time of 1ns. - -As the expiry time is in the past, the timer ends up as the first expiring -timer in the per CPU hrtimer base and the clockevent device is programmed -with the minimum delta value. If the machine is fast enough, this ends up -in a endless loop of programming the delta value to the minimum value -defined by the clock event device, before the timer interrupt can fire, -which starves the interrupt and consequently triggers the lockup detector -because the hrtimer callback of the lockup mechanism is never invoked. - -As a first step to prevent this, avoid reprogramming the clock event device -when: - - a forced minimum delta event is pending - - the new expiry delta is less then or equal to the minimum delta - -Thanks to Calvin for providing the reproducer and to Borislav for testing -and providing data from his Zen5 machine. - -The problem is not limited to Zen5, but depending on the underlying -clock event device (e.g. TSC deadline timer on Intel) and the CPU speed -not necessarily observable. - -This change serves only as the last resort and further changes will be made -to prevent this scenario earlier in the call chain as far as possible. - -[ tglx: Updated to restore the old behaviour vs. !force and delta <= 0 and - fixed up the tick-broadcast handlers as pointed out by Borislav ] - -Fixes: d316c57ff6bf ("[PATCH] clockevents: add core functionality") -Reported-by: Calvin Owens -Signed-off-by: Thomas Gleixner -Tested-by: Calvin Owens -Tested-by: Borislav Petkov -Link: https://lore.kernel.org/lkml/acMe-QZUel-bBYUh@mozart.vkv.me/ -Link: https://patch.msgid.link/20260407083247.562657657@kernel.org -Signed-off-by: Sasha Levin ---- - include/linux/clockchips.h | 2 ++ - kernel/time/clockevents.c | 27 +++++++++++++++++++-------- - kernel/time/hrtimer.c | 1 + - kernel/time/tick-broadcast.c | 8 +++++++- - kernel/time/tick-common.c | 1 + - kernel/time/tick-sched.c | 1 + - 6 files changed, 31 insertions(+), 9 deletions(-) - -diff --git a/include/linux/clockchips.h b/include/linux/clockchips.h -index b0df28ddd394b..50cdc9da8d32a 100644 ---- a/include/linux/clockchips.h -+++ b/include/linux/clockchips.h -@@ -80,6 +80,7 @@ enum clock_event_state { - * @shift: nanoseconds to cycles divisor (power of two) - * @state_use_accessors:current state of the device, assigned by the core code - * @features: features -+ * @next_event_forced: True if the last programming was a forced event - * @retries: number of forced programming retries - * @set_state_periodic: switch state to periodic - * @set_state_oneshot: switch state to oneshot -@@ -108,6 +109,7 @@ struct clock_event_device { - u32 shift; - enum clock_event_state state_use_accessors; - unsigned int features; -+ unsigned int next_event_forced; - unsigned long retries; - - int (*set_state_periodic)(struct clock_event_device *); -diff --git a/kernel/time/clockevents.c b/kernel/time/clockevents.c -index 78c7bd64d0ddf..6f4257e63bba8 100644 ---- a/kernel/time/clockevents.c -+++ b/kernel/time/clockevents.c -@@ -172,6 +172,7 @@ void clockevents_shutdown(struct clock_event_device *dev) - { - clockevents_switch_state(dev, CLOCK_EVT_STATE_SHUTDOWN); - dev->next_event = KTIME_MAX; -+ dev->next_event_forced = 0; - } - - /** -@@ -305,7 +306,6 @@ int clockevents_program_event(struct clock_event_device *dev, ktime_t expires, - { - unsigned long long clc; - int64_t delta; -- int rc; - - if (WARN_ON_ONCE(expires < 0)) - return -ETIME; -@@ -324,16 +324,27 @@ int clockevents_program_event(struct clock_event_device *dev, ktime_t expires, - return dev->set_next_ktime(expires, dev); - - delta = ktime_to_ns(ktime_sub(expires, ktime_get())); -- if (delta <= 0) -- return force ? clockevents_program_min_delta(dev) : -ETIME; - -- delta = min(delta, (int64_t) dev->max_delta_ns); -- delta = max(delta, (int64_t) dev->min_delta_ns); -+ /* Required for tick_periodic() during early boot */ -+ if (delta <= 0 && !force) -+ return -ETIME; -+ -+ if (delta > (int64_t)dev->min_delta_ns) { -+ delta = min(delta, (int64_t) dev->max_delta_ns); -+ clc = ((unsigned long long) delta * dev->mult) >> dev->shift; -+ if (!dev->set_next_event((unsigned long) clc, dev)) -+ return 0; -+ } - -- clc = ((unsigned long long) delta * dev->mult) >> dev->shift; -- rc = dev->set_next_event((unsigned long) clc, dev); -+ if (dev->next_event_forced) -+ return 0; - -- return (rc && force) ? clockevents_program_min_delta(dev) : rc; -+ if (dev->set_next_event(dev->min_delta_ticks, dev)) { -+ if (!force || clockevents_program_min_delta(dev)) -+ return -ETIME; -+ } -+ dev->next_event_forced = 1; -+ return 0; - } - - /* -diff --git a/kernel/time/hrtimer.c b/kernel/time/hrtimer.c -index 640d2ea4bd1fa..7c57fe7d20d9a 100644 ---- a/kernel/time/hrtimer.c -+++ b/kernel/time/hrtimer.c -@@ -1852,6 +1852,7 @@ void hrtimer_interrupt(struct clock_event_device *dev) - BUG_ON(!cpu_base->hres_active); - cpu_base->nr_events++; - dev->next_event = KTIME_MAX; -+ dev->next_event_forced = 0; - - raw_spin_lock_irqsave(&cpu_base->lock, flags); - entry_time = now = hrtimer_update_base(cpu_base); -diff --git a/kernel/time/tick-broadcast.c b/kernel/time/tick-broadcast.c -index ed58eebb4e8f4..99d2978ef9b98 100644 ---- a/kernel/time/tick-broadcast.c -+++ b/kernel/time/tick-broadcast.c -@@ -76,8 +76,10 @@ const struct clock_event_device *tick_get_wakeup_device(int cpu) - */ - static void tick_broadcast_start_periodic(struct clock_event_device *bc) - { -- if (bc) -+ if (bc) { -+ bc->next_event_forced = 0; - tick_setup_periodic(bc, 1); -+ } - } - - /* -@@ -403,6 +405,7 @@ static void tick_handle_periodic_broadcast(struct clock_event_device *dev) - bool bc_local; - - raw_spin_lock(&tick_broadcast_lock); -+ tick_broadcast_device.evtdev->next_event_forced = 0; - - /* Handle spurious interrupts gracefully */ - if (clockevent_state_shutdown(tick_broadcast_device.evtdev)) { -@@ -696,6 +699,7 @@ static void tick_handle_oneshot_broadcast(struct clock_event_device *dev) - - raw_spin_lock(&tick_broadcast_lock); - dev->next_event = KTIME_MAX; -+ tick_broadcast_device.evtdev->next_event_forced = 0; - next_event = KTIME_MAX; - cpumask_clear(tmpmask); - now = ktime_get(); -@@ -1061,6 +1065,7 @@ static void tick_broadcast_setup_oneshot(struct clock_event_device *bc, - - - bc->event_handler = tick_handle_oneshot_broadcast; -+ bc->next_event_forced = 0; - bc->next_event = KTIME_MAX; - - /* -@@ -1173,6 +1178,7 @@ void hotplug_cpu__broadcast_tick_pull(int deadcpu) - } - - /* This moves the broadcast assignment to this CPU: */ -+ bc->next_event_forced = 0; - clockevents_program_event(bc, bc->next_event, 1); - } - raw_spin_unlock_irqrestore(&tick_broadcast_lock, flags); -diff --git a/kernel/time/tick-common.c b/kernel/time/tick-common.c -index 9a3859443c042..4b5a42192afa2 100644 ---- a/kernel/time/tick-common.c -+++ b/kernel/time/tick-common.c -@@ -110,6 +110,7 @@ void tick_handle_periodic(struct clock_event_device *dev) - int cpu = smp_processor_id(); - ktime_t next = dev->next_event; - -+ dev->next_event_forced = 0; - tick_periodic(cpu); - - /* -diff --git a/kernel/time/tick-sched.c b/kernel/time/tick-sched.c -index f203f000da1ad..e385555b456e8 100644 ---- a/kernel/time/tick-sched.c -+++ b/kernel/time/tick-sched.c -@@ -1488,6 +1488,7 @@ static void tick_nohz_lowres_handler(struct clock_event_device *dev) - struct tick_sched *ts = this_cpu_ptr(&tick_cpu_sched); - - dev->next_event = KTIME_MAX; -+ dev->next_event_forced = 0; - - if (likely(tick_nohz_handler(&ts->sched_timer) == HRTIMER_RESTART)) - tick_program_event(hrtimer_get_expires(&ts->sched_timer), 1); --- -2.53.0 - diff --git a/queue-6.12/series b/queue-6.12/series index 1e66b0a779..6a061ed243 100644 --- a/queue-6.12/series +++ b/queue-6.12/series @@ -81,7 +81,6 @@ gpio-tegra-fix-irq_release_resources-calling-enable-.patch crypto-af_alg-limit-rx-sg-extraction-by-receive-buff.patch perf-x86-intel-uncore-skip-discovery-table-for-offli.patch sched-deadline-use-revised-wakeup-rule-for-dl_server.patch -clockevents-prevent-timer-interrupt-starvation.patch crypto-algif_aead-fix-minimum-rx-size-check-for-decr.patch netfilter-conntrack-add-missing-netlink-policy-valid.patch revert-drm-xe-mmio-avoid-double-adjust-in-64-bit-rea.patch diff --git a/queue-6.18/clockevents-prevent-timer-interrupt-starvation.patch b/queue-6.18/clockevents-prevent-timer-interrupt-starvation.patch deleted file mode 100644 index fb0798fd6d..0000000000 --- a/queue-6.18/clockevents-prevent-timer-interrupt-starvation.patch +++ /dev/null @@ -1,218 +0,0 @@ -From ff3638ff00c87218340038cfcb28b7446240b4bd Mon Sep 17 00:00:00 2001 -From: Sasha Levin -Date: Tue, 7 Apr 2026 10:54:17 +0200 -Subject: clockevents: Prevent timer interrupt starvation - -From: Thomas Gleixner - -[ Upstream commit d6e152d905bdb1f32f9d99775e2f453350399a6a ] - -Calvin reported an odd NMI watchdog lockup which claims that the CPU locked -up in user space. He provided a reproducer, which sets up a timerfd based -timer and then rearms it in a loop with an absolute expiry time of 1ns. - -As the expiry time is in the past, the timer ends up as the first expiring -timer in the per CPU hrtimer base and the clockevent device is programmed -with the minimum delta value. If the machine is fast enough, this ends up -in a endless loop of programming the delta value to the minimum value -defined by the clock event device, before the timer interrupt can fire, -which starves the interrupt and consequently triggers the lockup detector -because the hrtimer callback of the lockup mechanism is never invoked. - -As a first step to prevent this, avoid reprogramming the clock event device -when: - - a forced minimum delta event is pending - - the new expiry delta is less then or equal to the minimum delta - -Thanks to Calvin for providing the reproducer and to Borislav for testing -and providing data from his Zen5 machine. - -The problem is not limited to Zen5, but depending on the underlying -clock event device (e.g. TSC deadline timer on Intel) and the CPU speed -not necessarily observable. - -This change serves only as the last resort and further changes will be made -to prevent this scenario earlier in the call chain as far as possible. - -[ tglx: Updated to restore the old behaviour vs. !force and delta <= 0 and - fixed up the tick-broadcast handlers as pointed out by Borislav ] - -Fixes: d316c57ff6bf ("[PATCH] clockevents: add core functionality") -Reported-by: Calvin Owens -Signed-off-by: Thomas Gleixner -Tested-by: Calvin Owens -Tested-by: Borislav Petkov -Link: https://lore.kernel.org/lkml/acMe-QZUel-bBYUh@mozart.vkv.me/ -Link: https://patch.msgid.link/20260407083247.562657657@kernel.org -Signed-off-by: Sasha Levin ---- - include/linux/clockchips.h | 2 ++ - kernel/time/clockevents.c | 27 +++++++++++++++++++-------- - kernel/time/hrtimer.c | 1 + - kernel/time/tick-broadcast.c | 8 +++++++- - kernel/time/tick-common.c | 1 + - kernel/time/tick-sched.c | 1 + - 6 files changed, 31 insertions(+), 9 deletions(-) - -diff --git a/include/linux/clockchips.h b/include/linux/clockchips.h -index b0df28ddd394b..50cdc9da8d32a 100644 ---- a/include/linux/clockchips.h -+++ b/include/linux/clockchips.h -@@ -80,6 +80,7 @@ enum clock_event_state { - * @shift: nanoseconds to cycles divisor (power of two) - * @state_use_accessors:current state of the device, assigned by the core code - * @features: features -+ * @next_event_forced: True if the last programming was a forced event - * @retries: number of forced programming retries - * @set_state_periodic: switch state to periodic - * @set_state_oneshot: switch state to oneshot -@@ -108,6 +109,7 @@ struct clock_event_device { - u32 shift; - enum clock_event_state state_use_accessors; - unsigned int features; -+ unsigned int next_event_forced; - unsigned long retries; - - int (*set_state_periodic)(struct clock_event_device *); -diff --git a/kernel/time/clockevents.c b/kernel/time/clockevents.c -index a59bc75ab7c5b..e7b0163eeeb44 100644 ---- a/kernel/time/clockevents.c -+++ b/kernel/time/clockevents.c -@@ -172,6 +172,7 @@ void clockevents_shutdown(struct clock_event_device *dev) - { - clockevents_switch_state(dev, CLOCK_EVT_STATE_SHUTDOWN); - dev->next_event = KTIME_MAX; -+ dev->next_event_forced = 0; - } - - /** -@@ -305,7 +306,6 @@ int clockevents_program_event(struct clock_event_device *dev, ktime_t expires, - { - unsigned long long clc; - int64_t delta; -- int rc; - - if (WARN_ON_ONCE(expires < 0)) - return -ETIME; -@@ -324,16 +324,27 @@ int clockevents_program_event(struct clock_event_device *dev, ktime_t expires, - return dev->set_next_ktime(expires, dev); - - delta = ktime_to_ns(ktime_sub(expires, ktime_get())); -- if (delta <= 0) -- return force ? clockevents_program_min_delta(dev) : -ETIME; - -- delta = min(delta, (int64_t) dev->max_delta_ns); -- delta = max(delta, (int64_t) dev->min_delta_ns); -+ /* Required for tick_periodic() during early boot */ -+ if (delta <= 0 && !force) -+ return -ETIME; -+ -+ if (delta > (int64_t)dev->min_delta_ns) { -+ delta = min(delta, (int64_t) dev->max_delta_ns); -+ clc = ((unsigned long long) delta * dev->mult) >> dev->shift; -+ if (!dev->set_next_event((unsigned long) clc, dev)) -+ return 0; -+ } - -- clc = ((unsigned long long) delta * dev->mult) >> dev->shift; -- rc = dev->set_next_event((unsigned long) clc, dev); -+ if (dev->next_event_forced) -+ return 0; - -- return (rc && force) ? clockevents_program_min_delta(dev) : rc; -+ if (dev->set_next_event(dev->min_delta_ticks, dev)) { -+ if (!force || clockevents_program_min_delta(dev)) -+ return -ETIME; -+ } -+ dev->next_event_forced = 1; -+ return 0; - } - - /* -diff --git a/kernel/time/hrtimer.c b/kernel/time/hrtimer.c -index 21b6d93401480..fde64bfed98fe 100644 ---- a/kernel/time/hrtimer.c -+++ b/kernel/time/hrtimer.c -@@ -1880,6 +1880,7 @@ void hrtimer_interrupt(struct clock_event_device *dev) - BUG_ON(!cpu_base->hres_active); - cpu_base->nr_events++; - dev->next_event = KTIME_MAX; -+ dev->next_event_forced = 0; - - raw_spin_lock_irqsave(&cpu_base->lock, flags); - entry_time = now = hrtimer_update_base(cpu_base); -diff --git a/kernel/time/tick-broadcast.c b/kernel/time/tick-broadcast.c -index 0207868c8b4d2..e411a378db949 100644 ---- a/kernel/time/tick-broadcast.c -+++ b/kernel/time/tick-broadcast.c -@@ -76,8 +76,10 @@ const struct clock_event_device *tick_get_wakeup_device(int cpu) - */ - static void tick_broadcast_start_periodic(struct clock_event_device *bc) - { -- if (bc) -+ if (bc) { -+ bc->next_event_forced = 0; - tick_setup_periodic(bc, 1); -+ } - } - - /* -@@ -403,6 +405,7 @@ static void tick_handle_periodic_broadcast(struct clock_event_device *dev) - bool bc_local; - - raw_spin_lock(&tick_broadcast_lock); -+ tick_broadcast_device.evtdev->next_event_forced = 0; - - /* Handle spurious interrupts gracefully */ - if (clockevent_state_shutdown(tick_broadcast_device.evtdev)) { -@@ -696,6 +699,7 @@ static void tick_handle_oneshot_broadcast(struct clock_event_device *dev) - - raw_spin_lock(&tick_broadcast_lock); - dev->next_event = KTIME_MAX; -+ tick_broadcast_device.evtdev->next_event_forced = 0; - next_event = KTIME_MAX; - cpumask_clear(tmpmask); - now = ktime_get(); -@@ -1063,6 +1067,7 @@ static void tick_broadcast_setup_oneshot(struct clock_event_device *bc, - - - bc->event_handler = tick_handle_oneshot_broadcast; -+ bc->next_event_forced = 0; - bc->next_event = KTIME_MAX; - - /* -@@ -1175,6 +1180,7 @@ void hotplug_cpu__broadcast_tick_pull(int deadcpu) - } - - /* This moves the broadcast assignment to this CPU: */ -+ bc->next_event_forced = 0; - clockevents_program_event(bc, bc->next_event, 1); - } - raw_spin_unlock_irqrestore(&tick_broadcast_lock, flags); -diff --git a/kernel/time/tick-common.c b/kernel/time/tick-common.c -index 7e33d3f2e889b..b0c669a7745a7 100644 ---- a/kernel/time/tick-common.c -+++ b/kernel/time/tick-common.c -@@ -110,6 +110,7 @@ void tick_handle_periodic(struct clock_event_device *dev) - int cpu = smp_processor_id(); - ktime_t next = dev->next_event; - -+ dev->next_event_forced = 0; - tick_periodic(cpu); - - /* -diff --git a/kernel/time/tick-sched.c b/kernel/time/tick-sched.c -index 466e083c82721..36f27a8ae6c03 100644 ---- a/kernel/time/tick-sched.c -+++ b/kernel/time/tick-sched.c -@@ -1482,6 +1482,7 @@ static void tick_nohz_lowres_handler(struct clock_event_device *dev) - struct tick_sched *ts = this_cpu_ptr(&tick_cpu_sched); - - dev->next_event = KTIME_MAX; -+ dev->next_event_forced = 0; - - if (likely(tick_nohz_handler(&ts->sched_timer) == HRTIMER_RESTART)) - tick_program_event(hrtimer_get_expires(&ts->sched_timer), 1); --- -2.53.0 - diff --git a/queue-6.18/series b/queue-6.18/series index 6ed3079f42..8c501a4334 100644 --- a/queue-6.18/series +++ b/queue-6.18/series @@ -115,7 +115,6 @@ gpio-tegra-fix-irq_release_resources-calling-enable-.patch crypto-af_alg-limit-rx-sg-extraction-by-receive-buff.patch perf-x86-intel-uncore-skip-discovery-table-for-offli.patch sched-deadline-use-revised-wakeup-rule-for-dl_server.patch -clockevents-prevent-timer-interrupt-starvation.patch crypto-af_alg-fix-page-reassignment-overflow-in-af_a.patch crypto-algif_aead-fix-minimum-rx-size-check-for-decr.patch netfilter-conntrack-add-missing-netlink-policy-valid.patch diff --git a/queue-6.19/clockevents-prevent-timer-interrupt-starvation.patch b/queue-6.19/clockevents-prevent-timer-interrupt-starvation.patch deleted file mode 100644 index 27be2ec51a..0000000000 --- a/queue-6.19/clockevents-prevent-timer-interrupt-starvation.patch +++ /dev/null @@ -1,218 +0,0 @@ -From 8c7a391b93a21a2bbf1e6e8f6e685affdf59b886 Mon Sep 17 00:00:00 2001 -From: Sasha Levin -Date: Tue, 7 Apr 2026 10:54:17 +0200 -Subject: clockevents: Prevent timer interrupt starvation - -From: Thomas Gleixner - -[ Upstream commit d6e152d905bdb1f32f9d99775e2f453350399a6a ] - -Calvin reported an odd NMI watchdog lockup which claims that the CPU locked -up in user space. He provided a reproducer, which sets up a timerfd based -timer and then rearms it in a loop with an absolute expiry time of 1ns. - -As the expiry time is in the past, the timer ends up as the first expiring -timer in the per CPU hrtimer base and the clockevent device is programmed -with the minimum delta value. If the machine is fast enough, this ends up -in a endless loop of programming the delta value to the minimum value -defined by the clock event device, before the timer interrupt can fire, -which starves the interrupt and consequently triggers the lockup detector -because the hrtimer callback of the lockup mechanism is never invoked. - -As a first step to prevent this, avoid reprogramming the clock event device -when: - - a forced minimum delta event is pending - - the new expiry delta is less then or equal to the minimum delta - -Thanks to Calvin for providing the reproducer and to Borislav for testing -and providing data from his Zen5 machine. - -The problem is not limited to Zen5, but depending on the underlying -clock event device (e.g. TSC deadline timer on Intel) and the CPU speed -not necessarily observable. - -This change serves only as the last resort and further changes will be made -to prevent this scenario earlier in the call chain as far as possible. - -[ tglx: Updated to restore the old behaviour vs. !force and delta <= 0 and - fixed up the tick-broadcast handlers as pointed out by Borislav ] - -Fixes: d316c57ff6bf ("[PATCH] clockevents: add core functionality") -Reported-by: Calvin Owens -Signed-off-by: Thomas Gleixner -Tested-by: Calvin Owens -Tested-by: Borislav Petkov -Link: https://lore.kernel.org/lkml/acMe-QZUel-bBYUh@mozart.vkv.me/ -Link: https://patch.msgid.link/20260407083247.562657657@kernel.org -Signed-off-by: Sasha Levin ---- - include/linux/clockchips.h | 2 ++ - kernel/time/clockevents.c | 27 +++++++++++++++++++-------- - kernel/time/hrtimer.c | 1 + - kernel/time/tick-broadcast.c | 8 +++++++- - kernel/time/tick-common.c | 1 + - kernel/time/tick-sched.c | 1 + - 6 files changed, 31 insertions(+), 9 deletions(-) - -diff --git a/include/linux/clockchips.h b/include/linux/clockchips.h -index b0df28ddd394b..50cdc9da8d32a 100644 ---- a/include/linux/clockchips.h -+++ b/include/linux/clockchips.h -@@ -80,6 +80,7 @@ enum clock_event_state { - * @shift: nanoseconds to cycles divisor (power of two) - * @state_use_accessors:current state of the device, assigned by the core code - * @features: features -+ * @next_event_forced: True if the last programming was a forced event - * @retries: number of forced programming retries - * @set_state_periodic: switch state to periodic - * @set_state_oneshot: switch state to oneshot -@@ -108,6 +109,7 @@ struct clock_event_device { - u32 shift; - enum clock_event_state state_use_accessors; - unsigned int features; -+ unsigned int next_event_forced; - unsigned long retries; - - int (*set_state_periodic)(struct clock_event_device *); -diff --git a/kernel/time/clockevents.c b/kernel/time/clockevents.c -index eaae1ce9f0600..38570998a19b8 100644 ---- a/kernel/time/clockevents.c -+++ b/kernel/time/clockevents.c -@@ -172,6 +172,7 @@ void clockevents_shutdown(struct clock_event_device *dev) - { - clockevents_switch_state(dev, CLOCK_EVT_STATE_SHUTDOWN); - dev->next_event = KTIME_MAX; -+ dev->next_event_forced = 0; - } - - /** -@@ -305,7 +306,6 @@ int clockevents_program_event(struct clock_event_device *dev, ktime_t expires, - { - unsigned long long clc; - int64_t delta; -- int rc; - - if (WARN_ON_ONCE(expires < 0)) - return -ETIME; -@@ -324,16 +324,27 @@ int clockevents_program_event(struct clock_event_device *dev, ktime_t expires, - return dev->set_next_ktime(expires, dev); - - delta = ktime_to_ns(ktime_sub(expires, ktime_get())); -- if (delta <= 0) -- return force ? clockevents_program_min_delta(dev) : -ETIME; - -- delta = min(delta, (int64_t) dev->max_delta_ns); -- delta = max(delta, (int64_t) dev->min_delta_ns); -+ /* Required for tick_periodic() during early boot */ -+ if (delta <= 0 && !force) -+ return -ETIME; -+ -+ if (delta > (int64_t)dev->min_delta_ns) { -+ delta = min(delta, (int64_t) dev->max_delta_ns); -+ clc = ((unsigned long long) delta * dev->mult) >> dev->shift; -+ if (!dev->set_next_event((unsigned long) clc, dev)) -+ return 0; -+ } - -- clc = ((unsigned long long) delta * dev->mult) >> dev->shift; -- rc = dev->set_next_event((unsigned long) clc, dev); -+ if (dev->next_event_forced) -+ return 0; - -- return (rc && force) ? clockevents_program_min_delta(dev) : rc; -+ if (dev->set_next_event(dev->min_delta_ticks, dev)) { -+ if (!force || clockevents_program_min_delta(dev)) -+ return -ETIME; -+ } -+ dev->next_event_forced = 1; -+ return 0; - } - - /* -diff --git a/kernel/time/hrtimer.c b/kernel/time/hrtimer.c -index 84c8ab2a0cebf..141b2beac63a4 100644 ---- a/kernel/time/hrtimer.c -+++ b/kernel/time/hrtimer.c -@@ -1880,6 +1880,7 @@ void hrtimer_interrupt(struct clock_event_device *dev) - BUG_ON(!cpu_base->hres_active); - cpu_base->nr_events++; - dev->next_event = KTIME_MAX; -+ dev->next_event_forced = 0; - - raw_spin_lock_irqsave(&cpu_base->lock, flags); - entry_time = now = hrtimer_update_base(cpu_base); -diff --git a/kernel/time/tick-broadcast.c b/kernel/time/tick-broadcast.c -index f63c65881364d..7e57fa31ee26f 100644 ---- a/kernel/time/tick-broadcast.c -+++ b/kernel/time/tick-broadcast.c -@@ -76,8 +76,10 @@ const struct clock_event_device *tick_get_wakeup_device(int cpu) - */ - static void tick_broadcast_start_periodic(struct clock_event_device *bc) - { -- if (bc) -+ if (bc) { -+ bc->next_event_forced = 0; - tick_setup_periodic(bc, 1); -+ } - } - - /* -@@ -403,6 +405,7 @@ static void tick_handle_periodic_broadcast(struct clock_event_device *dev) - bool bc_local; - - raw_spin_lock(&tick_broadcast_lock); -+ tick_broadcast_device.evtdev->next_event_forced = 0; - - /* Handle spurious interrupts gracefully */ - if (clockevent_state_shutdown(tick_broadcast_device.evtdev)) { -@@ -696,6 +699,7 @@ static void tick_handle_oneshot_broadcast(struct clock_event_device *dev) - - raw_spin_lock(&tick_broadcast_lock); - dev->next_event = KTIME_MAX; -+ tick_broadcast_device.evtdev->next_event_forced = 0; - next_event = KTIME_MAX; - cpumask_clear(tmpmask); - now = ktime_get(); -@@ -1063,6 +1067,7 @@ static void tick_broadcast_setup_oneshot(struct clock_event_device *bc, - - - bc->event_handler = tick_handle_oneshot_broadcast; -+ bc->next_event_forced = 0; - bc->next_event = KTIME_MAX; - - /* -@@ -1175,6 +1180,7 @@ void hotplug_cpu__broadcast_tick_pull(int deadcpu) - } - - /* This moves the broadcast assignment to this CPU: */ -+ bc->next_event_forced = 0; - clockevents_program_event(bc, bc->next_event, 1); - } - raw_spin_unlock_irqrestore(&tick_broadcast_lock, flags); -diff --git a/kernel/time/tick-common.c b/kernel/time/tick-common.c -index d305d85218961..6a9198a4279b5 100644 ---- a/kernel/time/tick-common.c -+++ b/kernel/time/tick-common.c -@@ -110,6 +110,7 @@ void tick_handle_periodic(struct clock_event_device *dev) - int cpu = smp_processor_id(); - ktime_t next = dev->next_event; - -+ dev->next_event_forced = 0; - tick_periodic(cpu); - - /* -diff --git a/kernel/time/tick-sched.c b/kernel/time/tick-sched.c -index 2f8a7923fa279..6e2f239a4813f 100644 ---- a/kernel/time/tick-sched.c -+++ b/kernel/time/tick-sched.c -@@ -1504,6 +1504,7 @@ static void tick_nohz_lowres_handler(struct clock_event_device *dev) - struct tick_sched *ts = this_cpu_ptr(&tick_cpu_sched); - - dev->next_event = KTIME_MAX; -+ dev->next_event_forced = 0; - - if (likely(tick_nohz_handler(&ts->sched_timer) == HRTIMER_RESTART)) - tick_program_event(hrtimer_get_expires(&ts->sched_timer), 1); --- -2.53.0 - diff --git a/queue-6.19/series b/queue-6.19/series index aeb59a6742..5c0a552971 100644 --- a/queue-6.19/series +++ b/queue-6.19/series @@ -134,7 +134,6 @@ crypto-af_alg-limit-rx-sg-extraction-by-receive-buff.patch perf-x86-intel-uncore-skip-discovery-table-for-offli.patch perf-x86-intel-uncore-fix-die-id-init-and-look-up-bu.patch sched-deadline-use-revised-wakeup-rule-for-dl_server.patch -clockevents-prevent-timer-interrupt-starvation.patch crypto-af_alg-fix-page-reassignment-overflow-in-af_a.patch crypto-algif_aead-fix-minimum-rx-size-check-for-decr.patch nfc-llcp-add-missing-return-after-llcp_closed-checks.patch diff --git a/queue-6.6/clockevents-prevent-timer-interrupt-starvation.patch b/queue-6.6/clockevents-prevent-timer-interrupt-starvation.patch deleted file mode 100644 index af4259eaab..0000000000 --- a/queue-6.6/clockevents-prevent-timer-interrupt-starvation.patch +++ /dev/null @@ -1,218 +0,0 @@ -From 051fea00173d929d0ed32c7ffa323fbe431d8242 Mon Sep 17 00:00:00 2001 -From: Sasha Levin -Date: Tue, 7 Apr 2026 10:54:17 +0200 -Subject: clockevents: Prevent timer interrupt starvation - -From: Thomas Gleixner - -[ Upstream commit d6e152d905bdb1f32f9d99775e2f453350399a6a ] - -Calvin reported an odd NMI watchdog lockup which claims that the CPU locked -up in user space. He provided a reproducer, which sets up a timerfd based -timer and then rearms it in a loop with an absolute expiry time of 1ns. - -As the expiry time is in the past, the timer ends up as the first expiring -timer in the per CPU hrtimer base and the clockevent device is programmed -with the minimum delta value. If the machine is fast enough, this ends up -in a endless loop of programming the delta value to the minimum value -defined by the clock event device, before the timer interrupt can fire, -which starves the interrupt and consequently triggers the lockup detector -because the hrtimer callback of the lockup mechanism is never invoked. - -As a first step to prevent this, avoid reprogramming the clock event device -when: - - a forced minimum delta event is pending - - the new expiry delta is less then or equal to the minimum delta - -Thanks to Calvin for providing the reproducer and to Borislav for testing -and providing data from his Zen5 machine. - -The problem is not limited to Zen5, but depending on the underlying -clock event device (e.g. TSC deadline timer on Intel) and the CPU speed -not necessarily observable. - -This change serves only as the last resort and further changes will be made -to prevent this scenario earlier in the call chain as far as possible. - -[ tglx: Updated to restore the old behaviour vs. !force and delta <= 0 and - fixed up the tick-broadcast handlers as pointed out by Borislav ] - -Fixes: d316c57ff6bf ("[PATCH] clockevents: add core functionality") -Reported-by: Calvin Owens -Signed-off-by: Thomas Gleixner -Tested-by: Calvin Owens -Tested-by: Borislav Petkov -Link: https://lore.kernel.org/lkml/acMe-QZUel-bBYUh@mozart.vkv.me/ -Link: https://patch.msgid.link/20260407083247.562657657@kernel.org -Signed-off-by: Sasha Levin ---- - include/linux/clockchips.h | 2 ++ - kernel/time/clockevents.c | 27 +++++++++++++++++++-------- - kernel/time/hrtimer.c | 1 + - kernel/time/tick-broadcast.c | 8 +++++++- - kernel/time/tick-common.c | 1 + - kernel/time/tick-sched.c | 1 + - 6 files changed, 31 insertions(+), 9 deletions(-) - -diff --git a/include/linux/clockchips.h b/include/linux/clockchips.h -index 9aac31d856f39..c0d767b8f4bd5 100644 ---- a/include/linux/clockchips.h -+++ b/include/linux/clockchips.h -@@ -80,6 +80,7 @@ enum clock_event_state { - * @shift: nanoseconds to cycles divisor (power of two) - * @state_use_accessors:current state of the device, assigned by the core code - * @features: features -+ * @next_event_forced: True if the last programming was a forced event - * @retries: number of forced programming retries - * @set_state_periodic: switch state to periodic - * @set_state_oneshot: switch state to oneshot -@@ -108,6 +109,7 @@ struct clock_event_device { - u32 shift; - enum clock_event_state state_use_accessors; - unsigned int features; -+ unsigned int next_event_forced; - unsigned long retries; - - int (*set_state_periodic)(struct clock_event_device *); -diff --git a/kernel/time/clockevents.c b/kernel/time/clockevents.c -index 960143b183cdb..0869b3902605e 100644 ---- a/kernel/time/clockevents.c -+++ b/kernel/time/clockevents.c -@@ -172,6 +172,7 @@ void clockevents_shutdown(struct clock_event_device *dev) - { - clockevents_switch_state(dev, CLOCK_EVT_STATE_SHUTDOWN); - dev->next_event = KTIME_MAX; -+ dev->next_event_forced = 0; - } - - /** -@@ -305,7 +306,6 @@ int clockevents_program_event(struct clock_event_device *dev, ktime_t expires, - { - unsigned long long clc; - int64_t delta; -- int rc; - - if (WARN_ON_ONCE(expires < 0)) - return -ETIME; -@@ -324,16 +324,27 @@ int clockevents_program_event(struct clock_event_device *dev, ktime_t expires, - return dev->set_next_ktime(expires, dev); - - delta = ktime_to_ns(ktime_sub(expires, ktime_get())); -- if (delta <= 0) -- return force ? clockevents_program_min_delta(dev) : -ETIME; - -- delta = min(delta, (int64_t) dev->max_delta_ns); -- delta = max(delta, (int64_t) dev->min_delta_ns); -+ /* Required for tick_periodic() during early boot */ -+ if (delta <= 0 && !force) -+ return -ETIME; -+ -+ if (delta > (int64_t)dev->min_delta_ns) { -+ delta = min(delta, (int64_t) dev->max_delta_ns); -+ clc = ((unsigned long long) delta * dev->mult) >> dev->shift; -+ if (!dev->set_next_event((unsigned long) clc, dev)) -+ return 0; -+ } - -- clc = ((unsigned long long) delta * dev->mult) >> dev->shift; -- rc = dev->set_next_event((unsigned long) clc, dev); -+ if (dev->next_event_forced) -+ return 0; - -- return (rc && force) ? clockevents_program_min_delta(dev) : rc; -+ if (dev->set_next_event(dev->min_delta_ticks, dev)) { -+ if (!force || clockevents_program_min_delta(dev)) -+ return -ETIME; -+ } -+ dev->next_event_forced = 1; -+ return 0; - } - - /* -diff --git a/kernel/time/hrtimer.c b/kernel/time/hrtimer.c -index 03f488f93cddf..9a8a2d36b9db6 100644 ---- a/kernel/time/hrtimer.c -+++ b/kernel/time/hrtimer.c -@@ -1853,6 +1853,7 @@ void hrtimer_interrupt(struct clock_event_device *dev) - BUG_ON(!cpu_base->hres_active); - cpu_base->nr_events++; - dev->next_event = KTIME_MAX; -+ dev->next_event_forced = 0; - - raw_spin_lock_irqsave(&cpu_base->lock, flags); - entry_time = now = hrtimer_update_base(cpu_base); -diff --git a/kernel/time/tick-broadcast.c b/kernel/time/tick-broadcast.c -index ed58eebb4e8f4..99d2978ef9b98 100644 ---- a/kernel/time/tick-broadcast.c -+++ b/kernel/time/tick-broadcast.c -@@ -76,8 +76,10 @@ const struct clock_event_device *tick_get_wakeup_device(int cpu) - */ - static void tick_broadcast_start_periodic(struct clock_event_device *bc) - { -- if (bc) -+ if (bc) { -+ bc->next_event_forced = 0; - tick_setup_periodic(bc, 1); -+ } - } - - /* -@@ -403,6 +405,7 @@ static void tick_handle_periodic_broadcast(struct clock_event_device *dev) - bool bc_local; - - raw_spin_lock(&tick_broadcast_lock); -+ tick_broadcast_device.evtdev->next_event_forced = 0; - - /* Handle spurious interrupts gracefully */ - if (clockevent_state_shutdown(tick_broadcast_device.evtdev)) { -@@ -696,6 +699,7 @@ static void tick_handle_oneshot_broadcast(struct clock_event_device *dev) - - raw_spin_lock(&tick_broadcast_lock); - dev->next_event = KTIME_MAX; -+ tick_broadcast_device.evtdev->next_event_forced = 0; - next_event = KTIME_MAX; - cpumask_clear(tmpmask); - now = ktime_get(); -@@ -1061,6 +1065,7 @@ static void tick_broadcast_setup_oneshot(struct clock_event_device *bc, - - - bc->event_handler = tick_handle_oneshot_broadcast; -+ bc->next_event_forced = 0; - bc->next_event = KTIME_MAX; - - /* -@@ -1173,6 +1178,7 @@ void hotplug_cpu__broadcast_tick_pull(int deadcpu) - } - - /* This moves the broadcast assignment to this CPU: */ -+ bc->next_event_forced = 0; - clockevents_program_event(bc, bc->next_event, 1); - } - raw_spin_unlock_irqrestore(&tick_broadcast_lock, flags); -diff --git a/kernel/time/tick-common.c b/kernel/time/tick-common.c -index ecdb8c2b2cab2..d5c9af9c6c333 100644 ---- a/kernel/time/tick-common.c -+++ b/kernel/time/tick-common.c -@@ -109,6 +109,7 @@ void tick_handle_periodic(struct clock_event_device *dev) - int cpu = smp_processor_id(); - ktime_t next = dev->next_event; - -+ dev->next_event_forced = 0; - tick_periodic(cpu); - - #if defined(CONFIG_HIGH_RES_TIMERS) || defined(CONFIG_NO_HZ_COMMON) -diff --git a/kernel/time/tick-sched.c b/kernel/time/tick-sched.c -index 55cbc49f70d14..bf3ff0dbf2a28 100644 ---- a/kernel/time/tick-sched.c -+++ b/kernel/time/tick-sched.c -@@ -1373,6 +1373,7 @@ static void tick_nohz_handler(struct clock_event_device *dev) - ktime_t now = ktime_get(); - - dev->next_event = KTIME_MAX; -+ dev->next_event_forced = 0; - - tick_sched_do_timer(ts, now); - tick_sched_handle(ts, regs); --- -2.53.0 - diff --git a/queue-6.6/series b/queue-6.6/series index 8849bdd7c8..f87ce12f70 100644 --- a/queue-6.6/series +++ b/queue-6.6/series @@ -60,7 +60,6 @@ net-ipa-fix-event-ring-index-not-programmed-for-ipa-.patch l2tp-drop-large-packets-with-udp-encap.patch gpio-tegra-fix-irq_release_resources-calling-enable-.patch perf-x86-intel-uncore-skip-discovery-table-for-offli.patch -clockevents-prevent-timer-interrupt-starvation.patch crypto-algif_aead-fix-minimum-rx-size-check-for-decr.patch netfilter-conntrack-add-missing-netlink-policy-valid.patch alsa-usb-audio-improve-focusrite-sample-rate-filteri.patch -- 2.47.3