From: Eric Biggers <ebiggers@kernel.org>
To: linux-crypto@vger.kernel.org
Cc: linux-kernel@vger.kernel.org, Ard Biesheuvel <ardb@kernel.org>,
"Jason A . Donenfeld" <Jason@zx2c4.com>,
Herbert Xu <herbert@gondor.apana.org.au>,
kunit-dev@googlegroups.com,
Brendan Higgins <brendan.higgins@linux.dev>,
David Gow <davidgow@google.com>, Rae Moar <raemoar63@gmail.com>,
Eric Biggers <ebiggers@kernel.org>,
stable@vger.kernel.org
Subject: [PATCH] kunit: irq: Ensure timer doesn't fire too frequently
Date: Mon, 23 Feb 2026 19:37:51 -0800 [thread overview]
Message-ID: <20260224033751.97615-1-ebiggers@kernel.org> (raw)
Fix a bug where kunit_run_irq_test() could hang if the system is too
slow. This was noticed with the crypto library tests in certain VMs.
Specifically, if kunit_irq_test_timer_func() and the associated hrtimer
code took over 5us to run, then the CPU would spend all its time
executing that code in hardirq context. As a result, the task executing
kunit_run_irq_test() never had a chance to run, exit the loop, and
cancel the timer.
To fix it, make kunit_irq_test_timer_func() increase the timer interval
when the other contexts aren't having a chance to run.
Fixes: 950a81224e8b ("lib/crypto: tests: Add hash-test-template.h and gen-hash-testvecs.py")
Cc: stable@vger.kernel.org
Signed-off-by: Eric Biggers <ebiggers@kernel.org>
---
This patch applies to v7.0-rc1 and is targeting libcrypto-fixes
include/kunit/run-in-irq-context.h | 44 +++++++++++++++++++-----------
1 file changed, 28 insertions(+), 16 deletions(-)
diff --git a/include/kunit/run-in-irq-context.h b/include/kunit/run-in-irq-context.h
index c89b1b1b12dd5..bfe60d6cf28d8 100644
--- a/include/kunit/run-in-irq-context.h
+++ b/include/kunit/run-in-irq-context.h
@@ -10,36 +10,47 @@
#include <kunit/test.h>
#include <linux/timekeeping.h>
#include <linux/hrtimer.h>
#include <linux/workqueue.h>
-#define KUNIT_IRQ_TEST_HRTIMER_INTERVAL us_to_ktime(5)
-
struct kunit_irq_test_state {
bool (*func)(void *test_specific_state);
void *test_specific_state;
bool task_func_reported_failure;
bool hardirq_func_reported_failure;
bool softirq_func_reported_failure;
+ atomic_t task_func_calls;
atomic_t hardirq_func_calls;
atomic_t softirq_func_calls;
+ ktime_t interval;
struct hrtimer timer;
struct work_struct bh_work;
};
static enum hrtimer_restart kunit_irq_test_timer_func(struct hrtimer *timer)
{
struct kunit_irq_test_state *state =
container_of(timer, typeof(*state), timer);
+ int task_calls, hardirq_calls, softirq_calls;
WARN_ON_ONCE(!in_hardirq());
- atomic_inc(&state->hardirq_func_calls);
+ task_calls = atomic_read(&state->task_func_calls);
+ hardirq_calls = atomic_inc_return(&state->hardirq_func_calls);
+ softirq_calls = atomic_read(&state->softirq_func_calls);
+
+ /*
+ * If the timer is firing too often for the softirq or task to ever have
+ * a chance to run, increase the timer interval. This is needed on very
+ * slow systems.
+ */
+ if (hardirq_calls >= 20 && (softirq_calls == 0 || task_calls == 0))
+ state->interval = ktime_add_ns(state->interval, 250);
if (!state->func(state->test_specific_state))
state->hardirq_func_reported_failure = true;
- hrtimer_forward_now(&state->timer, KUNIT_IRQ_TEST_HRTIMER_INTERVAL);
+ hrtimer_forward_now(&state->timer, state->interval);
queue_work(system_bh_wq, &state->bh_work);
return HRTIMER_RESTART;
}
static void kunit_irq_test_bh_work_func(struct work_struct *work)
@@ -84,14 +95,18 @@ static inline void kunit_run_irq_test(struct kunit *test, bool (*func)(void *),
void *test_specific_state)
{
struct kunit_irq_test_state state = {
.func = func,
.test_specific_state = test_specific_state,
+ /*
+ * Start with a 5us timer interval. If the system can't keep
+ * up, kunit_irq_test_timer_func() will increase it.
+ */
+ .interval = us_to_ktime(5),
};
unsigned long end_jiffies;
- int hardirq_calls, softirq_calls;
- bool allctx = false;
+ int task_calls, hardirq_calls, softirq_calls;
/*
* Set up a hrtimer (the way we access hardirq context) and a work
* struct for the BH workqueue (the way we access softirq context).
*/
@@ -102,25 +117,22 @@ static inline void kunit_run_irq_test(struct kunit *test, bool (*func)(void *),
/*
* Run for up to max_iterations (including at least one task, softirq,
* and hardirq), or 1 second, whichever comes first.
*/
end_jiffies = jiffies + HZ;
- hrtimer_start(&state.timer, KUNIT_IRQ_TEST_HRTIMER_INTERVAL,
- HRTIMER_MODE_REL_HARD);
- for (int task_calls = 0, calls = 0;
- ((calls < max_iterations) || !allctx) &&
- !time_after(jiffies, end_jiffies);
- task_calls++) {
+ hrtimer_start(&state.timer, state.interval, HRTIMER_MODE_REL_HARD);
+ do {
if (!func(test_specific_state))
state.task_func_reported_failure = true;
+ task_calls = atomic_inc_return(&state.task_func_calls);
hardirq_calls = atomic_read(&state.hardirq_func_calls);
softirq_calls = atomic_read(&state.softirq_func_calls);
- calls = task_calls + hardirq_calls + softirq_calls;
- allctx = (task_calls > 0) && (hardirq_calls > 0) &&
- (softirq_calls > 0);
- }
+ } while ((task_calls + hardirq_calls + softirq_calls < max_iterations ||
+ (task_calls == 0 || hardirq_calls == 0 ||
+ softirq_calls == 0)) &&
+ !time_after(jiffies, end_jiffies));
/* Cancel the timer and work. */
hrtimer_cancel(&state.timer);
flush_work(&state.bh_work);
base-commit: 6de23f81a5e08be8fbf5e8d7e9febc72a5b5f27f
--
2.53.0
next reply other threads:[~2026-02-24 3:40 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-02-24 3:37 Eric Biggers [this message]
2026-02-24 9:01 ` [PATCH] kunit: irq: Ensure timer doesn't fire too frequently David Gow
2026-02-24 22:46 ` Eric Biggers
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260224033751.97615-1-ebiggers@kernel.org \
--to=ebiggers@kernel.org \
--cc=Jason@zx2c4.com \
--cc=ardb@kernel.org \
--cc=brendan.higgins@linux.dev \
--cc=davidgow@google.com \
--cc=herbert@gondor.apana.org.au \
--cc=kunit-dev@googlegroups.com \
--cc=linux-crypto@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=raemoar63@gmail.com \
--cc=stable@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.