{"id":2220421,"url":"http://patchwork.ozlabs.org/api/1.1/patches/2220421/?format=json","web_url":"http://patchwork.ozlabs.org/project/netfilter-devel/patch/20260407083247.562657657@kernel.org/","project":{"id":26,"url":"http://patchwork.ozlabs.org/api/1.1/projects/26/?format=json","name":"Netfilter Development","link_name":"netfilter-devel","list_id":"netfilter-devel.vger.kernel.org","list_email":"netfilter-devel@vger.kernel.org","web_url":null,"scm_url":null,"webscm_url":null},"msgid":"<20260407083247.562657657@kernel.org>","date":"2026-04-07T08:54:17","name":"[01/12] clockevents: Prevent timer interrupt starvation","commit_ref":null,"pull_url":null,"state":"accepted","archived":true,"hash":"cb134c3438da00e9a5dd7accf3aab2353d2fd8e5","submitter":{"id":92397,"url":"http://patchwork.ozlabs.org/api/1.1/people/92397/?format=json","name":"Thomas Gleixner","email":"tglx@kernel.org"},"delegate":null,"mbox":"http://patchwork.ozlabs.org/project/netfilter-devel/patch/20260407083247.562657657@kernel.org/mbox/","series":[{"id":498944,"url":"http://patchwork.ozlabs.org/api/1.1/series/498944/?format=json","web_url":"http://patchwork.ozlabs.org/project/netfilter-devel/list/?series=498944","date":"2026-04-07T08:54:12","name":"hrtimers: Prevent hrtimer interrupt starvation","version":1,"mbox":"http://patchwork.ozlabs.org/series/498944/mbox/"}],"comments":"http://patchwork.ozlabs.org/api/patches/2220421/comments/","check":"pending","checks":"http://patchwork.ozlabs.org/api/patches/2220421/checks/","tags":{},"headers":{"Return-Path":"\n <netfilter-devel+bounces-11643-incoming=patchwork.ozlabs.org@vger.kernel.org>","X-Original-To":["incoming@patchwork.ozlabs.org","netfilter-devel@vger.kernel.org"],"Delivered-To":"patchwork-incoming@legolas.ozlabs.org","Authentication-Results":["legolas.ozlabs.org;\n\tdkim=pass (2048-bit key;\n unprotected) header.d=kernel.org header.i=@kernel.org header.a=rsa-sha256\n header.s=k20201202 header.b=eexOg75U;\n\tdkim-atps=neutral","legolas.ozlabs.org;\n spf=pass (sender SPF authorized) smtp.mailfrom=vger.kernel.org\n (client-ip=2600:3c0a:e001:db::12fc:5321; helo=sea.lore.kernel.org;\n envelope-from=netfilter-devel+bounces-11643-incoming=patchwork.ozlabs.org@vger.kernel.org;\n receiver=patchwork.ozlabs.org)","smtp.subspace.kernel.org;\n\tdkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org\n header.b=\"eexOg75U\"","smtp.subspace.kernel.org;\n arc=none smtp.client-ip=10.30.226.201"],"Received":["from sea.lore.kernel.org (sea.lore.kernel.org\n [IPv6:2600:3c0a:e001:db::12fc:5321])\n\t(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)\n\t key-exchange x25519)\n\t(No client certificate requested)\n\tby legolas.ozlabs.org (Postfix) with ESMTPS id 4fqg4y52zGz1xtJ\n\tfor <incoming@patchwork.ozlabs.org>; Tue, 07 Apr 2026 18:55:14 +1000 (AEST)","from smtp.subspace.kernel.org (conduit.subspace.kernel.org\n [100.90.174.1])\n\tby sea.lore.kernel.org (Postfix) with ESMTP id EFEEE300BDB5\n\tfor <incoming@patchwork.ozlabs.org>; Tue,  7 Apr 2026 08:54:22 +0000 (UTC)","from localhost.localdomain (localhost.localdomain [127.0.0.1])\n\tby smtp.subspace.kernel.org (Postfix) with ESMTP id B0DD739B49D;\n\tTue,  7 Apr 2026 08:54:21 +0000 (UTC)","from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org\n [10.30.226.201])\n\t(using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits))\n\t(No client certificate requested)\n\tby smtp.subspace.kernel.org (Postfix) with ESMTPS id 3B7B338C2B5;\n\tTue,  7 Apr 2026 08:54:21 +0000 (UTC)","by smtp.kernel.org (Postfix) with ESMTPSA id 58966C116C6;\n\tTue,  7 Apr 2026 08:54:20 +0000 (UTC)"],"ARC-Seal":"i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116;\n\tt=1775552061; cv=none;\n b=YWvNSgnfzumMH6xF/ShiFugPmXW0xjML4ng8l/EilGXY5LlISWgzIIPYLxQkBerCLPT3XYrYN/ySFMeJ7mV6fxG6Ven8ISk1HkLo8pDj0yJ1fL4GNnEUk28wPdbI1jC5hO+r6T8Po6PFle6fvMi35dAz3uM0evJyul/HXSvdo7Q=","ARC-Message-Signature":"i=1; a=rsa-sha256; d=subspace.kernel.org;\n\ts=arc-20240116; t=1775552061; c=relaxed/simple;\n\tbh=/xYs3O0kL0sYfj4X83LKJJkUOaxeLjU6FZ9MnfIN9Dc=;\n\th=Date:Message-ID:From:To:Cc:Subject:References:MIME-Version:\n\t Content-Type;\n b=Jxh4wDHm3/s2DkWqy7oSJrSXMzeUtVvPvarNLuE+s5WwwgLEN6X2ZDOl+V8Lbg7zGJQ0IKhaBuR/ZsN3WIVIxKr2pt6vtEQzTSV8bbqI5ATe72JK8vnzwBd333VgC06XJPsafFJ+OgT03e7S3GXJ9qUuh46EwFyJHRn25Ine1SM=","ARC-Authentication-Results":"i=1; smtp.subspace.kernel.org;\n dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org\n header.b=eexOg75U; arc=none smtp.client-ip=10.30.226.201","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org;\n\ts=k20201202; t=1775552060;\n\tbh=/xYs3O0kL0sYfj4X83LKJJkUOaxeLjU6FZ9MnfIN9Dc=;\n\th=Date:From:To:Cc:Subject:References:From;\n\tb=eexOg75UKzbZNb3GzltnQtK9klmrNpQkDWWUEByY54h7u0xNb/ev5e5LtUKXPRgfB\n\t Me1olXlOEEahjOtRCXiK9JcGOnEx/asFDIl5YcflKbJ5dGWGtNCpAK4wPI25vjnv1W\n\t eftegC0fHHElzJcLwlnFbGwyHkG0u7yipY5s64/tCMGtnBbyaL+e7V120l/Sxld9x8\n\t z4GeZCc8f4llZv7kDVmCqk7hmzK+XxZ4UNcw88vStrFc2HCtyyR/3+rsOvNH7yXy3K\n\t i1345GBKs2uaUWn3DdImYl8CnvsoAaWmMOfxbVZyV9nPwXsouXnh0TRak+Us4k5D/M\n\t acST9SMUSQU+Q==","Date":"Tue, 07 Apr 2026 10:54:17 +0200","Message-ID":"<20260407083247.562657657@kernel.org>","User-Agent":"quilt/0.68","From":"Thomas Gleixner <tglx@kernel.org>","To":"LKML <linux-kernel@vger.kernel.org>","Cc":"Calvin Owens <calvin@wbinvd.org>,\n Peter Zijlstra <peterz@infradead.org>,\n Anna-Maria Behnsen <anna-maria@linutronix.de>,\n Frederic Weisbecker <frederic@kernel.org>,\n Ingo Molnar <mingo@kernel.org>,\n John Stultz <jstultz@google.com>,\n Stephen Boyd <sboyd@kernel.org>,\n Alexander Viro <viro@zeniv.linux.org.uk>,\n Christian Brauner <brauner@kernel.org>,\n Jan Kara <jack@suse.cz>,\n linux-fsdevel@vger.kernel.org,\n Sebastian Reichel <sre@kernel.org>,\n linux-pm@vger.kernel.org,\n Pablo Neira Ayuso <pablo@netfilter.org>,\n Florian Westphal <fw@strlen.de>,\n Phil Sutter <phil@nwl.cc>,\n netfilter-devel@vger.kernel.org,\n coreteam@netfilter.org","Subject":"[patch 01/12] clockevents: Prevent timer interrupt starvation","References":"<20260407083219.478203185@kernel.org>","Precedence":"bulk","X-Mailing-List":"netfilter-devel@vger.kernel.org","List-Id":"<netfilter-devel.vger.kernel.org>","List-Subscribe":"<mailto:netfilter-devel+subscribe@vger.kernel.org>","List-Unsubscribe":"<mailto:netfilter-devel+unsubscribe@vger.kernel.org>","MIME-Version":"1.0","Content-Type":"text/plain; charset=UTF-8"},"content":"From: Thomas Gleixner <tglx@kernel.org>\n\nCalvin reported an odd NMI watchdog lockup which claims that the CPU locked\nup in user space. He provided a reproducer, which sets up a timerfd based\ntimer and then rearms it in a loop with an absolute expiry time of 1ns.\n\nAs the expiry time is in the past, the timer ends up as the first expiring\ntimer in the per CPU hrtimer base and the clockevent device is programmed\nwith the minimum delta value. If the machine is fast enough, this ends up\nin a endless loop of programming the delta value to the minimum value\ndefined by the clock event device, before the timer interrupt can fire,\nwhich starves the interrupt and consequently triggers the lockup detector\nbecause the hrtimer callback of the lockup mechanism is never invoked.\n\nAs a first step to prevent this, avoid reprogramming the clock event device\nwhen:\n     - a forced minimum delta event is pending\n     - the new expiry delta is less then or equal to the minimum delta\n\nThanks to Calvin for providing the reproducer and to Borislav for testing\nand providing data from his Zen5 machine.\n\nThe problem is not limited to Zen5, but depending on the underlying\nclock event device (e.g. TSC deadline timer on Intel) and the CPU speed\nnot necessarily observable.\n\nThis change serves only as the last resort and further changes will be made\nto prevent this scenario earlier in the call chain as far as possible.\n\nFixes: d316c57ff6bf (\"[PATCH] clockevents: add core functionality\")\nReported-by: Calvin Owens <calvin@wbinvd.org>\nSigned-off-by: Thomas Gleixner <tglx@kernel.org>\nCc: Peter Zijlstra <peterz@infradead.org>\nCc: Anna-Maria Behnsen <anna-maria@linutronix.de>\nCc: Frederic Weisbecker <frederic@kernel.org>\nCc: Ingo Molnar <mingo@kernel.org>\nLink: https://lore.kernel.org/lkml/acMe-QZUel-bBYUh@mozart.vkv.me/\n---\nV2: Simplified the clockevents code - Peter\n---\n include/linux/clockchips.h |    2 ++\n kernel/time/clockevents.c  |   23 +++++++++++++++--------\n kernel/time/hrtimer.c      |    1 +\n kernel/time/tick-common.c  |    1 +\n kernel/time/tick-sched.c   |    1 +\n 5 files changed, 20 insertions(+), 8 deletions(-)","diff":"--- a/include/linux/clockchips.h\n+++ b/include/linux/clockchips.h\n@@ -80,6 +80,7 @@ enum clock_event_state {\n  * @shift:\t\tnanoseconds to cycles divisor (power of two)\n  * @state_use_accessors:current state of the device, assigned by the core code\n  * @features:\t\tfeatures\n+ * @next_event_forced:\tTrue if the last programming was a forced event\n  * @retries:\t\tnumber of forced programming retries\n  * @set_state_periodic:\tswitch state to periodic\n  * @set_state_oneshot:\tswitch state to oneshot\n@@ -108,6 +109,7 @@ struct clock_event_device {\n \tu32\t\t\tshift;\n \tenum clock_event_state\tstate_use_accessors;\n \tunsigned int\t\tfeatures;\n+\tunsigned int\t\tnext_event_forced;\n \tunsigned long\t\tretries;\n \n \tint\t\t\t(*set_state_periodic)(struct clock_event_device *);\n--- a/kernel/time/clockevents.c\n+++ b/kernel/time/clockevents.c\n@@ -172,6 +172,7 @@ void clockevents_shutdown(struct clock_e\n {\n \tclockevents_switch_state(dev, CLOCK_EVT_STATE_SHUTDOWN);\n \tdev->next_event = KTIME_MAX;\n+\tdev->next_event_forced = 0;\n }\n \n /**\n@@ -305,7 +306,6 @@ int clockevents_program_event(struct clo\n {\n \tunsigned long long clc;\n \tint64_t delta;\n-\tint rc;\n \n \tif (WARN_ON_ONCE(expires < 0))\n \t\treturn -ETIME;\n@@ -324,16 +324,23 @@ int clockevents_program_event(struct clo\n \t\treturn dev->set_next_ktime(expires, dev);\n \n \tdelta = ktime_to_ns(ktime_sub(expires, ktime_get()));\n-\tif (delta <= 0)\n-\t\treturn force ? clockevents_program_min_delta(dev) : -ETIME;\n \n-\tdelta = min(delta, (int64_t) dev->max_delta_ns);\n-\tdelta = max(delta, (int64_t) dev->min_delta_ns);\n+\tif (delta > (int64_t)dev->min_delta_ns) {\n+\t\tdelta = min(delta, (int64_t) dev->max_delta_ns);\n+\t\tclc = ((unsigned long long) delta * dev->mult) >> dev->shift;\n+\t\tif (!dev->set_next_event((unsigned long) clc, dev))\n+\t\t\treturn 0;\n+\t}\n \n-\tclc = ((unsigned long long) delta * dev->mult) >> dev->shift;\n-\trc = dev->set_next_event((unsigned long) clc, dev);\n+\tif (dev->next_event_forced)\n+\t\treturn 0;\n \n-\treturn (rc && force) ? clockevents_program_min_delta(dev) : rc;\n+\tif (dev->set_next_event(dev->min_delta_ticks, dev)) {\n+\t\tif (!force || clockevents_program_min_delta(dev))\n+\t\t\treturn -ETIME;\n+\t}\n+\tdev->next_event_forced = 1;\n+\treturn 0;\n }\n \n /*\n--- a/kernel/time/hrtimer.c\n+++ b/kernel/time/hrtimer.c\n@@ -1888,6 +1888,7 @@ void hrtimer_interrupt(struct clock_even\n \tBUG_ON(!cpu_base->hres_active);\n \tcpu_base->nr_events++;\n \tdev->next_event = KTIME_MAX;\n+\tdev->next_event_forced = 0;\n \n \traw_spin_lock_irqsave(&cpu_base->lock, flags);\n \tentry_time = now = hrtimer_update_base(cpu_base);\n--- a/kernel/time/tick-common.c\n+++ b/kernel/time/tick-common.c\n@@ -110,6 +110,7 @@ void tick_handle_periodic(struct clock_e\n \tint cpu = smp_processor_id();\n \tktime_t next = dev->next_event;\n \n+\tdev->next_event_forced = 0;\n \ttick_periodic(cpu);\n \n \t/*\n--- a/kernel/time/tick-sched.c\n+++ b/kernel/time/tick-sched.c\n@@ -1513,6 +1513,7 @@ static void tick_nohz_lowres_handler(str\n \tstruct tick_sched *ts = this_cpu_ptr(&tick_cpu_sched);\n \n \tdev->next_event = KTIME_MAX;\n+\tdev->next_event_forced = 0;\n \n \tif (likely(tick_nohz_handler(&ts->sched_timer) == HRTIMER_RESTART))\n \t\ttick_program_event(hrtimer_get_expires(&ts->sched_timer), 1);\n","prefixes":["01/12"]}