From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mail-wr1-f48.google.com (mail-wr1-f48.google.com [209.85.221.48]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id E3BF430568B for ; Mon, 17 Aug 2026 01:43:43 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.221.48 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786931025; cv=none; b=Vi7i6ciG8EmNllIAr6m6VSL/mTpcGRXUnQCRf2QYNvjJcbFCTSxy50VLcRn19jAvz4ZDjlpYEBTJtfzsC58eG70e6XA66UrxvC6E3pWbL6FMOscgTgnxvRvUM154vIWxog/zjvBhh2y3Kl8SLqzYxaC/VLbeX3OaWjN0rIg+5PE= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786931025; c=relaxed/simple; bh=KTF4SbsujXMW774XFidlx28bgRQdG/juW8w2xk4oqNI=; h=Date:From:To:Cc:Subject:Message-ID:References:MIME-Version: Content-Type:Content-Disposition:In-Reply-To; b=hSby6cw3z3BkhLQevU1MBiVfWNXIHUFsVJBm8oX+MpNjCi4kPd8sABSAxorOl4I+SzDha9Hj7bxGLqYyT5SNJ9JNZNKk4TNWa1BRHYk9OFFNezhdVFdl+y0YRGuVXY+dlUqIX6SIM08ZCVe516nssnqKzy7EW8aprP5Xvd71ZGI= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=ewCLQdbk; arc=none smtp.client-ip=209.85.221.48 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="ewCLQdbk" Received: by mail-wr1-f48.google.com with SMTP id ffacd0b85a97d-47ddf7b09e5so2896600f8f.1 for ; Sun, 16 Aug 2026 18:43:43 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1786931022; x=1787535822; darn=vger.kernel.org; h=in-reply-to:content-disposition:content-type:mime-version :references:message-id:subject:cc:to:from:date:from:to:cc:subject :date:message-id:reply-to:content-type; bh=GNT8LbyIlLO1KA9N3Ppnv86v2THDT/5d+bmEcq3CPJY=; b=ewCLQdbkuitW5YY0QWHaQ21Vp0oDCdQ/eNnRXtuX3ewqG5eqpHA1jE7oJ8bZZl8Uh4 WOs8HvUQuxeiTA4b5L+bQVkDwQBh4DwuztBHpJgjRNl4s+ruviwVtp9SQNrO6bDCHeA2 lwxCDVhFELznnBp+JFOnMgEaXbN+txpRZ0p7Y0zf2M1s0NaeKnQdh1O9kaG8+e4mwlPC opypmKlMWTb/Em9hn272SZaWYaTl9Z9gm7xKYB/iQ0FbuJMqSOouN2kCIoIoPRF2Dmo1 e+jaMcDzfn+S2w6ijM2FSKONlTZ+UoMl63pdwwBJ+wt0zfvhH1/+RcgH7YV+kYFo1fV2 xN/g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1786931022; x=1787535822; h=in-reply-to:content-disposition:content-type:mime-version :references:message-id:subject:cc:to:from:date:x-gm-gg :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to :content-type; bh=GNT8LbyIlLO1KA9N3Ppnv86v2THDT/5d+bmEcq3CPJY=; b=npz/w1MaW4kaoH10AHoW9I+LQNHrNYFBxr92EhYifiRZs5wpWeut+ydgIsXN8kRQXj 2kcTcBF5VHiua+9U7VnQg1LK7iMyw5uk5S9FrjsPkZQg0aPNrDiMci2xwLmqk8RDATQD 3TiYscZkQzVuRQByNunujfRWRdbKp0yjYkgnMa0F2TT+YwvMKGaCz+I2p7wf99MFTLoh /4Rx2xGnQWksLVdPsw41F/UjVgnBvrzOnxUzjAABPBDpBO+FQ32bblzSg7wOrRjxTuwx SM7/bnayX5mQTiGOqVTZux/v4ubPQ2tKYATTdPJ4WWqnp6JK/UJjU0lRFmtnolFXEULE UdpA== X-Forwarded-Encrypted: i=1; AHgh+Rpv4QkcQgJl0KZnKjB6kvxLIuim1K4ETeOG/t9K7pmR+tTuFf5+R1XxZNJD07TJJdkzAMUlVbLw8SuWA3w=@vger.kernel.org X-Gm-Message-State: AOJu0YwCLeQnUb119Qx2d2hNSQp6+l3VOiKAi0N37W8+mx3IjedU6Z5v jXL/RSr1XCIrPAXDthZGHGwv7lAN5+Fo7epvIbBi4Co3iAs/igl2IW0C X-Gm-Gg: AR+sD11iQGelJlc+AsbHTJprf7hqhjJV9tGa6wFECaeFYkaLjUd2bhs/Hn3OE2JdODa jpfSIQc1xKyO6fRQQxmUbkUE/V5ra+qymp8fzx65oaMyXJDGKhkevahUjzZe2g6O4ZfnLW79CDl 8pf31DSeSqe1ZBLWhATgZ8ePyV1FcGJqp3d/D3iPDOehWG3qpbcNRZddq/9VdAtxcKGdWL55xnZ 3iaaMLwBnTgueLw8gkVvmgPWVWfsbJoKhJ8wIZXDFIswCke3GU1ks2fKhIZCvjiSFCTHP2ii7ho l0Gl1oPoq4+DvwypIWz3oWaErYcBB2imjk3YnrvlhABd79yukGTcDCtRBJBn1URWhCrxwKnbQnA TpMzgRgs4ypAadRszOB+uKl0kgtIdzDAV+tk5Oz46eq3f2SEa2LKJzVJ6C7UAxT2KnvmY+gnJRh BEphwihjfsiYdXfA5NYAWmyo/U/c+X5FE5yO2JWfOSOQc2phcOhq+dq6l2W9PcJYwqs5shA40Co /O8YWsKgaCSRo24WE0FJBHbUCTe96z94sBa3pYTpIw6nUgi0+NCKs+L1+YdhAcb7Goib2w07i7I 6Ry5jPJz+mM7qtcInMQyGHe2uQA/wt8Vwc51rmhIcZ3WtAF2A/biChY/G5l/eq/k/3yrhw== X-Received: by 2002:a05:6000:29cc:b0:47f:773f:2d68 with SMTP id ffacd0b85a97d-48160738c19mr25865875f8f.16.1786931021932; Sun, 16 Aug 2026 18:43:41 -0700 (PDT) Received: from unknown748F3CBA5068 (dynamic-2a02-3100-9dc5-9401-09c8-a88d-e919-d148.310.pool.telefonica.de. [2a02:3100:9dc5:9401:9c8:a88d:e919:d148]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-4815f2c18cbsm24837588f8f.29.2026.08.16.18.43.39 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 16 Aug 2026 18:43:41 -0700 (PDT) Date: Mon, 17 Aug 2026 03:43:39 +0200 From: Karl Mehltretter To: Peter Zijlstra Cc: Andrew Morton , Andrey Konovalov , Alexander Potapenko , Dmitry Vyukov , Marco Elver , Bradley Morgan , Anna-Maria Behnsen , Frederic Weisbecker , Thomas Gleixner , Ingo Molnar , Juri Lelli , Vincent Guittot , Dietmar Eggemann , Steven Rostedt , Ben Segall , Mel Gorman , Valentin Schneider , K Prateek Nayak , Sebastian Andrzej Siewior , Clark Williams , linux-rt-devel@lists.linux.dev, kasan-dev@googlegroups.com, linux-kernel@vger.kernel.org Subject: Re: [PATCH v2 3/6] hrtimer: Pause KCOV during deferred rearm Message-ID: References: <20260811154111.64669-1-kmehltretter@gmail.com> <20260811154111.64669-4-kmehltretter@gmail.com> <20260812102100.GF776954@noisy.programming.kicks-ass.net> <20260813130826.GW687043@noisy.programming.kicks-ass.net> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20260813130826.GW687043@noisy.programming.kicks-ass.net> On Thu, Aug 13, 2026 at 03:08:26PM +0100, Peter Zijlstra wrote: > Bah, so the only reason this one pops is because it is outside of the > softirq code, same for those two wakeups I suppose. > > Would something crazy like this work? That closes the holes in the > preempt_count munging around there. > > *completely* untested and all that > Thanks, I tested this. The idea helps, but the ksirqd check is not enough. __do_softirq() also runs from task context and ktimerd with ksirqd=false. Subtracting HARDIRQ_OFFSET there corrupts preempt_count. In the direct IRQ-exit path, __local_bh_disable_ip() also warns because HARDIRQ_OFFSET is still set. My version below checks in_hardirq() in handle_softirqs(). For direct IRQ-exit dispatch it replaces HARDIRQ_OFFSET with SOFTIRQ_OFFSET, then restores it. Other callers keep the normal local-BH accounting. tick_irq_exit() still runs after HARDIRQ_OFFSET is dropped. In a 400-round KCOV test, flaky PCs fell from 140 to 129. The average trace size fell from 147.7 to 141.6 PCs. But measured syzcaller coverage did not improve significantly. I also ran a targeted KCSAN test that intentionally produced 58 reports on each kernel. Baseline classified all IRQ-exit accesses as "by task". With this patch, all were "by interrupt". Both passed the KCSAN selftest. Lockdep and IRQ-tracing boots also passed. This patch does not replace the KCOV pause series. It only covers work dispatched directly from IRQ exit. Deferred rearm outside this path and task-context scheduler leaks remain. Karl --- diff --git a/kernel/softirq.c b/kernel/softirq.c index 7980a4a232f..d6be8ca2793 100644 --- a/kernel/softirq.c +++ b/kernel/softirq.c @@ -350,8 +350,8 @@ static inline void ksoftirqd_run_end(void) local_irq_enable(); } -static inline void softirq_handle_begin(void) { } -static inline void softirq_handle_end(void) { } +static inline bool softirq_handle_begin(void) { return false; } +static inline void softirq_handle_end(bool from_hardirq) { } static inline bool should_wake_ksoftirqd(void) { @@ -481,15 +481,35 @@ void __local_bh_enable_ip(unsigned long ip, unsigned int cnt) } EXPORT_SYMBOL(__local_bh_enable_ip); -static inline void softirq_handle_begin(void) +static inline bool softirq_handle_begin(void) { - __local_bh_disable_ip(_RET_IP_, SOFTIRQ_OFFSET); + bool from_hardirq = in_hardirq(); + + if (!from_hardirq) { + __local_bh_disable_ip(_RET_IP_, SOFTIRQ_OFFSET); + return false; + } + + /* Replace the retained hardirq context with normal softirq context. */ + __preempt_count_add((int)SOFTIRQ_OFFSET - (int)HARDIRQ_OFFSET); + if (softirq_count() == SOFTIRQ_OFFSET) + lockdep_softirqs_off(_RET_IP_); + + return true; } -static inline void softirq_handle_end(void) +static inline void softirq_handle_end(bool from_hardirq) { - __local_bh_enable(SOFTIRQ_OFFSET); - WARN_ON_ONCE(in_interrupt()); + if (!from_hardirq) { + __local_bh_enable(SOFTIRQ_OFFSET); + WARN_ON_ONCE(in_interrupt()); + return; + } + + if (softirq_count() == SOFTIRQ_OFFSET) + lockdep_softirqs_on(_RET_IP_); + __preempt_count_sub((int)SOFTIRQ_OFFSET - (int)HARDIRQ_OFFSET); + WARN_ON_ONCE(!in_hardirq()); } static inline void ksoftirqd_run_begin(void) @@ -605,6 +625,7 @@ static void handle_softirqs(bool ksirqd) unsigned long old_flags = current->flags; int max_restart = MAX_SOFTIRQ_RESTART; struct softirq_action *h; + bool from_hardirq; bool in_hardirq; __u32 pending; int softirq_bit; @@ -618,7 +639,7 @@ static void handle_softirqs(bool ksirqd) pending = local_softirq_pending(); - softirq_handle_begin(); + from_hardirq = softirq_handle_begin(); in_hardirq = lockdep_softirq_start(); account_softirq_enter(current); @@ -670,7 +691,7 @@ static void handle_softirqs(bool ksirqd) account_softirq_exit(current); lockdep_softirq_end(in_hardirq); - softirq_handle_end(); + softirq_handle_end(from_hardirq); current_restore_flags(old_flags, PF_MEMALLOC); } @@ -740,6 +761,9 @@ static inline void wake_timersd(void) { } #endif +#define IRQ_EXIT_TIMERS (NMI_MASK | HARDIRQ_MASK) +#define IRQ_EXIT_SOFTIRQ (IRQ_EXIT_TIMERS | HARDIRQ_DISABLE_MASK | SOFTIRQ_MASK) + static inline void __irq_exit_rcu(void) { #ifndef __ARCH_IRQ_EXIT_IRQS_DISABLED @@ -748,7 +772,6 @@ static inline void __irq_exit_rcu(void) lockdep_assert_irqs_disabled(); #endif account_hardirq_exit(current); - preempt_count_sub(HARDIRQ_OFFSET); /* * Interrupts may happen between hardirq_disable_enter() and * local_irq_save() in local_interrupt_disable(), if irq_exit() invokes @@ -757,7 +780,7 @@ static inline void __irq_exit_rcu(void) * hardirq disabling count is already 1, hence we need to prevent * invoking softirq when a local_interrupt_disable() is ongoing. */ - if (!in_interrupt() && !hardirq_disable_count() && + if ((preempt_count() & IRQ_EXIT_SOFTIRQ) == HARDIRQ_OFFSET && local_softirq_pending()) { /* * If we left hrtimers unarmed, make sure to arm them now, @@ -768,9 +791,11 @@ static inline void __irq_exit_rcu(void) } if (IS_ENABLED(CONFIG_IRQ_FORCED_THREADING) && force_irqthreads() && - local_timers_pending_force_th() && !(in_nmi() | in_hardirq())) + local_timers_pending_force_th() && + (preempt_count() & IRQ_EXIT_TIMERS) == HARDIRQ_OFFSET) wake_timersd(); + preempt_count_sub(HARDIRQ_OFFSET); tick_irq_exit(); }