]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
drop clockevents-prevent-timer-interrupt-starvation.patch master
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 20 Apr 2026 18:44:48 +0000 (20:44 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 20 Apr 2026 18:44:48 +0000 (20:44 +0200)
12 files changed:
queue-5.15/clockevents-prevent-timer-interrupt-starvation.patch [deleted file]
queue-5.15/series
queue-6.1/clockevents-prevent-timer-interrupt-starvation.patch [deleted file]
queue-6.1/series
queue-6.12/clockevents-prevent-timer-interrupt-starvation.patch [deleted file]
queue-6.12/series
queue-6.18/clockevents-prevent-timer-interrupt-starvation.patch [deleted file]
queue-6.18/series
queue-6.19/clockevents-prevent-timer-interrupt-starvation.patch [deleted file]
queue-6.19/series
queue-6.6/clockevents-prevent-timer-interrupt-starvation.patch [deleted file]
queue-6.6/series

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 (file)
index 01ffd7f..0000000
+++ /dev/null
@@ -1,218 +0,0 @@
-From 4b95adf98f5c5c0219c6eba726aa9626cdb3a351 Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Tue, 7 Apr 2026 10:54:17 +0200
-Subject: clockevents: Prevent timer interrupt starvation
-
-From: Thomas Gleixner <tglx@kernel.org>
-
-[ 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 <calvin@wbinvd.org>
-Signed-off-by: Thomas Gleixner <tglx@kernel.org>
-Tested-by: Calvin Owens <calvin@wbinvd.org>
-Tested-by: Borislav Petkov <bp@alien8.de>
-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 <sashal@kernel.org>
----
- 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
-
index 92548a4c824847206e2544e762047b977390e5da..f3c877b1dac7378c8d7cd048172191f6da07b534 100644 (file)
@@ -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 (file)
index add1136..0000000
+++ /dev/null
@@ -1,218 +0,0 @@
-From a53e2c11e05c64e57807aea194c2c4819d1369dd Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Tue, 7 Apr 2026 10:54:17 +0200
-Subject: clockevents: Prevent timer interrupt starvation
-
-From: Thomas Gleixner <tglx@kernel.org>
-
-[ 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 <calvin@wbinvd.org>
-Signed-off-by: Thomas Gleixner <tglx@kernel.org>
-Tested-by: Calvin Owens <calvin@wbinvd.org>
-Tested-by: Borislav Petkov <bp@alien8.de>
-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 <sashal@kernel.org>
----
- 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
-
index c3547790b140b814ad0274f66470f3ffb3d5aefb..a6bfb839deb7cb4a5377fcbbc934ea775d56475c 100644 (file)
@@ -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 (file)
index 1430415..0000000
+++ /dev/null
@@ -1,218 +0,0 @@
-From f0aa641eb7fe25dd725ef6835dde2dd178fc55e8 Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Tue, 7 Apr 2026 10:54:17 +0200
-Subject: clockevents: Prevent timer interrupt starvation
-
-From: Thomas Gleixner <tglx@kernel.org>
-
-[ 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 <calvin@wbinvd.org>
-Signed-off-by: Thomas Gleixner <tglx@kernel.org>
-Tested-by: Calvin Owens <calvin@wbinvd.org>
-Tested-by: Borislav Petkov <bp@alien8.de>
-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 <sashal@kernel.org>
----
- 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
-
index 1e66b0a779620dfa74cd92f5bc602cc003983966..6a061ed24320ed44dd33ceed56e0ce5e7b3af284 100644 (file)
@@ -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 (file)
index fb0798f..0000000
+++ /dev/null
@@ -1,218 +0,0 @@
-From ff3638ff00c87218340038cfcb28b7446240b4bd Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Tue, 7 Apr 2026 10:54:17 +0200
-Subject: clockevents: Prevent timer interrupt starvation
-
-From: Thomas Gleixner <tglx@kernel.org>
-
-[ 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 <calvin@wbinvd.org>
-Signed-off-by: Thomas Gleixner <tglx@kernel.org>
-Tested-by: Calvin Owens <calvin@wbinvd.org>
-Tested-by: Borislav Petkov <bp@alien8.de>
-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 <sashal@kernel.org>
----
- 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
-
index 6ed3079f421d230663683a79a3b69f77392a8c71..8c501a4334901f89ac837e10e4aeec405a26a356 100644 (file)
@@ -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 (file)
index 27be2ec..0000000
+++ /dev/null
@@ -1,218 +0,0 @@
-From 8c7a391b93a21a2bbf1e6e8f6e685affdf59b886 Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Tue, 7 Apr 2026 10:54:17 +0200
-Subject: clockevents: Prevent timer interrupt starvation
-
-From: Thomas Gleixner <tglx@kernel.org>
-
-[ 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 <calvin@wbinvd.org>
-Signed-off-by: Thomas Gleixner <tglx@kernel.org>
-Tested-by: Calvin Owens <calvin@wbinvd.org>
-Tested-by: Borislav Petkov <bp@alien8.de>
-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 <sashal@kernel.org>
----
- 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
-
index aeb59a6742fd3935b12354529ac63f85ef8af6d0..5c0a552971788bed7c39943d5ae201b777632c54 100644 (file)
@@ -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 (file)
index af4259e..0000000
+++ /dev/null
@@ -1,218 +0,0 @@
-From 051fea00173d929d0ed32c7ffa323fbe431d8242 Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Tue, 7 Apr 2026 10:54:17 +0200
-Subject: clockevents: Prevent timer interrupt starvation
-
-From: Thomas Gleixner <tglx@kernel.org>
-
-[ 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 <calvin@wbinvd.org>
-Signed-off-by: Thomas Gleixner <tglx@kernel.org>
-Tested-by: Calvin Owens <calvin@wbinvd.org>
-Tested-by: Borislav Petkov <bp@alien8.de>
-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 <sashal@kernel.org>
----
- 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
-
index 8849bdd7c857f8b15a945ee1df17f529d148e5a6..f87ce12f70e15700cb3558a86d043c150b9e039b 100644 (file)
@@ -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