From nobody Mon Feb 9 07:20:12 2026 Received: from mail-wm1-f73.google.com (mail-wm1-f73.google.com [209.85.128.73]) (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 0CA0B3446BB for ; Fri, 19 Dec 2025 15:46:19 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.128.73 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1766159182; cv=none; b=s2aONE1N/8e+vM0mKmXoNhzj6O+01o1x3xLHrtC/ya1kt6l9rWo2DPGxBQEWsN+PIWccnp1/rT1fthby08QAuWQSN0284INyKzXl1PJNAvEkvBC3LnvKi9AINllia5LUnAnJMa56vBbb0hQQRS/pEWA59cl59DRjTZg4Fl9A/yk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1766159182; c=relaxed/simple; bh=twLTnhf5u6L/bpwFTiOMumVPeFgZcHl3jJv/1Wf0m5s=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=S3nN7lMSHcZxndn2BTmCThMBsDoTTeizjjvJvKQjS2q4RzMfdhiwmXPm5SGzV+9PmV563EKtK8RpRLyY1XWUbInNekyEE+4vhorbE2fSyJ53n25sEi6inMkjtAWCEoa/20CplJCDGOjIqZV4nHDVsNDBX8+zqBt3BUnGE+xX+ec= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--elver.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=q6VHETu3; arc=none smtp.client-ip=209.85.128.73 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--elver.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="q6VHETu3" Received: by mail-wm1-f73.google.com with SMTP id 5b1f17b1804b1-477cf25ceccso19113585e9.0 for ; Fri, 19 Dec 2025 07:46:18 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1766159177; x=1766763977; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=xxzeiPbUa31+hz0U8Tv6bmU7luRcJmafBg2S0XNVzY0=; b=q6VHETu3P2tuxPJRg7rWfTyTwiv1PfoD8fe5S4TeAnmUYXc6bt+0f71H30Txa/bcqW ZKqnK3qliOElsmydWkN6vIF8f5Uq61prcno4x9uJqjoSQ0nxF3GXwR+iGJeuWDnK4ct+ ZD+vZ6QjNPFqv4CV3EWdV0XhMfPMomC80YqBOi72P+Yk/rY2u3OJZUe1aNuK4Jlqpw/R w1vRoFsRF5gL4UlThUdVqT1qcs7s1tpCxggCyB4bjGAyGSC+N5YxDrFdbGIiIryd9yCb LQCsy+0HndSG+5OuxUKlRdmnJh44xENck9ni2pSH06zsbqNCUJqbwYBfUDO4Cu40mTfb AaSg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1766159177; x=1766763977; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=xxzeiPbUa31+hz0U8Tv6bmU7luRcJmafBg2S0XNVzY0=; b=DxjgoNRonDSAizHyuULnc/FNfeDgeGWEWLMcFprQe8wi35HoHigT6p1vfX0HJTVyCd 5OpW3AX8053YQsEqcmDHaXKIpNK1DbkVrjH2ZmrC/8ItLTDOVFVwRPAXLtyCCBsm7f4z 0dBoLRowN9Gbo0ZKV3BQ5I3pUTwzXsJXakyjVrnKFnKXWPDVUeP3jgX3gKyetevuK7nh ony5JTrdYdfXGv/RL3jjW4JU5spXFJ4VfRPST+6B2mf8u4QL0Mr8olpLkwp6P369nlO9 Dt7EFXWSNa5tjEw/oKz44pqHOfZs1rVnzbxSg2yS3qBZkAK9LWPZREInSnWlvcRGQG3a F+hw== X-Forwarded-Encrypted: i=1; AJvYcCWazzCZFiM1k2/eKHFBYL+0G3VSZThSSZlO/jSCHf8B/REVXBTcFSpi8uoGF4JKDL/JSg13TbGZRwkv6bg=@vger.kernel.org X-Gm-Message-State: AOJu0YxatsZpMccSlJpoC75KB8NiV2ltGF/FT0Pcx86uM7aE7jV3dj2y v4aAxoo9Pbjg1PQrkK5wmJadp2Px35/1Vi/0Zj2bMpjit1piKCACF/e9szxviHbJBwStB8n6Erc KpA== X-Google-Smtp-Source: AGHT+IGaGS8VBg9MijqM6Ta4+HbU9bsl4GQbb/p7haK0nKuccuPDjffspfAf6ASbrAdFf7JACzcajKCfOA== X-Received: from wmbgx16.prod.google.com ([2002:a05:600c:8590:b0:47a:90c7:e279]) (user=elver job=prod-delivery.src-stubby-dispatcher) by 2002:a05:600c:820d:b0:479:3a87:208f with SMTP id 5b1f17b1804b1-47d195aa085mr30269305e9.36.1766159177290; Fri, 19 Dec 2025 07:46:17 -0800 (PST) Date: Fri, 19 Dec 2025 16:40:02 +0100 In-Reply-To: <20251219154418.3592607-1-elver@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20251219154418.3592607-1-elver@google.com> X-Mailer: git-send-email 2.52.0.322.g1dd061c0dc-goog Message-ID: <20251219154418.3592607-14-elver@google.com> Subject: [PATCH v5 13/36] bit_spinlock: Support Clang's context analysis From: Marco Elver To: elver@google.com, Peter Zijlstra , Boqun Feng , Ingo Molnar , Will Deacon Cc: "David S. Miller" , Luc Van Oostenryck , Chris Li , "Paul E. McKenney" , Alexander Potapenko , Arnd Bergmann , Bart Van Assche , Christoph Hellwig , Dmitry Vyukov , Eric Dumazet , Frederic Weisbecker , Greg Kroah-Hartman , Herbert Xu , Ian Rogers , Jann Horn , Joel Fernandes , Johannes Berg , Jonathan Corbet , Josh Triplett , Justin Stitt , Kees Cook , Kentaro Takeda , Lukas Bulwahn , Mark Rutland , Mathieu Desnoyers , Miguel Ojeda , Nathan Chancellor , Neeraj Upadhyay , Nick Desaulniers , Steven Rostedt , Tetsuo Handa , Thomas Gleixner , Thomas Graf , Uladzislau Rezki , Waiman Long , kasan-dev@googlegroups.com, linux-crypto@vger.kernel.org, linux-doc@vger.kernel.org, linux-kbuild@vger.kernel.org, linux-kernel@vger.kernel.org, linux-mm@kvack.org, linux-security-module@vger.kernel.org, linux-sparse@vger.kernel.org, linux-wireless@vger.kernel.org, llvm@lists.linux.dev, rcu@vger.kernel.org Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" The annotations for bit_spinlock.h have simply been using "bitlock" as the token. For Sparse, that was likely sufficient in most cases. But Clang's context analysis is more precise, and we need to ensure we can distinguish different bitlocks. To do so, add a token context, and a macro __bitlock(bitnum, addr) that is used to construct unique per-bitlock tokens. Add the appropriate test. is implicitly included through other includes, and requires 2 annotations to indicate that acquisition (without release) and release (without prior acquisition) of its bitlock is intended. Signed-off-by: Marco Elver --- v5: * Rename "context guard" -> "context lock". v4: * Rename capability -> context analysis. --- Documentation/dev-tools/context-analysis.rst | 3 ++- include/linux/bit_spinlock.h | 22 ++++++++++++++--- include/linux/list_bl.h | 2 ++ lib/test_context-analysis.c | 26 ++++++++++++++++++++ 4 files changed, 48 insertions(+), 5 deletions(-) diff --git a/Documentation/dev-tools/context-analysis.rst b/Documentation/d= ev-tools/context-analysis.rst index 690565910084..b2d69fb4a884 100644 --- a/Documentation/dev-tools/context-analysis.rst +++ b/Documentation/dev-tools/context-analysis.rst @@ -79,7 +79,8 @@ Supported Kernel Primitives ~~~~~~~~~~~~~~~~~~~~~~~~~~~ =20 Currently the following synchronization primitives are supported: -`raw_spinlock_t`, `spinlock_t`, `rwlock_t`, `mutex`, `seqlock_t`. +`raw_spinlock_t`, `spinlock_t`, `rwlock_t`, `mutex`, `seqlock_t`, +`bit_spinlock`. =20 For context locks with an initialization function (e.g., `spin_lock_init()= `), calling this function before initializing any guarded members or globals diff --git a/include/linux/bit_spinlock.h b/include/linux/bit_spinlock.h index 59e345f74b0e..7869a6e59b6a 100644 --- a/include/linux/bit_spinlock.h +++ b/include/linux/bit_spinlock.h @@ -9,6 +9,16 @@ =20 #include /* for cpu_relax() */ =20 +/* + * For static context analysis, we need a unique token for each possible b= it + * that can be used as a bit_spinlock. The easiest way to do that is to cr= eate a + * fake context that we can cast to with the __bitlock(bitnum, addr) macro + * below, which will give us unique instances for each (bit, addr) pair th= at the + * static analysis can use. + */ +context_lock_struct(__context_bitlock) { }; +#define __bitlock(bitnum, addr) (struct __context_bitlock *)(bitnum + (add= r)) + /* * bit-based spin_lock() * @@ -16,6 +26,7 @@ * are significantly faster. */ static __always_inline void bit_spin_lock(int bitnum, unsigned long *addr) + __acquires(__bitlock(bitnum, addr)) { /* * Assuming the lock is uncontended, this never enters @@ -34,13 +45,14 @@ static __always_inline void bit_spin_lock(int bitnum, u= nsigned long *addr) preempt_disable(); } #endif - __acquire(bitlock); + __acquire(__bitlock(bitnum, addr)); } =20 /* * Return true if it was acquired */ static __always_inline int bit_spin_trylock(int bitnum, unsigned long *add= r) + __cond_acquires(true, __bitlock(bitnum, addr)) { preempt_disable(); #if defined(CONFIG_SMP) || defined(CONFIG_DEBUG_SPINLOCK) @@ -49,7 +61,7 @@ static __always_inline int bit_spin_trylock(int bitnum, u= nsigned long *addr) return 0; } #endif - __acquire(bitlock); + __acquire(__bitlock(bitnum, addr)); return 1; } =20 @@ -57,6 +69,7 @@ static __always_inline int bit_spin_trylock(int bitnum, u= nsigned long *addr) * bit-based spin_unlock() */ static __always_inline void bit_spin_unlock(int bitnum, unsigned long *add= r) + __releases(__bitlock(bitnum, addr)) { #ifdef CONFIG_DEBUG_SPINLOCK BUG_ON(!test_bit(bitnum, addr)); @@ -65,7 +78,7 @@ static __always_inline void bit_spin_unlock(int bitnum, u= nsigned long *addr) clear_bit_unlock(bitnum, addr); #endif preempt_enable(); - __release(bitlock); + __release(__bitlock(bitnum, addr)); } =20 /* @@ -74,6 +87,7 @@ static __always_inline void bit_spin_unlock(int bitnum, u= nsigned long *addr) * protecting the rest of the flags in the word. */ static __always_inline void __bit_spin_unlock(int bitnum, unsigned long *a= ddr) + __releases(__bitlock(bitnum, addr)) { #ifdef CONFIG_DEBUG_SPINLOCK BUG_ON(!test_bit(bitnum, addr)); @@ -82,7 +96,7 @@ static __always_inline void __bit_spin_unlock(int bitnum,= unsigned long *addr) __clear_bit_unlock(bitnum, addr); #endif preempt_enable(); - __release(bitlock); + __release(__bitlock(bitnum, addr)); } =20 /* diff --git a/include/linux/list_bl.h b/include/linux/list_bl.h index ae1b541446c9..df9eebe6afca 100644 --- a/include/linux/list_bl.h +++ b/include/linux/list_bl.h @@ -144,11 +144,13 @@ static inline void hlist_bl_del_init(struct hlist_bl_= node *n) } =20 static inline void hlist_bl_lock(struct hlist_bl_head *b) + __acquires(__bitlock(0, b)) { bit_spin_lock(0, (unsigned long *)b); } =20 static inline void hlist_bl_unlock(struct hlist_bl_head *b) + __releases(__bitlock(0, b)) { __bit_spin_unlock(0, (unsigned long *)b); } diff --git a/lib/test_context-analysis.c b/lib/test_context-analysis.c index 53abea0008f2..be0c5d462a48 100644 --- a/lib/test_context-analysis.c +++ b/lib/test_context-analysis.c @@ -4,6 +4,7 @@ * positive errors when compiled with Clang's context analysis. */ =20 +#include #include #include #include @@ -258,3 +259,28 @@ static void __used test_seqlock_scoped(struct test_seq= lock_data *d) (void)d->counter; } } + +struct test_bit_spinlock_data { + unsigned long bits; + int counter __guarded_by(__bitlock(3, &bits)); +}; + +static void __used test_bit_spin_lock(struct test_bit_spinlock_data *d) +{ + /* + * Note, the analysis seems to have false negatives, because it won't + * precisely recognize the bit of the fake __bitlock() token. + */ + bit_spin_lock(3, &d->bits); + d->counter++; + bit_spin_unlock(3, &d->bits); + + bit_spin_lock(3, &d->bits); + d->counter++; + __bit_spin_unlock(3, &d->bits); + + if (bit_spin_trylock(3, &d->bits)) { + d->counter++; + bit_spin_unlock(3, &d->bits); + } +} --=20 2.52.0.322.g1dd061c0dc-goog